From ebf6f91df0397e14d8ff9669fade13be587f99d4 Mon Sep 17 00:00:00 2001 From: Tamer Sherif <69483382+tasherif-msft@users.noreply.github.com> Date: Wed, 3 May 2023 10:30:13 -0700 Subject: [PATCH 01/16] [AzDatalake] Generated Layer + mod file (#20725) * first generation * removed pagination * cleanup spacing and add build file * doc fix --- sdk/storage/azdatalake/go.mod | 11 + sdk/storage/azdatalake/go.sum | 12 + .../azdatalake/internal/generated/autorest.md | 81 + .../azdatalake/internal/generated/build.go | 10 + .../internal/generated/zz_constants.go | 158 ++ .../generated/zz_filesystem_client.go | 496 ++++++ .../internal/generated/zz_models.go | 679 ++++++++ .../internal/generated/zz_models_serde.go | 415 +++++ .../internal/generated/zz_path_client.go | 1530 +++++++++++++++++ .../internal/generated/zz_response_types.go | 557 ++++++ .../internal/generated/zz_service_client.go | 100 ++ .../internal/generated/zz_time_rfc1123.go | 43 + 12 files changed, 4092 insertions(+) create mode 100644 sdk/storage/azdatalake/go.mod create mode 100644 sdk/storage/azdatalake/go.sum create mode 100644 sdk/storage/azdatalake/internal/generated/autorest.md create mode 100644 sdk/storage/azdatalake/internal/generated/build.go create mode 100644 sdk/storage/azdatalake/internal/generated/zz_constants.go create mode 100644 sdk/storage/azdatalake/internal/generated/zz_filesystem_client.go create mode 100644 sdk/storage/azdatalake/internal/generated/zz_models.go create mode 100644 sdk/storage/azdatalake/internal/generated/zz_models_serde.go create mode 100644 sdk/storage/azdatalake/internal/generated/zz_path_client.go create mode 100644 sdk/storage/azdatalake/internal/generated/zz_response_types.go create mode 100644 sdk/storage/azdatalake/internal/generated/zz_service_client.go create mode 100644 sdk/storage/azdatalake/internal/generated/zz_time_rfc1123.go diff --git a/sdk/storage/azdatalake/go.mod b/sdk/storage/azdatalake/go.mod new file mode 100644 index 000000000000..dfd718eb5e06 --- /dev/null +++ b/sdk/storage/azdatalake/go.mod @@ -0,0 +1,11 @@ +module github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake + +go 1.19 + +require github.com/Azure/azure-sdk-for-go/sdk/azcore v1.5.0 + +require ( + github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0 // indirect + golang.org/x/net v0.8.0 // indirect + golang.org/x/text v0.8.0 // indirect +) diff --git a/sdk/storage/azdatalake/go.sum b/sdk/storage/azdatalake/go.sum new file mode 100644 index 000000000000..5b3d1f6c33e0 --- /dev/null +++ b/sdk/storage/azdatalake/go.sum @@ -0,0 +1,12 @@ +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.5.0 h1:xGLAFFd9D3iLGxYiUGPdITSzsFmU1K8VtfuUHWAoN7M= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.5.0/go.mod h1:bjGvMhVMb+EEm3VRNQawDMUyMMjo+S5ewNjflkep/0Q= +github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0 h1:sXr+ck84g/ZlZUOZiNELInmMgOsuGwdjjVkEIde0OtY= +github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0/go.mod h1:okt5dMMTOFjX/aovMlrjvvXoPMBVSPzk9185BT0+eZM= +github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= +golang.org/x/net v0.8.0 h1:Zrh2ngAOFYneWTAIAPethzeaQLuHwhuBkuV6ZiRnUaQ= +golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= +golang.org/x/text v0.8.0 h1:57P1ETyNKtuIjB4SRd15iJxuhj8Gc416Y78H3qgMh68= +golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= diff --git a/sdk/storage/azdatalake/internal/generated/autorest.md b/sdk/storage/azdatalake/internal/generated/autorest.md new file mode 100644 index 000000000000..9a83369f048b --- /dev/null +++ b/sdk/storage/azdatalake/internal/generated/autorest.md @@ -0,0 +1,81 @@ +# Code Generation - Azure Datalake SDK for Golang + +### Settings + +```yaml +go: true +clear-output-folder: false +version: "^3.0.0" +license-header: MICROSOFT_MIT_NO_VERSION +input-file: "https://raw.githubusercontent.com/Azure/azure-rest-api-specs/main/specification/storage/data-plane/Microsoft.StorageDataLake/preview/2020-10-02/DataLakeStorage.json" +credential-scope: "https://storage.azure.com/.default" +output-folder: ../generated +file-prefix: "zz_" +openapi-type: "data-plane" +verbose: true +security: AzureKey +modelerfour: + group-parameters: false + seal-single-value-enum-by-default: true + lenient-model-deduplication: true +export-clients: true +use: "@autorest/go@4.0.0-preview.45" +``` + +### Remove Filesystem and PathName from parameter list since they are not needed +``` yaml +directive: +- from: swagger-document + where: $["x-ms-paths"] + transform: > + for (const property in $) + { + if (property.includes('/{filesystem}/{path}')) + { + $[property]["parameters"] = $[property]["parameters"].filter(function(param) { return (typeof param['$ref'] === "undefined") || (false == param['$ref'].endsWith("#/parameters/FileSystem") && false == param['$ref'].endsWith("#/parameters/Path"))}); + } + else if (property.includes('/{filesystem}')) + { + $[property]["parameters"] = $[property]["parameters"].filter(function(param) { return (typeof param['$ref'] === "undefined") || (false == param['$ref'].endsWith("#/parameters/FileSystem"))}); + } + } +``` + +### Remove pager methods and export various generated methods in filesystem client + +``` yaml +directive: + - from: zz_filesystem_client.go + where: $ + transform: >- + return $. + replace(/func \(client \*FileSystemClient\) NewListBlobHierarchySegmentPager\(.+\/\/ listBlobHierarchySegmentCreateRequest creates the ListBlobHierarchySegment request/s, `//\n// ListBlobHierarchySegmentCreateRequest creates the ListBlobHierarchySegment request`). + replace(/\(client \*FileSystemClient\) listBlobHierarchySegmentCreateRequest\(/, `(client *FileSystemClient) ListBlobHierarchySegmentCreateRequest(`). + replace(/\(client \*FileSystemClient\) listBlobHierarchySegmentHandleResponse\(/, `(client *FileSystemClient) ListBlobHierarchySegmentHandleResponse(`); +``` + +### Remove pager methods and export various generated methods in filesystem client + +``` yaml +directive: + - from: zz_filesystem_client.go + where: $ + transform: >- + return $. + replace(/func \(client \*FileSystemClient\) NewListPathsPager\(.+\/\/ listPathsCreateRequest creates the ListPaths request/s, `//\n// ListPathsCreateRequest creates the ListPaths request`). + replace(/\(client \*FileSystemClient\) listPathsCreateRequest\(/, `(client *FileSystemClient) ListPathsCreateRequest(`). + replace(/\(client \*FileSystemClient\) listPathsHandleResponse\(/, `(client *FileSystemClient) ListPathsHandleResponse(`); +``` + +### Remove pager methods and export various generated methods in service client + +``` yaml +directive: + - from: zz_service_client.go + where: $ + 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(`); +``` \ No newline at end of file diff --git a/sdk/storage/azdatalake/internal/generated/build.go b/sdk/storage/azdatalake/internal/generated/build.go new file mode 100644 index 000000000000..57f112001bd2 --- /dev/null +++ b/sdk/storage/azdatalake/internal/generated/build.go @@ -0,0 +1,10 @@ +//go:build go1.18 +// +build go1.18 + +//go:generate autorest ./autorest.md +//go:generate gofmt -w . + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See License.txt in the project root for license information. + +package generated diff --git a/sdk/storage/azdatalake/internal/generated/zz_constants.go b/sdk/storage/azdatalake/internal/generated/zz_constants.go new file mode 100644 index 000000000000..ce7c1ce6f3b9 --- /dev/null +++ b/sdk/storage/azdatalake/internal/generated/zz_constants.go @@ -0,0 +1,158 @@ +//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. +// Code generated by Microsoft (R) AutoRest Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. +// DO NOT EDIT. + +package generated + +type ListBlobsIncludeItem string + +const ( + ListBlobsIncludeItemCopy ListBlobsIncludeItem = "copy" + ListBlobsIncludeItemDeleted ListBlobsIncludeItem = "deleted" + ListBlobsIncludeItemMetadata ListBlobsIncludeItem = "metadata" + ListBlobsIncludeItemSnapshots ListBlobsIncludeItem = "snapshots" + ListBlobsIncludeItemUncommittedblobs ListBlobsIncludeItem = "uncommittedblobs" + ListBlobsIncludeItemVersions ListBlobsIncludeItem = "versions" + ListBlobsIncludeItemTags ListBlobsIncludeItem = "tags" +) + +// PossibleListBlobsIncludeItemValues returns the possible values for the ListBlobsIncludeItem const type. +func PossibleListBlobsIncludeItemValues() []ListBlobsIncludeItem { + return []ListBlobsIncludeItem{ + ListBlobsIncludeItemCopy, + ListBlobsIncludeItemDeleted, + ListBlobsIncludeItemMetadata, + ListBlobsIncludeItemSnapshots, + ListBlobsIncludeItemUncommittedblobs, + ListBlobsIncludeItemVersions, + ListBlobsIncludeItemTags, + } +} + +type PathExpiryOptions string + +const ( + PathExpiryOptionsAbsolute PathExpiryOptions = "Absolute" + PathExpiryOptionsNeverExpire PathExpiryOptions = "NeverExpire" + PathExpiryOptionsRelativeToCreation PathExpiryOptions = "RelativeToCreation" + PathExpiryOptionsRelativeToNow PathExpiryOptions = "RelativeToNow" +) + +// PossiblePathExpiryOptionsValues returns the possible values for the PathExpiryOptions const type. +func PossiblePathExpiryOptionsValues() []PathExpiryOptions { + return []PathExpiryOptions{ + PathExpiryOptionsAbsolute, + PathExpiryOptionsNeverExpire, + PathExpiryOptionsRelativeToCreation, + PathExpiryOptionsRelativeToNow, + } +} + +type PathGetPropertiesAction string + +const ( + PathGetPropertiesActionGetAccessControl PathGetPropertiesAction = "getAccessControl" + PathGetPropertiesActionGetStatus PathGetPropertiesAction = "getStatus" +) + +// PossiblePathGetPropertiesActionValues returns the possible values for the PathGetPropertiesAction const type. +func PossiblePathGetPropertiesActionValues() []PathGetPropertiesAction { + return []PathGetPropertiesAction{ + PathGetPropertiesActionGetAccessControl, + PathGetPropertiesActionGetStatus, + } +} + +type PathLeaseAction string + +const ( + PathLeaseActionAcquire PathLeaseAction = "acquire" + PathLeaseActionBreak PathLeaseAction = "break" + PathLeaseActionChange PathLeaseAction = "change" + PathLeaseActionRenew PathLeaseAction = "renew" + PathLeaseActionRelease PathLeaseAction = "release" +) + +// PossiblePathLeaseActionValues returns the possible values for the PathLeaseAction const type. +func PossiblePathLeaseActionValues() []PathLeaseAction { + return []PathLeaseAction{ + PathLeaseActionAcquire, + PathLeaseActionBreak, + PathLeaseActionChange, + PathLeaseActionRenew, + PathLeaseActionRelease, + } +} + +type PathRenameMode string + +const ( + PathRenameModeLegacy PathRenameMode = "legacy" + PathRenameModePosix PathRenameMode = "posix" +) + +// PossiblePathRenameModeValues returns the possible values for the PathRenameMode const type. +func PossiblePathRenameModeValues() []PathRenameMode { + return []PathRenameMode{ + PathRenameModeLegacy, + PathRenameModePosix, + } +} + +type PathResourceType string + +const ( + PathResourceTypeDirectory PathResourceType = "directory" + PathResourceTypeFile PathResourceType = "file" +) + +// PossiblePathResourceTypeValues returns the possible values for the PathResourceType const type. +func PossiblePathResourceTypeValues() []PathResourceType { + return []PathResourceType{ + PathResourceTypeDirectory, + PathResourceTypeFile, + } +} + +type PathSetAccessControlRecursiveMode string + +const ( + PathSetAccessControlRecursiveModeSet PathSetAccessControlRecursiveMode = "set" + PathSetAccessControlRecursiveModeModify PathSetAccessControlRecursiveMode = "modify" + PathSetAccessControlRecursiveModeRemove PathSetAccessControlRecursiveMode = "remove" +) + +// PossiblePathSetAccessControlRecursiveModeValues returns the possible values for the PathSetAccessControlRecursiveMode const type. +func PossiblePathSetAccessControlRecursiveModeValues() []PathSetAccessControlRecursiveMode { + return []PathSetAccessControlRecursiveMode{ + PathSetAccessControlRecursiveModeSet, + PathSetAccessControlRecursiveModeModify, + PathSetAccessControlRecursiveModeRemove, + } +} + +type PathUpdateAction string + +const ( + PathUpdateActionAppend PathUpdateAction = "append" + PathUpdateActionFlush PathUpdateAction = "flush" + PathUpdateActionSetProperties PathUpdateAction = "setProperties" + PathUpdateActionSetAccessControl PathUpdateAction = "setAccessControl" + PathUpdateActionSetAccessControlRecursive PathUpdateAction = "setAccessControlRecursive" +) + +// PossiblePathUpdateActionValues returns the possible values for the PathUpdateAction const type. +func PossiblePathUpdateActionValues() []PathUpdateAction { + return []PathUpdateAction{ + PathUpdateActionAppend, + PathUpdateActionFlush, + PathUpdateActionSetProperties, + PathUpdateActionSetAccessControl, + PathUpdateActionSetAccessControlRecursive, + } +} diff --git a/sdk/storage/azdatalake/internal/generated/zz_filesystem_client.go b/sdk/storage/azdatalake/internal/generated/zz_filesystem_client.go new file mode 100644 index 000000000000..900c08f05fa0 --- /dev/null +++ b/sdk/storage/azdatalake/internal/generated/zz_filesystem_client.go @@ -0,0 +1,496 @@ +//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. +// Code generated by Microsoft (R) AutoRest Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. +// DO NOT EDIT. + +package generated + +import ( + "context" + "fmt" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/policy" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime" + "net/http" + "strconv" + "strings" + "time" +) + +// FileSystemClient contains the methods for the FileSystem group. +// Don't use this type directly, use NewFileSystemClient() instead. +type FileSystemClient struct { + endpoint string + pl runtime.Pipeline +} + +// NewFileSystemClient creates a new instance of FileSystemClient with the specified values. +// - endpoint - The URL of the service account, container, or blob that is the target of the desired operation. +// - pl - the pipeline used for sending requests and handling responses. +func NewFileSystemClient(endpoint string, pl runtime.Pipeline) *FileSystemClient { + client := &FileSystemClient{ + endpoint: endpoint, + pl: pl, + } + return client +} + +// Create - Create a FileSystem rooted at the specified location. If the FileSystem already exists, the operation fails. This +// operation does not support conditional HTTP requests. +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2020-10-02 +// - options - FileSystemClientCreateOptions contains the optional parameters for the FileSystemClient.Create method. +func (client *FileSystemClient) Create(ctx context.Context, options *FileSystemClientCreateOptions) (FileSystemClientCreateResponse, error) { + req, err := client.createCreateRequest(ctx, options) + if err != nil { + return FileSystemClientCreateResponse{}, err + } + resp, err := client.pl.Do(req) + if err != nil { + return FileSystemClientCreateResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusCreated) { + return FileSystemClientCreateResponse{}, runtime.NewResponseError(resp) + } + return client.createHandleResponse(resp) +} + +// createCreateRequest creates the Create request. +func (client *FileSystemClient) createCreateRequest(ctx context.Context, options *FileSystemClientCreateOptions) (*policy.Request, error) { + req, err := runtime.NewRequest(ctx, http.MethodPut, client.endpoint) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("resource", "filesystem") + if options != nil && options.Timeout != nil { + reqQP.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + } + req.Raw().URL.RawQuery = reqQP.Encode() + if options != nil && options.RequestID != nil { + req.Raw().Header["x-ms-client-request-id"] = []string{*options.RequestID} + } + req.Raw().Header["x-ms-version"] = []string{"2020-10-02"} + if options != nil && options.Properties != nil { + req.Raw().Header["x-ms-properties"] = []string{*options.Properties} + } + req.Raw().Header["Accept"] = []string{"application/json"} + return req, nil +} + +// createHandleResponse handles the Create response. +func (client *FileSystemClient) createHandleResponse(resp *http.Response) (FileSystemClientCreateResponse, error) { + result := FileSystemClientCreateResponse{} + if val := resp.Header.Get("Date"); val != "" { + date, err := time.Parse(time.RFC1123, val) + if err != nil { + return FileSystemClientCreateResponse{}, err + } + result.Date = &date + } + if val := resp.Header.Get("ETag"); val != "" { + result.ETag = &val + } + if val := resp.Header.Get("Last-Modified"); val != "" { + lastModified, err := time.Parse(time.RFC1123, val) + if err != nil { + return FileSystemClientCreateResponse{}, err + } + result.LastModified = &lastModified + } + if val := resp.Header.Get("x-ms-request-id"); val != "" { + result.ClientRequestID = &val + } + if val := resp.Header.Get("x-ms-version"); val != "" { + result.Version = &val + } + if val := resp.Header.Get("x-ms-namespace-enabled"); val != "" { + result.NamespaceEnabled = &val + } + return result, nil +} + +// Delete - Marks the FileSystem for deletion. When a FileSystem is deleted, a FileSystem with the same identifier cannot +// be created for at least 30 seconds. While the filesystem is being deleted, attempts to +// create a filesystem with the same identifier will fail with status code 409 (Conflict), with the service returning additional +// error information indicating that the filesystem is being deleted. All +// other operations, including operations on any files or directories within the filesystem, will fail with status code 404 +// (Not Found) while the filesystem is being deleted. This operation supports +// conditional HTTP requests. For more information, see Specifying Conditional Headers for Blob Service Operations +// [https://docs.microsoft.com/en-us/rest/api/storageservices/specifying-conditional-headers-for-blob-service-operations]. +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2020-10-02 +// - options - FileSystemClientDeleteOptions contains the optional parameters for the FileSystemClient.Delete method. +// - ModifiedAccessConditions - ModifiedAccessConditions contains a group of parameters for the FileSystemClient.SetProperties +// method. +func (client *FileSystemClient) Delete(ctx context.Context, options *FileSystemClientDeleteOptions, modifiedAccessConditions *ModifiedAccessConditions) (FileSystemClientDeleteResponse, error) { + req, err := client.deleteCreateRequest(ctx, options, modifiedAccessConditions) + if err != nil { + return FileSystemClientDeleteResponse{}, err + } + resp, err := client.pl.Do(req) + if err != nil { + return FileSystemClientDeleteResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusAccepted) { + return FileSystemClientDeleteResponse{}, runtime.NewResponseError(resp) + } + return client.deleteHandleResponse(resp) +} + +// deleteCreateRequest creates the Delete request. +func (client *FileSystemClient) deleteCreateRequest(ctx context.Context, options *FileSystemClientDeleteOptions, modifiedAccessConditions *ModifiedAccessConditions) (*policy.Request, error) { + req, err := runtime.NewRequest(ctx, http.MethodDelete, client.endpoint) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("resource", "filesystem") + if options != nil && options.Timeout != nil { + reqQP.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + } + req.Raw().URL.RawQuery = reqQP.Encode() + if options != nil && options.RequestID != nil { + req.Raw().Header["x-ms-client-request-id"] = []string{*options.RequestID} + } + req.Raw().Header["x-ms-version"] = []string{"2020-10-02"} + if modifiedAccessConditions != nil && modifiedAccessConditions.IfModifiedSince != nil { + req.Raw().Header["If-Modified-Since"] = []string{modifiedAccessConditions.IfModifiedSince.Format(time.RFC1123)} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfUnmodifiedSince != nil { + req.Raw().Header["If-Unmodified-Since"] = []string{modifiedAccessConditions.IfUnmodifiedSince.Format(time.RFC1123)} + } + req.Raw().Header["Accept"] = []string{"application/json"} + return req, nil +} + +// deleteHandleResponse handles the Delete response. +func (client *FileSystemClient) deleteHandleResponse(resp *http.Response) (FileSystemClientDeleteResponse, error) { + result := FileSystemClientDeleteResponse{} + if val := resp.Header.Get("x-ms-request-id"); val != "" { + result.RequestID = &val + } + if val := resp.Header.Get("x-ms-version"); val != "" { + result.Version = &val + } + if val := resp.Header.Get("Date"); val != "" { + date, err := time.Parse(time.RFC1123, val) + if err != nil { + return FileSystemClientDeleteResponse{}, err + } + result.Date = &date + } + return result, nil +} + +// GetProperties - All system and user-defined filesystem properties are specified in the response headers. +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2020-10-02 +// - options - FileSystemClientGetPropertiesOptions contains the optional parameters for the FileSystemClient.GetProperties +// method. +func (client *FileSystemClient) GetProperties(ctx context.Context, options *FileSystemClientGetPropertiesOptions) (FileSystemClientGetPropertiesResponse, error) { + req, err := client.getPropertiesCreateRequest(ctx, options) + if err != nil { + return FileSystemClientGetPropertiesResponse{}, err + } + resp, err := client.pl.Do(req) + if err != nil { + return FileSystemClientGetPropertiesResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusOK) { + return FileSystemClientGetPropertiesResponse{}, runtime.NewResponseError(resp) + } + return client.getPropertiesHandleResponse(resp) +} + +// getPropertiesCreateRequest creates the GetProperties request. +func (client *FileSystemClient) getPropertiesCreateRequest(ctx context.Context, options *FileSystemClientGetPropertiesOptions) (*policy.Request, error) { + req, err := runtime.NewRequest(ctx, http.MethodHead, client.endpoint) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("resource", "filesystem") + if options != nil && options.Timeout != nil { + reqQP.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + } + req.Raw().URL.RawQuery = reqQP.Encode() + if options != nil && options.RequestID != nil { + req.Raw().Header["x-ms-client-request-id"] = []string{*options.RequestID} + } + req.Raw().Header["x-ms-version"] = []string{"2020-10-02"} + req.Raw().Header["Accept"] = []string{"application/json"} + return req, nil +} + +// getPropertiesHandleResponse handles the GetProperties response. +func (client *FileSystemClient) getPropertiesHandleResponse(resp *http.Response) (FileSystemClientGetPropertiesResponse, error) { + result := FileSystemClientGetPropertiesResponse{} + if val := resp.Header.Get("Date"); val != "" { + date, err := time.Parse(time.RFC1123, val) + if err != nil { + return FileSystemClientGetPropertiesResponse{}, err + } + result.Date = &date + } + if val := resp.Header.Get("ETag"); val != "" { + result.ETag = &val + } + if val := resp.Header.Get("Last-Modified"); val != "" { + lastModified, err := time.Parse(time.RFC1123, val) + if err != nil { + return FileSystemClientGetPropertiesResponse{}, err + } + result.LastModified = &lastModified + } + if val := resp.Header.Get("x-ms-request-id"); val != "" { + result.RequestID = &val + } + if val := resp.Header.Get("x-ms-version"); val != "" { + result.Version = &val + } + if val := resp.Header.Get("x-ms-properties"); val != "" { + result.Properties = &val + } + if val := resp.Header.Get("x-ms-namespace-enabled"); val != "" { + result.NamespaceEnabled = &val + } + return result, nil +} + +// NewListBlobHierarchySegmentPager - The List Blobs operation returns a list of the blobs under the specified container +// +// Generated from API version 2020-10-02 +// - options - FileSystemClientListBlobHierarchySegmentOptions contains the optional parameters for the FileSystemClient.NewListBlobHierarchySegmentPager +// method. +// +// ListBlobHierarchySegmentCreateRequest creates the ListBlobHierarchySegment request. +func (client *FileSystemClient) ListBlobHierarchySegmentCreateRequest(ctx context.Context, options *FileSystemClientListBlobHierarchySegmentOptions) (*policy.Request, error) { + req, err := runtime.NewRequest(ctx, http.MethodGet, client.endpoint) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("restype", "container") + reqQP.Set("comp", "list") + if options != nil && options.Prefix != nil { + reqQP.Set("prefix", *options.Prefix) + } + if options != nil && options.Delimiter != nil { + reqQP.Set("delimiter", *options.Delimiter) + } + if options != nil && options.Marker != nil { + reqQP.Set("marker", *options.Marker) + } + if options != nil && options.MaxResults != nil { + reqQP.Set("maxResults", strconv.FormatInt(int64(*options.MaxResults), 10)) + } + if options != nil && options.Include != nil { + reqQP.Set("include", strings.Join(strings.Fields(strings.Trim(fmt.Sprint(options.Include), "[]")), ",")) + } + if options != nil && options.Showonly != nil { + reqQP.Set("showonly", "deleted") + } + if options != nil && options.Timeout != nil { + reqQP.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + } + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["x-ms-version"] = []string{"2020-10-02"} + if options != nil && options.RequestID != nil { + req.Raw().Header["x-ms-client-request-id"] = []string{*options.RequestID} + } + req.Raw().Header["Accept"] = []string{"application/xml"} + return req, nil +} + +// listBlobHierarchySegmentHandleResponse handles the ListBlobHierarchySegment response. +func (client *FileSystemClient) ListBlobHierarchySegmentHandleResponse(resp *http.Response) (FileSystemClientListBlobHierarchySegmentResponse, error) { + result := FileSystemClientListBlobHierarchySegmentResponse{} + if val := resp.Header.Get("Content-Type"); val != "" { + result.ContentType = &val + } + if val := resp.Header.Get("x-ms-client-request-id"); val != "" { + result.ClientRequestID = &val + } + if val := resp.Header.Get("x-ms-request-id"); val != "" { + result.RequestID = &val + } + if val := resp.Header.Get("x-ms-version"); val != "" { + result.Version = &val + } + if val := resp.Header.Get("Date"); val != "" { + date, err := time.Parse(time.RFC1123, val) + if err != nil { + return FileSystemClientListBlobHierarchySegmentResponse{}, err + } + result.Date = &date + } + if err := runtime.UnmarshalAsXML(resp, &result.ListBlobsHierarchySegmentResponse); err != nil { + return FileSystemClientListBlobHierarchySegmentResponse{}, err + } + return result, nil +} + +// NewListPathsPager - List FileSystem paths and their properties. +// +// Generated from API version 2020-10-02 +// - recursive - Required +// - options - FileSystemClientListPathsOptions contains the optional parameters for the FileSystemClient.NewListPathsPager +// method. +// +// ListPathsCreateRequest creates the ListPaths request. +func (client *FileSystemClient) ListPathsCreateRequest(ctx context.Context, recursive bool, options *FileSystemClientListPathsOptions) (*policy.Request, error) { + req, err := runtime.NewRequest(ctx, http.MethodGet, client.endpoint) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("resource", "filesystem") + if options != nil && options.Timeout != nil { + reqQP.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + } + if options != nil && options.Continuation != nil { + reqQP.Set("continuation", *options.Continuation) + } + if options != nil && options.Path != nil { + reqQP.Set("directory", *options.Path) + } + reqQP.Set("recursive", strconv.FormatBool(recursive)) + if options != nil && options.MaxResults != nil { + reqQP.Set("maxResults", strconv.FormatInt(int64(*options.MaxResults), 10)) + } + if options != nil && options.Upn != nil { + reqQP.Set("upn", strconv.FormatBool(*options.Upn)) + } + req.Raw().URL.RawQuery = reqQP.Encode() + if options != nil && options.RequestID != nil { + req.Raw().Header["x-ms-client-request-id"] = []string{*options.RequestID} + } + req.Raw().Header["x-ms-version"] = []string{"2020-10-02"} + req.Raw().Header["Accept"] = []string{"application/json"} + return req, nil +} + +// listPathsHandleResponse handles the ListPaths response. +func (client *FileSystemClient) ListPathsHandleResponse(resp *http.Response) (FileSystemClientListPathsResponse, error) { + result := FileSystemClientListPathsResponse{} + if val := resp.Header.Get("Date"); val != "" { + date, err := time.Parse(time.RFC1123, val) + if err != nil { + return FileSystemClientListPathsResponse{}, err + } + result.Date = &date + } + if val := resp.Header.Get("ETag"); val != "" { + result.ETag = &val + } + if val := resp.Header.Get("Last-Modified"); val != "" { + lastModified, err := time.Parse(time.RFC1123, val) + if err != nil { + return FileSystemClientListPathsResponse{}, err + } + result.LastModified = &lastModified + } + if val := resp.Header.Get("x-ms-request-id"); val != "" { + result.RequestID = &val + } + if val := resp.Header.Get("x-ms-version"); val != "" { + result.Version = &val + } + if val := resp.Header.Get("x-ms-continuation"); val != "" { + result.Continuation = &val + } + if err := runtime.UnmarshalAsJSON(resp, &result.PathList); err != nil { + return FileSystemClientListPathsResponse{}, err + } + return result, nil +} + +// SetProperties - Set properties for the FileSystem. This operation supports conditional HTTP requests. For more information, +// see Specifying Conditional Headers for Blob Service Operations +// [https://docs.microsoft.com/en-us/rest/api/storageservices/specifying-conditional-headers-for-blob-service-operations]. +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2020-10-02 +// - options - FileSystemClientSetPropertiesOptions contains the optional parameters for the FileSystemClient.SetProperties +// method. +// - ModifiedAccessConditions - ModifiedAccessConditions contains a group of parameters for the FileSystemClient.SetProperties +// method. +func (client *FileSystemClient) SetProperties(ctx context.Context, options *FileSystemClientSetPropertiesOptions, modifiedAccessConditions *ModifiedAccessConditions) (FileSystemClientSetPropertiesResponse, error) { + req, err := client.setPropertiesCreateRequest(ctx, options, modifiedAccessConditions) + if err != nil { + return FileSystemClientSetPropertiesResponse{}, err + } + resp, err := client.pl.Do(req) + if err != nil { + return FileSystemClientSetPropertiesResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusOK) { + return FileSystemClientSetPropertiesResponse{}, runtime.NewResponseError(resp) + } + return client.setPropertiesHandleResponse(resp) +} + +// setPropertiesCreateRequest creates the SetProperties request. +func (client *FileSystemClient) setPropertiesCreateRequest(ctx context.Context, options *FileSystemClientSetPropertiesOptions, modifiedAccessConditions *ModifiedAccessConditions) (*policy.Request, error) { + req, err := runtime.NewRequest(ctx, http.MethodPatch, client.endpoint) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("resource", "filesystem") + if options != nil && options.Timeout != nil { + reqQP.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + } + req.Raw().URL.RawQuery = reqQP.Encode() + if options != nil && options.RequestID != nil { + req.Raw().Header["x-ms-client-request-id"] = []string{*options.RequestID} + } + req.Raw().Header["x-ms-version"] = []string{"2020-10-02"} + if options != nil && options.Properties != nil { + req.Raw().Header["x-ms-properties"] = []string{*options.Properties} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfModifiedSince != nil { + req.Raw().Header["If-Modified-Since"] = []string{modifiedAccessConditions.IfModifiedSince.Format(time.RFC1123)} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfUnmodifiedSince != nil { + req.Raw().Header["If-Unmodified-Since"] = []string{modifiedAccessConditions.IfUnmodifiedSince.Format(time.RFC1123)} + } + req.Raw().Header["Accept"] = []string{"application/json"} + return req, nil +} + +// setPropertiesHandleResponse handles the SetProperties response. +func (client *FileSystemClient) setPropertiesHandleResponse(resp *http.Response) (FileSystemClientSetPropertiesResponse, error) { + result := FileSystemClientSetPropertiesResponse{} + if val := resp.Header.Get("Date"); val != "" { + date, err := time.Parse(time.RFC1123, val) + if err != nil { + return FileSystemClientSetPropertiesResponse{}, err + } + result.Date = &date + } + if val := resp.Header.Get("ETag"); val != "" { + result.ETag = &val + } + if val := resp.Header.Get("Last-Modified"); val != "" { + lastModified, err := time.Parse(time.RFC1123, val) + if err != nil { + return FileSystemClientSetPropertiesResponse{}, err + } + result.LastModified = &lastModified + } + if val := resp.Header.Get("x-ms-request-id"); val != "" { + result.RequestID = &val + } + if val := resp.Header.Get("x-ms-version"); val != "" { + result.Version = &val + } + return result, nil +} diff --git a/sdk/storage/azdatalake/internal/generated/zz_models.go b/sdk/storage/azdatalake/internal/generated/zz_models.go new file mode 100644 index 000000000000..1edd40a69a4a --- /dev/null +++ b/sdk/storage/azdatalake/internal/generated/zz_models.go @@ -0,0 +1,679 @@ +//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. +// Code generated by Microsoft (R) AutoRest Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. +// DO NOT EDIT. + +package generated + +import "time" + +type ACLFailedEntry struct { + ErrorMessage *string `json:"errorMessage,omitempty"` + Name *string `json:"name,omitempty"` + Type *string `json:"type,omitempty"` +} + +type BlobHierarchyListSegment struct { + // REQUIRED + BlobItems []*BlobItemInternal `xml:"Blob"` + BlobPrefixes []*BlobPrefix `xml:"BlobPrefix"` +} + +// BlobItemInternal - An Azure Storage blob +type BlobItemInternal struct { + // REQUIRED + Deleted *bool `xml:"Deleted"` + + // REQUIRED + Name *string `xml:"Name"` + + // REQUIRED; Properties of a blob + Properties *BlobPropertiesInternal `xml:"Properties"` + + // REQUIRED + Snapshot *string `xml:"Snapshot"` + DeletionID *string `xml:"DeletionId"` + IsCurrentVersion *bool `xml:"IsCurrentVersion"` + VersionID *string `xml:"VersionId"` +} + +type BlobPrefix struct { + // REQUIRED + Name *string `xml:"Name"` +} + +// BlobPropertiesInternal - Properties of a blob +type BlobPropertiesInternal struct { + // REQUIRED + Etag *string `xml:"Etag"` + + // REQUIRED + LastModified *time.Time `xml:"Last-Modified"` + AccessTierChangeTime *time.Time `xml:"AccessTierChangeTime"` + AccessTierInferred *bool `xml:"AccessTierInferred"` + BlobSequenceNumber *int64 `xml:"x-ms-blob-sequence-number"` + CacheControl *string `xml:"Cache-Control"` + ContentDisposition *string `xml:"Content-Disposition"` + ContentEncoding *string `xml:"Content-Encoding"` + ContentLanguage *string `xml:"Content-Language"` + + // Size in bytes + ContentLength *int64 `xml:"Content-Length"` + ContentMD5 []byte `xml:"Content-MD5"` + ContentType *string `xml:"Content-Type"` + CopyCompletionTime *time.Time `xml:"CopyCompletionTime"` + CopyID *string `xml:"CopyId"` + CopyProgress *string `xml:"CopyProgress"` + CopySource *string `xml:"CopySource"` + CopyStatusDescription *string `xml:"CopyStatusDescription"` + CreationTime *time.Time `xml:"Creation-Time"` + CustomerProvidedKeySHA256 *string `xml:"CustomerProvidedKeySha256"` + DeleteTime *time.Time `xml:"DeleteTime"` + DeletedTime *time.Time `xml:"DeletedTime"` + DestinationSnapshot *string `xml:"DestinationSnapshot"` + + // The name of the encryption scope under which the blob is encrypted. + EncryptionScope *string `xml:"EncryptionScope"` + ExpiresOn *time.Time `xml:"Expiry-Time"` + IncrementalCopy *bool `xml:"IncrementalCopy"` + IsSealed *bool `xml:"Sealed"` + LastAccessedOn *time.Time `xml:"LastAccessTime"` + RemainingRetentionDays *int32 `xml:"RemainingRetentionDays"` + ServerEncrypted *bool `xml:"ServerEncrypted"` + TagCount *int32 `xml:"TagCount"` +} + +// CpkInfo contains a group of parameters for the PathClient.Create method. +type CpkInfo struct { + // The algorithm used to produce the encryption key hash. Currently, the only accepted value is "AES256". Must be provided + // if the x-ms-encryption-key header is provided.. Specifying any value will set the value to AES256. + EncryptionAlgorithm *string + // Optional. Specifies the encryption key to use to encrypt the data provided in the request. If not specified, encryption + // is performed with the root account encryption key. For more information, see + // Encryption at Rest for Azure Storage Services. + EncryptionKey *string + // The SHA-256 hash of the provided encryption key. Must be provided if the x-ms-encryption-key header is provided. + EncryptionKeySHA256 *string +} + +type FileSystem struct { + ETag *string `json:"eTag,omitempty"` + LastModified *string `json:"lastModified,omitempty"` + Name *string `json:"name,omitempty"` +} + +// FileSystemClientCreateOptions contains the optional parameters for the FileSystemClient.Create method. +type FileSystemClientCreateOptions struct { + // Optional. User-defined properties to be stored with the filesystem, in the format of a comma-separated list of name and + // value pairs "n1=v1, n2=v2, …", where each value is a base64 encoded string. Note + // that the string may only contain ASCII characters in the ISO-8859-1 character set. If the filesystem exists, any properties + // not included in the list will be removed. All properties are removed if the + // header is omitted. To merge new and existing properties, first get all existing properties and the current E-Tag, then + // make a conditional request with the E-Tag and include values for all properties. + Properties *string + // Provides a client-generated, opaque value with a 1 KB character limit that is recorded in the analytics logs when storage + // analytics logging is enabled. + RequestID *string + // The timeout parameter is expressed in seconds. For more information, see Setting Timeouts for Blob Service Operations. + // [https://docs.microsoft.com/en-us/rest/api/storageservices/fileservices/setting-timeouts-for-blob-service-operations] + Timeout *int32 +} + +// FileSystemClientDeleteOptions contains the optional parameters for the FileSystemClient.Delete method. +type FileSystemClientDeleteOptions struct { + // Provides a client-generated, opaque value with a 1 KB character limit that is recorded in the analytics logs when storage + // analytics logging is enabled. + RequestID *string + // The timeout parameter is expressed in seconds. For more information, see Setting Timeouts for Blob Service Operations. + // [https://docs.microsoft.com/en-us/rest/api/storageservices/fileservices/setting-timeouts-for-blob-service-operations] + Timeout *int32 +} + +// FileSystemClientGetPropertiesOptions contains the optional parameters for the FileSystemClient.GetProperties method. +type FileSystemClientGetPropertiesOptions struct { + // Provides a client-generated, opaque value with a 1 KB character limit that is recorded in the analytics logs when storage + // analytics logging is enabled. + RequestID *string + // The timeout parameter is expressed in seconds. For more information, see Setting Timeouts for Blob Service Operations. + // [https://docs.microsoft.com/en-us/rest/api/storageservices/fileservices/setting-timeouts-for-blob-service-operations] + Timeout *int32 +} + +// FileSystemClientListBlobHierarchySegmentOptions contains the optional parameters for the FileSystemClient.NewListBlobHierarchySegmentPager +// method. +type FileSystemClientListBlobHierarchySegmentOptions struct { + // When the request includes this parameter, the operation returns a BlobPrefix element in the response body that acts as + // a placeholder for all blobs whose names begin with the same substring up to the + // appearance of the delimiter character. The delimiter may be a single character or a string. + Delimiter *string + // Include this parameter to specify one or more datasets to include in the response. + Include []ListBlobsIncludeItem + // A string value that identifies the portion of the list of containers to be returned with the next listing operation. The + // operation returns the NextMarker value within the response body if the listing + // operation did not return all containers remaining to be listed with the current page. The NextMarker value can be used + // as the value for the marker parameter in a subsequent call to request the next + // page of list items. The marker value is opaque to the client. + Marker *string + // An optional value that specifies the maximum number of items to return. If omitted or greater than 5,000, the response + // will include up to 5,000 items. + MaxResults *int32 + // Filters results to filesystems within the specified prefix. + Prefix *string + // Provides a client-generated, opaque value with a 1 KB character limit that is recorded in the analytics logs when storage + // analytics logging is enabled. + RequestID *string + // Include this parameter to specify one or more datasets to include in the response.. Specifying any value will set the value + // to deleted. + Showonly *string + // The timeout parameter is expressed in seconds. For more information, see Setting Timeouts for Blob Service Operations. + // [https://docs.microsoft.com/en-us/rest/api/storageservices/fileservices/setting-timeouts-for-blob-service-operations] + Timeout *int32 +} + +// FileSystemClientListPathsOptions contains the optional parameters for the FileSystemClient.NewListPathsPager method. +type FileSystemClientListPathsOptions struct { + // Optional. When deleting a directory, the number of paths that are deleted with each invocation is limited. If the number + // of paths to be deleted exceeds this limit, a continuation token is returned in + // this response header. When a continuation token is returned in the response, it must be specified in a subsequent invocation + // of the delete operation to continue deleting the directory. + Continuation *string + // An optional value that specifies the maximum number of items to return. If omitted or greater than 5,000, the response + // will include up to 5,000 items. + MaxResults *int32 + // Optional. Filters results to paths within the specified directory. An error occurs if the directory does not exist. + Path *string + // Provides a client-generated, opaque value with a 1 KB character limit that is recorded in the analytics logs when storage + // analytics logging is enabled. + RequestID *string + // The timeout parameter is expressed in seconds. For more information, see Setting Timeouts for Blob Service Operations. + // [https://docs.microsoft.com/en-us/rest/api/storageservices/fileservices/setting-timeouts-for-blob-service-operations] + Timeout *int32 + // Optional. Valid only when Hierarchical Namespace is enabled for the account. If "true", the user identity values returned + // in the x-ms-owner, x-ms-group, and x-ms-acl response headers will be + // transformed from Azure Active Directory Object IDs to User Principal Names. If "false", the values will be returned as + // Azure Active Directory Object IDs. The default value is false. Note that group + // and application Object IDs are not translated because they do not have unique friendly names. + Upn *bool +} + +// FileSystemClientSetPropertiesOptions contains the optional parameters for the FileSystemClient.SetProperties method. +type FileSystemClientSetPropertiesOptions struct { + // Optional. User-defined properties to be stored with the filesystem, in the format of a comma-separated list of name and + // value pairs "n1=v1, n2=v2, …", where each value is a base64 encoded string. Note + // that the string may only contain ASCII characters in the ISO-8859-1 character set. If the filesystem exists, any properties + // not included in the list will be removed. All properties are removed if the + // header is omitted. To merge new and existing properties, first get all existing properties and the current E-Tag, then + // make a conditional request with the E-Tag and include values for all properties. + Properties *string + // Provides a client-generated, opaque value with a 1 KB character limit that is recorded in the analytics logs when storage + // analytics logging is enabled. + RequestID *string + // The timeout parameter is expressed in seconds. For more information, see Setting Timeouts for Blob Service Operations. + // [https://docs.microsoft.com/en-us/rest/api/storageservices/fileservices/setting-timeouts-for-blob-service-operations] + Timeout *int32 +} + +type FileSystemList struct { + Filesystems []*FileSystem `json:"filesystems,omitempty"` +} + +// LeaseAccessConditions contains a group of parameters for the PathClient.Create method. +type LeaseAccessConditions struct { + // If specified, the operation only succeeds if the resource's lease is active and matches this ID. + LeaseID *string +} + +// ListBlobsHierarchySegmentResponse - An enumeration of blobs +type ListBlobsHierarchySegmentResponse struct { + // REQUIRED + ContainerName *string `xml:"ContainerName,attr"` + + // REQUIRED + Segment *BlobHierarchyListSegment `xml:"Blobs"` + + // REQUIRED + ServiceEndpoint *string `xml:"ServiceEndpoint,attr"` + Delimiter *string `xml:"Delimiter"` + Marker *string `xml:"Marker"` + MaxResults *int32 `xml:"MaxResults"` + NextMarker *string `xml:"NextMarker"` + Prefix *string `xml:"Prefix"` +} + +// ModifiedAccessConditions contains a group of parameters for the FileSystemClient.SetProperties method. +type ModifiedAccessConditions struct { + // Specify an ETag value to operate only on blobs with a matching value. + IfMatch *string + // Specify this header value to operate only on a blob if it has been modified since the specified date/time. + IfModifiedSince *time.Time + // Specify an ETag value to operate only on blobs without a matching value. + IfNoneMatch *string + // Specify this header value to operate only on a blob if it has not been modified since the specified date/time. + IfUnmodifiedSince *time.Time +} + +type Path struct { + ContentLength *int64 `json:"contentLength,omitempty"` + CreationTime *string `json:"creationTime,omitempty"` + ETag *string `json:"eTag,omitempty"` + + // The name of the encryption scope under which the blob is encrypted. + EncryptionScope *string `json:"EncryptionScope,omitempty"` + ExpiryTime *string `json:"expiryTime,omitempty"` + Group *string `json:"group,omitempty"` + IsDirectory *bool `json:"isDirectory,omitempty"` + LastModified *string `json:"lastModified,omitempty"` + Name *string `json:"name,omitempty"` + Owner *string `json:"owner,omitempty"` + Permissions *string `json:"permissions,omitempty"` +} + +// PathClientAppendDataOptions contains the optional parameters for the PathClient.AppendData method. +type PathClientAppendDataOptions struct { + // Required for "Append Data" and "Flush Data". Must be 0 for "Flush Data". Must be the length of the request content in bytes + // for "Append Data". + ContentLength *int64 + // This parameter allows the caller to upload data in parallel and control the order in which it is appended to the file. + // It is required when uploading data to be appended to the file and when flushing + // previously uploaded data to the file. The value must be the position where the data is to be appended. Uploaded data is + // not immediately flushed, or written, to the file. To flush, the previously + // uploaded data must be contiguous, the position parameter must be specified and equal to the length of the file after all + // data has been written, and there must not be a request entity body included + // with the request. + Position *int64 + // Provides a client-generated, opaque value with a 1 KB character limit that is recorded in the analytics logs when storage + // analytics logging is enabled. + RequestID *string + // The timeout parameter is expressed in seconds. For more information, see Setting Timeouts for Blob Service Operations. + // [https://docs.microsoft.com/en-us/rest/api/storageservices/fileservices/setting-timeouts-for-blob-service-operations] + Timeout *int32 + // Specify the transactional crc64 for the body, to be validated by the service. + TransactionalContentCRC64 []byte +} + +// PathClientCreateOptions contains the optional parameters for the PathClient.Create method. +type PathClientCreateOptions struct { + // Optional. When deleting a directory, the number of paths that are deleted with each invocation is limited. If the number + // of paths to be deleted exceeds this limit, a continuation token is returned in + // this response header. When a continuation token is returned in the response, it must be specified in a subsequent invocation + // of the delete operation to continue deleting the directory. + Continuation *string + // Optional. Valid only when namespace is enabled. This parameter determines the behavior of the rename operation. The value + // must be "legacy" or "posix", and the default value will be "posix". + Mode *PathRenameMode + // Optional and only valid if Hierarchical Namespace is enabled for the account. Sets POSIX access permissions for the file + // owner, the file owning group, and others. Each class may be granted read, + // write, or execute permission. The sticky bit is also supported. Both symbolic (rwxrw-rw-) and 4-digit octal notation (e.g. + // 0766) are supported. + Permissions *string + // Optional. User-defined properties to be stored with the filesystem, in the format of a comma-separated list of name and + // value pairs "n1=v1, n2=v2, …", where each value is a base64 encoded string. Note + // that the string may only contain ASCII characters in the ISO-8859-1 character set. If the filesystem exists, any properties + // not included in the list will be removed. All properties are removed if the + // header is omitted. To merge new and existing properties, first get all existing properties and the current E-Tag, then + // make a conditional request with the E-Tag and include values for all properties. + Properties *string + // An optional file or directory to be renamed. The value must have the following format: "/{filesystem}/{path}". If "x-ms-properties" + // is specified, the properties will overwrite the existing properties; + // otherwise, the existing properties will be preserved. This value must be a URL percent-encoded string. Note that the string + // may only contain ASCII characters in the ISO-8859-1 character set. + RenameSource *string + // Provides a client-generated, opaque value with a 1 KB character limit that is recorded in the analytics logs when storage + // analytics logging is enabled. + RequestID *string + // Required only for Create File and Create Directory. The value must be "file" or "directory". + Resource *PathResourceType + // A lease ID for the source path. If specified, the source path must have an active lease and the lease ID must match. + SourceLeaseID *string + // The timeout parameter is expressed in seconds. For more information, see Setting Timeouts for Blob Service Operations. + // [https://docs.microsoft.com/en-us/rest/api/storageservices/fileservices/setting-timeouts-for-blob-service-operations] + Timeout *int32 + // Optional and only valid if Hierarchical Namespace is enabled for the account. When creating a file or directory and the + // parent folder does not have a default ACL, the umask restricts the permissions + // of the file or directory to be created. The resulting permission is given by p bitwise and not u, where p is the permission + // and u is the umask. For example, if p is 0777 and u is 0057, then the + // resulting permission is 0720. The default permission is 0777 for a directory and 0666 for a file. The default umask is + // 0027. The umask must be specified in 4-digit octal notation (e.g. 0766). + Umask *string +} + +// PathClientDeleteOptions contains the optional parameters for the PathClient.Delete method. +type PathClientDeleteOptions struct { + // Optional. When deleting a directory, the number of paths that are deleted with each invocation is limited. If the number + // of paths to be deleted exceeds this limit, a continuation token is returned in + // this response header. When a continuation token is returned in the response, it must be specified in a subsequent invocation + // of the delete operation to continue deleting the directory. + Continuation *string + // Required + Recursive *bool + // Provides a client-generated, opaque value with a 1 KB character limit that is recorded in the analytics logs when storage + // analytics logging is enabled. + RequestID *string + // The timeout parameter is expressed in seconds. For more information, see Setting Timeouts for Blob Service Operations. + // [https://docs.microsoft.com/en-us/rest/api/storageservices/fileservices/setting-timeouts-for-blob-service-operations] + Timeout *int32 +} + +// PathClientFlushDataOptions contains the optional parameters for the PathClient.FlushData method. +type PathClientFlushDataOptions struct { + // Azure Storage Events allow applications to receive notifications when files change. When Azure Storage Events are enabled, + // a file changed event is raised. This event has a property indicating whether + // this is the final change to distinguish the difference between an intermediate flush to a file stream and the final close + // of a file stream. The close query parameter is valid only when the action is + // "flush" and change notifications are enabled. If the value of close is "true" and the flush operation completes successfully, + // the service raises a file change notification with a property indicating + // that this is the final update (the file stream has been closed). If "false" a change notification is raised indicating + // the file has changed. The default is false. This query parameter is set to true + // by the Hadoop ABFS driver to indicate that the file stream has been closed." + Close *bool + // Required for "Append Data" and "Flush Data". Must be 0 for "Flush Data". Must be the length of the request content in bytes + // for "Append Data". + ContentLength *int64 + // This parameter allows the caller to upload data in parallel and control the order in which it is appended to the file. + // It is required when uploading data to be appended to the file and when flushing + // previously uploaded data to the file. The value must be the position where the data is to be appended. Uploaded data is + // not immediately flushed, or written, to the file. To flush, the previously + // uploaded data must be contiguous, the position parameter must be specified and equal to the length of the file after all + // data has been written, and there must not be a request entity body included + // with the request. + Position *int64 + // Provides a client-generated, opaque value with a 1 KB character limit that is recorded in the analytics logs when storage + // analytics logging is enabled. + RequestID *string + // Valid only for flush operations. If "true", uncommitted data is retained after the flush operation completes; otherwise, + // the uncommitted data is deleted after the flush operation. The default is + // false. Data at offsets less than the specified position are written to the file when flush succeeds, but this optional + // parameter allows data after the flush position to be retained for a future flush + // operation. + RetainUncommittedData *bool + // The timeout parameter is expressed in seconds. For more information, see Setting Timeouts for Blob Service Operations. + // [https://docs.microsoft.com/en-us/rest/api/storageservices/fileservices/setting-timeouts-for-blob-service-operations] + Timeout *int32 +} + +// PathClientGetPropertiesOptions contains the optional parameters for the PathClient.GetProperties method. +type PathClientGetPropertiesOptions struct { + // Optional. If the value is "getStatus" only the system defined properties for the path are returned. If the value is "getAccessControl" + // the access control list is returned in the response headers + // (Hierarchical Namespace must be enabled for the account), otherwise the properties are returned. + Action *PathGetPropertiesAction + // Provides a client-generated, opaque value with a 1 KB character limit that is recorded in the analytics logs when storage + // analytics logging is enabled. + RequestID *string + // The timeout parameter is expressed in seconds. For more information, see Setting Timeouts for Blob Service Operations. + // [https://docs.microsoft.com/en-us/rest/api/storageservices/fileservices/setting-timeouts-for-blob-service-operations] + Timeout *int32 + // Optional. Valid only when Hierarchical Namespace is enabled for the account. If "true", the user identity values returned + // in the x-ms-owner, x-ms-group, and x-ms-acl response headers will be + // transformed from Azure Active Directory Object IDs to User Principal Names. If "false", the values will be returned as + // Azure Active Directory Object IDs. The default value is false. Note that group + // and application Object IDs are not translated because they do not have unique friendly names. + Upn *bool +} + +// PathClientLeaseOptions contains the optional parameters for the PathClient.Lease method. +type PathClientLeaseOptions struct { + // Proposed lease ID, in a GUID string format. The Blob service returns 400 (Invalid request) if the proposed lease ID is + // not in the correct format. See Guid Constructor (String) for a list of valid GUID + // string formats. + ProposedLeaseID *string + // Provides a client-generated, opaque value with a 1 KB character limit that is recorded in the analytics logs when storage + // analytics logging is enabled. + RequestID *string + // The timeout parameter is expressed in seconds. For more information, see Setting Timeouts for Blob Service Operations. + // [https://docs.microsoft.com/en-us/rest/api/storageservices/fileservices/setting-timeouts-for-blob-service-operations] + Timeout *int32 + // The lease break period duration is optional to break a lease, and specifies the break period of the lease in seconds. The + // lease break duration must be between 0 and 60 seconds. + XMSLeaseBreakPeriod *int32 + // The lease duration is required to acquire a lease, and specifies the duration of the lease in seconds. The lease duration + // must be between 15 and 60 seconds or -1 for infinite lease. + XMSLeaseDuration *int32 +} + +// PathClientReadOptions contains the optional parameters for the PathClient.Read method. +type PathClientReadOptions struct { + // The HTTP Range request header specifies one or more byte ranges of the resource to be retrieved. + Range *string + // Provides a client-generated, opaque value with a 1 KB character limit that is recorded in the analytics logs when storage + // analytics logging is enabled. + RequestID *string + // The timeout parameter is expressed in seconds. For more information, see Setting Timeouts for Blob Service Operations. + // [https://docs.microsoft.com/en-us/rest/api/storageservices/fileservices/setting-timeouts-for-blob-service-operations] + Timeout *int32 + // Optional. When this header is set to "true" and specified together with the Range header, the service returns the MD5 hash + // for the range, as long as the range is less than or equal to 4MB in size. If + // this header is specified without the Range header, the service returns status code 400 (Bad Request). If this header is + // set to true when the range exceeds 4 MB in size, the service returns status code + // 400 (Bad Request). + XMSRangeGetContentMD5 *bool +} + +// PathClientSetAccessControlOptions contains the optional parameters for the PathClient.SetAccessControl method. +type PathClientSetAccessControlOptions struct { + // Sets POSIX access control rights on files and directories. The value is a comma-separated list of access control entries. + // Each access control entry (ACE) consists of a scope, a type, a user or group + // identifier, and permissions in the format "[scope:][type]:[id]:[permissions]". + ACL *string + // Optional. The owning group of the blob or directory. + Group *string + // Optional. The owner of the blob or directory. + Owner *string + // Optional and only valid if Hierarchical Namespace is enabled for the account. Sets POSIX access permissions for the file + // owner, the file owning group, and others. Each class may be granted read, + // write, or execute permission. The sticky bit is also supported. Both symbolic (rwxrw-rw-) and 4-digit octal notation (e.g. + // 0766) are supported. + Permissions *string + // Provides a client-generated, opaque value with a 1 KB character limit that is recorded in the analytics logs when storage + // analytics logging is enabled. + RequestID *string + // The timeout parameter is expressed in seconds. For more information, see Setting Timeouts for Blob Service Operations. + // [https://docs.microsoft.com/en-us/rest/api/storageservices/fileservices/setting-timeouts-for-blob-service-operations] + Timeout *int32 +} + +// PathClientSetAccessControlRecursiveOptions contains the optional parameters for the PathClient.SetAccessControlRecursive +// method. +type PathClientSetAccessControlRecursiveOptions struct { + // Sets POSIX access control rights on files and directories. The value is a comma-separated list of access control entries. + // Each access control entry (ACE) consists of a scope, a type, a user or group + // identifier, and permissions in the format "[scope:][type]:[id]:[permissions]". + ACL *string + // Optional. When deleting a directory, the number of paths that are deleted with each invocation is limited. If the number + // of paths to be deleted exceeds this limit, a continuation token is returned in + // this response header. When a continuation token is returned in the response, it must be specified in a subsequent invocation + // of the delete operation to continue deleting the directory. + Continuation *string + // Optional. Valid for "SetAccessControlRecursive" operation. If set to false, the operation will terminate quickly on encountering + // user errors (4XX). If true, the operation will ignore user errors and + // proceed with the operation on other sub-entities of the directory. Continuation token will only be returned when forceFlag + // is true in case of user errors. If not set the default value is false for + // this. + ForceFlag *bool + // Optional. It specifies the maximum number of files or directories on which the acl change will be applied. If omitted or + // greater than 2,000, the request will process up to 2,000 items + MaxRecords *int32 + // Provides a client-generated, opaque value with a 1 KB character limit that is recorded in the analytics logs when storage + // analytics logging is enabled. + RequestID *string + // The timeout parameter is expressed in seconds. For more information, see Setting Timeouts for Blob Service Operations. + // [https://docs.microsoft.com/en-us/rest/api/storageservices/fileservices/setting-timeouts-for-blob-service-operations] + Timeout *int32 +} + +// PathClientSetExpiryOptions contains the optional parameters for the PathClient.SetExpiry method. +type PathClientSetExpiryOptions struct { + // The time to set the blob to expiry + ExpiresOn *string + // Provides a client-generated, opaque value with a 1 KB character limit that is recorded in the analytics logs when storage + // analytics logging is enabled. + RequestID *string + // The timeout parameter is expressed in seconds. For more information, see Setting Timeouts for Blob Service Operations. + // [https://docs.microsoft.com/en-us/rest/api/storageservices/fileservices/setting-timeouts-for-blob-service-operations] + Timeout *int32 +} + +// PathClientUndeleteOptions contains the optional parameters for the PathClient.Undelete method. +type PathClientUndeleteOptions struct { + // Provides a client-generated, opaque value with a 1 KB character limit that is recorded in the analytics logs when storage + // analytics logging is enabled. + RequestID *string + // The timeout parameter is expressed in seconds. For more information, see Setting Timeouts for Blob Service Operations. + // [https://docs.microsoft.com/en-us/rest/api/storageservices/fileservices/setting-timeouts-for-blob-service-operations] + Timeout *int32 + // Only for hierarchical namespace enabled accounts. Optional. The path of the soft deleted blob to undelete. + UndeleteSource *string +} + +// PathClientUpdateOptions contains the optional parameters for the PathClient.Update method. +type PathClientUpdateOptions struct { + // Sets POSIX access control rights on files and directories. The value is a comma-separated list of access control entries. + // Each access control entry (ACE) consists of a scope, a type, a user or group + // identifier, and permissions in the format "[scope:][type]:[id]:[permissions]". + ACL *string + // Azure Storage Events allow applications to receive notifications when files change. When Azure Storage Events are enabled, + // a file changed event is raised. This event has a property indicating whether + // this is the final change to distinguish the difference between an intermediate flush to a file stream and the final close + // of a file stream. The close query parameter is valid only when the action is + // "flush" and change notifications are enabled. If the value of close is "true" and the flush operation completes successfully, + // the service raises a file change notification with a property indicating + // that this is the final update (the file stream has been closed). If "false" a change notification is raised indicating + // the file has changed. The default is false. This query parameter is set to true + // by the Hadoop ABFS driver to indicate that the file stream has been closed." + Close *bool + // Required for "Append Data" and "Flush Data". Must be 0 for "Flush Data". Must be the length of the request content in bytes + // for "Append Data". + ContentLength *int64 + // Optional. The number of paths processed with each invocation is limited. If the number of paths to be processed exceeds + // this limit, a continuation token is returned in the response header + // x-ms-continuation. When a continuation token is returned in the response, it must be percent-encoded and specified in a + // subsequent invocation of setAccessControlRecursive operation. + Continuation *string + // Optional. Valid for "SetAccessControlRecursive" operation. If set to false, the operation will terminate quickly on encountering + // user errors (4XX). If true, the operation will ignore user errors and + // proceed with the operation on other sub-entities of the directory. Continuation token will only be returned when forceFlag + // is true in case of user errors. If not set the default value is false for + // this. + ForceFlag *bool + // Optional. The owning group of the blob or directory. + Group *string + // Optional. Valid for "SetAccessControlRecursive" operation. It specifies the maximum number of files or directories on which + // the acl change will be applied. If omitted or greater than 2,000, the + // request will process up to 2,000 items + MaxRecords *int32 + // Optional. The owner of the blob or directory. + Owner *string + // Optional and only valid if Hierarchical Namespace is enabled for the account. Sets POSIX access permissions for the file + // owner, the file owning group, and others. Each class may be granted read, + // write, or execute permission. The sticky bit is also supported. Both symbolic (rwxrw-rw-) and 4-digit octal notation (e.g. + // 0766) are supported. + Permissions *string + // This parameter allows the caller to upload data in parallel and control the order in which it is appended to the file. + // It is required when uploading data to be appended to the file and when flushing + // previously uploaded data to the file. The value must be the position where the data is to be appended. Uploaded data is + // not immediately flushed, or written, to the file. To flush, the previously + // uploaded data must be contiguous, the position parameter must be specified and equal to the length of the file after all + // data has been written, and there must not be a request entity body included + // with the request. + Position *int64 + // Optional. User-defined properties to be stored with the filesystem, in the format of a comma-separated list of name and + // value pairs "n1=v1, n2=v2, …", where each value is a base64 encoded string. Note + // that the string may only contain ASCII characters in the ISO-8859-1 character set. If the filesystem exists, any properties + // not included in the list will be removed. All properties are removed if the + // header is omitted. To merge new and existing properties, first get all existing properties and the current E-Tag, then + // make a conditional request with the E-Tag and include values for all properties. + Properties *string + // Provides a client-generated, opaque value with a 1 KB character limit that is recorded in the analytics logs when storage + // analytics logging is enabled. + RequestID *string + // Valid only for flush operations. If "true", uncommitted data is retained after the flush operation completes; otherwise, + // the uncommitted data is deleted after the flush operation. The default is + // false. Data at offsets less than the specified position are written to the file when flush succeeds, but this optional + // parameter allows data after the flush position to be retained for a future flush + // operation. + RetainUncommittedData *bool + // The timeout parameter is expressed in seconds. For more information, see Setting Timeouts for Blob Service Operations. + // [https://docs.microsoft.com/en-us/rest/api/storageservices/fileservices/setting-timeouts-for-blob-service-operations] + Timeout *int32 +} + +// PathHTTPHeaders contains a group of parameters for the PathClient.Create method. +type PathHTTPHeaders struct { + // Optional. Sets the blob's cache control. If specified, this property is stored with the blob and returned with a read request. + CacheControl *string + // Optional. Sets the blob's Content-Disposition header. + ContentDisposition *string + // Optional. Sets the blob's content encoding. If specified, this property is stored with the blob and returned with a read + // request. + ContentEncoding *string + // Optional. Set the blob's content language. If specified, this property is stored with the blob and returned with a read + // request. + ContentLanguage *string + // Specify the transactional md5 for the body, to be validated by the service. + ContentMD5 []byte + // Optional. Sets the blob's content type. If specified, this property is stored with the blob and returned with a read request. + ContentType *string + // Specify the transactional md5 for the body, to be validated by the service. + TransactionalContentHash []byte +} + +type PathList struct { + Paths []*Path `json:"paths,omitempty"` +} + +// ServiceClientListFileSystemsOptions contains the optional parameters for the ServiceClient.NewListFileSystemsPager method. +type ServiceClientListFileSystemsOptions struct { + // Optional. When deleting a directory, the number of paths that are deleted with each invocation is limited. If the number + // of paths to be deleted exceeds this limit, a continuation token is returned in + // this response header. When a continuation token is returned in the response, it must be specified in a subsequent invocation + // of the delete operation to continue deleting the directory. + Continuation *string + // An optional value that specifies the maximum number of items to return. If omitted or greater than 5,000, the response + // will include up to 5,000 items. + MaxResults *int32 + // Filters results to filesystems within the specified prefix. + Prefix *string + // Provides a client-generated, opaque value with a 1 KB character limit that is recorded in the analytics logs when storage + // analytics logging is enabled. + RequestID *string + // The timeout parameter is expressed in seconds. For more information, see Setting Timeouts for Blob Service Operations. + // [https://docs.microsoft.com/en-us/rest/api/storageservices/fileservices/setting-timeouts-for-blob-service-operations] + Timeout *int32 +} + +type SetAccessControlRecursiveResponse struct { + DirectoriesSuccessful *int32 `json:"directoriesSuccessful,omitempty"` + FailedEntries []*ACLFailedEntry `json:"failedEntries,omitempty"` + FailureCount *int32 `json:"failureCount,omitempty"` + FilesSuccessful *int32 `json:"filesSuccessful,omitempty"` +} + +// SourceModifiedAccessConditions contains a group of parameters for the PathClient.Create method. +type SourceModifiedAccessConditions struct { + // Specify an ETag value to operate only on blobs with a matching value. + SourceIfMatch *string + // Specify this header value to operate only on a blob if it has been modified since the specified date/time. + SourceIfModifiedSince *time.Time + // Specify an ETag value to operate only on blobs without a matching value. + SourceIfNoneMatch *string + // Specify this header value to operate only on a blob if it has not been modified since the specified date/time. + SourceIfUnmodifiedSince *time.Time +} + +type StorageError struct { + // The service error response object. + Error *StorageErrorError `json:"error,omitempty"` +} + +// StorageErrorError - The service error response object. +type StorageErrorError struct { + // The service error code. + Code *string `json:"Code,omitempty"` + + // The service error message. + Message *string `json:"Message,omitempty"` +} diff --git a/sdk/storage/azdatalake/internal/generated/zz_models_serde.go b/sdk/storage/azdatalake/internal/generated/zz_models_serde.go new file mode 100644 index 000000000000..0bcadcc50c20 --- /dev/null +++ b/sdk/storage/azdatalake/internal/generated/zz_models_serde.go @@ -0,0 +1,415 @@ +//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. +// Code generated by Microsoft (R) AutoRest Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. +// DO NOT EDIT. + +package generated + +import ( + "encoding/json" + "encoding/xml" + "fmt" + "github.com/Azure/azure-sdk-for-go/sdk/azcore" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime" + "reflect" + "time" +) + +// MarshalJSON implements the json.Marshaller interface for type ACLFailedEntry. +func (a ACLFailedEntry) MarshalJSON() ([]byte, error) { + objectMap := make(map[string]any) + populate(objectMap, "errorMessage", a.ErrorMessage) + populate(objectMap, "name", a.Name) + populate(objectMap, "type", a.Type) + return json.Marshal(objectMap) +} + +// UnmarshalJSON implements the json.Unmarshaller interface for type ACLFailedEntry. +func (a *ACLFailedEntry) UnmarshalJSON(data []byte) error { + var rawMsg map[string]json.RawMessage + if err := json.Unmarshal(data, &rawMsg); err != nil { + return fmt.Errorf("unmarshalling type %T: %v", a, err) + } + for key, val := range rawMsg { + var err error + switch key { + case "errorMessage": + err = unpopulate(val, "ErrorMessage", &a.ErrorMessage) + delete(rawMsg, key) + case "name": + err = unpopulate(val, "Name", &a.Name) + delete(rawMsg, key) + case "type": + err = unpopulate(val, "Type", &a.Type) + delete(rawMsg, key) + } + if err != nil { + return fmt.Errorf("unmarshalling type %T: %v", a, err) + } + } + return nil +} + +// MarshalXML implements the xml.Marshaller interface for type BlobHierarchyListSegment. +func (b BlobHierarchyListSegment) MarshalXML(enc *xml.Encoder, start xml.StartElement) error { + type alias BlobHierarchyListSegment + aux := &struct { + *alias + BlobItems *[]*BlobItemInternal `xml:"Blob"` + BlobPrefixes *[]*BlobPrefix `xml:"BlobPrefix"` + }{ + alias: (*alias)(&b), + } + if b.BlobItems != nil { + aux.BlobItems = &b.BlobItems + } + if b.BlobPrefixes != nil { + aux.BlobPrefixes = &b.BlobPrefixes + } + return enc.EncodeElement(aux, start) +} + +// MarshalXML implements the xml.Marshaller interface for type BlobPropertiesInternal. +func (b BlobPropertiesInternal) MarshalXML(enc *xml.Encoder, start xml.StartElement) error { + type alias BlobPropertiesInternal + aux := &struct { + *alias + AccessTierChangeTime *timeRFC1123 `xml:"AccessTierChangeTime"` + ContentMD5 *string `xml:"Content-MD5"` + CopyCompletionTime *timeRFC1123 `xml:"CopyCompletionTime"` + CreationTime *timeRFC1123 `xml:"Creation-Time"` + DeleteTime *timeRFC1123 `xml:"DeleteTime"` + DeletedTime *timeRFC1123 `xml:"DeletedTime"` + ExpiresOn *timeRFC1123 `xml:"Expiry-Time"` + LastAccessedOn *timeRFC1123 `xml:"LastAccessTime"` + LastModified *timeRFC1123 `xml:"Last-Modified"` + }{ + alias: (*alias)(&b), + AccessTierChangeTime: (*timeRFC1123)(b.AccessTierChangeTime), + CopyCompletionTime: (*timeRFC1123)(b.CopyCompletionTime), + CreationTime: (*timeRFC1123)(b.CreationTime), + DeleteTime: (*timeRFC1123)(b.DeleteTime), + DeletedTime: (*timeRFC1123)(b.DeletedTime), + ExpiresOn: (*timeRFC1123)(b.ExpiresOn), + LastAccessedOn: (*timeRFC1123)(b.LastAccessedOn), + LastModified: (*timeRFC1123)(b.LastModified), + } + if b.ContentMD5 != nil { + encodedContentMD5 := runtime.EncodeByteArray(b.ContentMD5, runtime.Base64StdFormat) + aux.ContentMD5 = &encodedContentMD5 + } + return enc.EncodeElement(aux, start) +} + +// UnmarshalXML implements the xml.Unmarshaller interface for type BlobPropertiesInternal. +func (b *BlobPropertiesInternal) UnmarshalXML(dec *xml.Decoder, start xml.StartElement) error { + type alias BlobPropertiesInternal + aux := &struct { + *alias + AccessTierChangeTime *timeRFC1123 `xml:"AccessTierChangeTime"` + ContentMD5 *string `xml:"Content-MD5"` + CopyCompletionTime *timeRFC1123 `xml:"CopyCompletionTime"` + CreationTime *timeRFC1123 `xml:"Creation-Time"` + DeleteTime *timeRFC1123 `xml:"DeleteTime"` + DeletedTime *timeRFC1123 `xml:"DeletedTime"` + ExpiresOn *timeRFC1123 `xml:"Expiry-Time"` + LastAccessedOn *timeRFC1123 `xml:"LastAccessTime"` + LastModified *timeRFC1123 `xml:"Last-Modified"` + }{ + alias: (*alias)(b), + } + if err := dec.DecodeElement(aux, &start); err != nil { + return err + } + b.AccessTierChangeTime = (*time.Time)(aux.AccessTierChangeTime) + if aux.ContentMD5 != nil { + if err := runtime.DecodeByteArray(*aux.ContentMD5, &b.ContentMD5, runtime.Base64StdFormat); err != nil { + return err + } + } + b.CopyCompletionTime = (*time.Time)(aux.CopyCompletionTime) + b.CreationTime = (*time.Time)(aux.CreationTime) + b.DeleteTime = (*time.Time)(aux.DeleteTime) + b.DeletedTime = (*time.Time)(aux.DeletedTime) + b.ExpiresOn = (*time.Time)(aux.ExpiresOn) + b.LastAccessedOn = (*time.Time)(aux.LastAccessedOn) + b.LastModified = (*time.Time)(aux.LastModified) + return nil +} + +// MarshalJSON implements the json.Marshaller interface for type FileSystem. +func (f FileSystem) MarshalJSON() ([]byte, error) { + objectMap := make(map[string]any) + populate(objectMap, "eTag", f.ETag) + populate(objectMap, "lastModified", f.LastModified) + populate(objectMap, "name", f.Name) + return json.Marshal(objectMap) +} + +// UnmarshalJSON implements the json.Unmarshaller interface for type FileSystem. +func (f *FileSystem) UnmarshalJSON(data []byte) error { + var rawMsg map[string]json.RawMessage + if err := json.Unmarshal(data, &rawMsg); err != nil { + return fmt.Errorf("unmarshalling type %T: %v", f, err) + } + for key, val := range rawMsg { + var err error + switch key { + case "eTag": + err = unpopulate(val, "ETag", &f.ETag) + delete(rawMsg, key) + case "lastModified": + err = unpopulate(val, "LastModified", &f.LastModified) + delete(rawMsg, key) + case "name": + err = unpopulate(val, "Name", &f.Name) + delete(rawMsg, key) + } + if err != nil { + return fmt.Errorf("unmarshalling type %T: %v", f, err) + } + } + return nil +} + +// MarshalJSON implements the json.Marshaller interface for type FileSystemList. +func (f FileSystemList) MarshalJSON() ([]byte, error) { + objectMap := make(map[string]any) + populate(objectMap, "filesystems", f.Filesystems) + return json.Marshal(objectMap) +} + +// UnmarshalJSON implements the json.Unmarshaller interface for type FileSystemList. +func (f *FileSystemList) UnmarshalJSON(data []byte) error { + var rawMsg map[string]json.RawMessage + if err := json.Unmarshal(data, &rawMsg); err != nil { + return fmt.Errorf("unmarshalling type %T: %v", f, err) + } + for key, val := range rawMsg { + var err error + switch key { + case "filesystems": + err = unpopulate(val, "Filesystems", &f.Filesystems) + delete(rawMsg, key) + } + if err != nil { + return fmt.Errorf("unmarshalling type %T: %v", f, err) + } + } + return nil +} + +// MarshalJSON implements the json.Marshaller interface for type Path. +func (p Path) MarshalJSON() ([]byte, error) { + objectMap := make(map[string]any) + populate(objectMap, "contentLength", p.ContentLength) + populate(objectMap, "creationTime", p.CreationTime) + populate(objectMap, "eTag", p.ETag) + populate(objectMap, "EncryptionScope", p.EncryptionScope) + populate(objectMap, "expiryTime", p.ExpiryTime) + populate(objectMap, "group", p.Group) + populate(objectMap, "isDirectory", p.IsDirectory) + populate(objectMap, "lastModified", p.LastModified) + populate(objectMap, "name", p.Name) + populate(objectMap, "owner", p.Owner) + populate(objectMap, "permissions", p.Permissions) + return json.Marshal(objectMap) +} + +// UnmarshalJSON implements the json.Unmarshaller interface for type Path. +func (p *Path) UnmarshalJSON(data []byte) error { + var rawMsg map[string]json.RawMessage + if err := json.Unmarshal(data, &rawMsg); err != nil { + return fmt.Errorf("unmarshalling type %T: %v", p, err) + } + for key, val := range rawMsg { + var err error + switch key { + case "contentLength": + err = unpopulate(val, "ContentLength", &p.ContentLength) + delete(rawMsg, key) + case "creationTime": + err = unpopulate(val, "CreationTime", &p.CreationTime) + delete(rawMsg, key) + case "eTag": + err = unpopulate(val, "ETag", &p.ETag) + delete(rawMsg, key) + case "EncryptionScope": + err = unpopulate(val, "EncryptionScope", &p.EncryptionScope) + delete(rawMsg, key) + case "expiryTime": + err = unpopulate(val, "ExpiryTime", &p.ExpiryTime) + delete(rawMsg, key) + case "group": + err = unpopulate(val, "Group", &p.Group) + delete(rawMsg, key) + case "isDirectory": + err = unpopulate(val, "IsDirectory", &p.IsDirectory) + delete(rawMsg, key) + case "lastModified": + err = unpopulate(val, "LastModified", &p.LastModified) + delete(rawMsg, key) + case "name": + err = unpopulate(val, "Name", &p.Name) + delete(rawMsg, key) + case "owner": + err = unpopulate(val, "Owner", &p.Owner) + delete(rawMsg, key) + case "permissions": + err = unpopulate(val, "Permissions", &p.Permissions) + delete(rawMsg, key) + } + if err != nil { + return fmt.Errorf("unmarshalling type %T: %v", p, err) + } + } + return nil +} + +// MarshalJSON implements the json.Marshaller interface for type PathList. +func (p PathList) MarshalJSON() ([]byte, error) { + objectMap := make(map[string]any) + populate(objectMap, "paths", p.Paths) + return json.Marshal(objectMap) +} + +// UnmarshalJSON implements the json.Unmarshaller interface for type PathList. +func (p *PathList) UnmarshalJSON(data []byte) error { + var rawMsg map[string]json.RawMessage + if err := json.Unmarshal(data, &rawMsg); err != nil { + return fmt.Errorf("unmarshalling type %T: %v", p, err) + } + for key, val := range rawMsg { + var err error + switch key { + case "paths": + err = unpopulate(val, "Paths", &p.Paths) + delete(rawMsg, key) + } + if err != nil { + return fmt.Errorf("unmarshalling type %T: %v", p, err) + } + } + return nil +} + +// MarshalJSON implements the json.Marshaller interface for type SetAccessControlRecursiveResponse. +func (s SetAccessControlRecursiveResponse) MarshalJSON() ([]byte, error) { + objectMap := make(map[string]any) + populate(objectMap, "directoriesSuccessful", s.DirectoriesSuccessful) + populate(objectMap, "failedEntries", s.FailedEntries) + populate(objectMap, "failureCount", s.FailureCount) + populate(objectMap, "filesSuccessful", s.FilesSuccessful) + return json.Marshal(objectMap) +} + +// UnmarshalJSON implements the json.Unmarshaller interface for type SetAccessControlRecursiveResponse. +func (s *SetAccessControlRecursiveResponse) UnmarshalJSON(data []byte) error { + var rawMsg map[string]json.RawMessage + if err := json.Unmarshal(data, &rawMsg); err != nil { + return fmt.Errorf("unmarshalling type %T: %v", s, err) + } + for key, val := range rawMsg { + var err error + switch key { + case "directoriesSuccessful": + err = unpopulate(val, "DirectoriesSuccessful", &s.DirectoriesSuccessful) + delete(rawMsg, key) + case "failedEntries": + err = unpopulate(val, "FailedEntries", &s.FailedEntries) + delete(rawMsg, key) + case "failureCount": + err = unpopulate(val, "FailureCount", &s.FailureCount) + delete(rawMsg, key) + case "filesSuccessful": + err = unpopulate(val, "FilesSuccessful", &s.FilesSuccessful) + delete(rawMsg, key) + } + if err != nil { + return fmt.Errorf("unmarshalling type %T: %v", s, err) + } + } + return nil +} + +// MarshalJSON implements the json.Marshaller interface for type StorageError. +func (s StorageError) MarshalJSON() ([]byte, error) { + objectMap := make(map[string]any) + populate(objectMap, "error", s.Error) + return json.Marshal(objectMap) +} + +// UnmarshalJSON implements the json.Unmarshaller interface for type StorageError. +func (s *StorageError) UnmarshalJSON(data []byte) error { + var rawMsg map[string]json.RawMessage + if err := json.Unmarshal(data, &rawMsg); err != nil { + return fmt.Errorf("unmarshalling type %T: %v", s, err) + } + for key, val := range rawMsg { + var err error + switch key { + case "error": + err = unpopulate(val, "Error", &s.Error) + delete(rawMsg, key) + } + if err != nil { + return fmt.Errorf("unmarshalling type %T: %v", s, err) + } + } + return nil +} + +// MarshalJSON implements the json.Marshaller interface for type StorageErrorError. +func (s StorageErrorError) MarshalJSON() ([]byte, error) { + objectMap := make(map[string]any) + populate(objectMap, "Code", s.Code) + populate(objectMap, "Message", s.Message) + return json.Marshal(objectMap) +} + +// UnmarshalJSON implements the json.Unmarshaller interface for type StorageErrorError. +func (s *StorageErrorError) UnmarshalJSON(data []byte) error { + var rawMsg map[string]json.RawMessage + if err := json.Unmarshal(data, &rawMsg); err != nil { + return fmt.Errorf("unmarshalling type %T: %v", s, err) + } + for key, val := range rawMsg { + var err error + switch key { + case "Code": + err = unpopulate(val, "Code", &s.Code) + delete(rawMsg, key) + case "Message": + err = unpopulate(val, "Message", &s.Message) + delete(rawMsg, key) + } + if err != nil { + return fmt.Errorf("unmarshalling type %T: %v", s, err) + } + } + return nil +} + +func populate(m map[string]any, k string, v any) { + if v == nil { + return + } else if azcore.IsNullValue(v) { + m[k] = nil + } else if !reflect.ValueOf(v).IsNil() { + m[k] = v + } +} + +func unpopulate(data json.RawMessage, fn string, v any) error { + if data == nil { + return nil + } + if err := json.Unmarshal(data, v); err != nil { + return fmt.Errorf("struct field %s: %v", fn, err) + } + return nil +} diff --git a/sdk/storage/azdatalake/internal/generated/zz_path_client.go b/sdk/storage/azdatalake/internal/generated/zz_path_client.go new file mode 100644 index 000000000000..876f13e3f14d --- /dev/null +++ b/sdk/storage/azdatalake/internal/generated/zz_path_client.go @@ -0,0 +1,1530 @@ +//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. +// Code generated by Microsoft (R) AutoRest Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. +// DO NOT EDIT. + +package generated + +import ( + "context" + "encoding/base64" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/policy" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime" + "io" + "net/http" + "strconv" + "time" +) + +// PathClient contains the methods for the Path group. +// Don't use this type directly, use NewPathClient() instead. +type PathClient struct { + endpoint string + pl runtime.Pipeline +} + +// NewPathClient creates a new instance of PathClient with the specified values. +// - endpoint - The URL of the service account, container, or blob that is the target of the desired operation. +// - pl - the pipeline used for sending requests and handling responses. +func NewPathClient(endpoint string, pl runtime.Pipeline) *PathClient { + client := &PathClient{ + endpoint: endpoint, + pl: pl, + } + return client +} + +// AppendData - Append data to the file. +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2020-10-02 +// - body - Initial data +// - options - PathClientAppendDataOptions contains the optional parameters for the PathClient.AppendData method. +// - PathHTTPHeaders - PathHTTPHeaders contains a group of parameters for the PathClient.Create method. +// - LeaseAccessConditions - LeaseAccessConditions contains a group of parameters for the PathClient.Create method. +// - CpkInfo - CpkInfo contains a group of parameters for the PathClient.Create method. +func (client *PathClient) AppendData(ctx context.Context, body io.ReadSeekCloser, options *PathClientAppendDataOptions, pathHTTPHeaders *PathHTTPHeaders, leaseAccessConditions *LeaseAccessConditions, cpkInfo *CpkInfo) (PathClientAppendDataResponse, error) { + req, err := client.appendDataCreateRequest(ctx, body, options, pathHTTPHeaders, leaseAccessConditions, cpkInfo) + if err != nil { + return PathClientAppendDataResponse{}, err + } + resp, err := client.pl.Do(req) + if err != nil { + return PathClientAppendDataResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusAccepted) { + return PathClientAppendDataResponse{}, runtime.NewResponseError(resp) + } + return client.appendDataHandleResponse(resp) +} + +// appendDataCreateRequest creates the AppendData request. +func (client *PathClient) appendDataCreateRequest(ctx context.Context, body io.ReadSeekCloser, options *PathClientAppendDataOptions, pathHTTPHeaders *PathHTTPHeaders, leaseAccessConditions *LeaseAccessConditions, cpkInfo *CpkInfo) (*policy.Request, error) { + req, err := runtime.NewRequest(ctx, http.MethodPatch, client.endpoint) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("action", "append") + if options != nil && options.Position != nil { + reqQP.Set("position", strconv.FormatInt(*options.Position, 10)) + } + if options != nil && options.Timeout != nil { + reqQP.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + } + req.Raw().URL.RawQuery = reqQP.Encode() + if options != nil && options.ContentLength != nil { + req.Raw().Header["Content-Length"] = []string{strconv.FormatInt(*options.ContentLength, 10)} + } + if pathHTTPHeaders != nil && pathHTTPHeaders.TransactionalContentHash != nil { + req.Raw().Header["Content-MD5"] = []string{base64.StdEncoding.EncodeToString(pathHTTPHeaders.TransactionalContentHash)} + } + if options != nil && options.TransactionalContentCRC64 != nil { + req.Raw().Header["x-ms-content-crc64"] = []string{base64.StdEncoding.EncodeToString(options.TransactionalContentCRC64)} + } + if leaseAccessConditions != nil && leaseAccessConditions.LeaseID != nil { + req.Raw().Header["x-ms-lease-id"] = []string{*leaseAccessConditions.LeaseID} + } + if options != nil && options.RequestID != nil { + req.Raw().Header["x-ms-client-request-id"] = []string{*options.RequestID} + } + req.Raw().Header["x-ms-version"] = []string{"2020-10-02"} + if cpkInfo != nil && cpkInfo.EncryptionKey != nil { + req.Raw().Header["x-ms-encryption-key"] = []string{*cpkInfo.EncryptionKey} + } + if cpkInfo != nil && cpkInfo.EncryptionKeySHA256 != nil { + req.Raw().Header["x-ms-encryption-key-sha256"] = []string{*cpkInfo.EncryptionKeySHA256} + } + if cpkInfo != nil && cpkInfo.EncryptionAlgorithm != nil { + req.Raw().Header["x-ms-encryption-algorithm"] = []string{"AES256"} + } + req.Raw().Header["Accept"] = []string{"application/json"} + return req, req.SetBody(body, "application/json") +} + +// appendDataHandleResponse handles the AppendData response. +func (client *PathClient) appendDataHandleResponse(resp *http.Response) (PathClientAppendDataResponse, error) { + result := PathClientAppendDataResponse{} + if val := resp.Header.Get("Date"); val != "" { + date, err := time.Parse(time.RFC1123, val) + if err != nil { + return PathClientAppendDataResponse{}, err + } + result.Date = &date + } + if val := resp.Header.Get("x-ms-request-id"); val != "" { + result.RequestID = &val + } + if val := resp.Header.Get("x-ms-client-request-id"); val != "" { + result.ClientRequestID = &val + } + if val := resp.Header.Get("x-ms-version"); val != "" { + result.Version = &val + } + if val := resp.Header.Get("ETag"); val != "" { + result.ETag = &val + } + if val := resp.Header.Get("Content-MD5"); val != "" { + contentMD5, err := base64.StdEncoding.DecodeString(val) + if err != nil { + return PathClientAppendDataResponse{}, err + } + result.ContentMD5 = contentMD5 + } + if val := resp.Header.Get("x-ms-content-crc64"); val != "" { + xMSContentCRC64, err := base64.StdEncoding.DecodeString(val) + if err != nil { + return PathClientAppendDataResponse{}, err + } + result.XMSContentCRC64 = xMSContentCRC64 + } + if val := resp.Header.Get("x-ms-request-server-encrypted"); val != "" { + isServerEncrypted, err := strconv.ParseBool(val) + if err != nil { + return PathClientAppendDataResponse{}, err + } + result.IsServerEncrypted = &isServerEncrypted + } + if val := resp.Header.Get("x-ms-encryption-key-sha256"); val != "" { + result.EncryptionKeySHA256 = &val + } + return result, nil +} + +// Create - Create or rename a file or directory. By default, the destination is overwritten and if the destination already +// exists and has a lease the lease is broken. This operation supports conditional HTTP +// requests. For more information, see Specifying Conditional Headers for Blob Service Operations +// [https://docs.microsoft.com/en-us/rest/api/storageservices/specifying-conditional-headers-for-blob-service-operations]. +// To fail if the destination already exists, use a conditional request with +// If-None-Match: "*". +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2020-10-02 +// - options - PathClientCreateOptions contains the optional parameters for the PathClient.Create method. +// - PathHTTPHeaders - PathHTTPHeaders contains a group of parameters for the PathClient.Create method. +// - LeaseAccessConditions - LeaseAccessConditions contains a group of parameters for the PathClient.Create method. +// - ModifiedAccessConditions - ModifiedAccessConditions contains a group of parameters for the FileSystemClient.SetProperties +// method. +// - SourceModifiedAccessConditions - SourceModifiedAccessConditions contains a group of parameters for the PathClient.Create +// method. +// - CpkInfo - CpkInfo contains a group of parameters for the PathClient.Create method. +func (client *PathClient) Create(ctx context.Context, options *PathClientCreateOptions, pathHTTPHeaders *PathHTTPHeaders, leaseAccessConditions *LeaseAccessConditions, modifiedAccessConditions *ModifiedAccessConditions, sourceModifiedAccessConditions *SourceModifiedAccessConditions, cpkInfo *CpkInfo) (PathClientCreateResponse, error) { + req, err := client.createCreateRequest(ctx, options, pathHTTPHeaders, leaseAccessConditions, modifiedAccessConditions, sourceModifiedAccessConditions, cpkInfo) + if err != nil { + return PathClientCreateResponse{}, err + } + resp, err := client.pl.Do(req) + if err != nil { + return PathClientCreateResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusCreated) { + return PathClientCreateResponse{}, runtime.NewResponseError(resp) + } + return client.createHandleResponse(resp) +} + +// createCreateRequest creates the Create request. +func (client *PathClient) createCreateRequest(ctx context.Context, options *PathClientCreateOptions, pathHTTPHeaders *PathHTTPHeaders, leaseAccessConditions *LeaseAccessConditions, modifiedAccessConditions *ModifiedAccessConditions, sourceModifiedAccessConditions *SourceModifiedAccessConditions, cpkInfo *CpkInfo) (*policy.Request, error) { + req, err := runtime.NewRequest(ctx, http.MethodPut, client.endpoint) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + if options != nil && options.Timeout != nil { + reqQP.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + } + if options != nil && options.Resource != nil { + reqQP.Set("resource", string(*options.Resource)) + } + if options != nil && options.Continuation != nil { + reqQP.Set("continuation", *options.Continuation) + } + if options != nil && options.Mode != nil { + reqQP.Set("mode", string(*options.Mode)) + } + req.Raw().URL.RawQuery = reqQP.Encode() + if options != nil && options.RequestID != nil { + req.Raw().Header["x-ms-client-request-id"] = []string{*options.RequestID} + } + req.Raw().Header["x-ms-version"] = []string{"2020-10-02"} + if pathHTTPHeaders != nil && pathHTTPHeaders.CacheControl != nil { + req.Raw().Header["x-ms-cache-control"] = []string{*pathHTTPHeaders.CacheControl} + } + if pathHTTPHeaders != nil && pathHTTPHeaders.ContentEncoding != nil { + req.Raw().Header["x-ms-content-encoding"] = []string{*pathHTTPHeaders.ContentEncoding} + } + if pathHTTPHeaders != nil && pathHTTPHeaders.ContentLanguage != nil { + req.Raw().Header["x-ms-content-language"] = []string{*pathHTTPHeaders.ContentLanguage} + } + if pathHTTPHeaders != nil && pathHTTPHeaders.ContentDisposition != nil { + req.Raw().Header["x-ms-content-disposition"] = []string{*pathHTTPHeaders.ContentDisposition} + } + if pathHTTPHeaders != nil && pathHTTPHeaders.ContentType != nil { + req.Raw().Header["x-ms-content-type"] = []string{*pathHTTPHeaders.ContentType} + } + if options != nil && options.RenameSource != nil { + req.Raw().Header["x-ms-rename-source"] = []string{*options.RenameSource} + } + if leaseAccessConditions != nil && leaseAccessConditions.LeaseID != nil { + req.Raw().Header["x-ms-lease-id"] = []string{*leaseAccessConditions.LeaseID} + } + if options != nil && options.SourceLeaseID != nil { + req.Raw().Header["x-ms-source-lease-id"] = []string{*options.SourceLeaseID} + } + if options != nil && options.Properties != nil { + req.Raw().Header["x-ms-properties"] = []string{*options.Properties} + } + if options != nil && options.Permissions != nil { + req.Raw().Header["x-ms-permissions"] = []string{*options.Permissions} + } + if options != nil && options.Umask != nil { + req.Raw().Header["x-ms-umask"] = []string{*options.Umask} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfMatch != nil { + req.Raw().Header["If-Match"] = []string{*modifiedAccessConditions.IfMatch} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfNoneMatch != nil { + req.Raw().Header["If-None-Match"] = []string{*modifiedAccessConditions.IfNoneMatch} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfModifiedSince != nil { + req.Raw().Header["If-Modified-Since"] = []string{modifiedAccessConditions.IfModifiedSince.Format(time.RFC1123)} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfUnmodifiedSince != nil { + req.Raw().Header["If-Unmodified-Since"] = []string{modifiedAccessConditions.IfUnmodifiedSince.Format(time.RFC1123)} + } + if sourceModifiedAccessConditions != nil && sourceModifiedAccessConditions.SourceIfMatch != nil { + req.Raw().Header["x-ms-source-if-match"] = []string{*sourceModifiedAccessConditions.SourceIfMatch} + } + if sourceModifiedAccessConditions != nil && sourceModifiedAccessConditions.SourceIfNoneMatch != nil { + req.Raw().Header["x-ms-source-if-none-match"] = []string{*sourceModifiedAccessConditions.SourceIfNoneMatch} + } + if sourceModifiedAccessConditions != nil && sourceModifiedAccessConditions.SourceIfModifiedSince != nil { + req.Raw().Header["x-ms-source-if-modified-since"] = []string{sourceModifiedAccessConditions.SourceIfModifiedSince.Format(time.RFC1123)} + } + if sourceModifiedAccessConditions != nil && sourceModifiedAccessConditions.SourceIfUnmodifiedSince != nil { + req.Raw().Header["x-ms-source-if-unmodified-since"] = []string{sourceModifiedAccessConditions.SourceIfUnmodifiedSince.Format(time.RFC1123)} + } + if cpkInfo != nil && cpkInfo.EncryptionKey != nil { + req.Raw().Header["x-ms-encryption-key"] = []string{*cpkInfo.EncryptionKey} + } + if cpkInfo != nil && cpkInfo.EncryptionKeySHA256 != nil { + req.Raw().Header["x-ms-encryption-key-sha256"] = []string{*cpkInfo.EncryptionKeySHA256} + } + if cpkInfo != nil && cpkInfo.EncryptionAlgorithm != nil { + req.Raw().Header["x-ms-encryption-algorithm"] = []string{"AES256"} + } + req.Raw().Header["Accept"] = []string{"application/json"} + return req, nil +} + +// createHandleResponse handles the Create response. +func (client *PathClient) createHandleResponse(resp *http.Response) (PathClientCreateResponse, error) { + result := PathClientCreateResponse{} + if val := resp.Header.Get("Date"); val != "" { + date, err := time.Parse(time.RFC1123, val) + if err != nil { + return PathClientCreateResponse{}, err + } + result.Date = &date + } + if val := resp.Header.Get("ETag"); val != "" { + result.ETag = &val + } + if val := resp.Header.Get("Last-Modified"); val != "" { + lastModified, err := time.Parse(time.RFC1123, val) + if err != nil { + return PathClientCreateResponse{}, err + } + result.LastModified = &lastModified + } + if val := resp.Header.Get("x-ms-request-id"); val != "" { + result.RequestID = &val + } + if val := resp.Header.Get("x-ms-version"); val != "" { + result.Version = &val + } + if val := resp.Header.Get("x-ms-continuation"); val != "" { + result.Continuation = &val + } + if val := resp.Header.Get("Content-Length"); val != "" { + contentLength, err := strconv.ParseInt(val, 10, 64) + if err != nil { + return PathClientCreateResponse{}, err + } + result.ContentLength = &contentLength + } + if val := resp.Header.Get("x-ms-request-server-encrypted"); val != "" { + isServerEncrypted, err := strconv.ParseBool(val) + if err != nil { + return PathClientCreateResponse{}, err + } + result.IsServerEncrypted = &isServerEncrypted + } + if val := resp.Header.Get("x-ms-encryption-key-sha256"); val != "" { + result.EncryptionKeySHA256 = &val + } + return result, nil +} + +// Delete - Delete the file or directory. This operation supports conditional HTTP requests. For more information, see Specifying +// Conditional Headers for Blob Service Operations +// [https://docs.microsoft.com/en-us/rest/api/storageservices/specifying-conditional-headers-for-blob-service-operations]. +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2020-10-02 +// - options - PathClientDeleteOptions contains the optional parameters for the PathClient.Delete method. +// - LeaseAccessConditions - LeaseAccessConditions contains a group of parameters for the PathClient.Create method. +// - ModifiedAccessConditions - ModifiedAccessConditions contains a group of parameters for the FileSystemClient.SetProperties +// method. +func (client *PathClient) Delete(ctx context.Context, options *PathClientDeleteOptions, leaseAccessConditions *LeaseAccessConditions, modifiedAccessConditions *ModifiedAccessConditions) (PathClientDeleteResponse, error) { + req, err := client.deleteCreateRequest(ctx, options, leaseAccessConditions, modifiedAccessConditions) + if err != nil { + return PathClientDeleteResponse{}, err + } + resp, err := client.pl.Do(req) + if err != nil { + return PathClientDeleteResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusOK) { + return PathClientDeleteResponse{}, runtime.NewResponseError(resp) + } + return client.deleteHandleResponse(resp) +} + +// deleteCreateRequest creates the Delete request. +func (client *PathClient) deleteCreateRequest(ctx context.Context, options *PathClientDeleteOptions, leaseAccessConditions *LeaseAccessConditions, modifiedAccessConditions *ModifiedAccessConditions) (*policy.Request, error) { + req, err := runtime.NewRequest(ctx, http.MethodDelete, client.endpoint) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + if options != nil && options.Timeout != nil { + reqQP.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + } + if options != nil && options.Recursive != nil { + reqQP.Set("recursive", strconv.FormatBool(*options.Recursive)) + } + if options != nil && options.Continuation != nil { + reqQP.Set("continuation", *options.Continuation) + } + req.Raw().URL.RawQuery = reqQP.Encode() + if options != nil && options.RequestID != nil { + req.Raw().Header["x-ms-client-request-id"] = []string{*options.RequestID} + } + req.Raw().Header["x-ms-version"] = []string{"2020-10-02"} + if leaseAccessConditions != nil && leaseAccessConditions.LeaseID != nil { + req.Raw().Header["x-ms-lease-id"] = []string{*leaseAccessConditions.LeaseID} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfMatch != nil { + req.Raw().Header["If-Match"] = []string{*modifiedAccessConditions.IfMatch} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfNoneMatch != nil { + req.Raw().Header["If-None-Match"] = []string{*modifiedAccessConditions.IfNoneMatch} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfModifiedSince != nil { + req.Raw().Header["If-Modified-Since"] = []string{modifiedAccessConditions.IfModifiedSince.Format(time.RFC1123)} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfUnmodifiedSince != nil { + req.Raw().Header["If-Unmodified-Since"] = []string{modifiedAccessConditions.IfUnmodifiedSince.Format(time.RFC1123)} + } + req.Raw().Header["Accept"] = []string{"application/json"} + return req, nil +} + +// deleteHandleResponse handles the Delete response. +func (client *PathClient) deleteHandleResponse(resp *http.Response) (PathClientDeleteResponse, error) { + result := PathClientDeleteResponse{} + if val := resp.Header.Get("Date"); val != "" { + date, err := time.Parse(time.RFC1123, val) + if err != nil { + return PathClientDeleteResponse{}, err + } + result.Date = &date + } + if val := resp.Header.Get("x-ms-request-id"); val != "" { + result.RequestID = &val + } + if val := resp.Header.Get("x-ms-version"); val != "" { + result.Version = &val + } + if val := resp.Header.Get("x-ms-continuation"); val != "" { + result.Continuation = &val + } + if val := resp.Header.Get("x-ms-deletion-id"); val != "" { + result.DeletionID = &val + } + return result, nil +} + +// FlushData - Set the owner, group, permissions, or access control list for a path. +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2020-10-02 +// - options - PathClientFlushDataOptions contains the optional parameters for the PathClient.FlushData method. +// - PathHTTPHeaders - PathHTTPHeaders contains a group of parameters for the PathClient.Create method. +// - LeaseAccessConditions - LeaseAccessConditions contains a group of parameters for the PathClient.Create method. +// - ModifiedAccessConditions - ModifiedAccessConditions contains a group of parameters for the FileSystemClient.SetProperties +// method. +// - CpkInfo - CpkInfo contains a group of parameters for the PathClient.Create method. +func (client *PathClient) FlushData(ctx context.Context, options *PathClientFlushDataOptions, pathHTTPHeaders *PathHTTPHeaders, leaseAccessConditions *LeaseAccessConditions, modifiedAccessConditions *ModifiedAccessConditions, cpkInfo *CpkInfo) (PathClientFlushDataResponse, error) { + req, err := client.flushDataCreateRequest(ctx, options, pathHTTPHeaders, leaseAccessConditions, modifiedAccessConditions, cpkInfo) + if err != nil { + return PathClientFlushDataResponse{}, err + } + resp, err := client.pl.Do(req) + if err != nil { + return PathClientFlushDataResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusOK) { + return PathClientFlushDataResponse{}, runtime.NewResponseError(resp) + } + return client.flushDataHandleResponse(resp) +} + +// flushDataCreateRequest creates the FlushData request. +func (client *PathClient) flushDataCreateRequest(ctx context.Context, options *PathClientFlushDataOptions, pathHTTPHeaders *PathHTTPHeaders, leaseAccessConditions *LeaseAccessConditions, modifiedAccessConditions *ModifiedAccessConditions, cpkInfo *CpkInfo) (*policy.Request, error) { + req, err := runtime.NewRequest(ctx, http.MethodPatch, client.endpoint) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("action", "flush") + if options != nil && options.Timeout != nil { + reqQP.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + } + if options != nil && options.Position != nil { + reqQP.Set("position", strconv.FormatInt(*options.Position, 10)) + } + if options != nil && options.RetainUncommittedData != nil { + reqQP.Set("retainUncommittedData", strconv.FormatBool(*options.RetainUncommittedData)) + } + if options != nil && options.Close != nil { + reqQP.Set("close", strconv.FormatBool(*options.Close)) + } + req.Raw().URL.RawQuery = reqQP.Encode() + if options != nil && options.ContentLength != nil { + req.Raw().Header["Content-Length"] = []string{strconv.FormatInt(*options.ContentLength, 10)} + } + if pathHTTPHeaders != nil && pathHTTPHeaders.ContentMD5 != nil { + req.Raw().Header["x-ms-content-md5"] = []string{base64.StdEncoding.EncodeToString(pathHTTPHeaders.ContentMD5)} + } + if leaseAccessConditions != nil && leaseAccessConditions.LeaseID != nil { + req.Raw().Header["x-ms-lease-id"] = []string{*leaseAccessConditions.LeaseID} + } + if pathHTTPHeaders != nil && pathHTTPHeaders.CacheControl != nil { + req.Raw().Header["x-ms-cache-control"] = []string{*pathHTTPHeaders.CacheControl} + } + if pathHTTPHeaders != nil && pathHTTPHeaders.ContentType != nil { + req.Raw().Header["x-ms-content-type"] = []string{*pathHTTPHeaders.ContentType} + } + if pathHTTPHeaders != nil && pathHTTPHeaders.ContentDisposition != nil { + req.Raw().Header["x-ms-content-disposition"] = []string{*pathHTTPHeaders.ContentDisposition} + } + if pathHTTPHeaders != nil && pathHTTPHeaders.ContentEncoding != nil { + req.Raw().Header["x-ms-content-encoding"] = []string{*pathHTTPHeaders.ContentEncoding} + } + if pathHTTPHeaders != nil && pathHTTPHeaders.ContentLanguage != nil { + req.Raw().Header["x-ms-content-language"] = []string{*pathHTTPHeaders.ContentLanguage} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfMatch != nil { + req.Raw().Header["If-Match"] = []string{*modifiedAccessConditions.IfMatch} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfNoneMatch != nil { + req.Raw().Header["If-None-Match"] = []string{*modifiedAccessConditions.IfNoneMatch} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfModifiedSince != nil { + req.Raw().Header["If-Modified-Since"] = []string{modifiedAccessConditions.IfModifiedSince.Format(time.RFC1123)} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfUnmodifiedSince != nil { + req.Raw().Header["If-Unmodified-Since"] = []string{modifiedAccessConditions.IfUnmodifiedSince.Format(time.RFC1123)} + } + if options != nil && options.RequestID != nil { + req.Raw().Header["x-ms-client-request-id"] = []string{*options.RequestID} + } + req.Raw().Header["x-ms-version"] = []string{"2020-10-02"} + if cpkInfo != nil && cpkInfo.EncryptionKey != nil { + req.Raw().Header["x-ms-encryption-key"] = []string{*cpkInfo.EncryptionKey} + } + if cpkInfo != nil && cpkInfo.EncryptionKeySHA256 != nil { + req.Raw().Header["x-ms-encryption-key-sha256"] = []string{*cpkInfo.EncryptionKeySHA256} + } + if cpkInfo != nil && cpkInfo.EncryptionAlgorithm != nil { + req.Raw().Header["x-ms-encryption-algorithm"] = []string{"AES256"} + } + req.Raw().Header["Accept"] = []string{"application/json"} + return req, nil +} + +// flushDataHandleResponse handles the FlushData response. +func (client *PathClient) flushDataHandleResponse(resp *http.Response) (PathClientFlushDataResponse, error) { + result := PathClientFlushDataResponse{} + if val := resp.Header.Get("Date"); val != "" { + date, err := time.Parse(time.RFC1123, val) + if err != nil { + return PathClientFlushDataResponse{}, err + } + result.Date = &date + } + if val := resp.Header.Get("ETag"); val != "" { + result.ETag = &val + } + if val := resp.Header.Get("Last-Modified"); val != "" { + lastModified, err := time.Parse(time.RFC1123, val) + if err != nil { + return PathClientFlushDataResponse{}, err + } + result.LastModified = &lastModified + } + if val := resp.Header.Get("Content-Length"); val != "" { + contentLength, err := strconv.ParseInt(val, 10, 64) + if err != nil { + return PathClientFlushDataResponse{}, err + } + result.ContentLength = &contentLength + } + if val := resp.Header.Get("x-ms-client-request-id"); val != "" { + result.ClientRequestID = &val + } + if val := resp.Header.Get("x-ms-request-id"); val != "" { + result.RequestID = &val + } + if val := resp.Header.Get("x-ms-version"); val != "" { + result.Version = &val + } + if val := resp.Header.Get("x-ms-request-server-encrypted"); val != "" { + isServerEncrypted, err := strconv.ParseBool(val) + if err != nil { + return PathClientFlushDataResponse{}, err + } + result.IsServerEncrypted = &isServerEncrypted + } + if val := resp.Header.Get("x-ms-encryption-key-sha256"); val != "" { + result.EncryptionKeySHA256 = &val + } + return result, nil +} + +// GetProperties - Get Properties returns all system and user defined properties for a path. Get Status returns all system +// defined properties for a path. Get Access Control List returns the access control list for a +// path. This operation supports conditional HTTP requests. For more information, see Specifying Conditional Headers for Blob +// Service Operations +// [https://docs.microsoft.com/en-us/rest/api/storageservices/specifying-conditional-headers-for-blob-service-operations]. +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2020-10-02 +// - options - PathClientGetPropertiesOptions contains the optional parameters for the PathClient.GetProperties method. +// - LeaseAccessConditions - LeaseAccessConditions contains a group of parameters for the PathClient.Create method. +// - ModifiedAccessConditions - ModifiedAccessConditions contains a group of parameters for the FileSystemClient.SetProperties +// method. +func (client *PathClient) GetProperties(ctx context.Context, options *PathClientGetPropertiesOptions, leaseAccessConditions *LeaseAccessConditions, modifiedAccessConditions *ModifiedAccessConditions) (PathClientGetPropertiesResponse, error) { + req, err := client.getPropertiesCreateRequest(ctx, options, leaseAccessConditions, modifiedAccessConditions) + if err != nil { + return PathClientGetPropertiesResponse{}, err + } + resp, err := client.pl.Do(req) + if err != nil { + return PathClientGetPropertiesResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusOK) { + return PathClientGetPropertiesResponse{}, runtime.NewResponseError(resp) + } + return client.getPropertiesHandleResponse(resp) +} + +// getPropertiesCreateRequest creates the GetProperties request. +func (client *PathClient) getPropertiesCreateRequest(ctx context.Context, options *PathClientGetPropertiesOptions, leaseAccessConditions *LeaseAccessConditions, modifiedAccessConditions *ModifiedAccessConditions) (*policy.Request, error) { + req, err := runtime.NewRequest(ctx, http.MethodHead, client.endpoint) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + if options != nil && options.Timeout != nil { + reqQP.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + } + if options != nil && options.Action != nil { + reqQP.Set("action", string(*options.Action)) + } + if options != nil && options.Upn != nil { + reqQP.Set("upn", strconv.FormatBool(*options.Upn)) + } + req.Raw().URL.RawQuery = reqQP.Encode() + if options != nil && options.RequestID != nil { + req.Raw().Header["x-ms-client-request-id"] = []string{*options.RequestID} + } + req.Raw().Header["x-ms-version"] = []string{"2020-10-02"} + if leaseAccessConditions != nil && leaseAccessConditions.LeaseID != nil { + req.Raw().Header["x-ms-lease-id"] = []string{*leaseAccessConditions.LeaseID} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfMatch != nil { + req.Raw().Header["If-Match"] = []string{*modifiedAccessConditions.IfMatch} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfNoneMatch != nil { + req.Raw().Header["If-None-Match"] = []string{*modifiedAccessConditions.IfNoneMatch} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfModifiedSince != nil { + req.Raw().Header["If-Modified-Since"] = []string{modifiedAccessConditions.IfModifiedSince.Format(time.RFC1123)} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfUnmodifiedSince != nil { + req.Raw().Header["If-Unmodified-Since"] = []string{modifiedAccessConditions.IfUnmodifiedSince.Format(time.RFC1123)} + } + req.Raw().Header["Accept"] = []string{"application/json"} + return req, nil +} + +// getPropertiesHandleResponse handles the GetProperties response. +func (client *PathClient) getPropertiesHandleResponse(resp *http.Response) (PathClientGetPropertiesResponse, error) { + result := PathClientGetPropertiesResponse{} + if val := resp.Header.Get("Accept-Ranges"); val != "" { + result.AcceptRanges = &val + } + if val := resp.Header.Get("Cache-Control"); val != "" { + result.CacheControl = &val + } + if val := resp.Header.Get("Content-Disposition"); val != "" { + result.ContentDisposition = &val + } + if val := resp.Header.Get("Content-Encoding"); val != "" { + result.ContentEncoding = &val + } + if val := resp.Header.Get("Content-Language"); val != "" { + result.ContentLanguage = &val + } + if val := resp.Header.Get("Content-Length"); val != "" { + contentLength, err := strconv.ParseInt(val, 10, 64) + if err != nil { + return PathClientGetPropertiesResponse{}, err + } + result.ContentLength = &contentLength + } + if val := resp.Header.Get("Content-Range"); val != "" { + result.ContentRange = &val + } + if val := resp.Header.Get("Content-Type"); val != "" { + result.ContentType = &val + } + if val := resp.Header.Get("Content-MD5"); val != "" { + result.ContentMD5 = &val + } + if val := resp.Header.Get("Date"); val != "" { + date, err := time.Parse(time.RFC1123, val) + if err != nil { + return PathClientGetPropertiesResponse{}, err + } + result.Date = &date + } + if val := resp.Header.Get("ETag"); val != "" { + result.ETag = &val + } + if val := resp.Header.Get("Last-Modified"); val != "" { + lastModified, err := time.Parse(time.RFC1123, val) + if err != nil { + return PathClientGetPropertiesResponse{}, err + } + result.LastModified = &lastModified + } + if val := resp.Header.Get("x-ms-request-id"); val != "" { + result.RequestID = &val + } + if val := resp.Header.Get("x-ms-version"); val != "" { + result.Version = &val + } + if val := resp.Header.Get("x-ms-resource-type"); val != "" { + result.ResourceType = &val + } + if val := resp.Header.Get("x-ms-properties"); val != "" { + result.Properties = &val + } + if val := resp.Header.Get("x-ms-owner"); val != "" { + result.Owner = &val + } + if val := resp.Header.Get("x-ms-group"); val != "" { + result.Group = &val + } + if val := resp.Header.Get("x-ms-permissions"); val != "" { + result.Permissions = &val + } + if val := resp.Header.Get("x-ms-acl"); val != "" { + result.ACL = &val + } + if val := resp.Header.Get("x-ms-lease-duration"); val != "" { + result.LeaseDuration = &val + } + if val := resp.Header.Get("x-ms-lease-state"); val != "" { + result.LeaseState = &val + } + if val := resp.Header.Get("x-ms-lease-status"); val != "" { + result.LeaseStatus = &val + } + return result, nil +} + +// Lease - Create and manage a lease to restrict write and delete access to the path. This operation supports conditional +// HTTP requests. For more information, see Specifying Conditional Headers for Blob Service +// Operations [https://docs.microsoft.com/en-us/rest/api/storageservices/specifying-conditional-headers-for-blob-service-operations]. +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2020-10-02 +// - xmsLeaseAction - There are five lease actions: "acquire", "break", "change", "renew", and "release". Use "acquire" and +// specify the "x-ms-proposed-lease-id" and "x-ms-lease-duration" to acquire a new lease. Use "break" +// to break an existing lease. When a lease is broken, the lease break period is allowed to elapse, during which time no lease +// operation except break and release can be performed on the file. When a +// lease is successfully broken, the response indicates the interval in seconds until a new lease can be acquired. Use "change" +// and specify the current lease ID in "x-ms-lease-id" and the new lease ID in +// "x-ms-proposed-lease-id" to change the lease ID of an active lease. Use "renew" and specify the "x-ms-lease-id" to renew +// an existing lease. Use "release" and specify the "x-ms-lease-id" to release a +// lease. +// - options - PathClientLeaseOptions contains the optional parameters for the PathClient.Lease method. +// - LeaseAccessConditions - LeaseAccessConditions contains a group of parameters for the PathClient.Create method. +// - ModifiedAccessConditions - ModifiedAccessConditions contains a group of parameters for the FileSystemClient.SetProperties +// method. +func (client *PathClient) Lease(ctx context.Context, xmsLeaseAction PathLeaseAction, options *PathClientLeaseOptions, leaseAccessConditions *LeaseAccessConditions, modifiedAccessConditions *ModifiedAccessConditions) (PathClientLeaseResponse, error) { + req, err := client.leaseCreateRequest(ctx, xmsLeaseAction, options, leaseAccessConditions, modifiedAccessConditions) + if err != nil { + return PathClientLeaseResponse{}, err + } + resp, err := client.pl.Do(req) + if err != nil { + return PathClientLeaseResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusOK, http.StatusCreated, http.StatusAccepted) { + return PathClientLeaseResponse{}, runtime.NewResponseError(resp) + } + return client.leaseHandleResponse(resp) +} + +// leaseCreateRequest creates the Lease request. +func (client *PathClient) leaseCreateRequest(ctx context.Context, xmsLeaseAction PathLeaseAction, options *PathClientLeaseOptions, leaseAccessConditions *LeaseAccessConditions, modifiedAccessConditions *ModifiedAccessConditions) (*policy.Request, error) { + req, err := runtime.NewRequest(ctx, http.MethodPost, client.endpoint) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + if options != nil && options.Timeout != nil { + reqQP.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + } + req.Raw().URL.RawQuery = reqQP.Encode() + if options != nil && options.RequestID != nil { + req.Raw().Header["x-ms-client-request-id"] = []string{*options.RequestID} + } + req.Raw().Header["x-ms-version"] = []string{"2020-10-02"} + req.Raw().Header["x-ms-lease-action"] = []string{string(xmsLeaseAction)} + if options != nil && options.XMSLeaseDuration != nil { + req.Raw().Header["x-ms-lease-duration"] = []string{strconv.FormatInt(int64(*options.XMSLeaseDuration), 10)} + } + if options != nil && options.XMSLeaseBreakPeriod != nil { + req.Raw().Header["x-ms-lease-break-period"] = []string{strconv.FormatInt(int64(*options.XMSLeaseBreakPeriod), 10)} + } + if leaseAccessConditions != nil && leaseAccessConditions.LeaseID != nil { + req.Raw().Header["x-ms-lease-id"] = []string{*leaseAccessConditions.LeaseID} + } + if options != nil && options.ProposedLeaseID != nil { + req.Raw().Header["x-ms-proposed-lease-id"] = []string{*options.ProposedLeaseID} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfMatch != nil { + req.Raw().Header["If-Match"] = []string{*modifiedAccessConditions.IfMatch} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfNoneMatch != nil { + req.Raw().Header["If-None-Match"] = []string{*modifiedAccessConditions.IfNoneMatch} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfModifiedSince != nil { + req.Raw().Header["If-Modified-Since"] = []string{modifiedAccessConditions.IfModifiedSince.Format(time.RFC1123)} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfUnmodifiedSince != nil { + req.Raw().Header["If-Unmodified-Since"] = []string{modifiedAccessConditions.IfUnmodifiedSince.Format(time.RFC1123)} + } + req.Raw().Header["Accept"] = []string{"application/json"} + return req, nil +} + +// leaseHandleResponse handles the Lease response. +func (client *PathClient) leaseHandleResponse(resp *http.Response) (PathClientLeaseResponse, error) { + result := PathClientLeaseResponse{} + if val := resp.Header.Get("Date"); val != "" { + date, err := time.Parse(time.RFC1123, val) + if err != nil { + return PathClientLeaseResponse{}, err + } + result.Date = &date + } + if val := resp.Header.Get("ETag"); val != "" { + result.ETag = &val + } + if val := resp.Header.Get("Last-Modified"); val != "" { + lastModified, err := time.Parse(time.RFC1123, val) + if err != nil { + return PathClientLeaseResponse{}, err + } + result.LastModified = &lastModified + } + if val := resp.Header.Get("x-ms-request-id"); val != "" { + result.RequestID = &val + } + if val := resp.Header.Get("x-ms-version"); val != "" { + result.Version = &val + } + if val := resp.Header.Get("x-ms-lease-id"); val != "" { + result.LeaseID = &val + } + if val := resp.Header.Get("x-ms-lease-time"); val != "" { + result.LeaseTime = &val + } + return result, nil +} + +// Read - Read the contents of a file. For read operations, range requests are supported. This operation supports conditional +// HTTP requests. For more information, see Specifying Conditional Headers for Blob +// Service Operations [https://docs.microsoft.com/en-us/rest/api/storageservices/specifying-conditional-headers-for-blob-service-operations]. +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2020-10-02 +// - options - PathClientReadOptions contains the optional parameters for the PathClient.Read method. +// - LeaseAccessConditions - LeaseAccessConditions contains a group of parameters for the PathClient.Create method. +// - ModifiedAccessConditions - ModifiedAccessConditions contains a group of parameters for the FileSystemClient.SetProperties +// method. +// - CpkInfo - CpkInfo contains a group of parameters for the PathClient.Create method. +func (client *PathClient) Read(ctx context.Context, options *PathClientReadOptions, leaseAccessConditions *LeaseAccessConditions, modifiedAccessConditions *ModifiedAccessConditions, cpkInfo *CpkInfo) (PathClientReadResponse, error) { + req, err := client.readCreateRequest(ctx, options, leaseAccessConditions, modifiedAccessConditions, cpkInfo) + if err != nil { + return PathClientReadResponse{}, err + } + resp, err := client.pl.Do(req) + if err != nil { + return PathClientReadResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusOK, http.StatusPartialContent) { + return PathClientReadResponse{}, runtime.NewResponseError(resp) + } + return client.readHandleResponse(resp) +} + +// readCreateRequest creates the Read request. +func (client *PathClient) readCreateRequest(ctx context.Context, options *PathClientReadOptions, leaseAccessConditions *LeaseAccessConditions, modifiedAccessConditions *ModifiedAccessConditions, cpkInfo *CpkInfo) (*policy.Request, error) { + req, err := runtime.NewRequest(ctx, http.MethodGet, client.endpoint) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + if options != nil && options.Timeout != nil { + reqQP.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + } + req.Raw().URL.RawQuery = reqQP.Encode() + runtime.SkipBodyDownload(req) + if options != nil && options.RequestID != nil { + req.Raw().Header["x-ms-client-request-id"] = []string{*options.RequestID} + } + req.Raw().Header["x-ms-version"] = []string{"2020-10-02"} + if options != nil && options.Range != nil { + req.Raw().Header["Range"] = []string{*options.Range} + } + if leaseAccessConditions != nil && leaseAccessConditions.LeaseID != nil { + req.Raw().Header["x-ms-lease-id"] = []string{*leaseAccessConditions.LeaseID} + } + if options != nil && options.XMSRangeGetContentMD5 != nil { + req.Raw().Header["x-ms-range-get-content-md5"] = []string{strconv.FormatBool(*options.XMSRangeGetContentMD5)} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfMatch != nil { + req.Raw().Header["If-Match"] = []string{*modifiedAccessConditions.IfMatch} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfNoneMatch != nil { + req.Raw().Header["If-None-Match"] = []string{*modifiedAccessConditions.IfNoneMatch} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfModifiedSince != nil { + req.Raw().Header["If-Modified-Since"] = []string{modifiedAccessConditions.IfModifiedSince.Format(time.RFC1123)} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfUnmodifiedSince != nil { + req.Raw().Header["If-Unmodified-Since"] = []string{modifiedAccessConditions.IfUnmodifiedSince.Format(time.RFC1123)} + } + if cpkInfo != nil && cpkInfo.EncryptionKey != nil { + req.Raw().Header["x-ms-encryption-key"] = []string{*cpkInfo.EncryptionKey} + } + if cpkInfo != nil && cpkInfo.EncryptionKeySHA256 != nil { + req.Raw().Header["x-ms-encryption-key-sha256"] = []string{*cpkInfo.EncryptionKeySHA256} + } + if cpkInfo != nil && cpkInfo.EncryptionAlgorithm != nil { + req.Raw().Header["x-ms-encryption-algorithm"] = []string{"AES256"} + } + req.Raw().Header["Accept"] = []string{"application/json"} + return req, nil +} + +// readHandleResponse handles the Read response. +func (client *PathClient) readHandleResponse(resp *http.Response) (PathClientReadResponse, error) { + result := PathClientReadResponse{Body: resp.Body} + if val := resp.Header.Get("Accept-Ranges"); val != "" { + result.AcceptRanges = &val + } + if val := resp.Header.Get("Cache-Control"); val != "" { + result.CacheControl = &val + } + if val := resp.Header.Get("Content-Disposition"); val != "" { + result.ContentDisposition = &val + } + if val := resp.Header.Get("Content-Encoding"); val != "" { + result.ContentEncoding = &val + } + if val := resp.Header.Get("Content-Language"); val != "" { + result.ContentLanguage = &val + } + if val := resp.Header.Get("Content-Length"); val != "" { + contentLength, err := strconv.ParseInt(val, 10, 64) + if err != nil { + return PathClientReadResponse{}, err + } + result.ContentLength = &contentLength + } + if val := resp.Header.Get("Content-Range"); val != "" { + result.ContentRange = &val + } + if val := resp.Header.Get("Content-Type"); val != "" { + result.ContentType = &val + } + if val := resp.Header.Get("Content-MD5"); val != "" { + result.ContentMD5 = &val + } + if val := resp.Header.Get("Date"); val != "" { + date, err := time.Parse(time.RFC1123, val) + if err != nil { + return PathClientReadResponse{}, err + } + result.Date = &date + } + if val := resp.Header.Get("ETag"); val != "" { + result.ETag = &val + } + if val := resp.Header.Get("Last-Modified"); val != "" { + lastModified, err := time.Parse(time.RFC1123, val) + if err != nil { + return PathClientReadResponse{}, err + } + result.LastModified = &lastModified + } + if val := resp.Header.Get("x-ms-request-id"); val != "" { + result.RequestID = &val + } + if val := resp.Header.Get("x-ms-version"); val != "" { + result.Version = &val + } + if val := resp.Header.Get("x-ms-resource-type"); val != "" { + result.ResourceType = &val + } + if val := resp.Header.Get("x-ms-properties"); val != "" { + result.Properties = &val + } + if val := resp.Header.Get("x-ms-lease-duration"); val != "" { + result.LeaseDuration = &val + } + if val := resp.Header.Get("x-ms-lease-state"); val != "" { + result.LeaseState = &val + } + if val := resp.Header.Get("x-ms-lease-status"); val != "" { + result.LeaseStatus = &val + } + if val := resp.Header.Get("x-ms-request-server-encrypted"); val != "" { + isServerEncrypted, err := strconv.ParseBool(val) + if err != nil { + return PathClientReadResponse{}, err + } + result.IsServerEncrypted = &isServerEncrypted + } + if val := resp.Header.Get("x-ms-encryption-key-sha256"); val != "" { + result.EncryptionKeySHA256 = &val + } + if val := resp.Header.Get("x-ms-content-md5"); val != "" { + result.XMSContentMD5 = &val + } + return result, nil +} + +// SetAccessControl - Set the owner, group, permissions, or access control list for a path. +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2020-10-02 +// - options - PathClientSetAccessControlOptions contains the optional parameters for the PathClient.SetAccessControl method. +// - LeaseAccessConditions - LeaseAccessConditions contains a group of parameters for the PathClient.Create method. +// - ModifiedAccessConditions - ModifiedAccessConditions contains a group of parameters for the FileSystemClient.SetProperties +// method. +func (client *PathClient) SetAccessControl(ctx context.Context, options *PathClientSetAccessControlOptions, leaseAccessConditions *LeaseAccessConditions, modifiedAccessConditions *ModifiedAccessConditions) (PathClientSetAccessControlResponse, error) { + req, err := client.setAccessControlCreateRequest(ctx, options, leaseAccessConditions, modifiedAccessConditions) + if err != nil { + return PathClientSetAccessControlResponse{}, err + } + resp, err := client.pl.Do(req) + if err != nil { + return PathClientSetAccessControlResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusOK) { + return PathClientSetAccessControlResponse{}, runtime.NewResponseError(resp) + } + return client.setAccessControlHandleResponse(resp) +} + +// setAccessControlCreateRequest creates the SetAccessControl request. +func (client *PathClient) setAccessControlCreateRequest(ctx context.Context, options *PathClientSetAccessControlOptions, leaseAccessConditions *LeaseAccessConditions, modifiedAccessConditions *ModifiedAccessConditions) (*policy.Request, error) { + req, err := runtime.NewRequest(ctx, http.MethodPatch, client.endpoint) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("action", "setAccessControl") + if options != nil && options.Timeout != nil { + reqQP.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + } + req.Raw().URL.RawQuery = reqQP.Encode() + if leaseAccessConditions != nil && leaseAccessConditions.LeaseID != nil { + req.Raw().Header["x-ms-lease-id"] = []string{*leaseAccessConditions.LeaseID} + } + if options != nil && options.Owner != nil { + req.Raw().Header["x-ms-owner"] = []string{*options.Owner} + } + if options != nil && options.Group != nil { + req.Raw().Header["x-ms-group"] = []string{*options.Group} + } + if options != nil && options.Permissions != nil { + req.Raw().Header["x-ms-permissions"] = []string{*options.Permissions} + } + if options != nil && options.ACL != nil { + req.Raw().Header["x-ms-acl"] = []string{*options.ACL} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfMatch != nil { + req.Raw().Header["If-Match"] = []string{*modifiedAccessConditions.IfMatch} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfNoneMatch != nil { + req.Raw().Header["If-None-Match"] = []string{*modifiedAccessConditions.IfNoneMatch} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfModifiedSince != nil { + req.Raw().Header["If-Modified-Since"] = []string{modifiedAccessConditions.IfModifiedSince.Format(time.RFC1123)} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfUnmodifiedSince != nil { + req.Raw().Header["If-Unmodified-Since"] = []string{modifiedAccessConditions.IfUnmodifiedSince.Format(time.RFC1123)} + } + if options != nil && options.RequestID != nil { + req.Raw().Header["x-ms-client-request-id"] = []string{*options.RequestID} + } + req.Raw().Header["x-ms-version"] = []string{"2020-10-02"} + req.Raw().Header["Accept"] = []string{"application/json"} + return req, nil +} + +// setAccessControlHandleResponse handles the SetAccessControl response. +func (client *PathClient) setAccessControlHandleResponse(resp *http.Response) (PathClientSetAccessControlResponse, error) { + result := PathClientSetAccessControlResponse{} + if val := resp.Header.Get("Date"); val != "" { + date, err := time.Parse(time.RFC1123, val) + if err != nil { + return PathClientSetAccessControlResponse{}, err + } + result.Date = &date + } + if val := resp.Header.Get("ETag"); val != "" { + result.ETag = &val + } + if val := resp.Header.Get("Last-Modified"); val != "" { + lastModified, err := time.Parse(time.RFC1123, val) + if err != nil { + return PathClientSetAccessControlResponse{}, err + } + result.LastModified = &lastModified + } + if val := resp.Header.Get("x-ms-client-request-id"); val != "" { + result.ClientRequestID = &val + } + if val := resp.Header.Get("x-ms-request-id"); val != "" { + result.RequestID = &val + } + if val := resp.Header.Get("x-ms-version"); val != "" { + result.Version = &val + } + return result, nil +} + +// SetAccessControlRecursive - Set the access control list for a path and sub-paths. +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2020-10-02 +// - mode - Mode "set" sets POSIX access control rights on files and directories, "modify" modifies one or more POSIX access +// control rights that pre-exist on files and directories, "remove" removes one or more +// POSIX access control rights that were present earlier on files and directories +// - 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) + if err != nil { + return PathClientSetAccessControlRecursiveResponse{}, err + } + resp, err := client.pl.Do(req) + if err != nil { + return PathClientSetAccessControlRecursiveResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusOK) { + return PathClientSetAccessControlRecursiveResponse{}, runtime.NewResponseError(resp) + } + return client.setAccessControlRecursiveHandleResponse(resp) +} + +// 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 + } + reqQP := req.Raw().URL.Query() + reqQP.Set("action", "setAccessControlRecursive") + if options != nil && options.Timeout != nil { + reqQP.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + } + if options != nil && options.Continuation != nil { + reqQP.Set("continuation", *options.Continuation) + } + reqQP.Set("mode", string(mode)) + if options != nil && options.ForceFlag != nil { + reqQP.Set("forceFlag", strconv.FormatBool(*options.ForceFlag)) + } + if options != nil && options.MaxRecords != nil { + reqQP.Set("maxRecords", strconv.FormatInt(int64(*options.MaxRecords), 10)) + } + req.Raw().URL.RawQuery = reqQP.Encode() + if options != nil && options.ACL != nil { + req.Raw().Header["x-ms-acl"] = []string{*options.ACL} + } + if options != nil && options.RequestID != nil { + req.Raw().Header["x-ms-client-request-id"] = []string{*options.RequestID} + } + req.Raw().Header["x-ms-version"] = []string{"2020-10-02"} + req.Raw().Header["Accept"] = []string{"application/json"} + return req, nil +} + +// 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) + if err != nil { + return PathClientSetAccessControlRecursiveResponse{}, err + } + result.Date = &date + } + if val := resp.Header.Get("x-ms-client-request-id"); val != "" { + result.ClientRequestID = &val + } + if val := resp.Header.Get("x-ms-continuation"); val != "" { + result.Continuation = &val + } + if val := resp.Header.Get("x-ms-request-id"); val != "" { + result.RequestID = &val + } + if val := resp.Header.Get("x-ms-version"); val != "" { + result.Version = &val + } + if err := runtime.UnmarshalAsJSON(resp, &result.SetAccessControlRecursiveResponse); err != nil { + return PathClientSetAccessControlRecursiveResponse{}, err + } + return result, nil +} + +// SetExpiry - Sets the time a blob will expire and be deleted. +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2020-10-02 +// - expiryOptions - Required. Indicates mode of the expiry time +// - options - PathClientSetExpiryOptions contains the optional parameters for the PathClient.SetExpiry method. +func (client *PathClient) SetExpiry(ctx context.Context, expiryOptions PathExpiryOptions, options *PathClientSetExpiryOptions) (PathClientSetExpiryResponse, error) { + req, err := client.setExpiryCreateRequest(ctx, expiryOptions, options) + if err != nil { + return PathClientSetExpiryResponse{}, err + } + resp, err := client.pl.Do(req) + if err != nil { + return PathClientSetExpiryResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusOK) { + return PathClientSetExpiryResponse{}, runtime.NewResponseError(resp) + } + return client.setExpiryHandleResponse(resp) +} + +// setExpiryCreateRequest creates the SetExpiry request. +func (client *PathClient) setExpiryCreateRequest(ctx context.Context, expiryOptions PathExpiryOptions, options *PathClientSetExpiryOptions) (*policy.Request, error) { + req, err := runtime.NewRequest(ctx, http.MethodPut, client.endpoint) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("comp", "expiry") + if options != nil && options.Timeout != nil { + reqQP.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + } + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["x-ms-version"] = []string{"2020-10-02"} + if options != nil && options.RequestID != nil { + req.Raw().Header["x-ms-client-request-id"] = []string{*options.RequestID} + } + req.Raw().Header["x-ms-expiry-option"] = []string{string(expiryOptions)} + if options != nil && options.ExpiresOn != nil { + req.Raw().Header["x-ms-expiry-time"] = []string{*options.ExpiresOn} + } + req.Raw().Header["Accept"] = []string{"application/json"} + return req, nil +} + +// setExpiryHandleResponse handles the SetExpiry response. +func (client *PathClient) setExpiryHandleResponse(resp *http.Response) (PathClientSetExpiryResponse, error) { + result := PathClientSetExpiryResponse{} + if val := resp.Header.Get("ETag"); val != "" { + result.ETag = &val + } + if val := resp.Header.Get("Last-Modified"); val != "" { + lastModified, err := time.Parse(time.RFC1123, val) + if err != nil { + return PathClientSetExpiryResponse{}, err + } + result.LastModified = &lastModified + } + if val := resp.Header.Get("x-ms-client-request-id"); val != "" { + result.ClientRequestID = &val + } + if val := resp.Header.Get("x-ms-request-id"); val != "" { + result.RequestID = &val + } + if val := resp.Header.Get("x-ms-version"); val != "" { + result.Version = &val + } + if val := resp.Header.Get("Date"); val != "" { + date, err := time.Parse(time.RFC1123, val) + if err != nil { + return PathClientSetExpiryResponse{}, err + } + result.Date = &date + } + return result, nil +} + +// Undelete - Undelete a path that was previously soft deleted +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2020-10-02 +// - options - PathClientUndeleteOptions contains the optional parameters for the PathClient.Undelete method. +func (client *PathClient) Undelete(ctx context.Context, options *PathClientUndeleteOptions) (PathClientUndeleteResponse, error) { + req, err := client.undeleteCreateRequest(ctx, options) + if err != nil { + return PathClientUndeleteResponse{}, err + } + resp, err := client.pl.Do(req) + if err != nil { + return PathClientUndeleteResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusOK) { + return PathClientUndeleteResponse{}, runtime.NewResponseError(resp) + } + return client.undeleteHandleResponse(resp) +} + +// undeleteCreateRequest creates the Undelete request. +func (client *PathClient) undeleteCreateRequest(ctx context.Context, options *PathClientUndeleteOptions) (*policy.Request, error) { + req, err := runtime.NewRequest(ctx, http.MethodPut, client.endpoint) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("comp", "undelete") + if options != nil && options.Timeout != nil { + reqQP.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + } + req.Raw().URL.RawQuery = reqQP.Encode() + if options != nil && options.UndeleteSource != nil { + req.Raw().Header["x-ms-undelete-source"] = []string{*options.UndeleteSource} + } + req.Raw().Header["x-ms-version"] = []string{"2020-10-02"} + if options != nil && options.RequestID != nil { + req.Raw().Header["x-ms-client-request-id"] = []string{*options.RequestID} + } + req.Raw().Header["Accept"] = []string{"application/json"} + return req, nil +} + +// undeleteHandleResponse handles the Undelete response. +func (client *PathClient) undeleteHandleResponse(resp *http.Response) (PathClientUndeleteResponse, error) { + result := PathClientUndeleteResponse{} + if val := resp.Header.Get("x-ms-client-request-id"); val != "" { + result.ClientRequestID = &val + } + if val := resp.Header.Get("x-ms-request-id"); val != "" { + result.RequestID = &val + } + if val := resp.Header.Get("x-ms-resource-type"); val != "" { + result.ResourceType = &val + } + if val := resp.Header.Get("x-ms-version"); val != "" { + result.Version = &val + } + if val := resp.Header.Get("Date"); val != "" { + date, err := time.Parse(time.RFC1123, val) + if err != nil { + return PathClientUndeleteResponse{}, err + } + result.Date = &date + } + return result, nil +} + +// Update - Uploads data to be appended to a file, flushes (writes) previously uploaded data to a file, sets properties for +// a file or directory, or sets access control for a file or directory. Data can only be +// appended to a file. Concurrent writes to the same file using multiple clients are not supported. This operation supports +// conditional HTTP requests. For more information, see Specifying Conditional +// Headers for Blob Service Operations [https://docs.microsoft.com/en-us/rest/api/storageservices/specifying-conditional-headers-for-blob-service-operations]. +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2020-10-02 +// - action - The action must be "append" to upload data to be appended to a file, "flush" to flush previously uploaded data +// to a file, "setProperties" to set the properties of a file or directory, +// "setAccessControl" to set the owner, group, permissions, or access control list for a file or directory, or "setAccessControlRecursive" +// to set the access control list for a directory recursively. Note +// that Hierarchical Namespace must be enabled for the account in order to use access control. Also note that the Access Control +// List (ACL) includes permissions for the owner, owning group, and others, +// so the x-ms-permissions and x-ms-acl request headers are mutually exclusive. +// - mode - Mode "set" sets POSIX access control rights on files and directories, "modify" modifies one or more POSIX access +// control rights that pre-exist on files and directories, "remove" removes one or more +// POSIX access control rights that were present earlier on files and directories +// - body - Initial data +// - options - PathClientUpdateOptions contains the optional parameters for the PathClient.Update method. +// - PathHTTPHeaders - PathHTTPHeaders contains a group of parameters for the PathClient.Create method. +// - LeaseAccessConditions - LeaseAccessConditions contains a group of parameters for the PathClient.Create method. +// - ModifiedAccessConditions - ModifiedAccessConditions contains a group of parameters for the FileSystemClient.SetProperties +// method. +func (client *PathClient) Update(ctx context.Context, action PathUpdateAction, mode PathSetAccessControlRecursiveMode, body io.ReadSeekCloser, options *PathClientUpdateOptions, pathHTTPHeaders *PathHTTPHeaders, leaseAccessConditions *LeaseAccessConditions, modifiedAccessConditions *ModifiedAccessConditions) (PathClientUpdateResponse, error) { + req, err := client.updateCreateRequest(ctx, action, mode, body, options, pathHTTPHeaders, leaseAccessConditions, modifiedAccessConditions) + if err != nil { + return PathClientUpdateResponse{}, err + } + resp, err := client.pl.Do(req) + if err != nil { + return PathClientUpdateResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusOK, http.StatusAccepted) { + return PathClientUpdateResponse{}, runtime.NewResponseError(resp) + } + return client.updateHandleResponse(resp) +} + +// updateCreateRequest creates the Update request. +func (client *PathClient) updateCreateRequest(ctx context.Context, action PathUpdateAction, mode PathSetAccessControlRecursiveMode, body io.ReadSeekCloser, options *PathClientUpdateOptions, pathHTTPHeaders *PathHTTPHeaders, leaseAccessConditions *LeaseAccessConditions, modifiedAccessConditions *ModifiedAccessConditions) (*policy.Request, error) { + req, err := runtime.NewRequest(ctx, http.MethodPatch, client.endpoint) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + if options != nil && options.Timeout != nil { + reqQP.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + } + reqQP.Set("action", string(action)) + if options != nil && options.MaxRecords != nil { + reqQP.Set("maxRecords", strconv.FormatInt(int64(*options.MaxRecords), 10)) + } + if options != nil && options.Continuation != nil { + reqQP.Set("continuation", *options.Continuation) + } + reqQP.Set("mode", string(mode)) + if options != nil && options.ForceFlag != nil { + reqQP.Set("forceFlag", strconv.FormatBool(*options.ForceFlag)) + } + if options != nil && options.Position != nil { + reqQP.Set("position", strconv.FormatInt(*options.Position, 10)) + } + if options != nil && options.RetainUncommittedData != nil { + reqQP.Set("retainUncommittedData", strconv.FormatBool(*options.RetainUncommittedData)) + } + if options != nil && options.Close != nil { + reqQP.Set("close", strconv.FormatBool(*options.Close)) + } + req.Raw().URL.RawQuery = reqQP.Encode() + if options != nil && options.RequestID != nil { + req.Raw().Header["x-ms-client-request-id"] = []string{*options.RequestID} + } + req.Raw().Header["x-ms-version"] = []string{"2020-10-02"} + if options != nil && options.ContentLength != nil { + req.Raw().Header["Content-Length"] = []string{strconv.FormatInt(*options.ContentLength, 10)} + } + if pathHTTPHeaders != nil && pathHTTPHeaders.ContentMD5 != nil { + req.Raw().Header["x-ms-content-md5"] = []string{base64.StdEncoding.EncodeToString(pathHTTPHeaders.ContentMD5)} + } + if leaseAccessConditions != nil && leaseAccessConditions.LeaseID != nil { + req.Raw().Header["x-ms-lease-id"] = []string{*leaseAccessConditions.LeaseID} + } + if pathHTTPHeaders != nil && pathHTTPHeaders.CacheControl != nil { + req.Raw().Header["x-ms-cache-control"] = []string{*pathHTTPHeaders.CacheControl} + } + if pathHTTPHeaders != nil && pathHTTPHeaders.ContentType != nil { + req.Raw().Header["x-ms-content-type"] = []string{*pathHTTPHeaders.ContentType} + } + if pathHTTPHeaders != nil && pathHTTPHeaders.ContentDisposition != nil { + req.Raw().Header["x-ms-content-disposition"] = []string{*pathHTTPHeaders.ContentDisposition} + } + if pathHTTPHeaders != nil && pathHTTPHeaders.ContentEncoding != nil { + req.Raw().Header["x-ms-content-encoding"] = []string{*pathHTTPHeaders.ContentEncoding} + } + if pathHTTPHeaders != nil && pathHTTPHeaders.ContentLanguage != nil { + req.Raw().Header["x-ms-content-language"] = []string{*pathHTTPHeaders.ContentLanguage} + } + if options != nil && options.Properties != nil { + req.Raw().Header["x-ms-properties"] = []string{*options.Properties} + } + if options != nil && options.Owner != nil { + req.Raw().Header["x-ms-owner"] = []string{*options.Owner} + } + if options != nil && options.Group != nil { + req.Raw().Header["x-ms-group"] = []string{*options.Group} + } + if options != nil && options.Permissions != nil { + req.Raw().Header["x-ms-permissions"] = []string{*options.Permissions} + } + if options != nil && options.ACL != nil { + req.Raw().Header["x-ms-acl"] = []string{*options.ACL} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfMatch != nil { + req.Raw().Header["If-Match"] = []string{*modifiedAccessConditions.IfMatch} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfNoneMatch != nil { + req.Raw().Header["If-None-Match"] = []string{*modifiedAccessConditions.IfNoneMatch} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfModifiedSince != nil { + req.Raw().Header["If-Modified-Since"] = []string{modifiedAccessConditions.IfModifiedSince.Format(time.RFC1123)} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfUnmodifiedSince != nil { + req.Raw().Header["If-Unmodified-Since"] = []string{modifiedAccessConditions.IfUnmodifiedSince.Format(time.RFC1123)} + } + req.Raw().Header["Accept"] = []string{"application/json"} + return req, req.SetBody(body, "application/octet-stream") +} + +// updateHandleResponse handles the Update response. +func (client *PathClient) updateHandleResponse(resp *http.Response) (PathClientUpdateResponse, error) { + result := PathClientUpdateResponse{} + if val := resp.Header.Get("Date"); val != "" { + date, err := time.Parse(time.RFC1123, val) + if err != nil { + return PathClientUpdateResponse{}, err + } + result.Date = &date + } + if val := resp.Header.Get("ETag"); val != "" { + result.ETag = &val + } + if val := resp.Header.Get("Last-Modified"); val != "" { + lastModified, err := time.Parse(time.RFC1123, val) + if err != nil { + return PathClientUpdateResponse{}, err + } + result.LastModified = &lastModified + } + if val := resp.Header.Get("Accept-Ranges"); val != "" { + result.AcceptRanges = &val + } + if val := resp.Header.Get("Cache-Control"); val != "" { + result.CacheControl = &val + } + if val := resp.Header.Get("Content-Disposition"); val != "" { + result.ContentDisposition = &val + } + if val := resp.Header.Get("Content-Encoding"); val != "" { + result.ContentEncoding = &val + } + if val := resp.Header.Get("Content-Language"); val != "" { + result.ContentLanguage = &val + } + if val := resp.Header.Get("Content-Length"); val != "" { + contentLength, err := strconv.ParseInt(val, 10, 64) + if err != nil { + return PathClientUpdateResponse{}, err + } + result.ContentLength = &contentLength + } + if val := resp.Header.Get("Content-Range"); val != "" { + result.ContentRange = &val + } + if val := resp.Header.Get("Content-Type"); val != "" { + result.ContentType = &val + } + if val := resp.Header.Get("Content-MD5"); val != "" { + result.ContentMD5 = &val + } + if val := resp.Header.Get("x-ms-properties"); val != "" { + result.Properties = &val + } + if val := resp.Header.Get("x-ms-continuation"); val != "" { + result.XMSContinuation = &val + } + if val := resp.Header.Get("x-ms-request-id"); val != "" { + result.RequestID = &val + } + if val := resp.Header.Get("x-ms-version"); val != "" { + result.Version = &val + } + if err := runtime.UnmarshalAsJSON(resp, &result.SetAccessControlRecursiveResponse); err != nil { + return PathClientUpdateResponse{}, err + } + return result, nil +} diff --git a/sdk/storage/azdatalake/internal/generated/zz_response_types.go b/sdk/storage/azdatalake/internal/generated/zz_response_types.go new file mode 100644 index 000000000000..e95f5035e654 --- /dev/null +++ b/sdk/storage/azdatalake/internal/generated/zz_response_types.go @@ -0,0 +1,557 @@ +//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. +// Code generated by Microsoft (R) AutoRest Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. +// DO NOT EDIT. + +package generated + +import ( + "io" + "time" +) + +// FileSystemClientCreateResponse contains the response from method FileSystemClient.Create. +type FileSystemClientCreateResponse struct { + // ClientRequestID contains the information returned from the x-ms-request-id header response. + ClientRequestID *string + + // Date contains the information returned from the Date header response. + Date *time.Time + + // ETag contains the information returned from the ETag header response. + ETag *string + + // LastModified contains the information returned from the Last-Modified header response. + LastModified *time.Time + + // NamespaceEnabled contains the information returned from the x-ms-namespace-enabled header response. + NamespaceEnabled *string + + // Version contains the information returned from the x-ms-version header response. + Version *string +} + +// FileSystemClientDeleteResponse contains the response from method FileSystemClient.Delete. +type FileSystemClientDeleteResponse struct { + // Date contains the information returned from the Date header response. + Date *time.Time + + // RequestID contains the information returned from the x-ms-request-id header response. + RequestID *string + + // Version contains the information returned from the x-ms-version header response. + Version *string +} + +// FileSystemClientGetPropertiesResponse contains the response from method FileSystemClient.GetProperties. +type FileSystemClientGetPropertiesResponse struct { + // Date contains the information returned from the Date header response. + Date *time.Time + + // ETag contains the information returned from the ETag header response. + ETag *string + + // LastModified contains the information returned from the Last-Modified header response. + LastModified *time.Time + + // NamespaceEnabled contains the information returned from the x-ms-namespace-enabled header response. + NamespaceEnabled *string + + // Properties contains the information returned from the x-ms-properties header response. + Properties *string + + // RequestID contains the information returned from the x-ms-request-id header response. + RequestID *string + + // Version contains the information returned from the x-ms-version header response. + Version *string +} + +// FileSystemClientListBlobHierarchySegmentResponse contains the response from method FileSystemClient.NewListBlobHierarchySegmentPager. +type FileSystemClientListBlobHierarchySegmentResponse struct { + ListBlobsHierarchySegmentResponse + // ClientRequestID contains the information returned from the x-ms-client-request-id header response. + ClientRequestID *string `xml:"ClientRequestID"` + + // ContentType contains the information returned from the Content-Type header response. + ContentType *string `xml:"ContentType"` + + // Date contains the information returned from the Date header response. + Date *time.Time `xml:"Date"` + + // RequestID contains the information returned from the x-ms-request-id header response. + RequestID *string `xml:"RequestID"` + + // Version contains the information returned from the x-ms-version header response. + Version *string `xml:"Version"` +} + +// FileSystemClientListPathsResponse contains the response from method FileSystemClient.NewListPathsPager. +type FileSystemClientListPathsResponse struct { + PathList + // Continuation contains the information returned from the x-ms-continuation header response. + Continuation *string + + // Date contains the information returned from the Date header response. + Date *time.Time + + // ETag contains the information returned from the ETag header response. + ETag *string + + // LastModified contains the information returned from the Last-Modified header response. + LastModified *time.Time + + // RequestID contains the information returned from the x-ms-request-id header response. + RequestID *string + + // Version contains the information returned from the x-ms-version header response. + Version *string +} + +// FileSystemClientSetPropertiesResponse contains the response from method FileSystemClient.SetProperties. +type FileSystemClientSetPropertiesResponse struct { + // Date contains the information returned from the Date header response. + Date *time.Time + + // ETag contains the information returned from the ETag header response. + ETag *string + + // LastModified contains the information returned from the Last-Modified header response. + LastModified *time.Time + + // RequestID contains the information returned from the x-ms-request-id header response. + RequestID *string + + // Version contains the information returned from the x-ms-version header response. + Version *string +} + +// PathClientAppendDataResponse contains the response from method PathClient.AppendData. +type PathClientAppendDataResponse struct { + // ClientRequestID contains the information returned from the x-ms-client-request-id header response. + ClientRequestID *string + + // ContentMD5 contains the information returned from the Content-MD5 header response. + ContentMD5 []byte + + // Date contains the information returned from the Date header response. + Date *time.Time + + // ETag contains the information returned from the ETag header response. + ETag *string + + // EncryptionKeySHA256 contains the information returned from the x-ms-encryption-key-sha256 header response. + EncryptionKeySHA256 *string + + // IsServerEncrypted contains the information returned from the x-ms-request-server-encrypted header response. + IsServerEncrypted *bool + + // RequestID contains the information returned from the x-ms-request-id header response. + RequestID *string + + // Version contains the information returned from the x-ms-version header response. + Version *string + + // XMSContentCRC64 contains the information returned from the x-ms-content-crc64 header response. + XMSContentCRC64 []byte +} + +// PathClientCreateResponse contains the response from method PathClient.Create. +type PathClientCreateResponse struct { + // ContentLength contains the information returned from the Content-Length header response. + ContentLength *int64 + + // Continuation contains the information returned from the x-ms-continuation header response. + Continuation *string + + // Date contains the information returned from the Date header response. + Date *time.Time + + // ETag contains the information returned from the ETag header response. + ETag *string + + // EncryptionKeySHA256 contains the information returned from the x-ms-encryption-key-sha256 header response. + EncryptionKeySHA256 *string + + // IsServerEncrypted contains the information returned from the x-ms-request-server-encrypted header response. + IsServerEncrypted *bool + + // LastModified contains the information returned from the Last-Modified header response. + LastModified *time.Time + + // RequestID contains the information returned from the x-ms-request-id header response. + RequestID *string + + // Version contains the information returned from the x-ms-version header response. + Version *string +} + +// PathClientDeleteResponse contains the response from method PathClient.Delete. +type PathClientDeleteResponse struct { + // Continuation contains the information returned from the x-ms-continuation header response. + Continuation *string + + // Date contains the information returned from the Date header response. + Date *time.Time + + // DeletionID contains the information returned from the x-ms-deletion-id header response. + DeletionID *string + + // RequestID contains the information returned from the x-ms-request-id header response. + RequestID *string + + // Version contains the information returned from the x-ms-version header response. + Version *string +} + +// PathClientFlushDataResponse contains the response from method PathClient.FlushData. +type PathClientFlushDataResponse struct { + // ClientRequestID contains the information returned from the x-ms-client-request-id header response. + ClientRequestID *string + + // ContentLength contains the information returned from the Content-Length header response. + ContentLength *int64 + + // Date contains the information returned from the Date header response. + Date *time.Time + + // ETag contains the information returned from the ETag header response. + ETag *string + + // EncryptionKeySHA256 contains the information returned from the x-ms-encryption-key-sha256 header response. + EncryptionKeySHA256 *string + + // IsServerEncrypted contains the information returned from the x-ms-request-server-encrypted header response. + IsServerEncrypted *bool + + // LastModified contains the information returned from the Last-Modified header response. + LastModified *time.Time + + // RequestID contains the information returned from the x-ms-request-id header response. + RequestID *string + + // Version contains the information returned from the x-ms-version header response. + Version *string +} + +// PathClientGetPropertiesResponse contains the response from method PathClient.GetProperties. +type PathClientGetPropertiesResponse struct { + // ACL contains the information returned from the x-ms-acl header response. + ACL *string + + // AcceptRanges contains the information returned from the Accept-Ranges header response. + AcceptRanges *string + + // CacheControl contains the information returned from the Cache-Control header response. + CacheControl *string + + // ContentDisposition contains the information returned from the Content-Disposition header response. + ContentDisposition *string + + // ContentEncoding contains the information returned from the Content-Encoding header response. + ContentEncoding *string + + // ContentLanguage contains the information returned from the Content-Language header response. + ContentLanguage *string + + // ContentLength contains the information returned from the Content-Length header response. + ContentLength *int64 + + // ContentMD5 contains the information returned from the Content-MD5 header response. + ContentMD5 *string + + // ContentRange contains the information returned from the Content-Range header response. + ContentRange *string + + // ContentType contains the information returned from the Content-Type header response. + ContentType *string + + // Date contains the information returned from the Date header response. + Date *time.Time + + // ETag contains the information returned from the ETag header response. + ETag *string + + // Group contains the information returned from the x-ms-group header response. + Group *string + + // LastModified contains the information returned from the Last-Modified header response. + LastModified *time.Time + + // LeaseDuration contains the information returned from the x-ms-lease-duration header response. + LeaseDuration *string + + // LeaseState contains the information returned from the x-ms-lease-state header response. + LeaseState *string + + // LeaseStatus contains the information returned from the x-ms-lease-status header response. + LeaseStatus *string + + // Owner contains the information returned from the x-ms-owner header response. + Owner *string + + // Permissions contains the information returned from the x-ms-permissions header response. + Permissions *string + + // Properties contains the information returned from the x-ms-properties header response. + Properties *string + + // RequestID contains the information returned from the x-ms-request-id header response. + RequestID *string + + // ResourceType contains the information returned from the x-ms-resource-type header response. + ResourceType *string + + // Version contains the information returned from the x-ms-version header response. + Version *string +} + +// PathClientLeaseResponse contains the response from method PathClient.Lease. +type PathClientLeaseResponse struct { + // Date contains the information returned from the Date header response. + Date *time.Time + + // ETag contains the information returned from the ETag header response. + ETag *string + + // LastModified contains the information returned from the Last-Modified header response. + LastModified *time.Time + + // LeaseID contains the information returned from the x-ms-lease-id header response. + LeaseID *string + + // LeaseTime contains the information returned from the x-ms-lease-time header response. + LeaseTime *string + + // RequestID contains the information returned from the x-ms-request-id header response. + RequestID *string + + // Version contains the information returned from the x-ms-version header response. + Version *string +} + +// PathClientReadResponse contains the response from method PathClient.Read. +type PathClientReadResponse struct { + // AcceptRanges contains the information returned from the Accept-Ranges header response. + AcceptRanges *string + + // Body contains the streaming response. + Body io.ReadCloser + + // CacheControl contains the information returned from the Cache-Control header response. + CacheControl *string + + // ContentDisposition contains the information returned from the Content-Disposition header response. + ContentDisposition *string + + // ContentEncoding contains the information returned from the Content-Encoding header response. + ContentEncoding *string + + // ContentLanguage contains the information returned from the Content-Language header response. + ContentLanguage *string + + // ContentLength contains the information returned from the Content-Length header response. + ContentLength *int64 + + // ContentMD5 contains the information returned from the Content-MD5 header response. + ContentMD5 *string + + // ContentRange contains the information returned from the Content-Range header response. + ContentRange *string + + // ContentType contains the information returned from the Content-Type header response. + ContentType *string + + // Date contains the information returned from the Date header response. + Date *time.Time + + // ETag contains the information returned from the ETag header response. + ETag *string + + // EncryptionKeySHA256 contains the information returned from the x-ms-encryption-key-sha256 header response. + EncryptionKeySHA256 *string + + // IsServerEncrypted contains the information returned from the x-ms-request-server-encrypted header response. + IsServerEncrypted *bool + + // LastModified contains the information returned from the Last-Modified header response. + LastModified *time.Time + + // LeaseDuration contains the information returned from the x-ms-lease-duration header response. + LeaseDuration *string + + // LeaseState contains the information returned from the x-ms-lease-state header response. + LeaseState *string + + // LeaseStatus contains the information returned from the x-ms-lease-status header response. + LeaseStatus *string + + // Properties contains the information returned from the x-ms-properties header response. + Properties *string + + // RequestID contains the information returned from the x-ms-request-id header response. + RequestID *string + + // ResourceType contains the information returned from the x-ms-resource-type header response. + ResourceType *string + + // Version contains the information returned from the x-ms-version header response. + Version *string + + // XMSContentMD5 contains the information returned from the x-ms-content-md5 header response. + XMSContentMD5 *string +} + +// PathClientSetAccessControlRecursiveResponse contains the response from method PathClient.SetAccessControlRecursive. +type PathClientSetAccessControlRecursiveResponse struct { + SetAccessControlRecursiveResponse + // ClientRequestID contains the information returned from the x-ms-client-request-id header response. + ClientRequestID *string + + // Continuation contains the information returned from the x-ms-continuation header response. + Continuation *string + + // Date contains the information returned from the Date header response. + Date *time.Time + + // RequestID contains the information returned from the x-ms-request-id header response. + RequestID *string + + // Version contains the information returned from the x-ms-version header response. + Version *string +} + +// PathClientSetAccessControlResponse contains the response from method PathClient.SetAccessControl. +type PathClientSetAccessControlResponse struct { + // ClientRequestID contains the information returned from the x-ms-client-request-id header response. + ClientRequestID *string + + // Date contains the information returned from the Date header response. + Date *time.Time + + // ETag contains the information returned from the ETag header response. + ETag *string + + // LastModified contains the information returned from the Last-Modified header response. + LastModified *time.Time + + // RequestID contains the information returned from the x-ms-request-id header response. + RequestID *string + + // Version contains the information returned from the x-ms-version header response. + Version *string +} + +// PathClientSetExpiryResponse contains the response from method PathClient.SetExpiry. +type PathClientSetExpiryResponse struct { + // ClientRequestID contains the information returned from the x-ms-client-request-id header response. + ClientRequestID *string + + // Date contains the information returned from the Date header response. + Date *time.Time + + // ETag contains the information returned from the ETag header response. + ETag *string + + // LastModified contains the information returned from the Last-Modified header response. + LastModified *time.Time + + // RequestID contains the information returned from the x-ms-request-id header response. + RequestID *string + + // Version contains the information returned from the x-ms-version header response. + Version *string +} + +// PathClientUndeleteResponse contains the response from method PathClient.Undelete. +type PathClientUndeleteResponse struct { + // ClientRequestID contains the information returned from the x-ms-client-request-id header response. + ClientRequestID *string + + // Date contains the information returned from the Date header response. + Date *time.Time + + // RequestID contains the information returned from the x-ms-request-id header response. + RequestID *string + + // ResourceType contains the information returned from the x-ms-resource-type header response. + ResourceType *string + + // Version contains the information returned from the x-ms-version header response. + Version *string +} + +// PathClientUpdateResponse contains the response from method PathClient.Update. +type PathClientUpdateResponse struct { + SetAccessControlRecursiveResponse + // AcceptRanges contains the information returned from the Accept-Ranges header response. + AcceptRanges *string + + // CacheControl contains the information returned from the Cache-Control header response. + CacheControl *string + + // ContentDisposition contains the information returned from the Content-Disposition header response. + ContentDisposition *string + + // ContentEncoding contains the information returned from the Content-Encoding header response. + ContentEncoding *string + + // ContentLanguage contains the information returned from the Content-Language header response. + ContentLanguage *string + + // ContentLength contains the information returned from the Content-Length header response. + ContentLength *int64 + + // ContentMD5 contains the information returned from the Content-MD5 header response. + ContentMD5 *string + + // ContentRange contains the information returned from the Content-Range header response. + ContentRange *string + + // ContentType contains the information returned from the Content-Type header response. + ContentType *string + + // Date contains the information returned from the Date header response. + Date *time.Time + + // ETag contains the information returned from the ETag header response. + ETag *string + + // LastModified contains the information returned from the Last-Modified header response. + LastModified *time.Time + + // Properties contains the information returned from the x-ms-properties header response. + Properties *string + + // RequestID contains the information returned from the x-ms-request-id header response. + RequestID *string + + // Version contains the information returned from the x-ms-version header response. + Version *string + + // XMSContinuation contains the information returned from the x-ms-continuation header response. + XMSContinuation *string +} + +// ServiceClientListFileSystemsResponse contains the response from method ServiceClient.NewListFileSystemsPager. +type ServiceClientListFileSystemsResponse struct { + FileSystemList + // ContentType contains the information returned from the Content-Type header response. + ContentType *string + + // Continuation contains the information returned from the x-ms-continuation header response. + Continuation *string + + // Date contains the information returned from the Date header response. + Date *time.Time + + // RequestID contains the information returned from the x-ms-request-id header response. + RequestID *string + + // Version contains the information returned from the x-ms-version header response. + Version *string +} diff --git a/sdk/storage/azdatalake/internal/generated/zz_service_client.go b/sdk/storage/azdatalake/internal/generated/zz_service_client.go new file mode 100644 index 000000000000..40654cbdefbe --- /dev/null +++ b/sdk/storage/azdatalake/internal/generated/zz_service_client.go @@ -0,0 +1,100 @@ +//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. +// Code generated by Microsoft (R) AutoRest Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. +// DO NOT EDIT. + +package generated + +import ( + "context" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/policy" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime" + "net/http" + "strconv" + "time" +) + +// ServiceClient contains the methods for the Service group. +// Don't use this type directly, use NewServiceClient() instead. +type ServiceClient struct { + endpoint string + pl runtime.Pipeline +} + +// NewServiceClient creates a new instance of ServiceClient with the specified values. +// - endpoint - The URL of the service account, container, or blob that is the target of the desired operation. +// - pl - the pipeline used for sending requests and handling responses. +func NewServiceClient(endpoint string, pl runtime.Pipeline) *ServiceClient { + client := &ServiceClient{ + endpoint: endpoint, + pl: pl, + } + return client +} + +// NewListFileSystemsPager - List filesystems and their properties in given account. +// +// Generated from API version 2020-10-02 +// - options - ServiceClientListFileSystemsOptions contains the optional parameters for the ServiceClient.NewListFileSystemsPager +// method. +// +// ListFileSystemsCreateRequest creates the ListFileSystems request. +func (client *FileSystemClient) ListFileSystemsCreateRequest(ctx context.Context, options *ServiceClientListFileSystemsOptions) (*policy.Request, error) { + req, err := runtime.NewRequest(ctx, http.MethodGet, client.endpoint) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("resource", "account") + if options != nil && options.Prefix != nil { + reqQP.Set("prefix", *options.Prefix) + } + if options != nil && options.Continuation != nil { + reqQP.Set("continuation", *options.Continuation) + } + if options != nil && options.MaxResults != nil { + reqQP.Set("maxResults", strconv.FormatInt(int64(*options.MaxResults), 10)) + } + if options != nil && options.Timeout != nil { + reqQP.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + } + req.Raw().URL.RawQuery = reqQP.Encode() + if options != nil && options.RequestID != nil { + req.Raw().Header["x-ms-client-request-id"] = []string{*options.RequestID} + } + req.Raw().Header["x-ms-version"] = []string{"2020-10-02"} + req.Raw().Header["Accept"] = []string{"application/json"} + return req, nil +} + +// listFileSystemsHandleResponse handles the ListFileSystems response. +func (client *FileSystemClient) ListFileSystemsHandleResponse(resp *http.Response) (ServiceClientListFileSystemsResponse, error) { + result := ServiceClientListFileSystemsResponse{} + if val := resp.Header.Get("Date"); val != "" { + date, err := time.Parse(time.RFC1123, val) + if err != nil { + return ServiceClientListFileSystemsResponse{}, err + } + result.Date = &date + } + if val := resp.Header.Get("x-ms-request-id"); val != "" { + result.RequestID = &val + } + if val := resp.Header.Get("x-ms-version"); val != "" { + result.Version = &val + } + if val := resp.Header.Get("x-ms-continuation"); val != "" { + result.Continuation = &val + } + if val := resp.Header.Get("Content-Type"); val != "" { + result.ContentType = &val + } + if err := runtime.UnmarshalAsJSON(resp, &result.FileSystemList); err != nil { + return ServiceClientListFileSystemsResponse{}, err + } + return result, nil +} diff --git a/sdk/storage/azdatalake/internal/generated/zz_time_rfc1123.go b/sdk/storage/azdatalake/internal/generated/zz_time_rfc1123.go new file mode 100644 index 000000000000..4b4d51aa3994 --- /dev/null +++ b/sdk/storage/azdatalake/internal/generated/zz_time_rfc1123.go @@ -0,0 +1,43 @@ +//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. +// Code generated by Microsoft (R) AutoRest Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. +// DO NOT EDIT. + +package generated + +import ( + "strings" + "time" +) + +const ( + rfc1123JSON = `"` + time.RFC1123 + `"` +) + +type timeRFC1123 time.Time + +func (t timeRFC1123) MarshalJSON() ([]byte, error) { + b := []byte(time.Time(t).Format(rfc1123JSON)) + return b, nil +} + +func (t timeRFC1123) MarshalText() ([]byte, error) { + b := []byte(time.Time(t).Format(time.RFC1123)) + return b, nil +} + +func (t *timeRFC1123) UnmarshalJSON(data []byte) error { + p, err := time.Parse(rfc1123JSON, strings.ToUpper(string(data))) + *t = timeRFC1123(p) + return err +} + +func (t *timeRFC1123) UnmarshalText(data []byte) error { + p, err := time.Parse(time.RFC1123, string(data)) + *t = timeRFC1123(p) + return err +} From a93ed526d8b9724bff550541bcffd38748744770 Mon Sep 17 00:00:00 2001 From: Tamer Sherif <69483382+tasherif-msft@users.noreply.github.com> Date: Thu, 11 May 2023 13:20:38 -0700 Subject: [PATCH 02/16] Merge main into datalake feature branch (#20833) * Enable gocritic during linting (#20715) Enabled gocritic's evalOrder to catch dependencies on undefined behavior on return statements. Updated to latest version of golangci-lint. Fixed issue in azblob flagged by latest linter. * Cosmos DB: Enable merge support (#20716) * Adding header and value * Wiring and tests * format * Fixing value * change log * [azservicebus, azeventhubs] Stress test and logging improvement (#20710) Logging improvements: * Updating the logging to print more tracing information (per-link) in prep for the bigger release coming up. * Trimming out some of the verbose logging, seeing if I can get it a bit more reasonable. Stress tests: * Add a timestamp to the log name we generate and also default to append, not overwrite. * Use 0.5 cores, 0.5GB as our baseline. Some pods use more and I'll tune them more later. * update proxy version (#20712) Co-authored-by: Scott Beddall * Return an error when you try to send a message that's too large. (#20721) This now works just like the message batch - you'll get an ErrMessageTooLarge if you attempt to send a message that's too large for the link's configured size. NOTE: there's a patch to `internal/go-amqp/Sender.go` to match what's in go-amqp's main so it returns a programmatically useful error when the message is too large. Fixes #20647 * Changes in test that is failing in pipeline (#20693) * [azservicebus, azeventhubs] Treat 'entity full' as a fatal error (#20722) When the remote entity is full we get a resource-limit-exceeded condition. This isn't something we should keep retrying on and it's best to just abort and let the user know immediately, rather than hoping it might eventually clear out. This affected both Event Hubs and Service Bus. Fixes #20647 * [azservicebus/azeventhubs] Redirect stderr and stdout to tee (#20726) * Update changelog with latest features (#20730) * Update changelog with latest features Prepare for upcoming release. * bump minor version * pass along the artifact name so we can override it later (#20732) Co-authored-by: scbedd <45376673+scbedd@users.noreply.github.com> * [azeventhubs] Fixing checkpoint store race condition (#20727) The checkpoint store wasn't guarding against multiple owners claiming for the first time - fixing this by using IfNoneMatch Fixes #20717 * Fix azidentity troubleshooting guide link (#20736) * [Release] sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/0.1.0 (#20437) * [Release] sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/0.1.0 generation from spec commit: 85fb4ac6f8bfefd179e6c2632976a154b5c9ff04 * client factory * fix * fix * update * add sdk/resourcemanager/postgresql/armpostgresql live test (#20685) * add sdk/resourcemanager/postgresql/armpostgresql live test * update assets.json * set subscriptionId default value * format * add sdk/resourcemanager/eventhub/armeventhub live test (#20686) * add sdk/resourcemanager/eventhub/armeventhub live test * update assets * add sdk/resourcemanager/compute/armcompute live test (#20048) * add sdk/resourcemanager/compute/armcompute live test * skus filter * fix subscriptionId default value * fix * gofmt * update recording * sdk/resourcemanager/network/armnetwork live test (#20331) * sdk/resourcemanager/network/armnetwork live test * update subscriptionId default value * update recording * add sdk/resourcemanager/cosmos/armcosmos live test (#20705) * add sdk/resourcemanager/cosmos/armcosmos live test * update assets.json * update assets.json * update assets.json * update assets.json * Increment package version after release of azcore (#20740) * [azeventhubs] Improperly resetting etag in the checkpoint store (#20737) We shouldn't be resetting the etag to nil - it's what we use to enforce a "single winner" when doing ownership claims. The bug here was two-fold: I had bad logic in my previous claim ownership, which I fixed in a previous PR, but we need to reflect that same constraint properly in our in-memory checkpoint store for these tests. * Eng workflows sync and branch cleanup additions (#20743) Co-authored-by: James Suplizio * [azeventhubs] Latest start position can also be inclusive (ie, get the latest message) (#20744) * Update GitHubEventProcessor version and remove pull_request_review procesing (#20751) Co-authored-by: James Suplizio * Rename DisableAuthorityValidationAndInstanceDiscovery (#20746) * fix (#20707) * AzFile (#20739) * azfile: Fixing connection string parsing logic (#20798) * Fixing connection string parse logic * Update README * [azadmin] fix flaky test (#20758) * fix flaky test * charles suggestion * Prepare azidentity v1.3.0 for release (#20756) * Fix broken podman link (#20801) Co-authored-by: Wes Haggard * [azquery] update doc comments (#20755) * update doc comments * update statistics and visualization generation * prep-for-release * Fixed contribution section (#20752) Co-authored-by: Bob Tabor * [azeventhubs,azservicebus] Some API cleanup, renames (#20754) * Adding options to UpdateCheckpoint(), just for future potential expansion * Make Offset an int64, not a *int64 (it's not optional, it'll always come back with ReceivedEvents) * Adding more logging into the checkpoint store. * Point all imports at the production go-amqp * Add supporting features to enable distributed tracing (#20301) (#20708) * Add supporting features to enable distributed tracing This includes new internal pipeline policies and other supporting types. See the changelog for a full description. Added some missing doc comments. * fix linter issue * add net.peer.name trace attribute sequence custom HTTP header policy before logging policy. sequence logging policy after HTTP trace policy. keep body download policy at the end. * add span for iterating over pages * Restore ARM CAE support for azcore beta (#20657) This reverts commit 902097226ff3fe2fc6c3e7fc50d3478350253614. * Upgrade to stable azcore (#20808) * Increment package version after release of data/azcosmos (#20807) * Updating changelog (#20810) * Add fake package to azcore (#20711) * Add fake package to azcore This is the supporting infrastructure for the generated SDK fakes. * fix doc comment * Updating CHANGELOG.md (#20809) * changelog (#20811) * Increment package version after release of storage/azfile (#20813) * Update changelog (azblob) (#20815) * Updating CHANGELOG.md * Update the changelog with correct version * [azquery] migration guide (#20742) * migration guide * Charles feedback * Richard feedback --------- Co-authored-by: Charles Lowell <10964656+chlowell@users.noreply.github.com> * Increment package version after release of monitor/azquery (#20820) * [keyvault] prep for release (#20819) * prep for release * perf tests * update date --------- Co-authored-by: Joel Hendrix Co-authored-by: Matias Quaranta Co-authored-by: Richard Park <51494936+richardpark-msft@users.noreply.github.com> Co-authored-by: Azure SDK Bot <53356347+azure-sdk@users.noreply.github.com> Co-authored-by: Scott Beddall Co-authored-by: siminsavani-msft <77068571+siminsavani-msft@users.noreply.github.com> Co-authored-by: scbedd <45376673+scbedd@users.noreply.github.com> Co-authored-by: Charles Lowell <10964656+chlowell@users.noreply.github.com> Co-authored-by: Peng Jiahui <46921893+Alancere@users.noreply.github.com> Co-authored-by: James Suplizio Co-authored-by: Sourav Gupta <98318303+souravgupta-msft@users.noreply.github.com> Co-authored-by: gracewilcox <43627800+gracewilcox@users.noreply.github.com> Co-authored-by: Wes Haggard Co-authored-by: Bob Tabor Co-authored-by: Bob Tabor --- .github/workflows/event-processor.yml | 4 +- .../workflows/scheduled-event-processor.yml | 2 +- eng/.golangci.yml | 10 + .../templates/steps/detect-api-changes.yml | 2 + .../steps/eng-common-workflow-enforcer.yml | 12 +- eng/common/scripts/Delete-RemoteBranches.ps1 | 11 +- eng/common/testproxy/target_version.txt | 2 +- .../testproxy/transition-scripts/README.md | 2 +- eng/config.json | 4 + eng/pipelines/templates/variables/globals.yml | 2 +- .../generator/cmd/v2/common/fileProcessor.go | 6 +- sdk/azcore/CHANGELOG.md | 19 +- sdk/azcore/arm/runtime/pipeline.go | 3 +- sdk/azcore/arm/runtime/policy_bearer_token.go | 48 +- .../arm/runtime/policy_bearer_token_test.go | 8 +- .../arm/runtime/policy_trace_namespace.go | 31 + .../runtime/policy_trace_namespace_test.go | 97 + sdk/azcore/core.go | 3 + sdk/azcore/core_test.go | 41 + sdk/azcore/fake/example_test.go | 146 + sdk/azcore/fake/fake.go | 378 ++ sdk/azcore/fake/fake_test.go | 331 ++ sdk/azcore/internal/exported/exported.go | 4 + sdk/azcore/internal/exported/request.go | 8 + sdk/azcore/internal/exported/request_test.go | 17 + .../internal/exported/response_error.go | 3 +- .../internal/exported/response_error_test.go | 10 +- sdk/azcore/internal/pollers/fake/fake.go | 118 + sdk/azcore/internal/pollers/fake/fake_test.go | 185 + sdk/azcore/internal/shared/constants.go | 5 +- sdk/azcore/internal/shared/shared.go | 6 + sdk/azcore/policy/policy.go | 3 +- sdk/azcore/runtime/pager.go | 13 + sdk/azcore/runtime/pipeline.go | 30 +- sdk/azcore/runtime/policy_http_trace.go | 117 + sdk/azcore/runtime/policy_http_trace_test.go | 163 + sdk/azcore/runtime/poller.go | 103 +- sdk/azcore/runtime/poller_test.go | 65 +- sdk/azcore/runtime/request.go | 3 + sdk/azcore/tracing/tracing.go | 41 +- sdk/azcore/tracing/tracing_test.go | 22 +- sdk/azidentity/CHANGELOG.md | 7 +- sdk/azidentity/TROUBLESHOOTING.md | 2 +- sdk/azidentity/client_assertion_credential.go | 13 +- .../client_assertion_credential_test.go | 5 +- .../client_certificate_credential.go | 13 +- .../client_certificate_credential_test.go | 4 +- sdk/azidentity/client_secret_credential.go | 13 +- .../client_secret_credential_test.go | 4 +- sdk/azidentity/default_azure_credential.go | 19 +- sdk/azidentity/device_code_credential.go | 13 +- sdk/azidentity/device_code_credential_test.go | 9 +- sdk/azidentity/environment_credential.go | 17 +- sdk/azidentity/environment_credential_test.go | 16 +- sdk/azidentity/go.mod | 4 +- sdk/azidentity/go.sum | 8 +- .../interactive_browser_credential.go | 13 +- .../interactive_browser_credential_test.go | 12 +- sdk/azidentity/on_behalf_of_credential.go | 13 +- .../username_password_credential.go | 13 +- .../username_password_credential_test.go | 4 +- sdk/azidentity/version.go | 2 +- sdk/azidentity/workload_identity.go | 13 +- sdk/azidentity/workload_identity_test.go | 10 +- sdk/data/azcosmos/CHANGELOG.md | 13 + sdk/data/azcosmos/cosmos_client.go | 1 + sdk/data/azcosmos/cosmos_client_test.go | 4 + sdk/data/azcosmos/cosmos_headers.go | 1 + sdk/data/azcosmos/sdk_capabilities.go | 21 + sdk/data/azcosmos/version.go | 2 +- sdk/messaging/azeventhubs/CHANGELOG.md | 25 +- sdk/messaging/azeventhubs/amqp_message.go | 2 +- sdk/messaging/azeventhubs/checkpoint_store.go | 8 +- .../azeventhubs/checkpoints/blob_store.go | 89 +- .../checkpoints/blob_store_test.go | 125 +- .../consumer_client_internal_test.go | 2 +- .../azeventhubs/consumer_client_unit_test.go | 30 +- sdk/messaging/azeventhubs/event_data.go | 6 +- sdk/messaging/azeventhubs/event_data_batch.go | 2 +- .../azeventhubs/event_data_batch_unit_test.go | 2 +- sdk/messaging/azeventhubs/event_data_test.go | 6 +- .../example_checkpoint_migration_test.go | 2 +- ...example_consuming_with_checkpoints_test.go | 4 +- sdk/messaging/azeventhubs/go.mod | 3 +- sdk/messaging/azeventhubs/go.sum | 2 + .../inmemory_checkpoint_store_test.go | 17 +- .../azeventhubs/internal/amqp_fakes.go | 2 +- .../azeventhubs/internal/amqpwrap/amqpwrap.go | 2 +- .../internal/amqpwrap/mock_amqp_test.go | 2 +- .../azeventhubs/internal/amqpwrap/rpc.go | 2 +- sdk/messaging/azeventhubs/internal/cbs.go | 2 +- .../azeventhubs/internal/cbs_test.go | 2 +- .../azeventhubs/internal/eh/stress/deploy.ps1 | 4 +- .../eh/stress/templates/stress-test-job.yaml | 6 +- .../stress/tests/processor_stress_tester.go | 2 +- .../internal/eh/stress/tests/shared.go | 2 +- sdk/messaging/azeventhubs/internal/errors.go | 6 +- .../azeventhubs/internal/errors_test.go | 3 +- .../azeventhubs/internal/go-amqp/conn.go | 1135 ------ .../azeventhubs/internal/go-amqp/const.go | 96 - .../azeventhubs/internal/go-amqp/creditor.go | 119 - .../azeventhubs/internal/go-amqp/errors.go | 107 - .../go-amqp/internal/bitmap/bitmap.go | 99 - .../go-amqp/internal/buffer/buffer.go | 180 - .../internal/go-amqp/internal/debug/debug.go | 20 - .../go-amqp/internal/debug/debug_debug.go | 51 - .../go-amqp/internal/encoding/decode.go | 1150 ------ .../go-amqp/internal/encoding/encode.go | 573 --- .../go-amqp/internal/encoding/types.go | 2155 ---------- .../go-amqp/internal/frames/frames.go | 1543 ------- .../go-amqp/internal/frames/parsing.go | 162 - .../internal/go-amqp/internal/queue/queue.go | 164 - .../go-amqp/internal/shared/shared.go | 36 - .../azeventhubs/internal/go-amqp/link.go | 390 -- .../internal/go-amqp/link_options.go | 241 -- .../azeventhubs/internal/go-amqp/message.go | 492 --- .../azeventhubs/internal/go-amqp/receiver.go | 897 ----- .../azeventhubs/internal/go-amqp/sasl.go | 262 -- .../azeventhubs/internal/go-amqp/sender.go | 476 --- .../azeventhubs/internal/go-amqp/session.go | 792 ---- .../azeventhubs/internal/links_test.go | 2 +- .../azeventhubs/internal/links_unit_test.go | 2 +- .../azeventhubs/internal/mock/mock_amqp.go | 2 +- .../azeventhubs/internal/mock/mock_helpers.go | 2 +- .../azeventhubs/internal/namespace.go | 2 +- .../azeventhubs/internal/namespace_test.go | 2 +- sdk/messaging/azeventhubs/internal/rpc.go | 2 +- .../azeventhubs/internal/rpc_test.go | 2 +- .../azeventhubs/internal/test/test_helpers.go | 7 + .../internal/utils/retrier_test.go | 2 +- sdk/messaging/azeventhubs/mgmt.go | 2 +- sdk/messaging/azeventhubs/partition_client.go | 22 +- .../azeventhubs/partition_client_unit_test.go | 2 +- .../azeventhubs/processor_load_balancer.go | 43 +- .../azeventhubs/processor_partition_client.go | 20 +- sdk/messaging/azeventhubs/processor_test.go | 12 +- .../azeventhubs/processor_unit_test.go | 6 +- sdk/messaging/azeventhubs/producer_client.go | 2 +- sdk/messaging/azservicebus/CHANGELOG.md | 111 +- sdk/messaging/azservicebus/amqp_message.go | 2 +- sdk/messaging/azservicebus/client_test.go | 12 +- sdk/messaging/azservicebus/go.mod | 4 +- sdk/messaging/azservicebus/go.sum | 11 +- .../azservicebus/internal/amqpLinks.go | 161 +- .../azservicebus/internal/amqpLinks_test.go | 2 +- .../azservicebus/internal/amqp_test_utils.go | 11 +- .../internal/amqplinks_unit_test.go | 22 +- .../internal/amqpwrap/amqpwrap.go | 2 +- .../internal/amqpwrap/mock_amqp_test.go | 2 +- .../azservicebus/internal/amqpwrap/rpc.go | 2 +- sdk/messaging/azservicebus/internal/cbs.go | 2 +- sdk/messaging/azservicebus/internal/errors.go | 5 +- .../azservicebus/internal/errors_test.go | 3 +- .../internal/exported/error_test.go | 2 +- .../azservicebus/internal/go-amqp/LICENSE | 22 - .../azservicebus/internal/go-amqp/conn.go | 1135 ------ .../azservicebus/internal/go-amqp/const.go | 96 - .../azservicebus/internal/go-amqp/creditor.go | 119 - .../azservicebus/internal/go-amqp/errors.go | 107 - .../go-amqp/internal/bitmap/bitmap.go | 99 - .../go-amqp/internal/buffer/buffer.go | 180 - .../internal/go-amqp/internal/debug/debug.go | 20 - .../go-amqp/internal/debug/debug_debug.go | 51 - .../go-amqp/internal/encoding/decode.go | 1150 ------ .../go-amqp/internal/encoding/encode.go | 573 --- .../go-amqp/internal/encoding/types.go | 2155 ---------- .../go-amqp/internal/frames/frames.go | 1543 ------- .../go-amqp/internal/frames/parsing.go | 162 - .../internal/go-amqp/internal/queue/queue.go | 164 - .../go-amqp/internal/shared/shared.go | 36 - .../azservicebus/internal/go-amqp/link.go | 390 -- .../internal/go-amqp/link_options.go | 241 -- .../azservicebus/internal/go-amqp/message.go | 492 --- .../azservicebus/internal/go-amqp/receiver.go | 897 ----- .../azservicebus/internal/go-amqp/sasl.go | 262 -- .../azservicebus/internal/go-amqp/sender.go | 476 --- .../azservicebus/internal/go-amqp/session.go | 792 ---- sdk/messaging/azservicebus/internal/mgmt.go | 2 +- .../internal/mock/emulation/events.go | 2 +- .../internal/mock/emulation/mock_data.go | 2 +- .../mock/emulation/mock_data_receiver.go | 2 +- .../mock/emulation/mock_data_sender.go | 2 +- .../mock/emulation/mock_data_session.go | 2 +- .../internal/mock/emulation/mock_data_test.go | 2 +- .../internal/mock/emulation/queue.go | 2 +- .../internal/mock/emulation/queue_test.go | 2 +- .../azservicebus/internal/mock/mock_amqp.go | 2 +- .../internal/mock/mock_helpers.go | 2 +- .../azservicebus/internal/mock/mock_rpc.go | 2 +- .../azservicebus/internal/namespace.go | 2 +- .../azservicebus/internal/namespace_test.go | 2 +- sdk/messaging/azservicebus/internal/rpc.go | 5 +- .../azservicebus/internal/rpc_test.go | 23 +- .../azservicebus/internal/stress/.gitignore | 2 +- .../azservicebus/internal/stress/.helmignore | 1 + .../azservicebus/internal/stress/deploy.ps1 | 23 + .../internal/stress/scenarios-matrix.yaml | 24 +- .../stress/templates/stress-test-job.yaml | 4 +- .../internal/stress/tests/finite_peeks.go | 14 +- .../stress/tests/mostly_idle_receiver.go | 2 +- .../internal/test/test_helpers.go | 27 +- .../azservicebus/internal/utils/logger.go | 37 + .../azservicebus/internal/utils/retrier.go | 10 +- .../internal/utils/retrier_test.go | 12 +- sdk/messaging/azservicebus/message.go | 2 +- sdk/messaging/azservicebus/messageSettler.go | 2 +- sdk/messaging/azservicebus/message_batch.go | 5 +- .../azservicebus/message_batch_test.go | 2 +- sdk/messaging/azservicebus/message_test.go | 2 +- sdk/messaging/azservicebus/receiver.go | 22 +- .../azservicebus/receiver_helpers_test.go | 2 +- .../azservicebus/receiver_simulated_test.go | 8 +- sdk/messaging/azservicebus/receiver_test.go | 22 +- .../azservicebus/receiver_unit_test.go | 10 +- sdk/messaging/azservicebus/sender.go | 17 +- sdk/messaging/azservicebus/sender_test.go | 44 + .../azservicebus/sender_unit_test.go | 2 +- .../azservicebus/session_receiver.go | 2 +- .../azservicebus/session_receiver_test.go | 2 +- sdk/monitor/azquery/CHANGELOG.md | 7 +- sdk/monitor/azquery/MIGRATION.md | 177 + sdk/monitor/azquery/autorest.md | 64 +- sdk/monitor/azquery/build.go | 2 +- sdk/monitor/azquery/logs_client.go | 10 +- sdk/monitor/azquery/models.go | 8 +- sdk/monitor/azquery/models_serde.go | 8 +- sdk/monitor/azquery/version.go | 2 +- .../compute/armcompute/assets.json | 2 +- .../armcompute/availabilityset_live_test.go | 117 + .../availabilitysets_client_live_test.go | 120 - .../capacityreservation_live_test.go | 122 + .../armcompute/computerpcommon_live_test.go | 100 + .../armcompute/dedicatedhost_live_test.go | 174 + .../compute/armcompute/disk_live_test.go | 137 + .../armcompute/diskaccess_live_test.go | 129 + .../compute/armcompute/gallery_live_test.go | 265 ++ sdk/resourcemanager/compute/armcompute/go.mod | 3 +- sdk/resourcemanager/compute/armcompute/go.sum | 7 +- .../proximityplacementgroup_live_test.go | 118 + .../armcompute/restorepoint_live_test.go | 291 ++ .../armcompute/runcommand_live_test.go | 495 +++ .../compute/armcompute/skus_live_test.go | 73 + .../compute/armcompute/snapshot_live_test.go | 141 + .../armcompute/sshpublickey_live_test.go | 113 + .../armcompute/virtualmachine_live_test.go | 348 ++ .../virtualmachineextensionimage_live_test.go | 82 + .../virtualmachineimage_live_test.go | 93 + .../virtualmachines_client_live_test.go | 312 -- .../virtualmachinescaleset_live_test.go | 399 ++ ...irtualmachinescalesets_client_live_test.go | 195 - .../cosmos/armcosmos/assets.json | 2 +- .../armcosmos/cassandraresources_live_test.go | 266 ++ .../armcosmos/databaseaccounts_live_test.go | 223 ++ sdk/resourcemanager/cosmos/armcosmos/go.mod | 18 +- sdk/resourcemanager/cosmos/armcosmos/go.sum | 46 +- .../armcosmos/gremlinresources_live_test.go | 293 ++ .../armcosmos/mongodbresources_live_test.go | 256 ++ .../cosmos/armcosmos/operations_live_test.go | 88 + .../privateendpointconnection_live_test.go | 293 ++ .../cosmos/armcosmos/services_live_test.go | 122 + .../armcosmos/sqlresources_live_test.go | 465 +++ .../armcosmos/tableresources_live_test.go | 166 + .../eventhub/armeventhub/assets.json | 2 +- .../disasterrecoveryconfigs_live_test.go | 9 +- .../armeventhub/eventhub_live_test.go | 13 +- .../privateendpointconnections_live_test.go | 245 ++ ...iongatewaywafdynamicmanifests_live_test.go | 70 + .../applicationsecuritygroup_live_test.go | 114 + .../network/armnetwork/assets.json | 2 +- .../availabledelegations_live_test.go | 81 + .../availableservicealiases_live_test.go | 79 + .../azurefirewallfqdntag_live_test.go | 70 + .../armnetwork/azurewebcategory_live_test.go | 70 + .../armnetwork/bastionhost_live_test.go | 183 + .../checkdnsavailability_live_test.go | 66 + .../armnetwork/customipprefix_live_test.go | 109 + .../ddosprotectionplan_live_test.go | 114 + .../armnetwork/endpointservice_live_test.go | 70 + .../expressroutecircuit_live_test.go | 251 ++ .../armnetwork/firewallpolicy_live_test.go | 176 + sdk/resourcemanager/network/armnetwork/go.mod | 26 +- sdk/resourcemanager/network/armnetwork/go.sum | 57 +- .../armnetwork/ipgroups_client_live_test.go | 116 - .../network/armnetwork/ipgroups_live_test.go | 122 + .../armnetwork/loadbalancer_live_test.go | 335 ++ .../armnetwork/natgateway_live_test.go | 116 + .../armnetwork/networkinterface_live_test.go | 185 + .../armnetwork/networkmanager_live_test.go | 169 + .../networkmanagerconnection_live_test.go | 121 + ...agerconnectivityconfiguration_live_test.go | 145 + .../networkmanagergroup_live_test.go | 188 + ...gersecurityadminconfiguration_live_test.go | 252 ++ .../armnetwork/networkprofile_live_test.go | 161 + .../networksecuritygroup_live_test.go | 191 + .../armnetwork/networkwatcher_live_test.go | 113 + .../network/armnetwork/operation_live_test.go | 70 + .../armnetwork/publicipaddress_live_test.go | 113 + .../armnetwork/publicipprefix_live_test.go | 119 + .../armnetwork/routetable_live_test.go | 165 + .../armnetwork/servicecommunity_live_test.go | 70 + .../serviceendpointpolicy_live_test.go | 167 + .../armnetwork/servicetags_live_test.go | 79 + .../armnetwork/subnets_client_live_test.go | 122 - .../network/armnetwork/usage_live_test.go | 70 + .../armnetwork/virtualnetwork_live_test.go | 258 ++ .../virtualnetworkgateway_live_test.go | 237 ++ .../virtualnetworks_client_live_test.go | 117 - .../armnetwork/virtualwan_live_test.go | 461 +++ .../webapplicationfirewall_live_test.go | 120 + .../armpanngfw/CHANGELOG.md | 7 + .../armpanngfw/LICENSE.txt | 21 + .../paloaltonetworksngfw/armpanngfw/README.md | 85 + .../armpanngfw/autorest.md | 13 + .../paloaltonetworksngfw/armpanngfw/build.go | 7 + ...certificateobjectglobalrulestack_client.go | 284 ++ ...jectglobalrulestack_client_example_test.go | 299 ++ .../certificateobjectlocalrulestack_client.go | 323 ++ ...bjectlocalrulestack_client_example_test.go | 299 ++ .../paloaltonetworksngfw/armpanngfw/ci.yml | 28 + .../armpanngfw/client_factory.go | 109 + .../armpanngfw/constants.go | 488 +++ .../armpanngfw/firewalls_client.go | 647 +++ .../firewalls_client_example_test.go | 1734 ++++++++ .../armpanngfw/firewallstatus_client.go | 172 + .../firewallstatus_client_example_test.go | 170 + .../fqdnlistglobalrulestack_client.go | 284 ++ ...listglobalrulestack_client_example_test.go | 311 ++ .../fqdnlistlocalrulestack_client.go | 323 ++ ...nlistlocalrulestack_client_example_test.go | 311 ++ .../armpanngfw/globalrulestack_client.go | 791 ++++ .../globalrulestack_client_example_test.go | 987 +++++ .../paloaltonetworksngfw/armpanngfw/go.mod | 21 + .../paloaltonetworksngfw/armpanngfw/go.sum | 31 + .../armpanngfw/localrules_client.go | 509 +++ .../localrules_client_example_test.go | 629 +++ .../armpanngfw/localrulestacks_client.go | 1041 +++++ .../localrulestacks_client_example_test.go | 1171 ++++++ .../paloaltonetworksngfw/armpanngfw/models.go | 1924 +++++++++ .../armpanngfw/models_serde.go | 3530 +++++++++++++++++ .../armpanngfw/operations_client.go | 94 + .../operations_client_example_test.go | 85 + .../armpanngfw/postrules_client.go | 441 ++ .../postrules_client_example_test.go | 629 +++ .../prefixlistglobalrulestack_client.go | 284 ++ ...listglobalrulestack_client_example_test.go | 303 ++ .../prefixlistlocalrulestack_client.go | 323 ++ ...xlistlocalrulestack_client_example_test.go | 303 ++ .../armpanngfw/prerules_client.go | 441 ++ .../prerules_client_example_test.go | 629 +++ .../armpanngfw/response_types.go | 450 +++ .../armpanngfw/time_rfc3339.go | 87 + .../postgresql/armpostgresql/assets.json | 2 +- .../armpostgresql/postgresql_live_test.go | 191 +- .../privateendpointconnections_live_test.go | 271 ++ .../serversecurityalertpolicies_live_test.go | 126 + sdk/security/keyvault/azadmin/CHANGELOG.md | 11 +- sdk/security/keyvault/azadmin/go.mod | 16 +- sdk/security/keyvault/azadmin/go.sum | 32 +- .../keyvault/azadmin/internal/version.go | 2 +- .../keyvault/azadmin/settings/client_test.go | 14 +- .../keyvault/azcertificates/CHANGELOG.md | 9 +- sdk/security/keyvault/azcertificates/go.mod | 24 +- sdk/security/keyvault/azcertificates/go.sum | 54 +- .../azcertificates/testdata/perf/go.mod | 19 +- .../azcertificates/testdata/perf/go.sum | 86 +- .../keyvault/azcertificates/version.go | 2 +- sdk/security/keyvault/azkeys/CHANGELOG.md | 9 +- sdk/security/keyvault/azkeys/go.mod | 24 +- sdk/security/keyvault/azkeys/go.sum | 54 +- .../keyvault/azkeys/testdata/perf/go.mod | 19 +- .../keyvault/azkeys/testdata/perf/go.sum | 86 +- sdk/security/keyvault/azkeys/version.go | 2 +- sdk/security/keyvault/azsecrets/CHANGELOG.md | 9 +- sdk/security/keyvault/azsecrets/go.mod | 24 +- sdk/security/keyvault/azsecrets/go.sum | 54 +- .../keyvault/azsecrets/testdata/perf/go.mod | 19 +- .../keyvault/azsecrets/testdata/perf/go.sum | 49 +- sdk/security/keyvault/azsecrets/version.go | 2 +- sdk/storage/azblob/CHANGELOG.md | 6 +- sdk/storage/azblob/blockblob/mmf_windows.go | 4 +- .../azblob/internal/exported/version.go | 2 +- sdk/storage/azblob/service/client_test.go | 10 +- sdk/storage/azfile/CHANGELOG.md | 17 + .../LICENSE => storage/azfile/LICENSE.txt} | 5 +- sdk/storage/azfile/README.md | 266 ++ sdk/storage/azfile/assets.json | 6 + sdk/storage/azfile/ci.yml | 33 + sdk/storage/azfile/directory/client.go | 205 + sdk/storage/azfile/directory/client_test.go | 1117 ++++++ sdk/storage/azfile/directory/constants.go | 24 + sdk/storage/azfile/directory/examples_test.go | 193 + sdk/storage/azfile/directory/models.go | 255 ++ sdk/storage/azfile/directory/responses.go | 39 + sdk/storage/azfile/doc.go | 229 ++ sdk/storage/azfile/file/chunkwriting.go | 189 + sdk/storage/azfile/file/client.go | 505 +++ sdk/storage/azfile/file/client_test.go | 3119 +++++++++++++++ sdk/storage/azfile/file/constants.go | 78 + sdk/storage/azfile/file/examples_test.go | 650 +++ sdk/storage/azfile/file/mmf_unix.go | 38 + sdk/storage/azfile/file/mmf_windows.go | 56 + sdk/storage/azfile/file/models.go | 743 ++++ sdk/storage/azfile/file/responses.go | 93 + sdk/storage/azfile/file/retry_reader.go | 186 + sdk/storage/azfile/fileerror/error_codes.go | 107 + sdk/storage/azfile/go.mod | 28 + sdk/storage/azfile/go.sum | 46 + sdk/storage/azfile/internal/base/clients.go | 60 + .../azfile/internal/exported/access_policy.go | 62 + .../exported/copy_file_smb_options.go | 96 + .../azfile/internal/exported/exported.go | 33 + .../internal/exported/file_permissions.go | 32 + .../azfile/internal/exported/log_events.go | 17 + .../exported/shared_key_credential.go | 218 + .../azfile/internal/exported/smb_property.go | 98 + .../exported/transfer_validation_option.go | 28 + .../azfile/internal/exported/version.go | 12 + .../azfile/internal/generated/autorest.md | 309 ++ .../azfile/internal/generated/build.go | 10 + .../internal/generated/directory_client.go | 22 + .../azfile/internal/generated/file_client.go | 17 + .../azfile/internal/generated/models.go | 25 + .../internal/generated/service_client.go | 17 + .../azfile/internal/generated/share_client.go | 17 + .../azfile/internal/generated/zz_constants.go | 342 ++ .../internal/generated/zz_directory_client.go | 766 ++++ .../internal/generated/zz_file_client.go | 1826 +++++++++ .../azfile/internal/generated/zz_models.go | 932 +++++ .../internal/generated/zz_models_serde.go | 344 ++ .../internal/generated/zz_response_types.go | 1189 ++++++ .../internal/generated/zz_service_client.go | 195 + .../internal/generated/zz_share_client.go | 1437 +++++++ .../internal/generated/zz_time_rfc1123.go | 43 + .../internal/generated/zz_time_rfc3339.go | 59 + .../internal/generated/zz_xml_helper.go | 41 + .../azfile/internal/shared/batch_transfer.go | 77 + .../azfile/internal/shared/bytes_writer.go | 30 + .../internal/shared/bytes_writer_test.go | 37 + .../azfile/internal/shared/section_writer.go | 53 + .../internal/shared/section_writer_test.go | 98 + sdk/storage/azfile/internal/shared/shared.go | 226 ++ .../azfile/internal/shared/shared_test.go | 135 + .../internal/testcommon/clients_auth.go | 224 ++ .../azfile/internal/testcommon/common.go | 117 + sdk/storage/azfile/lease/client_test.go | 633 +++ sdk/storage/azfile/lease/constants.go | 51 + sdk/storage/azfile/lease/examples_test.go | 101 + sdk/storage/azfile/lease/file_client.go | 103 + sdk/storage/azfile/lease/models.go | 147 + sdk/storage/azfile/lease/responses.go | 36 + sdk/storage/azfile/lease/share_client.go | 116 + sdk/storage/azfile/log.go | 16 + sdk/storage/azfile/sas/account.go | 183 + sdk/storage/azfile/sas/account_test.go | 124 + sdk/storage/azfile/sas/query_params.go | 339 ++ sdk/storage/azfile/sas/query_params_test.go | 211 + sdk/storage/azfile/sas/service.go | 227 ++ sdk/storage/azfile/sas/service_test.go | 147 + sdk/storage/azfile/sas/url_parts.go | 147 + sdk/storage/azfile/sas/url_parts_test.go | 75 + sdk/storage/azfile/service/client.go | 214 + sdk/storage/azfile/service/client_test.go | 454 +++ sdk/storage/azfile/service/constants.go | 37 + sdk/storage/azfile/service/examples_test.go | 308 ++ sdk/storage/azfile/service/models.go | 171 + sdk/storage/azfile/service/responses.go | 30 + sdk/storage/azfile/share/client.go | 258 ++ sdk/storage/azfile/share/client_test.go | 1460 +++++++ sdk/storage/azfile/share/constants.go | 50 + sdk/storage/azfile/share/examples_test.go | 464 +++ sdk/storage/azfile/share/models.go | 312 ++ sdk/storage/azfile/share/responses.go | 45 + sdk/storage/azfile/test-resources.json | 579 +++ sdk/storage/azqueue/CHANGELOG.md | 9 +- sdk/storage/azqueue/README.md | 18 +- .../azqueue/internal/exported/version.go | 2 +- 476 files changed, 60240 insertions(+), 24542 deletions(-) create mode 100644 sdk/azcore/arm/runtime/policy_trace_namespace.go create mode 100644 sdk/azcore/arm/runtime/policy_trace_namespace_test.go create mode 100644 sdk/azcore/fake/example_test.go create mode 100644 sdk/azcore/fake/fake.go create mode 100644 sdk/azcore/fake/fake_test.go create mode 100644 sdk/azcore/internal/pollers/fake/fake.go create mode 100644 sdk/azcore/internal/pollers/fake/fake_test.go create mode 100644 sdk/azcore/runtime/policy_http_trace.go create mode 100644 sdk/azcore/runtime/policy_http_trace_test.go create mode 100644 sdk/data/azcosmos/sdk_capabilities.go delete mode 100644 sdk/messaging/azeventhubs/internal/go-amqp/conn.go delete mode 100644 sdk/messaging/azeventhubs/internal/go-amqp/const.go delete mode 100644 sdk/messaging/azeventhubs/internal/go-amqp/creditor.go delete mode 100644 sdk/messaging/azeventhubs/internal/go-amqp/errors.go delete mode 100644 sdk/messaging/azeventhubs/internal/go-amqp/internal/bitmap/bitmap.go delete mode 100644 sdk/messaging/azeventhubs/internal/go-amqp/internal/buffer/buffer.go delete mode 100644 sdk/messaging/azeventhubs/internal/go-amqp/internal/debug/debug.go delete mode 100644 sdk/messaging/azeventhubs/internal/go-amqp/internal/debug/debug_debug.go delete mode 100644 sdk/messaging/azeventhubs/internal/go-amqp/internal/encoding/decode.go delete mode 100644 sdk/messaging/azeventhubs/internal/go-amqp/internal/encoding/encode.go delete mode 100644 sdk/messaging/azeventhubs/internal/go-amqp/internal/encoding/types.go delete mode 100644 sdk/messaging/azeventhubs/internal/go-amqp/internal/frames/frames.go delete mode 100644 sdk/messaging/azeventhubs/internal/go-amqp/internal/frames/parsing.go delete mode 100644 sdk/messaging/azeventhubs/internal/go-amqp/internal/queue/queue.go delete mode 100644 sdk/messaging/azeventhubs/internal/go-amqp/internal/shared/shared.go delete mode 100644 sdk/messaging/azeventhubs/internal/go-amqp/link.go delete mode 100644 sdk/messaging/azeventhubs/internal/go-amqp/link_options.go delete mode 100644 sdk/messaging/azeventhubs/internal/go-amqp/message.go delete mode 100644 sdk/messaging/azeventhubs/internal/go-amqp/receiver.go delete mode 100644 sdk/messaging/azeventhubs/internal/go-amqp/sasl.go delete mode 100644 sdk/messaging/azeventhubs/internal/go-amqp/sender.go delete mode 100644 sdk/messaging/azeventhubs/internal/go-amqp/session.go delete mode 100644 sdk/messaging/azservicebus/internal/go-amqp/LICENSE delete mode 100644 sdk/messaging/azservicebus/internal/go-amqp/conn.go delete mode 100644 sdk/messaging/azservicebus/internal/go-amqp/const.go delete mode 100644 sdk/messaging/azservicebus/internal/go-amqp/creditor.go delete mode 100644 sdk/messaging/azservicebus/internal/go-amqp/errors.go delete mode 100644 sdk/messaging/azservicebus/internal/go-amqp/internal/bitmap/bitmap.go delete mode 100644 sdk/messaging/azservicebus/internal/go-amqp/internal/buffer/buffer.go delete mode 100644 sdk/messaging/azservicebus/internal/go-amqp/internal/debug/debug.go delete mode 100644 sdk/messaging/azservicebus/internal/go-amqp/internal/debug/debug_debug.go delete mode 100644 sdk/messaging/azservicebus/internal/go-amqp/internal/encoding/decode.go delete mode 100644 sdk/messaging/azservicebus/internal/go-amqp/internal/encoding/encode.go delete mode 100644 sdk/messaging/azservicebus/internal/go-amqp/internal/encoding/types.go delete mode 100644 sdk/messaging/azservicebus/internal/go-amqp/internal/frames/frames.go delete mode 100644 sdk/messaging/azservicebus/internal/go-amqp/internal/frames/parsing.go delete mode 100644 sdk/messaging/azservicebus/internal/go-amqp/internal/queue/queue.go delete mode 100644 sdk/messaging/azservicebus/internal/go-amqp/internal/shared/shared.go delete mode 100644 sdk/messaging/azservicebus/internal/go-amqp/link.go delete mode 100644 sdk/messaging/azservicebus/internal/go-amqp/link_options.go delete mode 100644 sdk/messaging/azservicebus/internal/go-amqp/message.go delete mode 100644 sdk/messaging/azservicebus/internal/go-amqp/receiver.go delete mode 100644 sdk/messaging/azservicebus/internal/go-amqp/sasl.go delete mode 100644 sdk/messaging/azservicebus/internal/go-amqp/sender.go delete mode 100644 sdk/messaging/azservicebus/internal/go-amqp/session.go create mode 100644 sdk/messaging/azservicebus/internal/utils/logger.go create mode 100644 sdk/monitor/azquery/MIGRATION.md create mode 100644 sdk/resourcemanager/compute/armcompute/availabilityset_live_test.go delete mode 100644 sdk/resourcemanager/compute/armcompute/availabilitysets_client_live_test.go create mode 100644 sdk/resourcemanager/compute/armcompute/capacityreservation_live_test.go create mode 100644 sdk/resourcemanager/compute/armcompute/computerpcommon_live_test.go create mode 100644 sdk/resourcemanager/compute/armcompute/dedicatedhost_live_test.go create mode 100644 sdk/resourcemanager/compute/armcompute/disk_live_test.go create mode 100644 sdk/resourcemanager/compute/armcompute/diskaccess_live_test.go create mode 100644 sdk/resourcemanager/compute/armcompute/gallery_live_test.go create mode 100644 sdk/resourcemanager/compute/armcompute/proximityplacementgroup_live_test.go create mode 100644 sdk/resourcemanager/compute/armcompute/restorepoint_live_test.go create mode 100644 sdk/resourcemanager/compute/armcompute/runcommand_live_test.go create mode 100644 sdk/resourcemanager/compute/armcompute/skus_live_test.go create mode 100644 sdk/resourcemanager/compute/armcompute/snapshot_live_test.go create mode 100644 sdk/resourcemanager/compute/armcompute/sshpublickey_live_test.go create mode 100644 sdk/resourcemanager/compute/armcompute/virtualmachine_live_test.go create mode 100644 sdk/resourcemanager/compute/armcompute/virtualmachineextensionimage_live_test.go create mode 100644 sdk/resourcemanager/compute/armcompute/virtualmachineimage_live_test.go delete mode 100644 sdk/resourcemanager/compute/armcompute/virtualmachines_client_live_test.go create mode 100644 sdk/resourcemanager/compute/armcompute/virtualmachinescaleset_live_test.go delete mode 100644 sdk/resourcemanager/compute/armcompute/virtualmachinescalesets_client_live_test.go create mode 100644 sdk/resourcemanager/cosmos/armcosmos/cassandraresources_live_test.go create mode 100644 sdk/resourcemanager/cosmos/armcosmos/databaseaccounts_live_test.go create mode 100644 sdk/resourcemanager/cosmos/armcosmos/gremlinresources_live_test.go create mode 100644 sdk/resourcemanager/cosmos/armcosmos/mongodbresources_live_test.go create mode 100644 sdk/resourcemanager/cosmos/armcosmos/operations_live_test.go create mode 100644 sdk/resourcemanager/cosmos/armcosmos/privateendpointconnection_live_test.go create mode 100644 sdk/resourcemanager/cosmos/armcosmos/services_live_test.go create mode 100644 sdk/resourcemanager/cosmos/armcosmos/sqlresources_live_test.go create mode 100644 sdk/resourcemanager/cosmos/armcosmos/tableresources_live_test.go create mode 100644 sdk/resourcemanager/eventhub/armeventhub/privateendpointconnections_live_test.go create mode 100644 sdk/resourcemanager/network/armnetwork/applicationgatewaywafdynamicmanifests_live_test.go create mode 100644 sdk/resourcemanager/network/armnetwork/applicationsecuritygroup_live_test.go create mode 100644 sdk/resourcemanager/network/armnetwork/availabledelegations_live_test.go create mode 100644 sdk/resourcemanager/network/armnetwork/availableservicealiases_live_test.go create mode 100644 sdk/resourcemanager/network/armnetwork/azurefirewallfqdntag_live_test.go create mode 100644 sdk/resourcemanager/network/armnetwork/azurewebcategory_live_test.go create mode 100644 sdk/resourcemanager/network/armnetwork/bastionhost_live_test.go create mode 100644 sdk/resourcemanager/network/armnetwork/checkdnsavailability_live_test.go create mode 100644 sdk/resourcemanager/network/armnetwork/customipprefix_live_test.go create mode 100644 sdk/resourcemanager/network/armnetwork/ddosprotectionplan_live_test.go create mode 100644 sdk/resourcemanager/network/armnetwork/endpointservice_live_test.go create mode 100644 sdk/resourcemanager/network/armnetwork/expressroutecircuit_live_test.go create mode 100644 sdk/resourcemanager/network/armnetwork/firewallpolicy_live_test.go delete mode 100644 sdk/resourcemanager/network/armnetwork/ipgroups_client_live_test.go create mode 100644 sdk/resourcemanager/network/armnetwork/ipgroups_live_test.go create mode 100644 sdk/resourcemanager/network/armnetwork/loadbalancer_live_test.go create mode 100644 sdk/resourcemanager/network/armnetwork/natgateway_live_test.go create mode 100644 sdk/resourcemanager/network/armnetwork/networkinterface_live_test.go create mode 100644 sdk/resourcemanager/network/armnetwork/networkmanager_live_test.go create mode 100644 sdk/resourcemanager/network/armnetwork/networkmanagerconnection_live_test.go create mode 100644 sdk/resourcemanager/network/armnetwork/networkmanagerconnectivityconfiguration_live_test.go create mode 100644 sdk/resourcemanager/network/armnetwork/networkmanagergroup_live_test.go create mode 100644 sdk/resourcemanager/network/armnetwork/networkmanagersecurityadminconfiguration_live_test.go create mode 100644 sdk/resourcemanager/network/armnetwork/networkprofile_live_test.go create mode 100644 sdk/resourcemanager/network/armnetwork/networksecuritygroup_live_test.go create mode 100644 sdk/resourcemanager/network/armnetwork/networkwatcher_live_test.go create mode 100644 sdk/resourcemanager/network/armnetwork/operation_live_test.go create mode 100644 sdk/resourcemanager/network/armnetwork/publicipaddress_live_test.go create mode 100644 sdk/resourcemanager/network/armnetwork/publicipprefix_live_test.go create mode 100644 sdk/resourcemanager/network/armnetwork/routetable_live_test.go create mode 100644 sdk/resourcemanager/network/armnetwork/servicecommunity_live_test.go create mode 100644 sdk/resourcemanager/network/armnetwork/serviceendpointpolicy_live_test.go create mode 100644 sdk/resourcemanager/network/armnetwork/servicetags_live_test.go delete mode 100644 sdk/resourcemanager/network/armnetwork/subnets_client_live_test.go create mode 100644 sdk/resourcemanager/network/armnetwork/usage_live_test.go create mode 100644 sdk/resourcemanager/network/armnetwork/virtualnetwork_live_test.go create mode 100644 sdk/resourcemanager/network/armnetwork/virtualnetworkgateway_live_test.go delete mode 100644 sdk/resourcemanager/network/armnetwork/virtualnetworks_client_live_test.go create mode 100644 sdk/resourcemanager/network/armnetwork/virtualwan_live_test.go create mode 100644 sdk/resourcemanager/network/armnetwork/webapplicationfirewall_live_test.go create mode 100644 sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/CHANGELOG.md create mode 100644 sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/LICENSE.txt create mode 100644 sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/README.md create mode 100644 sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/autorest.md create mode 100644 sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/build.go create mode 100644 sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/certificateobjectglobalrulestack_client.go create mode 100644 sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/certificateobjectglobalrulestack_client_example_test.go create mode 100644 sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/certificateobjectlocalrulestack_client.go create mode 100644 sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/certificateobjectlocalrulestack_client_example_test.go create mode 100644 sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/ci.yml create mode 100644 sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/client_factory.go create mode 100644 sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/constants.go create mode 100644 sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/firewalls_client.go create mode 100644 sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/firewalls_client_example_test.go create mode 100644 sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/firewallstatus_client.go create mode 100644 sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/firewallstatus_client_example_test.go create mode 100644 sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/fqdnlistglobalrulestack_client.go create mode 100644 sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/fqdnlistglobalrulestack_client_example_test.go create mode 100644 sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/fqdnlistlocalrulestack_client.go create mode 100644 sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/fqdnlistlocalrulestack_client_example_test.go create mode 100644 sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/globalrulestack_client.go create mode 100644 sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/globalrulestack_client_example_test.go create mode 100644 sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/go.mod create mode 100644 sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/go.sum create mode 100644 sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/localrules_client.go create mode 100644 sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/localrules_client_example_test.go create mode 100644 sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/localrulestacks_client.go create mode 100644 sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/localrulestacks_client_example_test.go create mode 100644 sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/models.go create mode 100644 sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/models_serde.go create mode 100644 sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/operations_client.go create mode 100644 sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/operations_client_example_test.go create mode 100644 sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/postrules_client.go create mode 100644 sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/postrules_client_example_test.go create mode 100644 sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/prefixlistglobalrulestack_client.go create mode 100644 sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/prefixlistglobalrulestack_client_example_test.go create mode 100644 sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/prefixlistlocalrulestack_client.go create mode 100644 sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/prefixlistlocalrulestack_client_example_test.go create mode 100644 sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/prerules_client.go create mode 100644 sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/prerules_client_example_test.go create mode 100644 sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/response_types.go create mode 100644 sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/time_rfc3339.go create mode 100644 sdk/resourcemanager/postgresql/armpostgresql/privateendpointconnections_live_test.go create mode 100644 sdk/resourcemanager/postgresql/armpostgresql/serversecurityalertpolicies_live_test.go create mode 100644 sdk/storage/azfile/CHANGELOG.md rename sdk/{messaging/azeventhubs/internal/go-amqp/LICENSE => storage/azfile/LICENSE.txt} (91%) create mode 100644 sdk/storage/azfile/README.md create mode 100644 sdk/storage/azfile/assets.json create mode 100644 sdk/storage/azfile/ci.yml create mode 100644 sdk/storage/azfile/directory/client.go create mode 100644 sdk/storage/azfile/directory/client_test.go create mode 100644 sdk/storage/azfile/directory/constants.go create mode 100644 sdk/storage/azfile/directory/examples_test.go create mode 100644 sdk/storage/azfile/directory/models.go create mode 100644 sdk/storage/azfile/directory/responses.go create mode 100644 sdk/storage/azfile/doc.go create mode 100644 sdk/storage/azfile/file/chunkwriting.go create mode 100644 sdk/storage/azfile/file/client.go create mode 100644 sdk/storage/azfile/file/client_test.go create mode 100644 sdk/storage/azfile/file/constants.go create mode 100644 sdk/storage/azfile/file/examples_test.go create mode 100644 sdk/storage/azfile/file/mmf_unix.go create mode 100644 sdk/storage/azfile/file/mmf_windows.go create mode 100644 sdk/storage/azfile/file/models.go create mode 100644 sdk/storage/azfile/file/responses.go create mode 100644 sdk/storage/azfile/file/retry_reader.go create mode 100644 sdk/storage/azfile/fileerror/error_codes.go create mode 100644 sdk/storage/azfile/go.mod create mode 100644 sdk/storage/azfile/go.sum create mode 100644 sdk/storage/azfile/internal/base/clients.go create mode 100644 sdk/storage/azfile/internal/exported/access_policy.go create mode 100644 sdk/storage/azfile/internal/exported/copy_file_smb_options.go create mode 100644 sdk/storage/azfile/internal/exported/exported.go create mode 100644 sdk/storage/azfile/internal/exported/file_permissions.go create mode 100644 sdk/storage/azfile/internal/exported/log_events.go create mode 100644 sdk/storage/azfile/internal/exported/shared_key_credential.go create mode 100644 sdk/storage/azfile/internal/exported/smb_property.go create mode 100644 sdk/storage/azfile/internal/exported/transfer_validation_option.go create mode 100644 sdk/storage/azfile/internal/exported/version.go create mode 100644 sdk/storage/azfile/internal/generated/autorest.md create mode 100644 sdk/storage/azfile/internal/generated/build.go create mode 100644 sdk/storage/azfile/internal/generated/directory_client.go create mode 100644 sdk/storage/azfile/internal/generated/file_client.go create mode 100644 sdk/storage/azfile/internal/generated/models.go create mode 100644 sdk/storage/azfile/internal/generated/service_client.go create mode 100644 sdk/storage/azfile/internal/generated/share_client.go create mode 100644 sdk/storage/azfile/internal/generated/zz_constants.go create mode 100644 sdk/storage/azfile/internal/generated/zz_directory_client.go create mode 100644 sdk/storage/azfile/internal/generated/zz_file_client.go create mode 100644 sdk/storage/azfile/internal/generated/zz_models.go create mode 100644 sdk/storage/azfile/internal/generated/zz_models_serde.go create mode 100644 sdk/storage/azfile/internal/generated/zz_response_types.go create mode 100644 sdk/storage/azfile/internal/generated/zz_service_client.go create mode 100644 sdk/storage/azfile/internal/generated/zz_share_client.go create mode 100644 sdk/storage/azfile/internal/generated/zz_time_rfc1123.go create mode 100644 sdk/storage/azfile/internal/generated/zz_time_rfc3339.go create mode 100644 sdk/storage/azfile/internal/generated/zz_xml_helper.go create mode 100644 sdk/storage/azfile/internal/shared/batch_transfer.go create mode 100644 sdk/storage/azfile/internal/shared/bytes_writer.go create mode 100644 sdk/storage/azfile/internal/shared/bytes_writer_test.go create mode 100644 sdk/storage/azfile/internal/shared/section_writer.go create mode 100644 sdk/storage/azfile/internal/shared/section_writer_test.go create mode 100644 sdk/storage/azfile/internal/shared/shared.go create mode 100644 sdk/storage/azfile/internal/shared/shared_test.go create mode 100644 sdk/storage/azfile/internal/testcommon/clients_auth.go create mode 100644 sdk/storage/azfile/internal/testcommon/common.go create mode 100644 sdk/storage/azfile/lease/client_test.go create mode 100644 sdk/storage/azfile/lease/constants.go create mode 100644 sdk/storage/azfile/lease/examples_test.go create mode 100644 sdk/storage/azfile/lease/file_client.go create mode 100644 sdk/storage/azfile/lease/models.go create mode 100644 sdk/storage/azfile/lease/responses.go create mode 100644 sdk/storage/azfile/lease/share_client.go create mode 100644 sdk/storage/azfile/log.go create mode 100644 sdk/storage/azfile/sas/account.go create mode 100644 sdk/storage/azfile/sas/account_test.go create mode 100644 sdk/storage/azfile/sas/query_params.go create mode 100644 sdk/storage/azfile/sas/query_params_test.go create mode 100644 sdk/storage/azfile/sas/service.go create mode 100644 sdk/storage/azfile/sas/service_test.go create mode 100644 sdk/storage/azfile/sas/url_parts.go create mode 100644 sdk/storage/azfile/sas/url_parts_test.go create mode 100644 sdk/storage/azfile/service/client.go create mode 100644 sdk/storage/azfile/service/client_test.go create mode 100644 sdk/storage/azfile/service/constants.go create mode 100644 sdk/storage/azfile/service/examples_test.go create mode 100644 sdk/storage/azfile/service/models.go create mode 100644 sdk/storage/azfile/service/responses.go create mode 100644 sdk/storage/azfile/share/client.go create mode 100644 sdk/storage/azfile/share/client_test.go create mode 100644 sdk/storage/azfile/share/constants.go create mode 100644 sdk/storage/azfile/share/examples_test.go create mode 100644 sdk/storage/azfile/share/models.go create mode 100644 sdk/storage/azfile/share/responses.go create mode 100644 sdk/storage/azfile/test-resources.json diff --git a/.github/workflows/event-processor.yml b/.github/workflows/event-processor.yml index f974387634c1..befc1d9a2e31 100644 --- a/.github/workflows/event-processor.yml +++ b/.github/workflows/event-processor.yml @@ -11,8 +11,6 @@ on: # pull request merged is the closed event with github.event.pull_request.merged = true pull_request_target: types: [closed, labeled, opened, reopened, review_requested, synchronize, unlabeled] - pull_request_review: - types: [submitted] # This removes all unnecessary permissions, the ones needed will be set below. # https://docs.github.com/en/actions/security-guides/automatic-token-authentication#permissions-for-the-github_token @@ -57,7 +55,7 @@ jobs: run: > dotnet tool install Azure.Sdk.Tools.GitHubEventProcessor - --version 1.0.0-dev.20230422.1 + --version 1.0.0-dev.20230505.2 --add-source https://pkgs.dev.azure.com/azure-sdk/public/_packaging/azure-sdk-for-net/nuget/v3/index.json --global shell: bash diff --git a/.github/workflows/scheduled-event-processor.yml b/.github/workflows/scheduled-event-processor.yml index 8b79f66e7d2c..53181c5a418c 100644 --- a/.github/workflows/scheduled-event-processor.yml +++ b/.github/workflows/scheduled-event-processor.yml @@ -34,7 +34,7 @@ jobs: run: > dotnet tool install Azure.Sdk.Tools.GitHubEventProcessor - --version 1.0.0-dev.20230422.1 + --version 1.0.0-dev.20230505.2 --add-source https://pkgs.dev.azure.com/azure-sdk/public/_packaging/azure-sdk-for-net/nuget/v3/index.json --global shell: bash diff --git a/eng/.golangci.yml b/eng/.golangci.yml index e4e98907a911..c02d708f5a68 100644 --- a/eng/.golangci.yml +++ b/eng/.golangci.yml @@ -3,3 +3,13 @@ run: # default is true. Enables skipping of directories: # vendor$, third_party$, testdata$, examples$, Godeps$, builtin$ skip-dirs-use-default: true + timeout: 10m + +linters: + enable: + - gocritic + +linters-settings: + gocritic: + enabled-checks: + - evalOrder diff --git a/eng/common/pipelines/templates/steps/detect-api-changes.yml b/eng/common/pipelines/templates/steps/detect-api-changes.yml index 833175ad7543..5210ebbe4b61 100644 --- a/eng/common/pipelines/templates/steps/detect-api-changes.yml +++ b/eng/common/pipelines/templates/steps/detect-api-changes.yml @@ -1,6 +1,7 @@ parameters: ArtifactPath: $(Build.ArtifactStagingDirectory) Artifacts: [] + ArtifactName: 'packages' steps: - pwsh: | @@ -20,6 +21,7 @@ steps: -PullRequestNumber $(System.PullRequest.PullRequestNumber) -RepoFullName $(Build.Repository.Name) -APIViewUri $(ApiChangeDetectRequestUrl) + -ArtifactName ${{ parameters.ArtifactName }} pwsh: true displayName: Detect API changes condition: and(succeededOrFailed(), eq(variables['Build.Reason'],'PullRequest')) diff --git a/eng/common/pipelines/templates/steps/eng-common-workflow-enforcer.yml b/eng/common/pipelines/templates/steps/eng-common-workflow-enforcer.yml index ff4927b8bb5f..af8b009b5825 100644 --- a/eng/common/pipelines/templates/steps/eng-common-workflow-enforcer.yml +++ b/eng/common/pipelines/templates/steps/eng-common-workflow-enforcer.yml @@ -19,5 +19,15 @@ steps: exit 1 } } - displayName: Prevent changes to eng/common outside of azure-sdk-tools repo + if ((!"$(System.PullRequest.SourceBranch)".StartsWith("sync-.github/workflows")) -and "$(System.PullRequest.TargetBranch)" -match "^(refs/heads/)?$(DefaultBranch)$") + { + $filesInCommonDir = & "eng/common/scripts/get-changedfiles.ps1" -DiffPath '.github/workflows/*' + if (($LASTEXITCODE -eq 0) -and ($filesInCommonDir.Count -gt 0)) + { + Write-Host "##vso[task.LogIssue type=error;]Changes to files under '.github/workflows' directory should not be made in this Repo`n${filesInCommonDir}" + Write-Host "##vso[task.LogIssue type=error;]Please follow workflow at https://github.com/Azure/azure-sdk-tools/blob/main/doc/workflows/engsys_workflows.md" + exit 1 + } + } + displayName: Prevent changes to eng/common and .github/workflows outside of azure-sdk-tools repo condition: and(succeeded(), ne(variables['Skip.EngCommonWorkflowEnforcer'], 'true'), not(endsWith(variables['Build.Repository.Name'], '-pr'))) \ No newline at end of file diff --git a/eng/common/scripts/Delete-RemoteBranches.ps1 b/eng/common/scripts/Delete-RemoteBranches.ps1 index 2d1c3c303316..49cc85cbe909 100644 --- a/eng/common/scripts/Delete-RemoteBranches.ps1 +++ b/eng/common/scripts/Delete-RemoteBranches.ps1 @@ -10,6 +10,7 @@ param( $CentralRepoId, # We start from the sync PRs, use the branch name to get the PR number of central repo. E.g. sync-eng/common-()-(). Have group name on PR number. # For sync-eng/common work, we use regex as "^sync-eng/common.*-(?\d+).*$". + # For sync-.github/workflows work, we use regex as "^sync-.github/workflows.*-(?\d+).*$". $BranchRegex, # Date format: e.g. Tuesday, April 12, 2022 1:36:02 PM. Allow to use other date format. [AllowNull()] @@ -69,7 +70,7 @@ foreach ($res in $responses) LogError "No PR number found in the branch name. Please check the branch name [ $branchName ]. Skipping..." continue } - + try { $centralPR = Get-GitHubPullRequest -RepoId $CentralRepoId -PullRequestNumber $pullRequestNumber -AuthToken $AuthToken LogDebug "Found central PR pull request: $($centralPR.html_url)" @@ -78,7 +79,7 @@ foreach ($res in $responses) continue } } - catch + catch { # If there is no central PR for the PR number, log error and skip. LogError "Get-GitHubPullRequests failed with exception:`n$_" @@ -107,15 +108,15 @@ foreach ($res in $responses) LogDebug "The branch $branch last commit date [ $commitDate ] is newer than the date $LastCommitOlderThan. Skipping." continue } - + LogDebug "Branch [ $branchName ] in repo [ $RepoId ] has a last commit date [ $commitDate ] that is older than $LastCommitOlderThan. " } catch { LogError "Get-GithubReferenceCommitDate failed with exception:`n$_" exit 1 } - } - + } + try { if ($PSCmdlet.ShouldProcess("[ $branchName ] in [ $RepoId ]", "Deleting branches on cleanup script")) { Remove-GitHubSourceReferences -RepoId $RepoId -Ref $branch -AuthToken $AuthToken diff --git a/eng/common/testproxy/target_version.txt b/eng/common/testproxy/target_version.txt index 5f4443c2a943..2e1adf9ccc4b 100644 --- a/eng/common/testproxy/target_version.txt +++ b/eng/common/testproxy/target_version.txt @@ -1 +1 @@ -1.0.0-dev.20230417.1 +1.0.0-dev.20230427.1 diff --git a/eng/common/testproxy/transition-scripts/README.md b/eng/common/testproxy/transition-scripts/README.md index 06290bd0c784..09c2b364f0f3 100644 --- a/eng/common/testproxy/transition-scripts/README.md +++ b/eng/common/testproxy/transition-scripts/README.md @@ -46,7 +46,7 @@ To utilize this methodology, the user must set input argument `TestProxyExe` to Other requirements: -- [x] Install [docker](https://docs.docker.com/engine/install/) or [podman](https://podman.io/getting-started/installation.html) +- [x] Install [docker](https://docs.docker.com/engine/install/) or [podman](https://podman.io/) - [x] Set the environment variable `GIT_TOKEN` a valid token representing YOUR user ## Permissions diff --git a/eng/config.json b/eng/config.json index cc51b095a269..09645b7b7bd1 100644 --- a/eng/config.json +++ b/eng/config.json @@ -28,6 +28,10 @@ "Name": "azqueue", "CoverageGoal": 0.60 }, + { + "Name": "azfile", + "CoverageGoal": 0.75 + }, { "Name": "aztemplate", "CoverageGoal": 0.50 diff --git a/eng/pipelines/templates/variables/globals.yml b/eng/pipelines/templates/variables/globals.yml index 071313330e97..98f4404689df 100644 --- a/eng/pipelines/templates/variables/globals.yml +++ b/eng/pipelines/templates/variables/globals.yml @@ -1,5 +1,5 @@ variables: - GoLintCLIVersion: 'v1.51.1' + GoLintCLIVersion: 'v1.52.2' Package.EnableSBOMSigning: true # Enable go native component governance detection # https://docs.opensource.microsoft.com/tools/cg/index.html diff --git a/eng/tools/generator/cmd/v2/common/fileProcessor.go b/eng/tools/generator/cmd/v2/common/fileProcessor.go index 6b8730746ae6..1636f36bbe5c 100644 --- a/eng/tools/generator/cmd/v2/common/fileProcessor.go +++ b/eng/tools/generator/cmd/v2/common/fileProcessor.go @@ -94,9 +94,9 @@ func ReadV2ModuleNameToGetNamespace(path string) (map[string][]PackageInfo, erro return nil, fmt.Errorf("last `track2` section does not properly end") } - s := strings.ReplaceAll(path, "\\", "/") - s1 := strings.Split(s, "/") - specName := s1[len(s1)-3] + _, after, _ := strings.Cut(strings.ReplaceAll(path, "\\", "/"), "specification") + before, _, _ := strings.Cut(after, "resource-manager") + specName := strings.Trim(before, "/") for i := range start { // get the content of the `track2` section diff --git a/sdk/azcore/CHANGELOG.md b/sdk/azcore/CHANGELOG.md index eb50de41dee3..c5c1daa74b55 100644 --- a/sdk/azcore/CHANGELOG.md +++ b/sdk/azcore/CHANGELOG.md @@ -1,8 +1,19 @@ # Release History -## 1.5.1 (Unreleased) +## 1.6.1 (Unreleased) ### Features Added +* Added supporting features to enable distributed tracing. + * Added func `runtime.StartSpan()` for use by SDKs to start spans. + * Added method `WithContext()` to `runtime.Request` to support shallow cloning with a new context. + * Added field `TracingNamespace` to `runtime.PipelineOptions`. + * Added field `Tracer` to `runtime.NewPollerOptions` and `runtime.NewPollerFromResumeTokenOptions` types. + * Added field `SpanFromContext` to `tracing.TracerOptions`. + * Added methods `Enabled()`, `SetAttributes()`, and `SpanFromContext()` to `tracing.Tracer`. + * Added supporting pipeline policies to include HTTP spans when creating clients. +* Added package `fake` to support generated fakes packages in SDKs. + * The package contains public surface area exposed by fake servers and supporting APIs intended only for use by the fake server implementations. + * Added an internal fake poller implementation. ### Breaking Changes @@ -10,6 +21,12 @@ ### Other Changes +## 1.6.0 (2023-05-04) + +### Features Added +* Added support for ARM cross-tenant authentication. Set the `AuxiliaryTenants` field of `arm.ClientOptions` to enable. +* Added `TenantID` field to `policy.TokenRequestOptions`. + ## 1.5.0 (2023-04-06) ### Features Added diff --git a/sdk/azcore/arm/runtime/pipeline.go b/sdk/azcore/arm/runtime/pipeline.go index 266c74b17bf1..302c19cd4265 100644 --- a/sdk/azcore/arm/runtime/pipeline.go +++ b/sdk/azcore/arm/runtime/pipeline.go @@ -13,6 +13,7 @@ import ( "github.com/Azure/azure-sdk-for-go/sdk/azcore" armpolicy "github.com/Azure/azure-sdk-for-go/sdk/azcore/arm/policy" "github.com/Azure/azure-sdk-for-go/sdk/azcore/cloud" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/exported" azpolicy "github.com/Azure/azure-sdk-for-go/sdk/azcore/policy" azruntime "github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime" ) @@ -34,7 +35,7 @@ func NewPipeline(module, version string, cred azcore.TokenCredential, plOpts azr }) perRetry := make([]azpolicy.Policy, len(plOpts.PerRetry), len(plOpts.PerRetry)+1) copy(perRetry, plOpts.PerRetry) - plOpts.PerRetry = append(perRetry, authPolicy) + plOpts.PerRetry = append(perRetry, authPolicy, exported.PolicyFunc(httpTraceNamespacePolicy)) if !options.DisableRPRegistration { regRPOpts := armpolicy.RegistrationOptions{ClientOptions: options.ClientOptions} regPolicy, err := NewRPRegistrationPolicy(cred, ®RPOpts) diff --git a/sdk/azcore/arm/runtime/policy_bearer_token.go b/sdk/azcore/arm/runtime/policy_bearer_token.go index 07f15991eb27..83f1bf86e65e 100644 --- a/sdk/azcore/arm/runtime/policy_bearer_token.go +++ b/sdk/azcore/arm/runtime/policy_bearer_token.go @@ -5,6 +5,7 @@ package runtime import ( "context" + "encoding/base64" "fmt" "net/http" "strings" @@ -63,11 +64,28 @@ func NewBearerTokenPolicy(cred azcore.TokenCredential, opts *armpolicy.BearerTok p.scopes = make([]string, len(opts.Scopes)) copy(p.scopes, opts.Scopes) p.btp = azruntime.NewBearerTokenPolicy(cred, opts.Scopes, &azpolicy.BearerTokenOptions{ - AuthorizationHandler: azpolicy.AuthorizationHandler{OnRequest: p.onRequest}, + AuthorizationHandler: azpolicy.AuthorizationHandler{ + OnChallenge: p.onChallenge, + OnRequest: p.onRequest, + }, }) return p } +func (b *BearerTokenPolicy) onChallenge(req *azpolicy.Request, res *http.Response, authNZ func(azpolicy.TokenRequestOptions) error) error { + challenge := res.Header.Get(shared.HeaderWWWAuthenticate) + claims, err := parseChallenge(challenge) + if err != nil { + // the challenge contains claims we can't parse + return err + } else if claims != "" { + // request a new token having the specified claims, send the request again + return authNZ(azpolicy.TokenRequestOptions{Claims: claims, Scopes: b.scopes}) + } + // auth challenge didn't include claims, so this is a simple authorization failure + return azruntime.NewResponseError(res) +} + // onRequest authorizes requests with one or more bearer tokens func (b *BearerTokenPolicy) onRequest(req *azpolicy.Request, authNZ func(azpolicy.TokenRequestOptions) error) error { // authorize the request with a token for the primary tenant @@ -97,3 +115,31 @@ func (b *BearerTokenPolicy) onRequest(req *azpolicy.Request, authNZ func(azpolic func (b *BearerTokenPolicy) Do(req *azpolicy.Request) (*http.Response, error) { return b.btp.Do(req) } + +// parseChallenge parses claims from an authentication challenge issued by ARM so a client can request a token +// that will satisfy conditional access policies. It returns a non-nil error when the given value contains +// claims it can't parse. If the value contains no claims, it returns an empty string and a nil error. +func parseChallenge(wwwAuthenticate string) (string, error) { + claims := "" + var err error + for _, param := range strings.Split(wwwAuthenticate, ",") { + if _, after, found := strings.Cut(param, "claims="); found { + if claims != "" { + // The header contains multiple challenges, at least two of which specify claims. The specs allow this + // but it's unclear what a client should do in this case and there's as yet no concrete example of it. + err = fmt.Errorf("found multiple claims challenges in %q", wwwAuthenticate) + break + } + // trim stuff that would get an error from RawURLEncoding; claims may or may not be padded + claims = strings.Trim(after, `\"=`) + // we don't return this error because it's something unhelpful like "illegal base64 data at input byte 42" + if b, decErr := base64.RawURLEncoding.DecodeString(claims); decErr == nil { + claims = string(b) + } else { + err = fmt.Errorf("failed to parse claims from %q", wwwAuthenticate) + break + } + } + } + return claims, err +} diff --git a/sdk/azcore/arm/runtime/policy_bearer_token_test.go b/sdk/azcore/arm/runtime/policy_bearer_token_test.go index 8357beb24c1b..1ab06ae00d76 100644 --- a/sdk/azcore/arm/runtime/policy_bearer_token_test.go +++ b/sdk/azcore/arm/runtime/policy_bearer_token_test.go @@ -203,7 +203,6 @@ func TestAuxiliaryTenants(t *testing.T) { } func TestBearerTokenPolicyChallengeParsing(t *testing.T) { - t.Skip("unskip this test after adding back CAE support") for _, test := range []struct { challenge, desc, expectedClaims string err error @@ -262,10 +261,9 @@ func TestBearerTokenPolicyChallengeParsing(t *testing.T) { cred := mockCredential{ getTokenImpl: func(ctx context.Context, actual azpolicy.TokenRequestOptions) (azcore.AccessToken, error) { calls += 1 - // TODO: uncomment after restoring TokenRequestOptions.Claims - // if calls == 2 && test.expectedClaims != "" { - // require.Equal(t, test.expectedClaims, actual.Claims) - // } + if calls == 2 && test.expectedClaims != "" { + require.Equal(t, test.expectedClaims, actual.Claims) + } return azcore.AccessToken{Token: "...", ExpiresOn: time.Now().Add(time.Hour).UTC()}, nil }, } diff --git a/sdk/azcore/arm/runtime/policy_trace_namespace.go b/sdk/azcore/arm/runtime/policy_trace_namespace.go new file mode 100644 index 000000000000..76aefe8550dd --- /dev/null +++ b/sdk/azcore/arm/runtime/policy_trace_namespace.go @@ -0,0 +1,31 @@ +//go:build go1.18 +// +build go1.18 + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package runtime + +import ( + "net/http" + + "github.com/Azure/azure-sdk-for-go/sdk/azcore/arm/internal/resource" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/shared" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/policy" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/tracing" +) + +// httpTraceNamespacePolicy is a policy that adds the az.namespace attribute to the current Span +func httpTraceNamespacePolicy(req *policy.Request) (resp *http.Response, err error) { + rawTracer := req.Raw().Context().Value(shared.CtxWithTracingTracer{}) + if tracer, ok := rawTracer.(tracing.Tracer); ok { + rt, err := resource.ParseResourceType(req.Raw().URL.Path) + if err == nil { + // add the namespace attribute to the current span + if span, ok := tracer.SpanFromContext(req.Raw().Context()); ok { + span.SetAttributes(tracing.Attribute{Key: "az.namespace", Value: rt.Namespace}) + } + } + } + return req.Next() +} diff --git a/sdk/azcore/arm/runtime/policy_trace_namespace_test.go b/sdk/azcore/arm/runtime/policy_trace_namespace_test.go new file mode 100644 index 000000000000..4ac7484823f8 --- /dev/null +++ b/sdk/azcore/arm/runtime/policy_trace_namespace_test.go @@ -0,0 +1,97 @@ +//go:build go1.18 +// +build go1.18 + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package runtime + +import ( + "context" + "net/http" + "testing" + + "github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/exported" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/shared" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/tracing" + "github.com/Azure/azure-sdk-for-go/sdk/internal/mock" + "github.com/stretchr/testify/require" +) + +func TestHTTPTraceNamespacePolicy(t *testing.T) { + srv, close := mock.NewServer() + defer close() + + pl := exported.NewPipeline(srv, exported.PolicyFunc(httpTraceNamespacePolicy)) + + // no tracer + req, err := exported.NewRequest(context.Background(), http.MethodGet, srv.URL()) + require.NoError(t, err) + srv.AppendResponse() + _, err = pl.Do(req) + require.NoError(t, err) + + // wrong tracer type + req, err = exported.NewRequest(context.WithValue(context.Background(), shared.CtxWithTracingTracer{}, 0), http.MethodGet, srv.URL()) + require.NoError(t, err) + srv.AppendResponse() + _, err = pl.Do(req) + require.NoError(t, err) + + // no SpanFromContext impl + tr := tracing.NewTracer(func(ctx context.Context, spanName string, options *tracing.SpanOptions) (context.Context, tracing.Span) { + return ctx, tracing.Span{} + }, nil) + req, err = exported.NewRequest(context.WithValue(context.Background(), shared.CtxWithTracingTracer{}, tr), http.MethodGet, srv.URL()) + require.NoError(t, err) + srv.AppendResponse() + _, err = pl.Do(req) + require.NoError(t, err) + + // failed to parse resource ID, shouldn't call SetAttributes + var attrString string + tr = tracing.NewTracer(func(ctx context.Context, spanName string, options *tracing.SpanOptions) (context.Context, tracing.Span) { + return ctx, tracing.Span{} + }, &tracing.TracerOptions{ + SpanFromContext: func(ctx context.Context) (tracing.Span, bool) { + spanImpl := tracing.SpanImpl{ + SetAttributes: func(a ...tracing.Attribute) { + require.Len(t, a, 1) + v, ok := a[0].Value.(string) + require.True(t, ok) + attrString = a[0].Key + ":" + v + }, + } + return tracing.NewSpan(spanImpl), true + }, + }) + req, err = exported.NewRequest(context.WithValue(context.Background(), shared.CtxWithTracingTracer{}, tr), http.MethodGet, srv.URL()) + require.NoError(t, err) + srv.AppendResponse() + _, err = pl.Do(req) + require.NoError(t, err) + require.Empty(t, attrString) + + // success + tr = tracing.NewTracer(func(ctx context.Context, spanName string, options *tracing.SpanOptions) (context.Context, tracing.Span) { + return ctx, tracing.Span{} + }, &tracing.TracerOptions{ + SpanFromContext: func(ctx context.Context) (tracing.Span, bool) { + spanImpl := tracing.SpanImpl{ + SetAttributes: func(a ...tracing.Attribute) { + require.Len(t, a, 1) + v, ok := a[0].Value.(string) + require.True(t, ok) + attrString = a[0].Key + ":" + v + }, + } + return tracing.NewSpan(spanImpl), true + }, + }) + req, err = exported.NewRequest(context.WithValue(context.Background(), shared.CtxWithTracingTracer{}, tr), http.MethodGet, srv.URL()+requestEndpoint) + require.NoError(t, err) + srv.AppendResponse() + _, err = pl.Do(req) + require.NoError(t, err) + require.EqualValues(t, "az.namespace:Microsoft.Storage", attrString) +} diff --git a/sdk/azcore/core.go b/sdk/azcore/core.go index 72c2cf21eef3..29666d2d021f 100644 --- a/sdk/azcore/core.go +++ b/sdk/azcore/core.go @@ -99,6 +99,9 @@ func NewClient(clientName, moduleVersion string, plOpts runtime.PipelineOptions, pl := runtime.NewPipeline(pkg, moduleVersion, plOpts, options) tr := options.TracingProvider.NewTracer(clientName, moduleVersion) + if tr.Enabled() && plOpts.TracingNamespace != "" { + tr.SetAttributes(tracing.Attribute{Key: "az.namespace", Value: plOpts.TracingNamespace}) + } return &Client{pl: pl, tr: tr}, nil } diff --git a/sdk/azcore/core_test.go b/sdk/azcore/core_test.go index 13d3361e1f77..78c4af58bc55 100644 --- a/sdk/azcore/core_test.go +++ b/sdk/azcore/core_test.go @@ -7,11 +7,17 @@ package azcore import ( + "context" + "net/http" "reflect" "testing" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/exported" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/shared" "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/azcore/tracing" + "github.com/Azure/azure-sdk-for-go/sdk/internal/mock" "github.com/stretchr/testify/require" ) @@ -131,3 +137,38 @@ func TestNewClientError(t *testing.T) { require.Error(t, err) require.Nil(t, client) } + +func TestNewClientTracingEnabled(t *testing.T) { + srv, close := mock.NewServer() + defer close() + + var attrString string + client, err := NewClient("package.Client", "v1.0.0", runtime.PipelineOptions{TracingNamespace: "Widget.Factory"}, &policy.ClientOptions{ + TracingProvider: tracing.NewProvider(func(name, version string) tracing.Tracer { + return tracing.NewTracer(func(ctx context.Context, spanName string, options *tracing.SpanOptions) (context.Context, tracing.Span) { + require.NotNil(t, options) + for _, attr := range options.Attributes { + if attr.Key == "az.namespace" { + v, ok := attr.Value.(string) + require.True(t, ok) + attrString = attr.Key + ":" + v + } + } + return ctx, tracing.Span{} + }, nil) + }, nil), + Transport: srv, + }) + require.NoError(t, err) + require.NotNil(t, client) + require.NotZero(t, client.Pipeline()) + require.NotZero(t, client.Tracer()) + + const requestEndpoint = "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/fakeResourceGroupo/providers/Microsoft.Storage/storageAccounts/fakeAccountName" + req, err := exported.NewRequest(context.WithValue(context.Background(), shared.CtxWithTracingTracer{}, client.Tracer()), http.MethodGet, srv.URL()+requestEndpoint) + require.NoError(t, err) + srv.AppendResponse() + _, err = client.Pipeline().Do(req) + require.NoError(t, err) + require.EqualValues(t, "az.namespace:Widget.Factory", attrString) +} diff --git a/sdk/azcore/fake/example_test.go b/sdk/azcore/fake/example_test.go new file mode 100644 index 000000000000..1fbd12314ea3 --- /dev/null +++ b/sdk/azcore/fake/example_test.go @@ -0,0 +1,146 @@ +//go:build go1.18 +// +build go1.18 + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package fake_test + +import ( + "errors" + "net/http" + + "github.com/Azure/azure-sdk-for-go/sdk/azcore" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/fake" +) + +// Widget is a hypothetical type used in the following examples. +type Widget struct { + ID int + Shape string +} + +// WidgetResponse is a hypothetical type used in the following examples. +type WidgetResponse struct { + Widget +} + +// WidgetListResponse is a hypothetical type used in the following examples. +type WidgetListResponse struct { + Widgets []Widget +} + +func ExampleNewTokenCredential() { + // create a fake azcore.TokenCredential + // the fake is used as the client credential during testing with fakes. + var _ azcore.TokenCredential = fake.NewTokenCredential() +} + +func ExampleTokenCredential_SetError() { + cred := fake.NewTokenCredential() + + // set an error to be returned during authentication + cred.SetError(errors.New("failed to authenticate")) +} + +func ExampleResponder() { + // for a hypothetical API GetNextWidget(context.Context) (WidgetResponse, error) + + // a Responder is used to build a scalar response + resp := fake.Responder[WidgetResponse]{} + + // here we set the instance of Widget the Responder is to return + resp.Set(WidgetResponse{ + Widget{ID: 123, Shape: "triangle"}, + }) + + // optional HTTP headers can also be included in the raw response + resp.SetHeader("custom-header1", "value1") + resp.SetHeader("custom-header2", "value2") +} + +func ExampleErrorResponder() { + // an ErrorResponder is used to build an error response + errResp := fake.ErrorResponder{} + + // use SetError to return a generic error + errResp.SetError(errors.New("the system is down")) + + // to return an *azcore.ResponseError, use SetResponseError + errResp.SetResponseError("ErrorCodeConflict", http.StatusConflict) + + // ErrorResponder returns a singular error, so calling Set* APIs overwrites any previous value +} + +func ExamplePagerResponder() { + // for a hypothetical API NewListWidgetsPager() *runtime.Pager[WidgetListResponse] + + // a PagerResponder is used to build a sequence of responses for a paged operation + pagerResp := fake.PagerResponder[WidgetListResponse]{} + + // use AddPage to add one or more pages to the response. + // responses are returned in the order in which they were added. + pagerResp.AddPage(WidgetListResponse{ + Widgets: []Widget{ + {ID: 1, Shape: "circle"}, + {ID: 2, Shape: "square"}, + {ID: 3, Shape: "triangle"}, + }, + }, nil) + pagerResp.AddPage(WidgetListResponse{ + Widgets: []Widget{ + {ID: 4, Shape: "rectangle"}, + {ID: 5, Shape: "rhombus"}, + }, + }, nil) + + // errors can also be included in the sequence of responses. + // this can be used to simulate an error during paging. + pagerResp.AddError(errors.New("network too slow")) + + pagerResp.AddPage(WidgetListResponse{ + Widgets: []Widget{ + {ID: 6, Shape: "trapezoid"}, + }, + }, nil) +} + +func ExamplePollerResponder() { + // for a hypothetical API BeginCreateWidget(context.Context) (*runtime.Poller[WidgetResponse], error) + + // a PollerResponder is used to build a sequence of responses for a long-running operation + pollerResp := fake.PollerResponder[WidgetResponse]{} + + // use AddNonTerminalResponse to add one or more non-terminal responses + // to the sequence of responses. this is to simulate polling on a LRO. + // non-terminal responses are optional. exclude them to simulate a LRO + // that synchronously completes. + pollerResp.AddNonTerminalResponse(nil) + + // non-terminal errors can also be included in the sequence of responses. + // use this to simulate an error during polling. + pollerResp.AddNonTerminalError(errors.New("flaky network")) + + // use SetTerminalResponse to successfully terminate the long-running operation. + // the provided value will be returned as the terminal response. + pollerResp.SetTerminalResponse(WidgetResponse{ + Widget: Widget{ + ID: 987, + Shape: "dodecahedron", + }, + }) +} + +func ExamplePollerResponder_SetTerminalError() { + // for a hypothetical API BeginCreateWidget(context.Context) (*runtime.Poller[WidgetResponse], error) + + // a PollerResponder is used to build a sequence of responses for a long-running operation + pollerResp := fake.PollerResponder[WidgetResponse]{} + + // use SetTerminalError to terminate the long-running operation with an error. + // this returns an *azcore.ResponseError as the terminal response. + pollerResp.SetTerminalError("NoMoreWidgets", http.StatusBadRequest) + + // note that SetTerminalResponse and SetTerminalError are meant to be mutually exclusive. + // in the event that both are called, the result from SetTerminalError will be used. +} diff --git a/sdk/azcore/fake/fake.go b/sdk/azcore/fake/fake.go new file mode 100644 index 000000000000..1e5091248620 --- /dev/null +++ b/sdk/azcore/fake/fake.go @@ -0,0 +1,378 @@ +//go:build go1.18 +// +build go1.18 + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// Package fake provides the building blocks for fake servers. +// This includes fakes for authentication, API responses, and more. +// +// Most of the content in this package is intended to be used by +// SDK authors in construction of their fakes. +package fake + +import ( + "context" + "encoding/json" + "errors" + "fmt" + "io" + "net/http" + "strconv" + "strings" + "time" + + "github.com/Azure/azure-sdk-for-go/sdk/azcore" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/exported" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/shared" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/policy" + "github.com/Azure/azure-sdk-for-go/sdk/internal/errorinfo" +) + +// NewTokenCredential creates an instance of the TokenCredential type. +func NewTokenCredential() *TokenCredential { + return &TokenCredential{} +} + +// TokenCredential is a fake credential that implements the azcore.TokenCredential interface. +type TokenCredential struct { + err error +} + +// SetError sets the specified error to be returned from GetToken(). +// Use this to simulate an error during authentication. +func (t *TokenCredential) SetError(err error) { + t.err = &nonRetriableError{err} +} + +// GetToken implements the azcore.TokenCredential for the TokenCredential type. +func (t *TokenCredential) GetToken(ctx context.Context, opts policy.TokenRequestOptions) (azcore.AccessToken, error) { + if t.err != nil { + return azcore.AccessToken{}, &nonRetriableError{t.err} + } + return azcore.AccessToken{Token: "fake_token", ExpiresOn: time.Now().Add(24 * time.Hour)}, nil +} + +///////////////////////////////////////////////////////////////////////////////////////////////////////////// + +// Responder represents a scalar response. +type Responder[T any] struct { + h http.Header + resp T +} + +// Set sets the specified value to be returned. +func (r *Responder[T]) Set(b T) { + r.resp = b +} + +// SetHeader sets the specified header key/value pairs to be returned. +// Call multiple times to set multiple headers. +func (r *Responder[T]) SetHeader(key, value string) { + if r.h == nil { + r.h = http.Header{} + } + r.h.Set(key, value) +} + +///////////////////////////////////////////////////////////////////////////////////////////////////////////// + +// ErrorResponder represents a scalar error response. +type ErrorResponder struct { + err error +} + +// SetError sets the specified error to be returned. +// Use SetResponseError for returning an *azcore.ResponseError. +func (e *ErrorResponder) SetError(err error) { + e.err = &nonRetriableError{err: err} +} + +// SetResponseError sets an *azcore.ResponseError with the specified values to be returned. +func (e *ErrorResponder) SetResponseError(errorCode string, httpStatus int) { + e.err = &nonRetriableError{err: &azcore.ResponseError{ErrorCode: errorCode, StatusCode: httpStatus}} +} + +///////////////////////////////////////////////////////////////////////////////////////////////////////////// + +// PagerResponder represents a sequence of paged responses. +// Responses are replayed in the order in which they were added. +type PagerResponder[T any] struct { + pages []any +} + +// AddPage adds a page to the sequence of respones. +func (p *PagerResponder[T]) AddPage(page T, o *AddPageOptions) { + p.pages = append(p.pages, page) +} + +// AddError adds an error to the sequence of responses. +// The error is returned from the call to runtime.Pager[T].NextPage(). +func (p *PagerResponder[T]) AddError(err error) { + p.pages = append(p.pages, &nonRetriableError{err: err}) +} + +// AddResponseError adds an *azcore.ResponseError to the sequence of responses. +// The error is returned from the call to runtime.Pager[T].NextPage(). +func (p *PagerResponder[T]) AddResponseError(errorCode string, httpStatus int) { + p.pages = append(p.pages, &nonRetriableError{err: &azcore.ResponseError{ErrorCode: errorCode, StatusCode: httpStatus}}) +} + +// AddPageOptions contains the optional values for PagerResponder[T].AddPage. +type AddPageOptions struct { + // placeholder for future options +} + +///////////////////////////////////////////////////////////////////////////////////////////////////////////// + +// PollerResponder represents a sequence of responses for a long-running operation. +// Any non-terminal responses are replayed in the order in which they were added. +// The terminal response, success or error, is always the final response. +type PollerResponder[T any] struct { + nonTermResps []nonTermResp + res *T + err *exported.ResponseError +} + +// AddNonTerminalResponse adds a non-terminal response to the sequence of responses. +func (p *PollerResponder[T]) AddNonTerminalResponse(o *AddNonTerminalResponseOptions) { + p.nonTermResps = append(p.nonTermResps, nonTermResp{status: "InProgress"}) +} + +// AddNonTerminalError adds a non-terminal error to the sequence of responses. +// Use this to simulate an error durring polling. +func (p *PollerResponder[T]) AddNonTerminalError(err error) { + p.nonTermResps = append(p.nonTermResps, nonTermResp{err: err}) +} + +// SetTerminalResponse sets the provided value as the successful, terminal response. +func (p *PollerResponder[T]) SetTerminalResponse(result T) { + p.res = &result +} + +// SetTerminalError sets an *azcore.ResponseError with the specified values as the failed terminal response. +func (p *PollerResponder[T]) SetTerminalError(errorCode string, httpStatus int) { + p.err = &exported.ResponseError{ErrorCode: errorCode, StatusCode: httpStatus} +} + +// AddNonTerminalResponseOptions contains the optional values for PollerResponder[T].AddNonTerminalResponse. +type AddNonTerminalResponseOptions struct { + // place holder for future optional values +} + +///////////////////////////////////////////////////////////////////////////////////////////////////////////// +// the following APIs are intended for use by fake servers +///////////////////////////////////////////////////////////////////////////////////////////////////////////// + +// MarshalResponseAsJSON converts the body into JSON and returns it in a *http.Response. +// This method is typically called by the fake server internals. +func MarshalResponseAsJSON[T any](r Responder[T], req *http.Request) (*http.Response, error) { + body, err := json.Marshal(r.resp) + if err != nil { + return nil, &nonRetriableError{err} + } + resp := newResponse(http.StatusOK, "OK", req, string(body)) + for key := range r.h { + resp.Header.Set(key, r.h.Get(key)) + } + return resp, nil +} + +// UnmarshalRequestAsJSON unmarshalls the request body into an instance of T. +// This method is typically called by the fake server internals. +func UnmarshalRequestAsJSON[T any](req *http.Request) (T, error) { + tt := *new(T) + body, err := io.ReadAll(req.Body) + if err != nil { + return tt, &nonRetriableError{err} + } + req.Body.Close() + if err = json.Unmarshal(body, &tt); err != nil { + err = &nonRetriableError{err} + } + return tt, err +} + +// GetError returns the error for this responder. +// This method is typically called by the fake server internals. +func GetError(e ErrorResponder, req *http.Request) error { + if e.err == nil { + return nil + } + + var respErr *azcore.ResponseError + if errors.As(e.err, &respErr) { + // fix up the raw response + respErr.RawResponse = newErrorResponse(respErr.ErrorCode, respErr.StatusCode, req) + } + return &nonRetriableError{e.err} +} + +// PagerResponderNext returns the next response in the sequence (a T or an error). +// This method is typically called by the fake server internals. +func PagerResponderNext[T any](p *PagerResponder[T], req *http.Request) (*http.Response, error) { + if len(p.pages) == 0 { + return nil, &nonRetriableError{errors.New("paged response has no pages")} + } + + page := p.pages[0] + p.pages = p.pages[1:] + + pageT, ok := page.(T) + if ok { + body, err := json.Marshal(pageT) + if err != nil { + return nil, &nonRetriableError{err} + } + return newResponse(http.StatusOK, "OK", req, string(body)), nil + } + + err := page.(error) + var respErr *azcore.ResponseError + if errors.As(err, &respErr) { + // fix up the raw response + respErr.RawResponse = newErrorResponse(respErr.ErrorCode, respErr.StatusCode, req) + } + return nil, &nonRetriableError{err} +} + +// PagerResponderMore returns true if there are more responses for consumption. +// This method is typically called by the fake server internals. +func PagerResponderMore[T any](p *PagerResponder[T]) bool { + return len(p.pages) > 0 +} + +type pageindex[T any] struct { + i int + page T +} + +// PagerResponderInjectNextLinks is used to populate the nextLink field. +// The inject callback is executed for every T in the sequence except for the last one. +// This method is typically called by the fake server internals. +func PagerResponderInjectNextLinks[T any](p *PagerResponder[T], req *http.Request, inject func(page *T, createLink func() string)) { + // first find all the actual pages in the list + pages := make([]pageindex[T], 0, len(p.pages)) + for i := range p.pages { + if pageT, ok := p.pages[i].(T); ok { + pages = append(pages, pageindex[T]{ + i: i, + page: pageT, + }) + } + } + + // now populate the next links + for i := range pages { + if i+1 == len(pages) { + // no nextLink for last page + break + } + + inject(&pages[i].page, func() string { + return fmt.Sprintf("%s://%s%s/page_%d", req.URL.Scheme, req.URL.Host, req.URL.Path, i+1) + }) + + // update the original slice with the modified page + p.pages[pages[i].i] = pages[i].page + } +} + +// PollerResponderMore returns true if there are more responses for consumption. +// This method is typically called by the fake server internals. +func PollerResponderMore[T any](p *PollerResponder[T]) bool { + return len(p.nonTermResps) > 0 || p.err != nil || p.res != nil +} + +// PollerResponderNext returns the next response in the sequence (a *http.Response or an error). +// This method is typically called by the fake server internals. +func PollerResponderNext[T any](p *PollerResponder[T], req *http.Request) (*http.Response, error) { + if len(p.nonTermResps) > 0 { + resp := p.nonTermResps[0] + p.nonTermResps = p.nonTermResps[1:] + + if resp.err != nil { + return nil, &nonRetriableError{resp.err} + } + + httpResp := newResponse(http.StatusOK, "OK", req, "") + httpResp.Header.Set(shared.HeaderFakePollerStatus, resp.status) + + if resp.retryAfter > 0 { + httpResp.Header.Add(shared.HeaderRetryAfter, strconv.Itoa(resp.retryAfter)) + } + + return httpResp, nil + } + + if p.err != nil { + err := p.err + err.RawResponse = newErrorResponse(p.err.ErrorCode, p.err.StatusCode, req) + p.err = nil + return nil, &nonRetriableError{err} + } else if p.res != nil { + body, err := json.Marshal(*p.res) + if err != nil { + return nil, &nonRetriableError{err} + } + p.res = nil + httpResp := newResponse(http.StatusOK, "OK", req, string(body)) + httpResp.Header.Set(shared.HeaderFakePollerStatus, "Succeeded") + return httpResp, nil + } else { + return nil, &nonRetriableError{fmt.Errorf("%T has no terminal response", p)} + } +} + +type nonTermResp struct { + status string + retryAfter int + err error +} + +func newResponse(statusCode int, status string, req *http.Request, body string) *http.Response { + resp := &http.Response{ + Body: http.NoBody, + Header: http.Header{}, + Proto: "HTTP/1.1", + ProtoMajor: 1, + ProtoMinor: 1, + Request: req, + Status: status, + StatusCode: statusCode, + } + + if l := int64(len(body)); l > 0 { + resp.Header.Set(shared.HeaderContentType, shared.ContentTypeAppJSON) + resp.ContentLength = l + resp.Body = io.NopCloser(strings.NewReader(body)) + } + + return resp +} + +func newErrorResponse(errorCode string, statusCode int, req *http.Request) *http.Response { + resp := newResponse(statusCode, "Operation Failed", req, "") + resp.Header.Set(shared.HeaderXMSErrorCode, errorCode) + return resp +} + +///////////////////////////////////////////////////////////////////////////////////////////////////////////// + +type nonRetriableError struct { + err error +} + +func (p *nonRetriableError) Error() string { + return p.err.Error() +} + +func (*nonRetriableError) NonRetriable() { + // marker method +} + +func (p *nonRetriableError) Unwrap() error { + return p.err +} + +var _ errorinfo.NonRetriable = (*nonRetriableError)(nil) diff --git a/sdk/azcore/fake/fake_test.go b/sdk/azcore/fake/fake_test.go new file mode 100644 index 000000000000..c37bd0feb88f --- /dev/null +++ b/sdk/azcore/fake/fake_test.go @@ -0,0 +1,331 @@ +//go:build go1.18 +// +build go1.18 + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package fake + +import ( + "context" + "encoding/json" + "errors" + "io" + "net/http" + "net/url" + "strings" + "testing" + + "github.com/Azure/azure-sdk-for-go/sdk/azcore" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/policy" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/to" + "github.com/Azure/azure-sdk-for-go/sdk/internal/errorinfo" + "github.com/stretchr/testify/require" +) + +type widget struct { + Name string +} + +type widgets struct { + NextPage *string + Widgets []widget +} + +func TestNewTokenCredential(t *testing.T) { + cred := NewTokenCredential() + require.NotNil(t, cred) + + tk, err := cred.GetToken(context.Background(), policy.TokenRequestOptions{}) + require.NoError(t, err) + require.NotZero(t, tk) + + myErr := errors.New("failed") + cred.SetError(myErr) + tk, err = cred.GetToken(context.Background(), policy.TokenRequestOptions{}) + require.ErrorIs(t, err, myErr) + require.Zero(t, tk) +} + +func TestResponder(t *testing.T) { + respr := Responder[widget]{} + respr.Set(widget{Name: "foo"}) + respr.SetHeader("one", "1") + respr.SetHeader("two", "2") + + req := &http.Request{} + resp, err := MarshalResponseAsJSON(respr, req) + require.NoError(t, err) + require.NotNil(t, resp) + require.Equal(t, req, resp.Request) + require.Equal(t, "1", resp.Header.Get("one")) + require.Equal(t, "2", resp.Header.Get("two")) + + body, err := io.ReadAll(resp.Body) + require.NoError(t, err) + require.NoError(t, resp.Body.Close()) + + w := widget{} + require.NoError(t, json.Unmarshal(body, &w)) + require.Equal(t, "foo", w.Name) +} + +type badWidget struct { + Count int +} + +func (badWidget) MarshalJSON() ([]byte, error) { + return nil, errors.New("failed") +} + +func (*badWidget) UnmarshalJSON([]byte) error { + return errors.New("failed") +} + +func TestResponderMarshallingError(t *testing.T) { + respr := Responder[badWidget]{} + + req := &http.Request{} + resp, err := MarshalResponseAsJSON(respr, req) + require.Error(t, err) + var nre errorinfo.NonRetriable + require.ErrorAs(t, err, &nre) + require.Nil(t, resp) +} + +func TestErrorResponder(t *testing.T) { + req := &http.Request{} + + errResp := ErrorResponder{} + require.NoError(t, GetError(errResp, req)) + + myErr := errors.New("failed") + errResp.SetError(myErr) + require.ErrorIs(t, GetError(errResp, req), myErr) + + errResp.SetResponseError("ErrorInvalidWidget", http.StatusBadRequest) + var respErr *azcore.ResponseError + require.ErrorAs(t, GetError(errResp, req), &respErr) + require.Equal(t, "ErrorInvalidWidget", respErr.ErrorCode) + require.Equal(t, http.StatusBadRequest, respErr.StatusCode) + require.NotNil(t, respErr.RawResponse) + require.Equal(t, req, respErr.RawResponse.Request) +} + +func unmarshal[T any](resp *http.Response) (T, error) { + var t T + body, err := io.ReadAll(resp.Body) + if err != nil { + return t, err + } + resp.Body.Close() + + err = json.Unmarshal(body, &t) + return t, err +} + +func TestPagerResponder(t *testing.T) { + req := &http.Request{URL: &url.URL{}} + req.URL.Scheme = "http" + req.URL.Host = "fakehost.org" + req.URL.Path = "/lister" + + pagerResp := PagerResponder[widgets]{} + + require.False(t, PagerResponderMore(&pagerResp)) + resp, err := PagerResponderNext(&pagerResp, req) + var nre errorinfo.NonRetriable + require.ErrorAs(t, err, &nre) + require.Nil(t, resp) + + pagerResp.AddError(errors.New("one")) + pagerResp.AddPage(widgets{ + Widgets: []widget{ + {Name: "foo"}, + {Name: "bar"}, + }, + }, nil) + pagerResp.AddError(errors.New("two")) + pagerResp.AddPage(widgets{ + Widgets: []widget{ + {Name: "baz"}, + }, + }, nil) + pagerResp.AddResponseError("ErrorPagerBlewUp", http.StatusBadRequest) + + PagerResponderInjectNextLinks(&pagerResp, req, func(p *widgets, create func() string) { + p.NextPage = to.Ptr(create()) + }) + + iterations := 0 + for PagerResponderMore(&pagerResp) { + resp, err := PagerResponderNext(&pagerResp, req) + switch iterations { + case 0: + require.Error(t, err) + require.Equal(t, "one", err.Error()) + require.Nil(t, resp) + case 1: + require.NoError(t, err) + require.NotNil(t, resp) + page, err := unmarshal[widgets](resp) + require.NoError(t, err) + require.NotNil(t, page.NextPage) + require.Equal(t, []widget{{Name: "foo"}, {Name: "bar"}}, page.Widgets) + case 2: + require.Error(t, err) + require.Equal(t, "two", err.Error()) + require.Nil(t, resp) + case 3: + require.NoError(t, err) + require.NotNil(t, resp) + page, err := unmarshal[widgets](resp) + require.NoError(t, err) + require.Nil(t, page.NextPage) + require.Equal(t, []widget{{Name: "baz"}}, page.Widgets) + case 4: + require.Error(t, err) + var respErr *azcore.ResponseError + require.ErrorAs(t, err, &respErr) + require.Equal(t, "ErrorPagerBlewUp", respErr.ErrorCode) + require.Equal(t, http.StatusBadRequest, respErr.StatusCode) + require.Nil(t, resp) + default: + t.Fatalf("unexpected case %d", iterations) + } + iterations++ + } + require.Equal(t, 5, iterations) +} + +func TestPollerResponder(t *testing.T) { + req := &http.Request{URL: &url.URL{}} + req.URL.Scheme = "http" + req.URL.Host = "fakehost.org" + req.URL.Path = "/lro" + + pollerResp := PollerResponder[widget]{} + + require.False(t, PollerResponderMore(&pollerResp)) + resp, err := PollerResponderNext(&pollerResp, req) + var nre errorinfo.NonRetriable + require.ErrorAs(t, err, &nre) + require.Nil(t, resp) + + pollerResp.AddNonTerminalResponse(nil) + pollerResp.AddNonTerminalError(errors.New("network glitch")) + pollerResp.AddNonTerminalResponse(nil) + pollerResp.SetTerminalResponse(widget{Name: "dodo"}) + + iterations := 0 + for PollerResponderMore(&pollerResp) { + resp, err := PollerResponderNext(&pollerResp, req) + switch iterations { + case 0: + require.NoError(t, err) + require.NotNil(t, resp) + case 1: + require.Error(t, err) + require.Nil(t, resp) + case 2: + require.NoError(t, err) + require.NotNil(t, resp) + case 3: + require.NoError(t, err) + require.NotNil(t, resp) + w, err := unmarshal[widget](resp) + require.NoError(t, err) + require.Equal(t, "dodo", w.Name) + default: + t.Fatalf("unexpected case %d", iterations) + } + iterations++ + } + require.Equal(t, 4, iterations) +} + +func TestPollerResponderTerminalFailure(t *testing.T) { + req := &http.Request{URL: &url.URL{}} + req.URL.Scheme = "http" + req.URL.Host = "fakehost.org" + req.URL.Path = "/lro" + + pollerResp := PollerResponder[widget]{} + + require.False(t, PollerResponderMore(&pollerResp)) + resp, err := PollerResponderNext(&pollerResp, req) + var nre errorinfo.NonRetriable + require.ErrorAs(t, err, &nre) + require.Nil(t, resp) + + pollerResp.AddNonTerminalError(errors.New("network glitch")) + pollerResp.AddNonTerminalResponse(nil) + pollerResp.SetTerminalError("ErrorConflictingOperation", http.StatusConflict) + + iterations := 0 + for PollerResponderMore(&pollerResp) { + resp, err := PollerResponderNext(&pollerResp, req) + switch iterations { + case 0: + require.Error(t, err) + require.Nil(t, resp) + case 1: + require.NoError(t, err) + require.NotNil(t, resp) + case 2: + require.Error(t, err) + require.Nil(t, resp) + var respErr *azcore.ResponseError + require.ErrorAs(t, err, &respErr) + require.Equal(t, "ErrorConflictingOperation", respErr.ErrorCode) + require.Equal(t, http.StatusConflict, respErr.StatusCode) + require.Equal(t, req, respErr.RawResponse.Request) + default: + t.Fatalf("unexpected case %d", iterations) + } + iterations++ + } + require.Equal(t, 3, iterations) +} + +func TestUnmarshalRequestAsJSON(t *testing.T) { + req, err := http.NewRequest(http.MethodPut, "https://foo.bar/baz", strings.NewReader(`{"Name": "foo"}`)) + require.NoError(t, err) + require.NotNil(t, req) + + w, err := UnmarshalRequestAsJSON[widget](req) + require.NoError(t, err) + require.Equal(t, "foo", w.Name) +} + +func TestUnmarshalRequestAsJSONReadFailure(t *testing.T) { + req, err := http.NewRequest(http.MethodPut, "https://foo.bar/baz", &readFailer{}) + require.NoError(t, err) + require.NotNil(t, req) + + w, err := UnmarshalRequestAsJSON[widget](req) + require.Error(t, err) + require.Zero(t, w) +} + +func TestUnmarshalRequestAsJSONUnmarshalFailure(t *testing.T) { + req, err := http.NewRequest(http.MethodPut, "https://foo.bar/baz", strings.NewReader(`{"Name": "foo"}`)) + require.NoError(t, err) + require.NotNil(t, req) + + w, err := UnmarshalRequestAsJSON[badWidget](req) + require.Error(t, err) + require.Zero(t, w) +} + +type readFailer struct { + wrapped io.ReadCloser +} + +func (r *readFailer) Close() error { + return r.wrapped.Close() +} + +func (r *readFailer) Read(p []byte) (int, error) { + return 0, errors.New("mock read failure") +} diff --git a/sdk/azcore/internal/exported/exported.go b/sdk/azcore/internal/exported/exported.go index a1236b362526..c389cdcd8a5c 100644 --- a/sdk/azcore/internal/exported/exported.go +++ b/sdk/azcore/internal/exported/exported.go @@ -51,6 +51,10 @@ type AccessToken struct { // TokenRequestOptions contain specific parameter that may be used by credentials types when attempting to get a token. // Exported as policy.TokenRequestOptions. type TokenRequestOptions struct { + // Claims are any additional claims required for the token to satisfy a conditional access policy, such as a + // service may return in a claims challenge following an authorization failure. If a service returned the + // claims value base64 encoded, it must be decoded before setting this field. + Claims string // Scopes contains the list of permission scopes required for the token. Scopes []string diff --git a/sdk/azcore/internal/exported/request.go b/sdk/azcore/internal/exported/request.go index fa99d1b7ed1f..48229f5ccd68 100644 --- a/sdk/azcore/internal/exported/request.go +++ b/sdk/azcore/internal/exported/request.go @@ -170,6 +170,14 @@ func (req *Request) Clone(ctx context.Context) *Request { return &r2 } +// WithContext returns a shallow copy of the request with its context changed to ctx. +func (req *Request) WithContext(ctx context.Context) *Request { + r2 := new(Request) + *r2 = *req + r2.req = r2.req.WithContext(ctx) + return r2 +} + // not exported but dependent on Request // PolicyFunc is a type that implements the Policy interface. diff --git a/sdk/azcore/internal/exported/request_test.go b/sdk/azcore/internal/exported/request_test.go index d26b734c82c9..3acc8e7a76ae 100644 --- a/sdk/azcore/internal/exported/request_test.go +++ b/sdk/azcore/internal/exported/request_test.go @@ -194,3 +194,20 @@ func TestNewRequestFail(t *testing.T) { t.Fatal("unexpected request") } } + +func TestRequestWithContext(t *testing.T) { + type ctxKey1 struct{} + type ctxKey2 struct{} + + req1, err := NewRequest(context.WithValue(context.Background(), ctxKey1{}, 1), http.MethodPost, testURL) + require.NoError(t, err) + require.NotNil(t, req1.Raw().Context().Value(ctxKey1{})) + + req2 := req1.WithContext(context.WithValue(context.Background(), ctxKey2{}, 1)) + require.Nil(t, req2.Raw().Context().Value(ctxKey1{})) + require.NotNil(t, req2.Raw().Context().Value(ctxKey2{})) + + // shallow copy, so changing req2 affects req1 + req2.Raw().Header.Add("added-req2", "value") + require.EqualValues(t, "value", req1.Raw().Header.Get("added-req2")) +} diff --git a/sdk/azcore/internal/exported/response_error.go b/sdk/azcore/internal/exported/response_error.go index 7df2f88c1c1a..76a8c068d143 100644 --- a/sdk/azcore/internal/exported/response_error.go +++ b/sdk/azcore/internal/exported/response_error.go @@ -13,6 +13,7 @@ import ( "net/http" "regexp" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/shared" "github.com/Azure/azure-sdk-for-go/sdk/internal/exported" ) @@ -25,7 +26,7 @@ func NewResponseError(resp *http.Response) error { } // prefer the error code in the response header - if ec := resp.Header.Get("x-ms-error-code"); ec != "" { + if ec := resp.Header.Get(shared.HeaderXMSErrorCode); ec != "" { respErr.ErrorCode = ec return respErr } diff --git a/sdk/azcore/internal/exported/response_error_test.go b/sdk/azcore/internal/exported/response_error_test.go index 7b4a44150ef1..97c8bc4d6a4c 100644 --- a/sdk/azcore/internal/exported/response_error_test.go +++ b/sdk/azcore/internal/exported/response_error_test.go @@ -13,6 +13,8 @@ import ( "net/url" "strings" "testing" + + "github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/shared" ) func TestNewResponseErrorNoBodyNoErrorCode(t *testing.T) { @@ -59,7 +61,7 @@ func TestNewResponseErrorNoBody(t *testing.T) { } respHeader := http.Header{} const errorCode = "ErrorTooManyCheats" - respHeader.Set("x-ms-error-code", errorCode) + respHeader.Set(shared.HeaderXMSErrorCode, errorCode) err = NewResponseError(&http.Response{ Status: "the system is down", StatusCode: http.StatusInternalServerError, @@ -136,7 +138,7 @@ func TestNewResponseErrorPreferErrorCodeHeader(t *testing.T) { t.Fatal(err) } respHeader := http.Header{} - respHeader.Set("x-ms-error-code", "ErrorTooManyCheats") + respHeader.Set(shared.HeaderXMSErrorCode, "ErrorTooManyCheats") err = NewResponseError(&http.Response{ Status: "the system is down", StatusCode: http.StatusInternalServerError, @@ -317,7 +319,7 @@ func TestNewResponseErrorErrorCodeHeaderXML(t *testing.T) { t.Fatal(err) } respHeader := http.Header{} - respHeader.Set("x-ms-error-code", "ContainerAlreadyExists") + respHeader.Set(shared.HeaderXMSErrorCode, "ContainerAlreadyExists") err = NewResponseError(&http.Response{ Status: "the system is down", StatusCode: http.StatusInternalServerError, @@ -354,7 +356,7 @@ func TestNewResponseErrorErrorCodeHeaderXMLWithNamespace(t *testing.T) { t.Fatal(err) } respHeader := http.Header{} - respHeader.Set("x-ms-error-code", "ContainerAlreadyExists") + respHeader.Set(shared.HeaderXMSErrorCode, "ContainerAlreadyExists") err = NewResponseError(&http.Response{ Status: "the system is down", StatusCode: http.StatusInternalServerError, diff --git a/sdk/azcore/internal/pollers/fake/fake.go b/sdk/azcore/internal/pollers/fake/fake.go new file mode 100644 index 000000000000..15adbee29f09 --- /dev/null +++ b/sdk/azcore/internal/pollers/fake/fake.go @@ -0,0 +1,118 @@ +//go:build go1.18 +// +build go1.18 + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package fake + +import ( + "context" + "errors" + "fmt" + "net/http" + + "github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/exported" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/log" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/pollers" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/shared" + "github.com/Azure/azure-sdk-for-go/sdk/internal/poller" +) + +// Applicable returns true if the LRO is a fake. +func Applicable(resp *http.Response) bool { + return resp.Header.Get(shared.HeaderFakePollerStatus) != "" +} + +// CanResume returns true if the token can rehydrate this poller type. +func CanResume(token map[string]interface{}) bool { + _, ok := token["fakeURL"] + return ok +} + +// Poller is an LRO poller that uses the Core-Fake-Poller pattern. +type Poller[T any] struct { + pl exported.Pipeline + + resp *http.Response + + // The API name from CtxAPINameKey + APIName string `json:"apiName"` + + // The URL from Core-Fake-Poller header. + FakeURL string `json:"fakeURL"` + + // The LRO's current state. + FakeStatus string `json:"status"` +} + +// New creates a new Poller from the provided initial response. +// Pass nil for response to create an empty Poller for rehydration. +func New[T any](pl exported.Pipeline, resp *http.Response) (*Poller[T], error) { + if resp == nil { + log.Write(log.EventLRO, "Resuming Core-Fake-Poller poller.") + return &Poller[T]{pl: pl}, nil + } + + log.Write(log.EventLRO, "Using Core-Fake-Poller poller.") + fakeStatus := resp.Header.Get(shared.HeaderFakePollerStatus) + if fakeStatus == "" { + return nil, errors.New("response is missing Fake-Poller-Status header") + } + + ctxVal := resp.Request.Context().Value(shared.CtxAPINameKey{}) + if ctxVal == nil { + return nil, errors.New("missing value for CtxAPINameKey") + } + + apiName, ok := ctxVal.(string) + if !ok { + return nil, fmt.Errorf("expected string for CtxAPINameKey, the type was %T", ctxVal) + } + + p := &Poller[T]{ + pl: pl, + resp: resp, + APIName: apiName, + FakeURL: fmt.Sprintf("%s://%s%s/get/fake/status", resp.Request.URL.Scheme, resp.Request.URL.Host, resp.Request.URL.Path), + FakeStatus: fakeStatus, + } + return p, nil +} + +// Done returns true if the LRO is in a terminal state. +func (p *Poller[T]) Done() bool { + return poller.IsTerminalState(p.FakeStatus) +} + +// Poll retrieves the current state of the LRO. +func (p *Poller[T]) Poll(ctx context.Context) (*http.Response, error) { + ctx = context.WithValue(ctx, shared.CtxAPINameKey{}, p.APIName) + err := pollers.PollHelper(ctx, p.FakeURL, p.pl, func(resp *http.Response) (string, error) { + if !poller.StatusCodeValid(resp) { + p.resp = resp + return "", exported.NewResponseError(resp) + } + fakeStatus := resp.Header.Get(shared.HeaderFakePollerStatus) + if fakeStatus == "" { + return "", errors.New("response is missing Fake-Poller-Status header") + } + p.resp = resp + p.FakeStatus = fakeStatus + return p.FakeStatus, nil + }) + if err != nil { + return nil, err + } + return p.resp, nil +} + +func (p *Poller[T]) Result(ctx context.Context, out *T) error { + if p.resp.StatusCode == http.StatusNoContent { + return nil + } else if poller.Failed(p.FakeStatus) { + return exported.NewResponseError(p.resp) + } + + return pollers.ResultHelper(p.resp, poller.Failed(p.FakeStatus), out) +} diff --git a/sdk/azcore/internal/pollers/fake/fake_test.go b/sdk/azcore/internal/pollers/fake/fake_test.go new file mode 100644 index 000000000000..0a32d6dd3a86 --- /dev/null +++ b/sdk/azcore/internal/pollers/fake/fake_test.go @@ -0,0 +1,185 @@ +//go:build go1.18 +// +build go1.18 + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package fake + +import ( + "context" + "io" + "net/http" + "strings" + "testing" + + "github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/exported" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/shared" + "github.com/Azure/azure-sdk-for-go/sdk/internal/poller" + "github.com/stretchr/testify/require" +) + +const ( + fakePollingURL = "https://foo.bar.baz/status" + fakeResourceURL = "https://foo.bar.baz/resource" +) + +func initialResponse(ctx context.Context, method string, resp io.Reader) *http.Response { + req, err := http.NewRequestWithContext(ctx, method, fakeResourceURL, nil) + if err != nil { + panic(err) + } + return &http.Response{ + Body: io.NopCloser(resp), + Header: http.Header{}, + Request: req, + } +} + +func TestApplicable(t *testing.T) { + resp := &http.Response{ + Header: http.Header{}, + } + require.False(t, Applicable(resp), "missing Fake-Poller-Status should not be applicable") + resp.Header.Set(shared.HeaderFakePollerStatus, fakePollingURL) + require.True(t, Applicable(resp), "having Fake-Poller-Status should be applicable") +} + +func TestCanResume(t *testing.T) { + token := map[string]interface{}{} + require.False(t, CanResume(token)) + token["fakeURL"] = fakePollingURL + require.True(t, CanResume(token)) +} + +func TestNew(t *testing.T) { + fp, err := New[struct{}](exported.Pipeline{}, nil) + require.NoError(t, err) + require.Empty(t, fp.FakeStatus) + + fp, err = New[struct{}](exported.Pipeline{}, &http.Response{Header: http.Header{}}) + require.Error(t, err) + require.Nil(t, fp) + + resp := initialResponse(context.Background(), http.MethodPut, http.NoBody) + resp.Header.Set(shared.HeaderFakePollerStatus, "faking") + fp, err = New[struct{}](exported.Pipeline{}, resp) + require.Error(t, err) + require.Nil(t, fp) + + resp = initialResponse(context.WithValue(context.Background(), shared.CtxAPINameKey{}, 123), http.MethodPut, http.NoBody) + resp.Header.Set(shared.HeaderFakePollerStatus, "faking") + fp, err = New[struct{}](exported.Pipeline{}, resp) + require.Error(t, err) + require.Nil(t, fp) + + resp = initialResponse(context.WithValue(context.Background(), shared.CtxAPINameKey{}, "FakeAPI"), http.MethodPut, http.NoBody) + resp.Header.Set(shared.HeaderFakePollerStatus, "faking") + fp, err = New[struct{}](exported.Pipeline{}, resp) + require.NoError(t, err) + require.NotNil(t, fp) + require.False(t, fp.Done()) +} + +func TestSynchronousCompletion(t *testing.T) { + resp := initialResponse(context.WithValue(context.Background(), shared.CtxAPINameKey{}, "FakeAPI"), http.MethodPut, http.NoBody) + resp.StatusCode = http.StatusNoContent + resp.Header.Set(shared.HeaderFakePollerStatus, poller.StatusSucceeded) + fp, err := New[struct{}](exported.Pipeline{}, resp) + require.NoError(t, err) + require.Equal(t, poller.StatusSucceeded, fp.FakeStatus) + require.True(t, fp.Done()) + require.NoError(t, fp.Result(context.Background(), nil)) +} + +type widget struct { + Shape string `json:"shape"` +} + +func TestPollSucceeded(t *testing.T) { + pollCtx := context.WithValue(context.Background(), shared.CtxAPINameKey{}, "FakeAPI") + resp := initialResponse(pollCtx, http.MethodPatch, http.NoBody) + resp.Header.Set(shared.HeaderFakePollerStatus, poller.StatusInProgress) + poller, err := New[widget](exported.NewPipeline(shared.TransportFunc(func(req *http.Request) (*http.Response, error) { + return &http.Response{ + StatusCode: http.StatusOK, + Header: http.Header{shared.HeaderFakePollerStatus: []string{"Succeeded"}}, + Body: io.NopCloser(strings.NewReader(`{ "shape": "triangle" }`)), + }, nil + })), resp) + require.NoError(t, err) + require.False(t, poller.Done()) + resp, err = poller.Poll(pollCtx) + require.NoError(t, err) + require.Equal(t, http.StatusOK, resp.StatusCode) + require.True(t, poller.Done()) + var result widget + require.NoError(t, poller.Result(context.Background(), &result)) + require.EqualValues(t, "triangle", result.Shape) +} + +func TestPollError(t *testing.T) { + pollCtx := context.WithValue(context.Background(), shared.CtxAPINameKey{}, "FakeAPI") + resp := initialResponse(pollCtx, http.MethodPatch, http.NoBody) + resp.Header.Set(shared.HeaderFakePollerStatus, poller.StatusInProgress) + poller, err := New[widget](exported.NewPipeline(shared.TransportFunc(func(req *http.Request) (*http.Response, error) { + return &http.Response{ + StatusCode: http.StatusNotFound, + Header: http.Header{shared.HeaderFakePollerStatus: []string{poller.StatusFailed}}, + Body: io.NopCloser(strings.NewReader(`{ "error": { "code": "NotFound", "message": "the item doesn't exist" } }`)), + }, nil + })), resp) + require.NoError(t, err) + require.False(t, poller.Done()) + resp, err = poller.Poll(pollCtx) + require.Error(t, err) + require.Nil(t, resp) + var respErr *exported.ResponseError + require.ErrorAs(t, err, &respErr) + require.Equal(t, http.StatusNotFound, respErr.StatusCode) + require.False(t, poller.Done()) + var result widget + require.Error(t, poller.Result(context.Background(), &result)) + require.ErrorAs(t, err, &respErr) +} + +func TestPollFailed(t *testing.T) { + pollCtx := context.WithValue(context.Background(), shared.CtxAPINameKey{}, "FakeAPI") + resp := initialResponse(pollCtx, http.MethodPatch, http.NoBody) + resp.Header.Set(shared.HeaderFakePollerStatus, poller.StatusInProgress) + poller, err := New[widget](exported.NewPipeline(shared.TransportFunc(func(req *http.Request) (*http.Response, error) { + return &http.Response{ + StatusCode: http.StatusOK, + Header: http.Header{shared.HeaderFakePollerStatus: []string{poller.StatusFailed}}, + Body: io.NopCloser(strings.NewReader(`{ "error": { "code": "FakeFailure", "message": "couldn't do the thing" } }`)), + }, nil + })), resp) + require.NoError(t, err) + require.False(t, poller.Done()) + resp, err = poller.Poll(pollCtx) + require.NoError(t, err) + require.Equal(t, http.StatusOK, resp.StatusCode) + require.True(t, poller.Done()) + var result widget + var respErr *exported.ResponseError + err = poller.Result(context.Background(), &result) + require.Error(t, err) + require.ErrorAs(t, err, &respErr) +} + +func TestPollErrorNoHeader(t *testing.T) { + pollCtx := context.WithValue(context.Background(), shared.CtxAPINameKey{}, "FakeAPI") + resp := initialResponse(pollCtx, http.MethodPatch, http.NoBody) + resp.Header.Set(shared.HeaderFakePollerStatus, poller.StatusInProgress) + poller, err := New[widget](exported.NewPipeline(shared.TransportFunc(func(req *http.Request) (*http.Response, error) { + return &http.Response{ + StatusCode: http.StatusNotFound, + Body: io.NopCloser(strings.NewReader(`{ "error": { "code": "NotFound", "message": "the item doesn't exist" } }`)), + }, nil + })), resp) + require.NoError(t, err) + require.False(t, poller.Done()) + resp, err = poller.Poll(pollCtx) + require.Error(t, err) + require.Nil(t, resp) +} diff --git a/sdk/azcore/internal/shared/constants.go b/sdk/azcore/internal/shared/constants.go index 9d6bc39c0a60..01f802537e4c 100644 --- a/sdk/azcore/internal/shared/constants.go +++ b/sdk/azcore/internal/shared/constants.go @@ -17,12 +17,15 @@ const ( HeaderAzureAsync = "Azure-AsyncOperation" HeaderContentLength = "Content-Length" HeaderContentType = "Content-Type" + HeaderFakePollerStatus = "Fake-Poller-Status" HeaderLocation = "Location" HeaderOperationLocation = "Operation-Location" HeaderRetryAfter = "Retry-After" HeaderUserAgent = "User-Agent" HeaderWWWAuthenticate = "WWW-Authenticate" HeaderXMSClientRequestID = "x-ms-client-request-id" + HeaderXMSRequestID = "x-ms-request-id" + HeaderXMSErrorCode = "x-ms-error-code" ) const BearerTokenPrefix = "Bearer " @@ -32,5 +35,5 @@ const ( Module = "azcore" // Version is the semantic version (see http://semver.org) of this module. - Version = "v1.5.1" + Version = "v1.6.1" ) diff --git a/sdk/azcore/internal/shared/shared.go b/sdk/azcore/internal/shared/shared.go index 930ab8c83999..69153854c77a 100644 --- a/sdk/azcore/internal/shared/shared.go +++ b/sdk/azcore/internal/shared/shared.go @@ -26,6 +26,12 @@ type CtxWithRetryOptionsKey struct{} // CtxIncludeResponseKey is used as a context key for retrieving the raw response. type CtxIncludeResponseKey struct{} +// CtxWithTracingTracer is used as a context key for adding/retrieving tracing.Tracer. +type CtxWithTracingTracer struct{} + +// CtxAPINameKey is used as a context key for adding/retrieving the API name. +type CtxAPINameKey struct{} + // Delay waits for the duration to elapse or the context to be cancelled. func Delay(ctx context.Context, delay time.Duration) error { select { diff --git a/sdk/azcore/policy/policy.go b/sdk/azcore/policy/policy.go index b200047834ce..2d7ad45f6167 100644 --- a/sdk/azcore/policy/policy.go +++ b/sdk/azcore/policy/policy.go @@ -29,7 +29,8 @@ type Request = exported.Request // ClientOptions contains optional settings for a client's pipeline. // All zero-value fields will be initialized with default values. type ClientOptions struct { - // APIVersion overrides the default version requested of the service. Set with caution as this package version has not been tested with arbitrary service versions. + // APIVersion overrides the default version requested of the service. + // Set with caution as this package version has not been tested with arbitrary service versions. APIVersion string // Cloud specifies a cloud for the client. The default is Azure Public Cloud. diff --git a/sdk/azcore/runtime/pager.go b/sdk/azcore/runtime/pager.go index 5507665d651d..b7e59527a3d8 100644 --- a/sdk/azcore/runtime/pager.go +++ b/sdk/azcore/runtime/pager.go @@ -10,6 +10,10 @@ import ( "context" "encoding/json" "errors" + "fmt" + "reflect" + + "github.com/Azure/azure-sdk-for-go/sdk/azcore/tracing" ) // PagingHandler contains the required data for constructing a Pager. @@ -20,12 +24,16 @@ type PagingHandler[T any] struct { // Fetcher fetches the first and subsequent pages. Fetcher func(context.Context, *T) (T, error) + + // Tracer contains the Tracer from the client that's creating the Pager. + Tracer tracing.Tracer } // Pager provides operations for iterating over paged responses. type Pager[T any] struct { current *T handler PagingHandler[T] + tracer tracing.Tracer firstPage bool } @@ -34,6 +42,7 @@ type Pager[T any] struct { func NewPager[T any](handler PagingHandler[T]) *Pager[T] { return &Pager[T]{ handler: handler, + tracer: handler.Tracer, firstPage: true, } } @@ -58,10 +67,14 @@ func (p *Pager[T]) NextPage(ctx context.Context) (T, error) { } else if !p.handler.More(*p.current) { return *new(T), errors.New("no more pages") } + ctx, endSpan := StartSpan(ctx, fmt.Sprintf("%s.NextPage", shortenTypeName(reflect.TypeOf(*p).Name())), p.tracer, nil) + defer endSpan(err) resp, err = p.handler.Fetcher(ctx, p.current) } else { // non-LRO case, first page p.firstPage = false + ctx, endSpan := StartSpan(ctx, fmt.Sprintf("%s.NextPage", shortenTypeName(reflect.TypeOf(*p).Name())), p.tracer, nil) + defer endSpan(err) resp, err = p.handler.Fetcher(ctx, nil) } if err != nil { diff --git a/sdk/azcore/runtime/pipeline.go b/sdk/azcore/runtime/pipeline.go index 9d9288f53d3d..ffb3ea1fcf65 100644 --- a/sdk/azcore/runtime/pipeline.go +++ b/sdk/azcore/runtime/pipeline.go @@ -13,9 +13,29 @@ import ( // PipelineOptions contains Pipeline options for SDK developers type PipelineOptions struct { - AllowedHeaders, AllowedQueryParameters []string - APIVersion APIVersionOptions - PerCall, PerRetry []policy.Policy + // AllowedHeaders is the slice of headers to log with their values intact. + // All headers not in the slice will have their values REDACTED. + // Applies to request and response headers. + AllowedHeaders []string + + // AllowedQueryParameters is the slice of query parameters to log with their values intact. + // All query parameters not in the slice will have their values REDACTED. + AllowedQueryParameters []string + + // APIVersion overrides the default version requested of the service. + // Set with caution as this package version has not been tested with arbitrary service versions. + APIVersion APIVersionOptions + + // PerCall contains custom policies to inject into the pipeline. + // Each policy is executed once per request. + PerCall []policy.Policy + + // PerRetry contains custom policies to inject into the pipeline. + // Each policy is executed once per request, and for each retry of that request. + PerRetry []policy.Policy + + // TracingNamespace contains the value to use for the az.namespace span attribute. + TracingNamespace string } // Pipeline represents a primitive for sending HTTP requests and receiving responses. @@ -56,8 +76,10 @@ func NewPipeline(module, version string, plOpts PipelineOptions, options *policy policies = append(policies, NewRetryPolicy(&cp.Retry)) policies = append(policies, plOpts.PerRetry...) policies = append(policies, cp.PerRetryPolicies...) + policies = append(policies, exported.PolicyFunc(httpHeaderPolicy)) + policies = append(policies, newHTTPTracePolicy(cp.Logging.AllowedQueryParams)) policies = append(policies, NewLogPolicy(&cp.Logging)) - policies = append(policies, exported.PolicyFunc(httpHeaderPolicy), exported.PolicyFunc(bodyDownloadPolicy)) + policies = append(policies, exported.PolicyFunc(bodyDownloadPolicy)) transport := cp.Transport if transport == nil { transport = defaultHTTPClient diff --git a/sdk/azcore/runtime/policy_http_trace.go b/sdk/azcore/runtime/policy_http_trace.go new file mode 100644 index 000000000000..55eb7fea07cc --- /dev/null +++ b/sdk/azcore/runtime/policy_http_trace.go @@ -0,0 +1,117 @@ +//go:build go1.18 +// +build go1.18 + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package runtime + +import ( + "context" + "fmt" + "net/http" + "strings" + + "github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/exported" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/shared" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/policy" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/tracing" +) + +const ( + attrHTTPMethod = "http.method" + attrHTTPURL = "http.url" + attrHTTPUserAgent = "http.user_agent" + attrHTTPStatusCode = "http.status_code" + + attrAZClientReqID = "az.client_request_id" + attrAZServiceReqID = "az.service_request_id" + + attrNetPeerName = "net.peer.name" +) + +// newHTTPTracePolicy creates a new instance of the httpTracePolicy. +// - allowedQueryParams contains the user-specified query parameters that don't need to be redacted from the trace +func newHTTPTracePolicy(allowedQueryParams []string) exported.Policy { + return &httpTracePolicy{allowedQP: getAllowedQueryParams(allowedQueryParams)} +} + +// httpTracePolicy is a policy that creates a trace for the HTTP request and its response +type httpTracePolicy struct { + allowedQP map[string]struct{} +} + +// Do implements the pipeline.Policy interfaces for the httpTracePolicy type. +func (h *httpTracePolicy) Do(req *policy.Request) (resp *http.Response, err error) { + rawTracer := req.Raw().Context().Value(shared.CtxWithTracingTracer{}) + if tracer, ok := rawTracer.(tracing.Tracer); ok { + attributes := []tracing.Attribute{ + {Key: attrHTTPMethod, Value: req.Raw().Method}, + {Key: attrHTTPURL, Value: getSanitizedURL(*req.Raw().URL, h.allowedQP)}, + {Key: attrNetPeerName, Value: req.Raw().URL.Host}, + } + + if ua := req.Raw().Header.Get(shared.HeaderUserAgent); ua != "" { + attributes = append(attributes, tracing.Attribute{Key: attrHTTPUserAgent, Value: ua}) + } + if reqID := req.Raw().Header.Get(shared.HeaderXMSClientRequestID); reqID != "" { + attributes = append(attributes, tracing.Attribute{Key: attrAZClientReqID, Value: reqID}) + } + + ctx := req.Raw().Context() + ctx, span := tracer.Start(ctx, "HTTP "+req.Raw().Method, &tracing.SpanOptions{ + Kind: tracing.SpanKindClient, + Attributes: attributes, + }) + + defer func() { + if resp != nil { + span.SetAttributes(tracing.Attribute{Key: attrHTTPStatusCode, Value: resp.StatusCode}) + if resp.StatusCode > 399 { + span.SetStatus(tracing.SpanStatusError, resp.Status) + } + if reqID := resp.Header.Get(shared.HeaderXMSRequestID); reqID != "" { + span.SetAttributes(tracing.Attribute{Key: attrAZServiceReqID, Value: reqID}) + } + } else if err != nil { + // including the output from err.Error() might disclose URL query parameters. + // so instead of attempting to sanitize the output, we simply output the error type. + span.SetStatus(tracing.SpanStatusError, fmt.Sprintf("%T", err)) + } + span.End() + }() + + req = req.WithContext(ctx) + } + resp, err = req.Next() + return +} + +// StartSpanOptions contains the optional values for StartSpan. +type StartSpanOptions struct { + // for future expansion +} + +// StartSpan starts a new tracing span. +// You must call the returned func to terminate the span. Pass the applicable error +// if the span will exit with an error condition. +// - ctx is the parent context of the newly created context +// - name is the name of the span. this is typically the fully qualified name of an API ("Client.Method") +// - tracer is the client's Tracer for creating spans +// - options contains optional values. pass nil to accept any default values +func StartSpan(ctx context.Context, name string, tracer tracing.Tracer, options *StartSpanOptions) (context.Context, func(error)) { + if !tracer.Enabled() { + return ctx, func(err error) {} + } + ctx, span := tracer.Start(ctx, name, &tracing.SpanOptions{ + Kind: tracing.SpanKindInternal, + }) + ctx = context.WithValue(ctx, shared.CtxWithTracingTracer{}, tracer) + return ctx, func(err error) { + if err != nil { + errType := strings.Replace(fmt.Sprintf("%T", err), "*exported.", "*azcore.", 1) + span.SetStatus(tracing.SpanStatusError, fmt.Sprintf("%s:\n%s", errType, err.Error())) + } + span.End() + } +} diff --git a/sdk/azcore/runtime/policy_http_trace_test.go b/sdk/azcore/runtime/policy_http_trace_test.go new file mode 100644 index 000000000000..16ae58604e1a --- /dev/null +++ b/sdk/azcore/runtime/policy_http_trace_test.go @@ -0,0 +1,163 @@ +//go:build go1.18 +// +build go1.18 + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package runtime + +import ( + "context" + "io" + "net" + "net/http" + "net/url" + "strings" + "testing" + + "github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/exported" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/shared" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/tracing" + "github.com/Azure/azure-sdk-for-go/sdk/internal/mock" + "github.com/stretchr/testify/require" +) + +func TestHTTPTracePolicy(t *testing.T) { + srv, close := mock.NewServer() + defer close() + + pl := exported.NewPipeline(srv, newHTTPTracePolicy([]string{"visibleqp"})) + + // no tracer + req, err := exported.NewRequest(context.Background(), http.MethodGet, srv.URL()) + require.NoError(t, err) + srv.AppendResponse() + _, err = pl.Do(req) + require.NoError(t, err) + + // wrong tracer type + req, err = exported.NewRequest(context.WithValue(context.Background(), shared.CtxWithTracingTracer{}, 0), http.MethodGet, srv.URL()) + require.NoError(t, err) + srv.AppendResponse() + _, err = pl.Do(req) + require.NoError(t, err) + + var fullSpanName string + var spanKind tracing.SpanKind + var spanAttrs []tracing.Attribute + var spanStatus tracing.SpanStatus + var spanStatusStr string + tr := tracing.NewTracer(func(ctx context.Context, spanName string, options *tracing.SpanOptions) (context.Context, tracing.Span) { + fullSpanName = spanName + require.NotNil(t, options) + spanKind = options.Kind + spanAttrs = options.Attributes + spanImpl := tracing.SpanImpl{ + SetAttributes: func(a ...tracing.Attribute) { spanAttrs = append(spanAttrs, a...) }, + SetStatus: func(ss tracing.SpanStatus, s string) { + spanStatus = ss + spanStatusStr = s + }, + } + return ctx, tracing.NewSpan(spanImpl) + }, nil) + + // HTTP ok + req, err = exported.NewRequest(context.WithValue(context.Background(), shared.CtxWithTracingTracer{}, tr), http.MethodGet, srv.URL()+"?foo=redactme&visibleqp=bar") + require.NoError(t, err) + req.Raw().Header.Add(shared.HeaderUserAgent, "my-user-agent") + req.Raw().Header.Add(shared.HeaderXMSClientRequestID, "my-client-request") + srv.AppendResponse(mock.WithHeader(shared.HeaderXMSRequestID, "request-id")) + _, err = pl.Do(req) + require.NoError(t, err) + require.EqualValues(t, tracing.SpanStatusUnset, spanStatus) + require.EqualValues(t, "HTTP GET", fullSpanName) + require.EqualValues(t, tracing.SpanKindClient, spanKind) + require.Len(t, spanAttrs, 7) + require.Contains(t, spanAttrs, tracing.Attribute{Key: attrHTTPMethod, Value: http.MethodGet}) + require.Contains(t, spanAttrs, tracing.Attribute{Key: attrHTTPURL, Value: srv.URL() + "?foo=REDACTED&visibleqp=bar"}) + require.Contains(t, spanAttrs, tracing.Attribute{Key: attrNetPeerName, Value: srv.URL()[7:]}) // strip off the http:// + require.Contains(t, spanAttrs, tracing.Attribute{Key: attrHTTPUserAgent, Value: "my-user-agent"}) + require.Contains(t, spanAttrs, tracing.Attribute{Key: attrAZClientReqID, Value: "my-client-request"}) + require.Contains(t, spanAttrs, tracing.Attribute{Key: attrHTTPStatusCode, Value: http.StatusOK}) + require.Contains(t, spanAttrs, tracing.Attribute{Key: attrAZServiceReqID, Value: "request-id"}) + + // HTTP bad request + req, err = exported.NewRequest(context.WithValue(context.Background(), shared.CtxWithTracingTracer{}, tr), http.MethodGet, srv.URL()) + require.NoError(t, err) + srv.AppendResponse(mock.WithStatusCode(http.StatusBadRequest)) + _, err = pl.Do(req) + require.NoError(t, err) + require.EqualValues(t, tracing.SpanStatusError, spanStatus) + require.EqualValues(t, "400 Bad Request", spanStatusStr) + require.Contains(t, spanAttrs, tracing.Attribute{Key: attrHTTPStatusCode, Value: http.StatusBadRequest}) + + // HTTP error + req, err = exported.NewRequest(context.WithValue(context.Background(), shared.CtxWithTracingTracer{}, tr), http.MethodGet, srv.URL()) + require.NoError(t, err) + srv.AppendError(net.ErrClosed) + _, err = pl.Do(req) + require.Error(t, err) + require.ErrorIs(t, err, net.ErrClosed) + require.EqualValues(t, tracing.SpanStatusError, spanStatus) + require.EqualValues(t, "poll.errNetClosing", spanStatusStr) +} + +func TestStartSpan(t *testing.T) { + // tracing disabled + ctx, end := StartSpan(context.Background(), "TestStartSpan", tracing.Tracer{}, nil) + end(nil) + require.Same(t, context.Background(), ctx) + + // span no error + var startCalled bool + var endCalled bool + tr := tracing.NewTracer(func(ctx context.Context, spanName string, options *tracing.SpanOptions) (context.Context, tracing.Span) { + startCalled = true + require.EqualValues(t, "TestStartSpan", spanName) + require.NotNil(t, options) + require.EqualValues(t, tracing.SpanKindInternal, options.Kind) + spanImpl := tracing.SpanImpl{ + End: func() { endCalled = true }, + } + return ctx, tracing.NewSpan(spanImpl) + }, nil) + ctx, end = StartSpan(context.Background(), "TestStartSpan", tr, nil) + end(nil) + ctxTr := ctx.Value(shared.CtxWithTracingTracer{}) + require.NotNil(t, ctxTr) + _, ok := ctxTr.(tracing.Tracer) + require.True(t, ok) + require.True(t, startCalled) + require.True(t, endCalled) + + // with error + var spanStatus tracing.SpanStatus + var errStr string + tr = tracing.NewTracer(func(ctx context.Context, spanName string, options *tracing.SpanOptions) (context.Context, tracing.Span) { + spanImpl := tracing.SpanImpl{ + End: func() { endCalled = true }, + SetStatus: func(ss tracing.SpanStatus, s string) { + spanStatus = ss + errStr = s + }, + } + return ctx, tracing.NewSpan(spanImpl) + }, nil) + _, end = StartSpan(context.Background(), "TestStartSpan", tr, nil) + u, err := url.Parse("https://contoso.com") + require.NoError(t, err) + resp := &http.Response{ + Status: "the operation failed", + StatusCode: http.StatusBadRequest, + Body: io.NopCloser(strings.NewReader(`{ "error": { "code": "ErrorItFailed", "message": "it's not working" } }`)), + Request: &http.Request{ + Method: http.MethodGet, + URL: u, + }, + } + end(exported.NewResponseError(resp)) + require.EqualValues(t, tracing.SpanStatusError, spanStatus) + require.Contains(t, errStr, "*azcore.ResponseError") + require.Contains(t, errStr, "ERROR CODE: ErrorItFailed") +} diff --git a/sdk/azcore/runtime/poller.go b/sdk/azcore/runtime/poller.go index 3d029a3d15b7..c373f68962e3 100644 --- a/sdk/azcore/runtime/poller.go +++ b/sdk/azcore/runtime/poller.go @@ -13,6 +13,8 @@ import ( "flag" "fmt" "net/http" + "reflect" + "strings" "time" "github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/exported" @@ -20,9 +22,11 @@ import ( "github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/pollers" "github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/pollers/async" "github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/pollers/body" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/pollers/fake" "github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/pollers/loc" "github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/pollers/op" "github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/shared" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/tracing" "github.com/Azure/azure-sdk-for-go/sdk/internal/poller" ) @@ -54,6 +58,9 @@ type NewPollerOptions[T any] struct { // Handler[T] contains a custom polling implementation. Handler PollingHandler[T] + + // Tracer contains the Tracer from the client that's creating the Poller. + Tracer tracing.Tracer } // NewPoller creates a Poller based on the provided initial response. @@ -70,6 +77,7 @@ func NewPoller[T any](resp *http.Response, pl exported.Pipeline, options *NewPol op: options.Handler, resp: resp, result: result, + tracer: options.Tracer, }, nil } @@ -83,7 +91,9 @@ func NewPoller[T any](resp *http.Response, pl exported.Pipeline, options *NewPol // determine the polling method var opr PollingHandler[T] var err error - if async.Applicable(resp) { + if fake.Applicable(resp) { + opr, err = fake.New[T](pl, resp) + } else if async.Applicable(resp) { // async poller must be checked first as it can also have a location header opr, err = async.New[T](pl, resp, options.FinalStateVia) } else if op.Applicable(resp) { @@ -110,6 +120,7 @@ func NewPoller[T any](resp *http.Response, pl exported.Pipeline, options *NewPol op: opr, resp: resp, result: result, + tracer: options.Tracer, }, nil } @@ -121,6 +132,9 @@ type NewPollerFromResumeTokenOptions[T any] struct { // Handler[T] contains a custom polling implementation. Handler PollingHandler[T] + + // Tracer contains the Tracer from the client that's creating the Poller. + Tracer tracing.Tracer } // NewPollerFromResumeToken creates a Poller from a resume token string. @@ -147,7 +161,9 @@ func NewPollerFromResumeToken[T any](token string, pl exported.Pipeline, options opr := options.Handler // now rehydrate the poller based on the encoded poller type - if opr != nil { + if fake.CanResume(asJSON) { + opr, _ = fake.New[T](pl, nil) + } else if opr != nil { log.Writef(log.EventLRO, "Resuming custom poller %T.", opr) } else if async.CanResume(asJSON) { opr, _ = async.New[T](pl, nil, "") @@ -166,6 +182,7 @@ func NewPollerFromResumeToken[T any](token string, pl exported.Pipeline, options return &Poller[T]{ op: opr, result: result, + tracer: options.Tracer, }, nil } @@ -188,6 +205,7 @@ type Poller[T any] struct { resp *http.Response err error result *T + tracer tracing.Tracer done bool } @@ -203,7 +221,7 @@ type PollUntilDoneOptions struct { // options: pass nil to accept the default values. // NOTE: the default polling frequency is 30 seconds which works well for most operations. However, some operations might // benefit from a shorter or longer duration. -func (p *Poller[T]) PollUntilDone(ctx context.Context, options *PollUntilDoneOptions) (T, error) { +func (p *Poller[T]) PollUntilDone(ctx context.Context, options *PollUntilDoneOptions) (res T, err error) { if options == nil { options = &PollUntilDoneOptions{} } @@ -212,9 +230,13 @@ func (p *Poller[T]) PollUntilDone(ctx context.Context, options *PollUntilDoneOpt cp.Frequency = 30 * time.Second } + ctx, endSpan := StartSpan(ctx, fmt.Sprintf("%s.PollUntilDone", shortenTypeName(reflect.TypeOf(*p).Name())), p.tracer, nil) + defer func() { endSpan(err) }() + // skip the floor check when executing tests so they don't take so long if isTest := flag.Lookup("test.v"); isTest == nil && cp.Frequency < time.Second { - return *new(T), errors.New("polling frequency minimum is one second") + err = errors.New("polling frequency minimum is one second") + return } start := time.Now() @@ -226,22 +248,24 @@ func (p *Poller[T]) PollUntilDone(ctx context.Context, options *PollUntilDoneOpt // initial check for a retry-after header existing on the initial response if retryAfter := shared.RetryAfter(p.resp); retryAfter > 0 { log.Writef(log.EventLRO, "initial Retry-After delay for %s", retryAfter.String()) - if err := shared.Delay(ctx, retryAfter); err != nil { + if err = shared.Delay(ctx, retryAfter); err != nil { logPollUntilDoneExit(err) - return *new(T), err + return } } } // begin polling the endpoint until a terminal state is reached for { - resp, err := p.Poll(ctx) + var resp *http.Response + resp, err = p.Poll(ctx) if err != nil { logPollUntilDoneExit(err) - return *new(T), err + return } if p.Done() { logPollUntilDoneExit("succeeded") - return p.Result(ctx) + res, err = p.Result(ctx) + return } d := cp.Frequency if retryAfter := shared.RetryAfter(resp); retryAfter > 0 { @@ -252,7 +276,7 @@ func (p *Poller[T]) PollUntilDone(ctx context.Context, options *PollUntilDoneOpt } if err = shared.Delay(ctx, d); err != nil { logPollUntilDoneExit(err) - return *new(T), err + return } } } @@ -261,17 +285,22 @@ func (p *Poller[T]) PollUntilDone(ctx context.Context, options *PollUntilDoneOpt // If Poll succeeds, the poller's state is updated and the HTTP response is returned. // If Poll fails, the poller's state is unmodified and the error is returned. // Calling Poll on an LRO that has reached a terminal state will return the last HTTP response. -func (p *Poller[T]) Poll(ctx context.Context) (*http.Response, error) { +func (p *Poller[T]) Poll(ctx context.Context) (resp *http.Response, err error) { if p.Done() { // the LRO has reached a terminal state, don't poll again - return p.resp, nil + resp = p.resp + return } - resp, err := p.op.Poll(ctx) + + ctx, endSpan := StartSpan(ctx, fmt.Sprintf("%s.Poll", shortenTypeName(reflect.TypeOf(*p).Name())), p.tracer, nil) + defer func() { endSpan(err) }() + + resp, err = p.op.Poll(ctx) if err != nil { - return nil, err + return } p.resp = resp - return p.resp, nil + return } // Done returns true if the LRO has reached a terminal state. @@ -284,31 +313,40 @@ func (p *Poller[T]) Done() bool { // If the LRO completed successfully, a populated instance of T is returned. // If the LRO failed or was canceled, an *azcore.ResponseError error is returned. // Calling this on an LRO in a non-terminal state will return an error. -func (p *Poller[T]) Result(ctx context.Context) (T, error) { +func (p *Poller[T]) Result(ctx context.Context) (res T, err error) { if !p.Done() { - return *new(T), errors.New("poller is in a non-terminal state") + err = errors.New("poller is in a non-terminal state") + return } if p.done { // the result has already been retrieved, return the cached value if p.err != nil { - return *new(T), p.err + err = p.err + return } - return *p.result, nil + res = *p.result + return } - err := p.op.Result(ctx, p.result) + + ctx, endSpan := StartSpan(ctx, fmt.Sprintf("%s.Result", shortenTypeName(reflect.TypeOf(*p).Name())), p.tracer, nil) + defer func() { endSpan(err) }() + + err = p.op.Result(ctx, p.result) var respErr *exported.ResponseError if errors.As(err, &respErr) { // the LRO failed. record the error p.err = err } else if err != nil { // the call to Result failed, don't cache anything in this case - return *new(T), err + return } p.done = true if p.err != nil { - return *new(T), p.err + err = p.err + return } - return *p.result, nil + res = *p.result + return } // ResumeToken returns a value representing the poller that can be used to resume @@ -325,3 +363,22 @@ func (p *Poller[T]) ResumeToken() (string, error) { } return tk, err } + +// extracts the type name from the string returned from reflect.Value.Name() +func shortenTypeName(s string) string { + // the value is formatted as follows + // Poller[module/Package.Type].Method + // we want to shorten the generic type parameter string to Type + // anything we don't recognize will be left as-is + begin := strings.Index(s, "[") + end := strings.Index(s, "]") + if begin == -1 || end == -1 { + return s + } + + typeName := s[begin+1 : end] + if i := strings.LastIndex(typeName, "."); i > -1 { + typeName = typeName[i+1:] + } + return s[:begin+1] + typeName + s[end:] +} diff --git a/sdk/azcore/runtime/poller_test.go b/sdk/azcore/runtime/poller_test.go index 3ce04097a0e5..a16f99f667df 100644 --- a/sdk/azcore/runtime/poller_test.go +++ b/sdk/azcore/runtime/poller_test.go @@ -23,9 +23,11 @@ import ( "github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/pollers" "github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/pollers/async" "github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/pollers/body" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/pollers/fake" "github.com/Azure/azure-sdk-for-go/sdk/azcore/internal/shared" "github.com/Azure/azure-sdk-for-go/sdk/azcore/policy" "github.com/Azure/azure-sdk-for-go/sdk/internal/mock" + "github.com/Azure/azure-sdk-for-go/sdk/internal/poller" "github.com/stretchr/testify/require" ) @@ -771,8 +773,8 @@ func getPipeline(srv *mock.Server) Pipeline { ) } -func initialResponse(method, u string, resp io.Reader) (*http.Response, mock.TrackedClose) { - req, err := http.NewRequest(method, u, nil) +func initialResponse(ctx context.Context, method, u string, resp io.Reader) (*http.Response, mock.TrackedClose) { + req, err := http.NewRequestWithContext(ctx, method, u, nil) if err != nil { panic(err) } @@ -795,7 +797,7 @@ func TestNewPollerAsync(t *testing.T) { srv.AppendResponse(mock.WithBody([]byte(statusInProgress))) srv.AppendResponse(mock.WithBody([]byte(statusSucceeded))) srv.AppendResponse(mock.WithBody([]byte(successResp))) - resp, closed := initialResponse(http.MethodPut, srv.URL(), strings.NewReader(provStateStarted)) + resp, closed := initialResponse(context.Background(), http.MethodPut, srv.URL(), strings.NewReader(provStateStarted)) resp.Header.Set(shared.HeaderAzureAsync, srv.URL()) resp.StatusCode = http.StatusCreated pl := getPipeline(srv) @@ -838,7 +840,7 @@ func TestNewPollerBody(t *testing.T) { defer close() srv.AppendResponse(mock.WithBody([]byte(provStateUpdating)), mock.WithHeader("Retry-After", "1")) srv.AppendResponse(mock.WithBody([]byte(provStateSucceeded))) - resp, closed := initialResponse(http.MethodPatch, srv.URL(), strings.NewReader(provStateStarted)) + resp, closed := initialResponse(context.Background(), http.MethodPatch, srv.URL(), strings.NewReader(provStateStarted)) resp.StatusCode = http.StatusCreated pl := getPipeline(srv) poller, err := NewPoller[mockType](resp, pl, nil) @@ -874,7 +876,7 @@ func TestNewPollerInitialRetryAfter(t *testing.T) { srv.AppendResponse(mock.WithBody([]byte(statusInProgress))) srv.AppendResponse(mock.WithBody([]byte(statusSucceeded))) srv.AppendResponse(mock.WithBody([]byte(successResp))) - resp, closed := initialResponse(http.MethodPut, srv.URL(), strings.NewReader(provStateStarted)) + resp, closed := initialResponse(context.Background(), http.MethodPut, srv.URL(), strings.NewReader(provStateStarted)) resp.Header.Set(shared.HeaderAzureAsync, srv.URL()) resp.Header.Set("Retry-After", "1") resp.StatusCode = http.StatusCreated @@ -903,7 +905,7 @@ func TestNewPollerCanceled(t *testing.T) { defer close() srv.AppendResponse(mock.WithBody([]byte(statusInProgress))) srv.AppendResponse(mock.WithBody([]byte(statusCanceled)), mock.WithStatusCode(http.StatusOK)) - resp, closed := initialResponse(http.MethodPut, srv.URL(), strings.NewReader(provStateStarted)) + resp, closed := initialResponse(context.Background(), http.MethodPut, srv.URL(), strings.NewReader(provStateStarted)) resp.Header.Set(shared.HeaderAzureAsync, srv.URL()) resp.StatusCode = http.StatusCreated pl := getPipeline(srv) @@ -941,7 +943,7 @@ func TestNewPollerFailed(t *testing.T) { srv, close := mock.NewServer() defer close() srv.AppendResponse(mock.WithBody([]byte(provStateFailed))) - resp, closed := initialResponse(http.MethodPut, srv.URL(), strings.NewReader(provStateStarted)) + resp, closed := initialResponse(context.Background(), http.MethodPut, srv.URL(), strings.NewReader(provStateStarted)) resp.Header.Set(shared.HeaderAzureAsync, srv.URL()) resp.StatusCode = http.StatusCreated pl := getPipeline(srv) @@ -966,7 +968,7 @@ func TestNewPollerFailedWithError(t *testing.T) { defer close() srv.AppendResponse(mock.WithBody([]byte(statusInProgress))) srv.AppendResponse(mock.WithStatusCode(http.StatusBadRequest)) - resp, closed := initialResponse(http.MethodPut, srv.URL(), strings.NewReader(provStateStarted)) + resp, closed := initialResponse(context.Background(), http.MethodPut, srv.URL(), strings.NewReader(provStateStarted)) resp.Header.Set(shared.HeaderAzureAsync, srv.URL()) resp.StatusCode = http.StatusCreated pl := getPipeline(srv) @@ -991,7 +993,7 @@ func TestNewPollerSuccessNoContent(t *testing.T) { defer close() srv.AppendResponse(mock.WithBody([]byte(provStateUpdating))) srv.AppendResponse(mock.WithStatusCode(http.StatusNoContent)) - resp, closed := initialResponse(http.MethodPatch, srv.URL(), strings.NewReader(provStateStarted)) + resp, closed := initialResponse(context.Background(), http.MethodPatch, srv.URL(), strings.NewReader(provStateStarted)) resp.StatusCode = http.StatusCreated pl := getPipeline(srv) poller, err := NewPoller[mockType](resp, pl, nil) @@ -1024,7 +1026,7 @@ func TestNewPollerSuccessNoContent(t *testing.T) { func TestNewPollerFail202NoHeaders(t *testing.T) { srv, close := mock.NewServer() defer close() - resp, closed := initialResponse(http.MethodDelete, srv.URL(), http.NoBody) + resp, closed := initialResponse(context.Background(), http.MethodDelete, srv.URL(), http.NoBody) resp.StatusCode = http.StatusAccepted pl := getPipeline(srv) poller, err := NewPoller[mockType](resp, pl, nil) @@ -1049,7 +1051,7 @@ func TestNewPollerWithResponseType(t *testing.T) { defer close() srv.AppendResponse(mock.WithBody([]byte(provStateUpdating)), mock.WithHeader("Retry-After", "1")) srv.AppendResponse(mock.WithBody([]byte(provStateSucceeded))) - resp, closed := initialResponse(http.MethodPatch, srv.URL(), strings.NewReader(provStateStarted)) + resp, closed := initialResponse(context.Background(), http.MethodPatch, srv.URL(), strings.NewReader(provStateStarted)) resp.StatusCode = http.StatusCreated pl := getPipeline(srv) poller, err := NewPoller[preconstructedMockType](resp, pl, nil) @@ -1146,7 +1148,7 @@ func TestNewPollerWithCustomHandler(t *testing.T) { srv.AppendResponse(mock.WithBody([]byte(statusInProgress))) srv.AppendResponse(mock.WithBody([]byte(statusSucceeded))) srv.AppendResponse(mock.WithBody([]byte(successResp))) - resp, closed := initialResponse(http.MethodPut, srv.URL(), strings.NewReader(provStateStarted)) + resp, closed := initialResponse(context.Background(), http.MethodPut, srv.URL(), strings.NewReader(provStateStarted)) resp.Header.Set(shared.HeaderAzureAsync, srv.URL()) resp.StatusCode = http.StatusCreated pl := getPipeline(srv) @@ -1176,3 +1178,42 @@ func TestNewPollerWithCustomHandler(t *testing.T) { require.NoError(t, err) require.EqualValues(t, "value", *result.Field) } + +func TestShortenPollerTypeName(t *testing.T) { + result := shortenTypeName("Poller[module/package.ClientOperationResponse].PollUntilDone") + require.EqualValues(t, "Poller[ClientOperationResponse].PollUntilDone", result) + + result = shortenTypeName("Poller[package.ClientOperationResponse].PollUntilDone") + require.EqualValues(t, "Poller[ClientOperationResponse].PollUntilDone", result) + + result = shortenTypeName("Poller[ClientOperationResponse].PollUntilDone") + require.EqualValues(t, "Poller[ClientOperationResponse].PollUntilDone", result) + + result = shortenTypeName("Poller.PollUntilDone") + require.EqualValues(t, "Poller.PollUntilDone", result) +} + +func TestNewFakePoller(t *testing.T) { + srv, close := mock.NewServer() + defer close() + srv.AppendResponse(mock.WithHeader(shared.HeaderFakePollerStatus, "FakePollerInProgress")) + srv.AppendResponse(mock.WithHeader(shared.HeaderFakePollerStatus, poller.StatusSucceeded), mock.WithStatusCode(http.StatusNoContent)) + pollCtx := context.WithValue(context.Background(), shared.CtxAPINameKey{}, "FakeAPI") + resp, closed := initialResponse(pollCtx, http.MethodPatch, srv.URL(), http.NoBody) + resp.StatusCode = http.StatusCreated + resp.Header.Set(shared.HeaderFakePollerStatus, "FakePollerInProgress") + pl := getPipeline(srv) + poller, err := NewPoller[mockType](resp, pl, nil) + require.NoError(t, err) + require.True(t, closed()) + if pt := typeOfOpField(poller); pt != reflect.TypeOf((*fake.Poller[mockType])(nil)) { + t.Fatalf("unexpected poller type %s", pt.String()) + } + tk, err := poller.ResumeToken() + require.NoError(t, err) + poller, err = NewPollerFromResumeToken[mockType](tk, pl, nil) + require.NoError(t, err) + result, err := poller.PollUntilDone(context.Background(), &PollUntilDoneOptions{Frequency: time.Millisecond}) + require.NoError(t, err) + require.Nil(t, result.Field) +} diff --git a/sdk/azcore/runtime/request.go b/sdk/azcore/runtime/request.go index 98e00718488e..cdbf8bde60b0 100644 --- a/sdk/azcore/runtime/request.go +++ b/sdk/azcore/runtime/request.go @@ -169,6 +169,9 @@ func SkipBodyDownload(req *policy.Request) { req.SetOperationValue(bodyDownloadPolicyOpValues{Skip: true}) } +// CtxAPINameKey is used as a context key for adding/retrieving the API name. +type CtxAPINameKey = shared.CtxAPINameKey + // returns a clone of the object graph pointed to by v, omitting values of all read-only // fields. if there are no read-only fields in the object graph, no clone is created. func cloneWithoutReadOnlyFields(v interface{}) interface{} { diff --git a/sdk/azcore/tracing/tracing.go b/sdk/azcore/tracing/tracing.go index 75f757cedd3b..f5157005f555 100644 --- a/sdk/azcore/tracing/tracing.go +++ b/sdk/azcore/tracing/tracing.go @@ -45,21 +45,28 @@ func (p Provider) NewTracer(name, version string) (tracer Tracer) { // TracerOptions contains the optional values when creating a Tracer. type TracerOptions struct { - // for future expansion + // SpanFromContext contains the implementation for the Tracer.SpanFromContext method. + SpanFromContext func(context.Context) (Span, bool) } // NewTracer creates a Tracer with the specified values. // - newSpanFn is the underlying implementation for creating Span instances // - options contains optional values; pass nil to accept the default value func NewTracer(newSpanFn func(ctx context.Context, spanName string, options *SpanOptions) (context.Context, Span), options *TracerOptions) Tracer { + if options == nil { + options = &TracerOptions{} + } return Tracer{ - newSpanFn: newSpanFn, + newSpanFn: newSpanFn, + spanFromContextFn: options.SpanFromContext, } } // Tracer is the factory that creates Span instances. type Tracer struct { - newSpanFn func(ctx context.Context, spanName string, options *SpanOptions) (context.Context, Span) + attrs []Attribute + newSpanFn func(ctx context.Context, spanName string, options *SpanOptions) (context.Context, Span) + spanFromContextFn func(ctx context.Context) (Span, bool) } // Start creates a new span and a context.Context that contains it. @@ -68,11 +75,37 @@ type Tracer struct { // - options contains optional values for the span, pass nil to accept any defaults func (t Tracer) Start(ctx context.Context, spanName string, options *SpanOptions) (context.Context, Span) { if t.newSpanFn != nil { - return t.newSpanFn(ctx, spanName, options) + opts := SpanOptions{} + if options != nil { + opts = *options + } + opts.Attributes = append(opts.Attributes, t.attrs...) + return t.newSpanFn(ctx, spanName, &opts) } return ctx, Span{} } +// SetAttributes sets attrs to be applied to each Span. If a key from attrs +// already exists for an attribute of the Span it will be overwritten with +// the value contained in attrs. +func (t *Tracer) SetAttributes(attrs ...Attribute) { + t.attrs = append(t.attrs, attrs...) +} + +// Enabled returns true if this Tracer is capable of creating Spans. +func (t Tracer) Enabled() bool { + return t.newSpanFn != nil +} + +// SpanFromContext returns the Span associated with the current context. +// If the provided context has no Span, false is returned. +func (t Tracer) SpanFromContext(ctx context.Context) (Span, bool) { + if t.spanFromContextFn != nil { + return t.spanFromContextFn(ctx) + } + return Span{}, false +} + // SpanOptions contains optional settings for creating a span. type SpanOptions struct { // Kind indicates the kind of Span. diff --git a/sdk/azcore/tracing/tracing_test.go b/sdk/azcore/tracing/tracing_test.go index da04627e3167..5ca8b3f267de 100644 --- a/sdk/azcore/tracing/tracing_test.go +++ b/sdk/azcore/tracing/tracing_test.go @@ -17,6 +17,8 @@ func TestProviderZeroValues(t *testing.T) { pr := Provider{} tr := pr.NewTracer("name", "version") require.Zero(t, tr) + require.False(t, tr.Enabled()) + tr.SetAttributes() ctx, sp := tr.Start(context.Background(), "spanName", nil) require.Equal(t, context.Background(), ctx) require.Zero(t, sp) @@ -25,6 +27,9 @@ func TestProviderZeroValues(t *testing.T) { sp.End() sp.SetAttributes(Attribute{}) sp.SetStatus(SpanStatusError, "boom") + sp, ok := tr.SpanFromContext(ctx) + require.False(t, ok) + require.Zero(t, sp) } func TestProvider(t *testing.T) { @@ -33,6 +38,7 @@ func TestProvider(t *testing.T) { var endCalled bool var setAttributesCalled bool var setStatusCalled bool + var spanFromContextCalled bool pr := NewProvider(func(name, version string) Tracer { return NewTracer(func(context.Context, string, *SpanOptions) (context.Context, Span) { @@ -43,10 +49,23 @@ func TestProvider(t *testing.T) { SetAttributes: func(...Attribute) { setAttributesCalled = true }, SetStatus: func(SpanStatus, string) { setStatusCalled = true }, }) - }, nil) + }, &TracerOptions{ + SpanFromContext: func(context.Context) (Span, bool) { + spanFromContextCalled = true + return Span{}, true + }, + }) }, nil) tr := pr.NewTracer("name", "version") require.NotZero(t, tr) + require.True(t, tr.Enabled()) + sp, ok := tr.SpanFromContext(context.Background()) + require.True(t, ok) + require.Zero(t, sp) + tr.SetAttributes(Attribute{Key: "some", Value: "attribute"}) + require.Len(t, tr.attrs, 1) + require.EqualValues(t, tr.attrs[0].Key, "some") + require.EqualValues(t, tr.attrs[0].Value, "attribute") ctx, sp := tr.Start(context.Background(), "name", nil) require.NotEqual(t, context.Background(), ctx) @@ -62,4 +81,5 @@ func TestProvider(t *testing.T) { require.True(t, endCalled) require.True(t, setAttributesCalled) require.True(t, setStatusCalled) + require.True(t, spanFromContextCalled) } diff --git a/sdk/azidentity/CHANGELOG.md b/sdk/azidentity/CHANGELOG.md index 57ff2c6509b0..cc8034cf7a8b 100644 --- a/sdk/azidentity/CHANGELOG.md +++ b/sdk/azidentity/CHANGELOG.md @@ -1,17 +1,12 @@ # Release History -## 1.3.0-beta.6 (Unreleased) - -### Features Added +## 1.3.0 (2023-05-09) ### Breaking Changes > These changes affect only code written against a beta version such as v1.3.0-beta.5 -* Renamed `DisableInstanceDiscovery` to `DisableAuthorityValidationAndInstanceDiscovery` * Renamed `NewOnBehalfOfCredentialFromCertificate` to `NewOnBehalfOfCredentialWithCertificate` * Renamed `NewOnBehalfOfCredentialFromSecret` to `NewOnBehalfOfCredentialWithSecret` -### Bugs Fixed - ### Other Changes * Upgraded to MSAL v1.0.0 diff --git a/sdk/azidentity/TROUBLESHOOTING.md b/sdk/azidentity/TROUBLESHOOTING.md index a6c1c5ca30ab..7b7515ebac22 100644 --- a/sdk/azidentity/TROUBLESHOOTING.md +++ b/sdk/azidentity/TROUBLESHOOTING.md @@ -80,7 +80,7 @@ azlog.SetEvents(azidentity.EventAuthentication) | Error |Description| Mitigation | |---|---|---| -|"DefaultAzureCredential failed to acquire a token"|No credential in the `DefaultAzureCredential` chain provided a token|
  • [Enable logging](#enable-and-configure-logging) to get further diagnostic information.
  • Consult the troubleshooting guide for underlying credential types for more information.
    • [EnvironmentCredential](#troubleshoot-environmentcredential-authentication-issues)
    • [ManagedIdentityCredential](#troubleshoot-visualstudiocredential-authentication-issues)
    • [AzureCLICredential](#troubleshoot-azureclicredential-authentication-issues)
    | +|"DefaultAzureCredential failed to acquire a token"|No credential in the `DefaultAzureCredential` chain provided a token|
    • [Enable logging](#enable-and-configure-logging) to get further diagnostic information.
    • Consult the troubleshooting guide for underlying credential types for more information.
      • [EnvironmentCredential](#troubleshoot-environmentcredential-authentication-issues)
      • [ManagedIdentityCredential](#troubleshoot-managedidentitycredential-authentication-issues)
      • [AzureCLICredential](#troubleshoot-azureclicredential-authentication-issues)
      | |Error from the client with a status code of 401 or 403|Authentication succeeded but the authorizing Azure service responded with a 401 (Unauthorized), or 403 (Forbidden) status code|
      • [Enable logging](#enable-and-configure-logging) to determine which credential in the chain returned the authenticating token.
      • If an unexpected credential is returning a token, check application configuration such as environment variables.
      • Ensure the correct role is assigned to the authenticated identity. For example, a service specific role rather than the subscription Owner role.
      | ## Troubleshoot EnvironmentCredential authentication issues diff --git a/sdk/azidentity/client_assertion_credential.go b/sdk/azidentity/client_assertion_credential.go index 7db693094ec8..d9d22996cd47 100644 --- a/sdk/azidentity/client_assertion_credential.go +++ b/sdk/azidentity/client_assertion_credential.go @@ -36,12 +36,11 @@ type ClientAssertionCredentialOptions struct { // Add the wildcard value "*" to allow the credential to acquire tokens for any tenant in which the // application is registered. AdditionallyAllowedTenants []string - // DisableAuthorityValidationAndInstanceDiscovery should be set true only by applications authenticating - // in disconnected clouds, or private clouds such as Azure Stack. It determines whether the credential - // requests Azure AD instance metadata from https://login.microsoft.com before authenticating. Setting - // this to true will skip this request, making the application responsible for ensuring the configured - // authority is valid and trustworthy. - DisableAuthorityValidationAndInstanceDiscovery bool + // DisableInstanceDiscovery should be set true only by applications authenticating in disconnected clouds, or + // private clouds such as Azure Stack. It determines whether the credential requests Azure AD instance metadata + // from https://login.microsoft.com before authenticating. Setting this to true will skip this request, making + // the application responsible for ensuring the configured authority is valid and trustworthy. + DisableInstanceDiscovery bool } // NewClientAssertionCredential constructs a ClientAssertionCredential. The getAssertion function must be thread safe. Pass nil for options to accept defaults. @@ -57,7 +56,7 @@ func NewClientAssertionCredential(tenantID, clientID string, getAssertion func(c return getAssertion(ctx) }, ) - c, err := getConfidentialClient(clientID, tenantID, cred, &options.ClientOptions, confidential.WithInstanceDiscovery(!options.DisableAuthorityValidationAndInstanceDiscovery)) + c, err := getConfidentialClient(clientID, tenantID, cred, &options.ClientOptions, confidential.WithInstanceDiscovery(!options.DisableInstanceDiscovery)) if err != nil { return nil, err } diff --git a/sdk/azidentity/client_assertion_credential_test.go b/sdk/azidentity/client_assertion_credential_test.go index 3477d0a39d70..b6ac65566cea 100644 --- a/sdk/azidentity/client_assertion_credential_test.go +++ b/sdk/azidentity/client_assertion_credential_test.go @@ -100,10 +100,7 @@ func TestClientAssertionCredential_Live(t *testing.T) { func(context.Context) (string, error) { return getAssertion(certs[0], key) }, - &ClientAssertionCredentialOptions{ - ClientOptions: o, - DisableAuthorityValidationAndInstanceDiscovery: d, - }, + &ClientAssertionCredentialOptions{ClientOptions: o, DisableInstanceDiscovery: d}, ) if err != nil { t.Fatal(err) diff --git a/sdk/azidentity/client_certificate_credential.go b/sdk/azidentity/client_certificate_credential.go index acd9360b6ba5..804eba899ecf 100644 --- a/sdk/azidentity/client_certificate_credential.go +++ b/sdk/azidentity/client_certificate_credential.go @@ -29,12 +29,11 @@ type ClientCertificateCredentialOptions struct { // Add the wildcard value "*" to allow the credential to acquire tokens for any tenant in which the // application is registered. AdditionallyAllowedTenants []string - // DisableAuthorityValidationAndInstanceDiscovery should be set true only by applications authenticating - // in disconnected clouds, or private clouds such as Azure Stack. It determines whether the credential - // requests Azure AD instance metadata from https://login.microsoft.com before authenticating. Setting - // this to true will skip this request, making the application responsible for ensuring the configured - // authority is valid and trustworthy. - DisableAuthorityValidationAndInstanceDiscovery bool + // DisableInstanceDiscovery should be set true only by applications authenticating in disconnected clouds, or + // private clouds such as Azure Stack. It determines whether the credential requests Azure AD instance metadata + // from https://login.microsoft.com before authenticating. Setting this to true will skip this request, making + // the application responsible for ensuring the configured authority is valid and trustworthy. + DisableInstanceDiscovery bool // SendCertificateChain controls whether the credential sends the public certificate chain in the x5c // header of each token request's JWT. This is required for Subject Name/Issuer (SNI) authentication. // Defaults to False. @@ -63,7 +62,7 @@ func NewClientCertificateCredential(tenantID string, clientID string, certs []*x if options.SendCertificateChain { o = append(o, confidential.WithX5C()) } - o = append(o, confidential.WithInstanceDiscovery(!options.DisableAuthorityValidationAndInstanceDiscovery)) + o = append(o, confidential.WithInstanceDiscovery(!options.DisableInstanceDiscovery)) c, err := getConfidentialClient(clientID, tenantID, cred, &options.ClientOptions, o...) if err != nil { return nil, err diff --git a/sdk/azidentity/client_certificate_credential_test.go b/sdk/azidentity/client_certificate_credential_test.go index 02820f452234..0137aa7302b5 100644 --- a/sdk/azidentity/client_certificate_credential_test.go +++ b/sdk/azidentity/client_certificate_credential_test.go @@ -239,7 +239,7 @@ func TestClientCertificateCredential_Live(t *testing.T) { } o, stop := initRecording(t) defer stop() - opts := &ClientCertificateCredentialOptions{ClientOptions: o, DisableAuthorityValidationAndInstanceDiscovery: true} + opts := &ClientCertificateCredentialOptions{ClientOptions: o, DisableInstanceDiscovery: true} cred, err := NewClientCertificateCredential(liveSP.tenantID, liveSP.clientID, certs, key, opts) if err != nil { t.Fatalf("failed to construct credential: %v", err) @@ -265,7 +265,7 @@ func TestClientCertificateCredentialADFS_Live(t *testing.T) { o, stop := initRecording(t) defer stop() o.Cloud.ActiveDirectoryAuthorityHost = adfsAuthority - opts := &ClientCertificateCredentialOptions{ClientOptions: o, DisableAuthorityValidationAndInstanceDiscovery: true} + opts := &ClientCertificateCredentialOptions{ClientOptions: o, DisableInstanceDiscovery: true} cred, err := NewClientCertificateCredential("adfs", adfsLiveSP.clientID, certs, key, opts) if err != nil { t.Fatalf("failed to construct credential: %v", err) diff --git a/sdk/azidentity/client_secret_credential.go b/sdk/azidentity/client_secret_credential.go index 727910455909..dda21f6b88d6 100644 --- a/sdk/azidentity/client_secret_credential.go +++ b/sdk/azidentity/client_secret_credential.go @@ -24,12 +24,11 @@ type ClientSecretCredentialOptions struct { // Add the wildcard value "*" to allow the credential to acquire tokens for any tenant in which the // application is registered. AdditionallyAllowedTenants []string - // DisableAuthorityValidationAndInstanceDiscovery should be set true only by applications authenticating - // in disconnected clouds, or private clouds such as Azure Stack. It determines whether the credential - // requests Azure AD instance metadata from https://login.microsoft.com before authenticating. Setting - // this to true will skip this request, making the application responsible for ensuring the configured - // authority is valid and trustworthy. - DisableAuthorityValidationAndInstanceDiscovery bool + // DisableInstanceDiscovery should be set true only by applications authenticating in disconnected clouds, or + // private clouds such as Azure Stack. It determines whether the credential requests Azure AD instance metadata + // from https://login.microsoft.com before authenticating. Setting this to true will skip this request, making + // the application responsible for ensuring the configured authority is valid and trustworthy. + DisableInstanceDiscovery bool } // ClientSecretCredential authenticates an application with a client secret. @@ -48,7 +47,7 @@ func NewClientSecretCredential(tenantID string, clientID string, clientSecret st return nil, err } c, err := getConfidentialClient( - clientID, tenantID, cred, &options.ClientOptions, confidential.WithInstanceDiscovery(!options.DisableAuthorityValidationAndInstanceDiscovery), + clientID, tenantID, cred, &options.ClientOptions, confidential.WithInstanceDiscovery(!options.DisableInstanceDiscovery), ) if err != nil { return nil, err diff --git a/sdk/azidentity/client_secret_credential_test.go b/sdk/azidentity/client_secret_credential_test.go index e5a7abe1efc1..9e6b230522f6 100644 --- a/sdk/azidentity/client_secret_credential_test.go +++ b/sdk/azidentity/client_secret_credential_test.go @@ -49,7 +49,7 @@ func TestClientSecretCredential_Live(t *testing.T) { t.Run(name, func(t *testing.T) { opts, stop := initRecording(t) defer stop() - o := ClientSecretCredentialOptions{ClientOptions: opts, DisableAuthorityValidationAndInstanceDiscovery: disabledID} + o := ClientSecretCredentialOptions{ClientOptions: opts, DisableInstanceDiscovery: disabledID} cred, err := NewClientSecretCredential(liveSP.tenantID, liveSP.clientID, liveSP.secret, &o) if err != nil { t.Fatalf("failed to construct credential: %v", err) @@ -68,7 +68,7 @@ func TestClientSecretCredentialADFS_Live(t *testing.T) { opts, stop := initRecording(t) defer stop() opts.Cloud.ActiveDirectoryAuthorityHost = adfsAuthority - o := ClientSecretCredentialOptions{ClientOptions: opts, DisableAuthorityValidationAndInstanceDiscovery: true} + o := ClientSecretCredentialOptions{ClientOptions: opts, DisableInstanceDiscovery: true} cred, err := NewClientSecretCredential("adfs", adfsLiveSP.clientID, adfsLiveSP.secret, &o) if err != nil { t.Fatalf("failed to construct credential: %v", err) diff --git a/sdk/azidentity/default_azure_credential.go b/sdk/azidentity/default_azure_credential.go index c3f580dc560b..1e3efdc97a96 100644 --- a/sdk/azidentity/default_azure_credential.go +++ b/sdk/azidentity/default_azure_credential.go @@ -27,12 +27,11 @@ type DefaultAzureCredentialOptions struct { // the wildcard value "*" to allow the credential to acquire tokens for any tenant. This value can also be // set as a semicolon delimited list of tenants in the environment variable AZURE_ADDITIONALLY_ALLOWED_TENANTS. AdditionallyAllowedTenants []string - // DisableAuthorityValidationAndInstanceDiscovery should be set true only by applications authenticating - // in disconnected clouds, or private clouds such as Azure Stack. It determines whether the credential - // requests Azure AD instance metadata from https://login.microsoft.com before authenticating. Setting - // this to true will skip this request, making the application responsible for ensuring the configured - // authority is valid and trustworthy. - DisableAuthorityValidationAndInstanceDiscovery bool + // DisableInstanceDiscovery should be set true only by applications authenticating in disconnected clouds, or + // private clouds such as Azure Stack. It determines whether the credential requests Azure AD instance metadata + // from https://login.microsoft.com before authenticating. Setting this to true will skip this request, making + // the application responsible for ensuring the configured authority is valid and trustworthy. + DisableInstanceDiscovery bool // TenantID identifies the tenant the Azure CLI should authenticate in. // Defaults to the CLI's default tenant, which is typically the home tenant of the user logged in to the CLI. TenantID string @@ -73,9 +72,9 @@ func NewDefaultAzureCredential(options *DefaultAzureCredentialOptions) (*Default } envCred, err := NewEnvironmentCredential(&EnvironmentCredentialOptions{ - ClientOptions: options.ClientOptions, - DisableAuthorityValidationAndInstanceDiscovery: options.DisableAuthorityValidationAndInstanceDiscovery, - additionallyAllowedTenants: additionalTenants, + ClientOptions: options.ClientOptions, + DisableInstanceDiscovery: options.DisableInstanceDiscovery, + additionallyAllowedTenants: additionalTenants, }) if err == nil { creds = append(creds, envCred) @@ -88,7 +87,7 @@ func NewDefaultAzureCredential(options *DefaultAzureCredentialOptions) (*Default wic, err := NewWorkloadIdentityCredential(&WorkloadIdentityCredentialOptions{ AdditionallyAllowedTenants: additionalTenants, ClientOptions: options.ClientOptions, - DisableAuthorityValidationAndInstanceDiscovery: options.DisableAuthorityValidationAndInstanceDiscovery, + DisableInstanceDiscovery: options.DisableInstanceDiscovery, }) if err == nil { creds = append(creds, wic) diff --git a/sdk/azidentity/device_code_credential.go b/sdk/azidentity/device_code_credential.go index a7c3376631c1..108e83c43aee 100644 --- a/sdk/azidentity/device_code_credential.go +++ b/sdk/azidentity/device_code_credential.go @@ -27,12 +27,11 @@ type DeviceCodeCredentialOptions struct { // ClientID is the ID of the application users will authenticate to. // Defaults to the ID of an Azure development application. ClientID string - // DisableAuthorityValidationAndInstanceDiscovery should be set true only by applications authenticating - // in disconnected clouds, or private clouds such as Azure Stack. It determines whether the credential - // requests Azure AD instance metadata from https://login.microsoft.com before authenticating. Setting - // this to true will skip this request, making the application responsible for ensuring the configured - // authority is valid and trustworthy. - DisableAuthorityValidationAndInstanceDiscovery bool + // DisableInstanceDiscovery should be set true only by applications authenticating in disconnected clouds, or + // private clouds such as Azure Stack. It determines whether the credential requests Azure AD instance metadata + // from https://login.microsoft.com before authenticating. Setting this to true will skip this request, making + // the application responsible for ensuring the configured authority is valid and trustworthy. + DisableInstanceDiscovery bool // TenantID is the Azure Active Directory tenant the credential authenticates in. Defaults to the // "organizations" tenant, which can authenticate work and school accounts. Required for single-tenant // applications. @@ -89,7 +88,7 @@ func NewDeviceCodeCredential(options *DeviceCodeCredentialOptions) (*DeviceCodeC } cp.init() c, err := getPublicClient( - cp.ClientID, cp.TenantID, &cp.ClientOptions, public.WithInstanceDiscovery(!cp.DisableAuthorityValidationAndInstanceDiscovery), + cp.ClientID, cp.TenantID, &cp.ClientOptions, public.WithInstanceDiscovery(!cp.DisableInstanceDiscovery), ) if err != nil { return nil, err diff --git a/sdk/azidentity/device_code_credential_test.go b/sdk/azidentity/device_code_credential_test.go index 0f91343a8042..de2eb7fe5962 100644 --- a/sdk/azidentity/device_code_credential_test.go +++ b/sdk/azidentity/device_code_credential_test.go @@ -99,7 +99,7 @@ func TestDeviceCodeCredential_Live(t *testing.T) { }, { desc: "instance discovery disabled", - opts: DeviceCodeCredentialOptions{DisableAuthorityValidationAndInstanceDiscovery: true, TenantID: liveSP.tenantID}, + opts: DeviceCodeCredentialOptions{DisableInstanceDiscovery: true, TenantID: liveSP.tenantID}, }, { desc: "optional tenant", @@ -133,9 +133,10 @@ func TestDeviceCodeCredentialADFS_Live(t *testing.T) { defer stop() o.Cloud.ActiveDirectoryAuthorityHost = adfsAuthority opts := DeviceCodeCredentialOptions{ - ClientID: adfsLiveUser.clientID, - ClientOptions: o, DisableAuthorityValidationAndInstanceDiscovery: true, - TenantID: "adfs", + ClientID: adfsLiveUser.clientID, + ClientOptions: o, + DisableInstanceDiscovery: true, + TenantID: "adfs", } if recording.GetRecordMode() == recording.PlaybackMode { opts.UserPrompt = func(ctx context.Context, m DeviceCodeMessage) error { return nil } diff --git a/sdk/azidentity/environment_credential.go b/sdk/azidentity/environment_credential.go index cefb1dd4da2a..7ecd928e0245 100644 --- a/sdk/azidentity/environment_credential.go +++ b/sdk/azidentity/environment_credential.go @@ -24,12 +24,11 @@ const envVarSendCertChain = "AZURE_CLIENT_SEND_CERTIFICATE_CHAIN" type EnvironmentCredentialOptions struct { azcore.ClientOptions - // DisableAuthorityValidationAndInstanceDiscovery should be set true only by applications authenticating - // in disconnected clouds, or private clouds such as Azure Stack. It determines whether the credential - // requests Azure AD instance metadata from https://login.microsoft.com before authenticating. Setting - // this to true will skip this request, making the application responsible for ensuring the configured - // authority is valid and trustworthy. - DisableAuthorityValidationAndInstanceDiscovery bool + // DisableInstanceDiscovery should be set true only by applications authenticating in disconnected clouds, or + // private clouds such as Azure Stack. It determines whether the credential requests Azure AD instance metadata + // from https://login.microsoft.com before authenticating. Setting this to true will skip this request, making + // the application responsible for ensuring the configured authority is valid and trustworthy. + DisableInstanceDiscovery bool // additionallyAllowedTenants is used only by NewDefaultAzureCredential() to enable that constructor's explicit // option to override the value of AZURE_ADDITIONALLY_ALLOWED_TENANTS. Applications using EnvironmentCredential // directly should set that variable instead. This field should remain unexported to preserve this credential's @@ -102,7 +101,7 @@ func NewEnvironmentCredential(options *EnvironmentCredentialOptions) (*Environme o := &ClientSecretCredentialOptions{ AdditionallyAllowedTenants: additionalTenants, ClientOptions: options.ClientOptions, - DisableAuthorityValidationAndInstanceDiscovery: options.DisableAuthorityValidationAndInstanceDiscovery, + DisableInstanceDiscovery: options.DisableInstanceDiscovery, } cred, err := NewClientSecretCredential(tenantID, clientID, clientSecret, o) if err != nil { @@ -127,7 +126,7 @@ func NewEnvironmentCredential(options *EnvironmentCredentialOptions) (*Environme o := &ClientCertificateCredentialOptions{ AdditionallyAllowedTenants: additionalTenants, ClientOptions: options.ClientOptions, - DisableAuthorityValidationAndInstanceDiscovery: options.DisableAuthorityValidationAndInstanceDiscovery, + DisableInstanceDiscovery: options.DisableInstanceDiscovery, } if v, ok := os.LookupEnv(envVarSendCertChain); ok { o.SendCertificateChain = v == "1" || strings.ToLower(v) == "true" @@ -144,7 +143,7 @@ func NewEnvironmentCredential(options *EnvironmentCredentialOptions) (*Environme o := &UsernamePasswordCredentialOptions{ AdditionallyAllowedTenants: additionalTenants, ClientOptions: options.ClientOptions, - DisableAuthorityValidationAndInstanceDiscovery: options.DisableAuthorityValidationAndInstanceDiscovery, + DisableInstanceDiscovery: options.DisableInstanceDiscovery, } cred, err := NewUsernamePasswordCredential(tenantID, clientID, username, password, o) if err != nil { diff --git a/sdk/azidentity/environment_credential_test.go b/sdk/azidentity/environment_credential_test.go index e8035efe6f8e..061acb16d33a 100644 --- a/sdk/azidentity/environment_credential_test.go +++ b/sdk/azidentity/environment_credential_test.go @@ -248,8 +248,8 @@ func TestEnvironmentCredential_ClientSecretLive(t *testing.T) { opts, stop := initRecording(t) defer stop() cred, err := NewEnvironmentCredential(&EnvironmentCredentialOptions{ - ClientOptions: opts, - DisableAuthorityValidationAndInstanceDiscovery: disabledID, + ClientOptions: opts, + DisableInstanceDiscovery: disabledID, }) if err != nil { t.Fatalf("failed to construct credential: %v", err) @@ -275,8 +275,8 @@ func TestEnvironmentCredentialADFS_ClientSecretLive(t *testing.T) { opts, stop := initRecording(t) defer stop() cred, err := NewEnvironmentCredential(&EnvironmentCredentialOptions{ - ClientOptions: opts, - DisableAuthorityValidationAndInstanceDiscovery: true, + ClientOptions: opts, + DisableInstanceDiscovery: true, }) if err != nil { t.Fatalf("failed to construct credential: %v", err) @@ -330,8 +330,8 @@ func TestEnvironmentCredential_UserPasswordLive(t *testing.T) { opts, stop := initRecording(t) defer stop() cred, err := NewEnvironmentCredential(&EnvironmentCredentialOptions{ - ClientOptions: opts, - DisableAuthorityValidationAndInstanceDiscovery: disabledID, + ClientOptions: opts, + DisableInstanceDiscovery: disabledID, }) if err != nil { t.Fatalf("failed to construct credential: %v", err) @@ -358,8 +358,8 @@ func TestEnvironmentCredentialADFS_UserPasswordLive(t *testing.T) { opts, stop := initRecording(t) defer stop() cred, err := NewEnvironmentCredential(&EnvironmentCredentialOptions{ - ClientOptions: opts, - DisableAuthorityValidationAndInstanceDiscovery: true, + ClientOptions: opts, + DisableInstanceDiscovery: true, }) if err != nil { t.Fatalf("failed to construct credential: %v", err) diff --git a/sdk/azidentity/go.mod b/sdk/azidentity/go.mod index b1158a670b2a..05eb779280ac 100644 --- a/sdk/azidentity/go.mod +++ b/sdk/azidentity/go.mod @@ -3,8 +3,8 @@ module github.com/Azure/azure-sdk-for-go/sdk/azidentity go 1.18 require ( - github.com/Azure/azure-sdk-for-go/sdk/azcore v1.5.0-beta.1 - github.com/Azure/azure-sdk-for-go/sdk/internal v1.2.0 + github.com/Azure/azure-sdk-for-go/sdk/azcore v1.6.0 + github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0 github.com/AzureAD/microsoft-authentication-library-for-go v1.0.0 github.com/golang-jwt/jwt/v4 v4.5.0 github.com/google/uuid v1.3.0 diff --git a/sdk/azidentity/go.sum b/sdk/azidentity/go.sum index a032d22d66c7..934934be4a7e 100644 --- a/sdk/azidentity/go.sum +++ b/sdk/azidentity/go.sum @@ -1,7 +1,7 @@ -github.com/Azure/azure-sdk-for-go/sdk/azcore v1.5.0-beta.1 h1:yLM4ZIC+NRvzwFGpXjUbf5FhPBVxJgmYXkjePgNAx64= -github.com/Azure/azure-sdk-for-go/sdk/azcore v1.5.0-beta.1/go.mod h1:ON4tFdPTwRcgWEaVDrN3584Ef+b7GgSJaXxe5fW9t4M= -github.com/Azure/azure-sdk-for-go/sdk/internal v1.2.0 h1:leh5DwKv6Ihwi+h60uHtn6UWAxBbZ0q8DwQVMzf61zw= -github.com/Azure/azure-sdk-for-go/sdk/internal v1.2.0/go.mod h1:eWRD7oawr1Mu1sLCawqVc0CUiF43ia3qQMxLscsKQ9w= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.6.0 h1:8kDqDngH+DmVBiCtIjCFTGa7MBnsIOkF9IccInFEbjk= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.6.0/go.mod h1:bjGvMhVMb+EEm3VRNQawDMUyMMjo+S5ewNjflkep/0Q= +github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0 h1:sXr+ck84g/ZlZUOZiNELInmMgOsuGwdjjVkEIde0OtY= +github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0/go.mod h1:okt5dMMTOFjX/aovMlrjvvXoPMBVSPzk9185BT0+eZM= github.com/AzureAD/microsoft-authentication-library-for-go v1.0.0 h1:OBhqkivkhkMqLPymWEppkm7vgPQY2XsHoEkaMQ0AdZY= github.com/AzureAD/microsoft-authentication-library-for-go v1.0.0/go.mod h1:kgDmCTgBzIEPFElEF+FK0SdjAor06dRq2Go927dnQ6o= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= diff --git a/sdk/azidentity/interactive_browser_credential.go b/sdk/azidentity/interactive_browser_credential.go index 17cca645c7e6..4868d22c3e1f 100644 --- a/sdk/azidentity/interactive_browser_credential.go +++ b/sdk/azidentity/interactive_browser_credential.go @@ -27,12 +27,11 @@ type InteractiveBrowserCredentialOptions struct { // Defaults to the ID of an Azure development application. ClientID string - // DisableAuthorityValidationAndInstanceDiscovery should be set true only by applications authenticating - // in disconnected clouds, or private clouds such as Azure Stack. It determines whether the credential - // requests Azure AD instance metadata from https://login.microsoft.com before authenticating. Setting - // this to true will skip this request, making the application responsible for ensuring the configured - // authority is valid and trustworthy. - DisableAuthorityValidationAndInstanceDiscovery bool + // DisableInstanceDiscovery should be set true only by applications authenticating in disconnected clouds, or + // private clouds such as Azure Stack. It determines whether the credential requests Azure AD instance metadata + // from https://login.microsoft.com before authenticating. Setting this to true will skip this request, making + // the application responsible for ensuring the configured authority is valid and trustworthy. + DisableInstanceDiscovery bool // LoginHint pre-populates the account prompt with a username. Users may choose to authenticate a different account. LoginHint string @@ -70,7 +69,7 @@ func NewInteractiveBrowserCredential(options *InteractiveBrowserCredentialOption cp = *options } cp.init() - c, err := getPublicClient(cp.ClientID, cp.TenantID, &cp.ClientOptions, public.WithInstanceDiscovery(!cp.DisableAuthorityValidationAndInstanceDiscovery)) + c, err := getPublicClient(cp.ClientID, cp.TenantID, &cp.ClientOptions, public.WithInstanceDiscovery(!cp.DisableInstanceDiscovery)) if err != nil { return nil, err } diff --git a/sdk/azidentity/interactive_browser_credential_test.go b/sdk/azidentity/interactive_browser_credential_test.go index e4c5d2b7970f..1f9c214b1c68 100644 --- a/sdk/azidentity/interactive_browser_credential_test.go +++ b/sdk/azidentity/interactive_browser_credential_test.go @@ -111,7 +111,7 @@ func TestInteractiveBrowserCredential_Live(t *testing.T) { PerCallPolicies: []policy.Policy{ &instanceDiscoveryPolicy{t}, }}, - DisableAuthorityValidationAndInstanceDiscovery: true, + DisableInstanceDiscovery: true, }) if err != nil { t.Fatal(err) @@ -135,11 +135,11 @@ func TestInteractiveBrowserCredentialADFS_Live(t *testing.T) { clientOptions := policy.ClientOptions{Cloud: cloudConfig} cred, err := NewInteractiveBrowserCredential(&InteractiveBrowserCredentialOptions{ - ClientOptions: clientOptions, - ClientID: adfsLiveUser.clientID, - DisableAuthorityValidationAndInstanceDiscovery: true, - RedirectURL: url, - TenantID: "adfs", + ClientOptions: clientOptions, + ClientID: adfsLiveUser.clientID, + DisableInstanceDiscovery: true, + RedirectURL: url, + TenantID: "adfs", }) if err != nil { t.Fatal(err) diff --git a/sdk/azidentity/on_behalf_of_credential.go b/sdk/azidentity/on_behalf_of_credential.go index a6e9f3ec6f2c..3e173f47d26d 100644 --- a/sdk/azidentity/on_behalf_of_credential.go +++ b/sdk/azidentity/on_behalf_of_credential.go @@ -38,12 +38,11 @@ type OnBehalfOfCredentialOptions struct { // Add the wildcard value "*" to allow the credential to acquire tokens for any tenant in which the // application is registered. AdditionallyAllowedTenants []string - // DisableAuthorityValidationAndInstanceDiscovery should be set true only by applications authenticating - // in disconnected clouds, or private clouds such as Azure Stack. It determines whether the credential - // requests Azure AD instance metadata from https://login.microsoft.com before authenticating. Setting - // this to true will skip this request, making the application responsible for ensuring the configured - // authority is valid and trustworthy. - DisableAuthorityValidationAndInstanceDiscovery bool + // DisableInstanceDiscovery should be set true only by applications authenticating in disconnected clouds, or + // private clouds such as Azure Stack. It determines whether the credential requests Azure AD instance metadata + // from https://login.microsoft.com before authenticating. Setting this to true will skip this request, making + // the application responsible for ensuring the configured authority is valid and trustworthy. + DisableInstanceDiscovery bool // SendCertificateChain applies only when the credential is configured to authenticate with a certificate. // This setting controls whether the credential sends the public certificate chain in the x5c header of each // token request's JWT. This is required for, and only used in, Subject Name/Issuer (SNI) authentication. @@ -77,7 +76,7 @@ func newOnBehalfOfCredential(tenantID, clientID, userAssertion string, cred conf if options.SendCertificateChain { opts = append(opts, confidential.WithX5C()) } - opts = append(opts, confidential.WithInstanceDiscovery(!options.DisableAuthorityValidationAndInstanceDiscovery)) + opts = append(opts, confidential.WithInstanceDiscovery(!options.DisableInstanceDiscovery)) c, err := getConfidentialClient(clientID, tenantID, cred, &options.ClientOptions, opts...) if err != nil { return nil, err diff --git a/sdk/azidentity/username_password_credential.go b/sdk/azidentity/username_password_credential.go index b6bbf7d92828..8e652e33ff6f 100644 --- a/sdk/azidentity/username_password_credential.go +++ b/sdk/azidentity/username_password_credential.go @@ -24,12 +24,11 @@ type UsernamePasswordCredentialOptions struct { // Add the wildcard value "*" to allow the credential to acquire tokens for any tenant in which the // application is registered. AdditionallyAllowedTenants []string - // DisableAuthorityValidationAndInstanceDiscovery should be set true only by applications authenticating - // in disconnected clouds, or private clouds such as Azure Stack. It determines whether the credential - // requests Azure AD instance metadata from https://login.microsoft.com before authenticating. Setting - // this to true will skip this request, making the application responsible for ensuring the configured - // authority is valid and trustworthy. - DisableAuthorityValidationAndInstanceDiscovery bool + // DisableInstanceDiscovery should be set true only by applications authenticating in disconnected clouds, or + // private clouds such as Azure Stack. It determines whether the credential requests Azure AD instance metadata + // from https://login.microsoft.com before authenticating. Setting this to true will skip this request, making + // the application responsible for ensuring the configured authority is valid and trustworthy. + DisableInstanceDiscovery bool } // UsernamePasswordCredential authenticates a user with a password. Microsoft doesn't recommend this kind of authentication, @@ -49,7 +48,7 @@ func NewUsernamePasswordCredential(tenantID string, clientID string, username st if options == nil { options = &UsernamePasswordCredentialOptions{} } - c, err := getPublicClient(clientID, tenantID, &options.ClientOptions, public.WithInstanceDiscovery(!options.DisableAuthorityValidationAndInstanceDiscovery)) + c, err := getPublicClient(clientID, tenantID, &options.ClientOptions, public.WithInstanceDiscovery(!options.DisableInstanceDiscovery)) if err != nil { return nil, err } diff --git a/sdk/azidentity/username_password_credential_test.go b/sdk/azidentity/username_password_credential_test.go index 82c68e50e058..304e24d03cc0 100644 --- a/sdk/azidentity/username_password_credential_test.go +++ b/sdk/azidentity/username_password_credential_test.go @@ -47,7 +47,7 @@ func TestUsernamePasswordCredential_Live(t *testing.T) { t.Run(name, func(t *testing.T) { o, stop := initRecording(t) defer stop() - opts := UsernamePasswordCredentialOptions{ClientOptions: o, DisableAuthorityValidationAndInstanceDiscovery: disabledID} + opts := UsernamePasswordCredentialOptions{ClientOptions: o, DisableInstanceDiscovery: disabledID} cred, err := NewUsernamePasswordCredential(liveUser.tenantID, developerSignOnClientID, liveUser.username, liveUser.password, &opts) if err != nil { t.Fatalf("Unable to create credential. Received: %v", err) @@ -66,7 +66,7 @@ func TestUsernamePasswordCredentialADFS_Live(t *testing.T) { o, stop := initRecording(t) o.Cloud.ActiveDirectoryAuthorityHost = adfsAuthority defer stop() - opts := UsernamePasswordCredentialOptions{ClientOptions: o, DisableAuthorityValidationAndInstanceDiscovery: true} + opts := UsernamePasswordCredentialOptions{ClientOptions: o, DisableInstanceDiscovery: true} cred, err := NewUsernamePasswordCredential("adfs", adfsLiveUser.clientID, adfsLiveUser.username, adfsLiveUser.password, &opts) if err != nil { t.Fatalf("Unable to create credential. Received: %v", err) diff --git a/sdk/azidentity/version.go b/sdk/azidentity/version.go index 91398c112d8a..1a526b2e874d 100644 --- a/sdk/azidentity/version.go +++ b/sdk/azidentity/version.go @@ -11,5 +11,5 @@ const ( component = "azidentity" // Version is the semantic version (see http://semver.org) of this module. - version = "v1.3.0-beta.6" + version = "v1.3.0" ) diff --git a/sdk/azidentity/workload_identity.go b/sdk/azidentity/workload_identity.go index f1b5f693821f..7bfb3436760d 100644 --- a/sdk/azidentity/workload_identity.go +++ b/sdk/azidentity/workload_identity.go @@ -40,12 +40,11 @@ type WorkloadIdentityCredentialOptions struct { AdditionallyAllowedTenants []string // ClientID of the service principal. Defaults to the value of the environment variable AZURE_CLIENT_ID. ClientID string - // DisableAuthorityValidationAndInstanceDiscovery should be set true only by applications authenticating - // in disconnected clouds, or private clouds such as Azure Stack. It determines whether the credential - // requests Azure AD instance metadata from https://login.microsoft.com before authenticating. Setting - // this to true will skip this request, making the application responsible for ensuring the configured - // authority is valid and trustworthy. - DisableAuthorityValidationAndInstanceDiscovery bool + // DisableInstanceDiscovery should be set true only by applications authenticating in disconnected clouds, or + // private clouds such as Azure Stack. It determines whether the credential requests Azure AD instance metadata + // from https://login.microsoft.com before authenticating. Setting this to true will skip this request, making + // the application responsible for ensuring the configured authority is valid and trustworthy. + DisableInstanceDiscovery bool // TenantID of the service principal. Defaults to the value of the environment variable AZURE_TENANT_ID. TenantID string // TokenFilePath is the path a file containing the workload identity token. Defaults to the value of the @@ -82,7 +81,7 @@ func NewWorkloadIdentityCredential(options *WorkloadIdentityCredentialOptions) ( caco := ClientAssertionCredentialOptions{ AdditionallyAllowedTenants: options.AdditionallyAllowedTenants, ClientOptions: options.ClientOptions, - DisableAuthorityValidationAndInstanceDiscovery: options.DisableAuthorityValidationAndInstanceDiscovery, + DisableInstanceDiscovery: options.DisableInstanceDiscovery, } cred, err := NewClientAssertionCredential(tenantID, clientID, w.getAssertion, &caco) if err != nil { diff --git a/sdk/azidentity/workload_identity_test.go b/sdk/azidentity/workload_identity_test.go index 83338315467b..121e60a0e389 100644 --- a/sdk/azidentity/workload_identity_test.go +++ b/sdk/azidentity/workload_identity_test.go @@ -71,11 +71,11 @@ func TestWorkloadIdentityCredential_Live(t *testing.T) { co, stop := initRecording(t) defer stop() cred, err := NewWorkloadIdentityCredential(&WorkloadIdentityCredentialOptions{ - ClientID: liveSP.clientID, - ClientOptions: co, - DisableAuthorityValidationAndInstanceDiscovery: b, - TenantID: liveSP.tenantID, - TokenFilePath: f, + ClientID: liveSP.clientID, + ClientOptions: co, + DisableInstanceDiscovery: b, + TenantID: liveSP.tenantID, + TokenFilePath: f, }) if err != nil { t.Fatal(err) diff --git a/sdk/data/azcosmos/CHANGELOG.md b/sdk/data/azcosmos/CHANGELOG.md index 951442859e4d..180606f1b413 100644 --- a/sdk/data/azcosmos/CHANGELOG.md +++ b/sdk/data/azcosmos/CHANGELOG.md @@ -1,7 +1,20 @@ # Release History +## 0.3.6 (Unreleased) + +### Features Added + +### Breaking Changes + +### Bugs Fixed + +### Other Changes + ## 0.3.5 (2023-05-09) +### Features Added +* Added support for accounts with [merge support](https://aka.ms/cosmosdbsdksupportformerge) enabled + ### Bugs Fixed * Fixed unmarshalling error when using projections in value queries diff --git a/sdk/data/azcosmos/cosmos_client.go b/sdk/data/azcosmos/cosmos_client.go index 94c455aed1e4..41807ab416e0 100644 --- a/sdk/data/azcosmos/cosmos_client.go +++ b/sdk/data/azcosmos/cosmos_client.go @@ -395,6 +395,7 @@ func (c *Client) createRequest( req.Raw().Header.Set(headerXmsDate, time.Now().UTC().Format(http.TimeFormat)) req.Raw().Header.Set(headerXmsVersion, "2020-11-05") + req.Raw().Header.Set(cosmosHeaderSDKSupportedCapabilities, supportedCapabilitiesHeaderValue) req.SetOperationValue(operationContext) diff --git a/sdk/data/azcosmos/cosmos_client_test.go b/sdk/data/azcosmos/cosmos_client_test.go index f33e730722a2..d93f4ca93d7c 100644 --- a/sdk/data/azcosmos/cosmos_client_test.go +++ b/sdk/data/azcosmos/cosmos_client_test.go @@ -258,6 +258,10 @@ func TestCreateRequest(t *testing.T) { t.Errorf("Expected %v, but got %v", "2020-11-05", req.Raw().Header.Get(headerXmsVersion)) } + if req.Raw().Header.Get(cosmosHeaderSDKSupportedCapabilities) != supportedCapabilitiesHeaderValue { + t.Errorf("Expected %v, but got %v", supportedCapabilitiesHeaderValue, req.Raw().Header.Get(cosmosHeaderSDKSupportedCapabilities)) + } + opValue := pipelineRequestOptions{} if !req.OperationValue(&opValue) { t.Error("Expected to find operation value") diff --git a/sdk/data/azcosmos/cosmos_headers.go b/sdk/data/azcosmos/cosmos_headers.go index d054bd652b93..5c8ea72c48bb 100644 --- a/sdk/data/azcosmos/cosmos_headers.go +++ b/sdk/data/azcosmos/cosmos_headers.go @@ -33,6 +33,7 @@ const ( cosmosHeaderIsBatchRequest string = "x-ms-cosmos-is-batch-request" cosmosHeaderIsBatchAtomic string = "x-ms-cosmos-batch-atomic" cosmosHeaderIsBatchOrdered string = "x-ms-cosmos-batch-ordered" + cosmosHeaderSDKSupportedCapabilities string = "x-ms-cosmos-sdk-supportedcapabilities" headerXmsDate string = "x-ms-date" headerAuthorization string = "Authorization" headerContentType string = "Content-Type" diff --git a/sdk/data/azcosmos/sdk_capabilities.go b/sdk/data/azcosmos/sdk_capabilities.go new file mode 100644 index 000000000000..71157b5fed27 --- /dev/null +++ b/sdk/data/azcosmos/sdk_capabilities.go @@ -0,0 +1,21 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package azcosmos + +import "strconv" + +type supportedCapabilities uint64 + +const ( + supportedCapabilitiesNone supportedCapabilities = 0 + supportedCapabilitiesPartitionMerge supportedCapabilities = 1 << 0 +) + +var supportedCapabilitiesHeaderValue = supportedCapabilitiesAsString() + +func supportedCapabilitiesAsString() string { + supported := supportedCapabilitiesNone + supported |= supportedCapabilitiesPartitionMerge + return strconv.FormatUint(uint64(supported), 10) +} diff --git a/sdk/data/azcosmos/version.go b/sdk/data/azcosmos/version.go index 6773a23e3474..5ef57c68794a 100644 --- a/sdk/data/azcosmos/version.go +++ b/sdk/data/azcosmos/version.go @@ -4,4 +4,4 @@ package azcosmos // serviceLibVersion is the semantic version (see http://semver.org) of this module. -const serviceLibVersion = "v0.3.5" +const serviceLibVersion = "v0.3.6" diff --git a/sdk/messaging/azeventhubs/CHANGELOG.md b/sdk/messaging/azeventhubs/CHANGELOG.md index 7d3c71c3266e..7cfbfb33ee54 100644 --- a/sdk/messaging/azeventhubs/CHANGELOG.md +++ b/sdk/messaging/azeventhubs/CHANGELOG.md @@ -1,6 +1,6 @@ # Release History -## 1.0.0 (2023-04-11) +## 1.0.0 (2023-05-09) ### Features Added @@ -13,13 +13,15 @@ - Recovery now includes internal timeouts and also handles restarting a connection if AMQP primitives aren't closed cleanly. - Potential leaks for $cbs and $management when there was a partial failure. (PR#20564) - Latest go-amqp changes have been merged in with fixes for robustness. +- Sending a message to an entity that is full will no longer retry. (PR#20722) +- Checkpoint store handles multiple initial owners properly, allowing only one through. (PR#20727) ## 0.6.0 (2023-03-07) ### Features Added -- Added the `ConsumerClientOptions.InstanceID` field. This optional field can enhance error messages from - Event Hubs. For example, error messages related to ownership changes for a partition will contain the +- Added the `ConsumerClientOptions.InstanceID` field. This optional field can enhance error messages from + Event Hubs. For example, error messages related to ownership changes for a partition will contain the name of the link that has taken ownership, which can help with traceability. ### Breaking Changes @@ -41,7 +43,7 @@ ### Breaking Changes - ProcessorOptions.OwnerLevel has been removed. The Processor uses 0 as the owner level. -- Uses the public release of `github.com/Azure/azure-sdk-for-go/sdk/storage/azblob` package rather than using an internal copy. +- Uses the public release of `github.com/Azure/azure-sdk-for-go/sdk/storage/azblob` package rather than using an internal copy. For an example, see [example_consuming_with_checkpoints_test.go](https://github.com/Azure/azure-sdk-for-go/blob/main/sdk/messaging/azeventhubs/example_consuming_with_checkpoints_test.go). ## 0.4.0 (2023-01-10) @@ -49,7 +51,7 @@ ### Bugs Fixed - User-Agent was incorrectly formatted in our AMQP-based clients. (PR#19712) -- Connection recovery has been improved, removing some unnecessasry retries as well as adding a bound around +- Connection recovery has been improved, removing some unnecessasry retries as well as adding a bound around some operations (Close) that could potentially block recovery for a long time. (PR#19683) ## 0.3.0 (2022-11-10) @@ -78,7 +80,7 @@ - NewWebSocketConnArgs renamed to WebSocketConnParams - Code renamed to ErrorCode, including associated constants like `ErrorCodeOwnershipLost`. - OwnershipData, CheckpointData, and CheckpointStoreAddress have been folded into their individual structs: Ownership and Checkpoint. -- StartPosition and OwnerLevel were erroneously included in the ConsumerClientOptions struct - they've been removed. These can be +- StartPosition and OwnerLevel were erroneously included in the ConsumerClientOptions struct - they've been removed. These can be configured in the PartitionClientOptions. ### Bugs Fixed @@ -90,8 +92,8 @@ ### Features Added -- Adding in the new Processor type, which can be used to do distributed (and load balanced) consumption of events, using a - CheckpointStore. The built-in checkpoints.BlobStore uses Azure Blob Storage for persistence. A full example is +- Adding in the new Processor type, which can be used to do distributed (and load balanced) consumption of events, using a + CheckpointStore. The built-in checkpoints.BlobStore uses Azure Blob Storage for persistence. A full example is in [example_consuming_with_checkpoints_test.go](https://github.com/Azure/azure-sdk-for-go/blob/main/sdk/messaging/azeventhubs/example_consuming_with_checkpoints_test.go). ### Breaking Changes @@ -101,6 +103,7 @@ instances (using ConsumerClient.NewPartitionClient), which allows you to share the same AMQP connection and receive from multiple partitions simultaneously. - Changes to EventData/ReceivedEventData: + - ReceivedEventData now embeds EventData for fields common between the two, making it easier to change and resend. - `ApplicationProperties` renamed to `Properties`. - `PartitionKey` removed from `EventData`. To send events using a PartitionKey you must set it in the options @@ -108,8 +111,8 @@ ```go batch, err := producerClient.NewEventDataBatch(context.TODO(), &azeventhubs.NewEventDataBatchOptions{ - PartitionKey: to.Ptr("partition key"), - }) + PartitionKey: to.Ptr("partition key"), + }) ``` ### Bugs Fixed @@ -120,4 +123,4 @@ ## 0.1.0 (2022-08-11) -- Initial preview for the new version of the Azure Event Hubs Go SDK. +- Initial preview for the new version of the Azure Event Hubs Go SDK. diff --git a/sdk/messaging/azeventhubs/amqp_message.go b/sdk/messaging/azeventhubs/amqp_message.go index 2b6ca2db8915..2e0bc54045f5 100644 --- a/sdk/messaging/azeventhubs/amqp_message.go +++ b/sdk/messaging/azeventhubs/amqp_message.go @@ -6,7 +6,7 @@ package azeventhubs import ( "time" - "github.com/Azure/azure-sdk-for-go/sdk/messaging/azeventhubs/internal/go-amqp" + "github.com/Azure/go-amqp" ) // AMQPAnnotatedMessage represents the AMQP message, as received from Event Hubs. diff --git a/sdk/messaging/azeventhubs/checkpoint_store.go b/sdk/messaging/azeventhubs/checkpoint_store.go index 3d321839251b..83c1c3e54fa7 100644 --- a/sdk/messaging/azeventhubs/checkpoint_store.go +++ b/sdk/messaging/azeventhubs/checkpoint_store.go @@ -22,8 +22,8 @@ type CheckpointStore interface { // ListOwnership lists all ownerships. ListOwnership(ctx context.Context, fullyQualifiedNamespace string, eventHubName string, consumerGroup string, options *ListOwnershipOptions) ([]Ownership, error) - // UpdateCheckpoint updates a specific checkpoint with a sequence and offset. - UpdateCheckpoint(ctx context.Context, checkpoint Checkpoint, options *UpdateCheckpointOptions) error + // SetCheckpoint updates a specific checkpoint with a sequence and offset. + SetCheckpoint(ctx context.Context, checkpoint Checkpoint, options *SetCheckpointOptions) error } // Ownership tracks which consumer owns a particular partition. @@ -59,8 +59,8 @@ type ListOwnershipOptions struct { // For future expansion } -// UpdateCheckpointOptions contains optional parameters for the UpdateCheckpoint function -type UpdateCheckpointOptions struct { +// SetCheckpointOptions contains optional parameters for the UpdateCheckpoint function +type SetCheckpointOptions struct { // For future expansion } diff --git a/sdk/messaging/azeventhubs/checkpoints/blob_store.go b/sdk/messaging/azeventhubs/checkpoints/blob_store.go index 453265e77c60..5bb0fe17068b 100644 --- a/sdk/messaging/azeventhubs/checkpoints/blob_store.go +++ b/sdk/messaging/azeventhubs/checkpoints/blob_store.go @@ -15,6 +15,7 @@ import ( "github.com/Azure/azure-sdk-for-go/sdk/azcore" "github.com/Azure/azure-sdk-for-go/sdk/azcore/streaming" "github.com/Azure/azure-sdk-for-go/sdk/azcore/to" + "github.com/Azure/azure-sdk-for-go/sdk/internal/log" "github.com/Azure/azure-sdk-for-go/sdk/messaging/azeventhubs" "github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/blob" "github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/bloberror" @@ -44,6 +45,9 @@ func NewBlobStore(containerClient *container.Client, options *BlobStoreOptions) // ClaimOwnership attempts to claim ownership of the partitions in partitionOwnership and returns // the actual partitions that were claimed. +// +// If we fail to claim ownership because of another update then it will be omitted from the +// returned slice of [Ownership]'s. It is not considered an error. func (b *BlobStore) ClaimOwnership(ctx context.Context, partitionOwnership []azeventhubs.Ownership, options *azeventhubs.ClaimOwnershipOptions) ([]azeventhubs.Ownership, error) { var ownerships []azeventhubs.Ownership @@ -54,13 +58,14 @@ func (b *BlobStore) ClaimOwnership(ctx context.Context, partitionOwnership []aze if err != nil { return nil, err } - lastModified, etag, err := b.setMetadata(ctx, blobName, newOwnershipBlobMetadata(po), po.ETag) + lastModified, etag, err := b.setOwnershipMetadata(ctx, blobName, po) if err != nil { - if bloberror.HasCode(err, bloberror.ConditionNotMet) { - // we can fail to claim ownership and that's okay - it's expected that clients will - // attempt to claim with whatever state they hold locally. If they fail it just means - // someone else claimed ownership before them. + if bloberror.HasCode(err, + bloberror.ConditionNotMet, // updated before we could update it + bloberror.BlobAlreadyExists) { // created before we could create it + + log.Writef(azeventhubs.EventConsumer, "[%s] skipping %s because: %s", po.OwnerID, po.PartitionID, err) continue } @@ -178,26 +183,30 @@ func (b *BlobStore) ListOwnership(ctx context.Context, fullyQualifiedNamespace s return ownerships, nil } -// UpdateCheckpoint updates a specific checkpoint with a sequence and offset. -func (b *BlobStore) UpdateCheckpoint(ctx context.Context, checkpoint azeventhubs.Checkpoint, options *azeventhubs.UpdateCheckpointOptions) error { +// SetCheckpoint updates a specific checkpoint with a sequence and offset. +// +// NOTE: This function doesn't attempt to prevent simultaneous checkpoint updates - ownership is assumed. +func (b *BlobStore) SetCheckpoint(ctx context.Context, checkpoint azeventhubs.Checkpoint, options *azeventhubs.SetCheckpointOptions) error { blobName, err := nameForCheckpointBlob(checkpoint) if err != nil { return err } - _, _, err = b.setMetadata(ctx, blobName, newCheckpointBlobMetadata(checkpoint), nil) + _, _, err = b.setCheckpointMetadata(ctx, blobName, checkpoint) return err } -func (b *BlobStore) setMetadata(ctx context.Context, blobName string, blobMetadata map[string]*string, etag *azcore.ETag) (*time.Time, azcore.ETag, error) { +func (b *BlobStore) setOwnershipMetadata(ctx context.Context, blobName string, ownership azeventhubs.Ownership) (*time.Time, azcore.ETag, error) { + blobMetadata := newOwnershipBlobMetadata(ownership) blobClient := b.cc.NewBlockBlobClient(blobName) - if etag != nil { + if ownership.ETag != nil { + log.Writef(azeventhubs.EventConsumer, "[%s] claiming ownership for %s with etag %s", ownership.OwnerID, ownership.PartitionID, string(*ownership.ETag)) setMetadataResp, err := blobClient.SetMetadata(ctx, blobMetadata, &blob.SetMetadataOptions{ AccessConditions: &blob.AccessConditions{ ModifiedAccessConditions: &blob.ModifiedAccessConditions{ - IfMatch: etag, + IfMatch: ownership.ETag, }, }, }) @@ -207,29 +216,53 @@ func (b *BlobStore) setMetadata(ctx context.Context, blobName string, blobMetada } return setMetadataResp.LastModified, *setMetadataResp.ETag, nil - } else { - setMetadataResp, err := blobClient.SetMetadata(ctx, blobMetadata, nil) + } - if err == nil { - return setMetadataResp.LastModified, *setMetadataResp.ETag, nil - } + log.Writef(azeventhubs.EventConsumer, "[%s] claiming ownership for %s with NO etags", ownership.PartitionID, ownership.OwnerID) + uploadResp, err := blobClient.Upload(ctx, streaming.NopCloser(bytes.NewReader([]byte{})), &blockblob.UploadOptions{ + Metadata: blobMetadata, + AccessConditions: &blob.AccessConditions{ + ModifiedAccessConditions: &blob.ModifiedAccessConditions{ + IfNoneMatch: to.Ptr(azcore.ETag("*")), + }, + }, + }) - if !bloberror.HasCode(err, bloberror.BlobNotFound) { - return nil, "", err - } + if err != nil { + return nil, "", err + } - // in JS they check to see if the error is BlobNotFound. If it is, then they - // do a full upload of a blob instead. - uploadResp, err := blobClient.Upload(ctx, streaming.NopCloser(bytes.NewReader([]byte{})), &blockblob.UploadOptions{ - Metadata: blobMetadata, - }) + return uploadResp.LastModified, *uploadResp.ETag, nil +} - if err != nil { - return nil, "", err - } +// setCheckpointMetadata sets the metadata for a checkpoint, falling back to creating +// the blob if it doesn't already exist. +// +// NOTE: unlike [setOwnershipMetadata] this function doesn't attempt to prevent simultaneous +// checkpoint updates - ownership is assumed. +func (b *BlobStore) setCheckpointMetadata(ctx context.Context, blobName string, checkpoint azeventhubs.Checkpoint) (*time.Time, azcore.ETag, error) { + blobMetadata := newCheckpointBlobMetadata(checkpoint) + blobClient := b.cc.NewBlockBlobClient(blobName) + + setMetadataResp, err := blobClient.SetMetadata(ctx, blobMetadata, nil) + + if err == nil { + return setMetadataResp.LastModified, *setMetadataResp.ETag, nil + } - return uploadResp.LastModified, *uploadResp.ETag, nil + if !bloberror.HasCode(err, bloberror.BlobNotFound) { + return nil, "", err } + + uploadResp, err := blobClient.Upload(ctx, streaming.NopCloser(bytes.NewReader([]byte{})), &blockblob.UploadOptions{ + Metadata: blobMetadata, + }) + + if err != nil { + return nil, "", err + } + + return uploadResp.LastModified, *uploadResp.ETag, nil } func nameForCheckpointBlob(a azeventhubs.Checkpoint) (string, error) { diff --git a/sdk/messaging/azeventhubs/checkpoints/blob_store_test.go b/sdk/messaging/azeventhubs/checkpoints/blob_store_test.go index 0537e60ac5e6..49923e1f46a5 100644 --- a/sdk/messaging/azeventhubs/checkpoints/blob_store_test.go +++ b/sdk/messaging/azeventhubs/checkpoints/blob_store_test.go @@ -4,6 +4,7 @@ package checkpoints_test import ( "context" + "fmt" "os" "strconv" "testing" @@ -32,7 +33,7 @@ func TestBlobStore_Checkpoints(t *testing.T) { require.NoError(t, err) require.Empty(t, checkpoints) - err = store.UpdateCheckpoint(context.Background(), azeventhubs.Checkpoint{ + err = store.SetCheckpoint(context.Background(), azeventhubs.Checkpoint{ ConsumerGroup: "$Default", EventHubName: "event-hub-name", FullyQualifiedNamespace: "ns.servicebus.windows.net", @@ -56,7 +57,7 @@ func TestBlobStore_Checkpoints(t *testing.T) { // There's a code path to allow updating the blob after it's been created but without an etag // in which case it just updates it. - err = store.UpdateCheckpoint(context.Background(), azeventhubs.Checkpoint{ + err = store.SetCheckpoint(context.Background(), azeventhubs.Checkpoint{ ConsumerGroup: "$Default", EventHubName: "event-hub-name", FullyQualifiedNamespace: "ns.servicebus.windows.net", @@ -216,6 +217,126 @@ func TestBlobStore_ListAndClaim(t *testing.T) { require.Empty(t, claimedOwnerships) } +func TestBlobStore_OnlyOneOwnershipClaimSucceeds(t *testing.T) { + testData := getContainerClient(t) + defer testData.Cleanup() + + cc, err := container.NewClientFromConnectionString(testData.ConnectionString, testData.ContainerName, nil) + require.NoError(t, err) + + store, err := checkpoints.NewBlobStore(cc, nil) + require.NoError(t, err) + + // we're going to make multiple calls to the blob store but only _one_ should succeed + // since it's "first one in wins" + claimsCh := make(chan []azeventhubs.Ownership, 20) + + t.Logf("Starting %d goroutines to claim ownership without an etag", cap(claimsCh)) + + // attempt to claim the same partition from multiple goroutines. Only _one_ of the + // goroutines should walk away thinking it claimed the partition. + for i := 0; i < cap(claimsCh); i++ { + go func() { + ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) + defer cancel() + + ownerships, err := store.ClaimOwnership(ctx, []azeventhubs.Ownership{ + {ConsumerGroup: azeventhubs.DefaultConsumerGroup, EventHubName: "name", FullyQualifiedNamespace: "ns", PartitionID: "0", OwnerID: "ownerID"}, + }, nil) + + if err != nil { + claimsCh <- nil + require.NoError(t, err) + } else { + claimsCh <- ownerships + } + }() + } + + claimed := map[string]bool{} + numFailedClaims := 0 + + for i := 0; i < cap(claimsCh); i++ { + claims := <-claimsCh + + if claims == nil { + numFailedClaims++ + continue + } + + for _, claim := range claims { + require.False(t, claimed[claim.PartitionID], fmt.Sprintf("Partition ID %s was claimed more than once", claim.PartitionID)) + require.NotNil(t, claim.ETag) + claimed[claim.PartitionID] = true + } + } + + require.Equal(t, cap(claimsCh)-1, numFailedClaims, fmt.Sprintf("One of the 1/%d wins and the rest all fail to claim", cap(claimsCh))) +} + +func TestBlobStore_OnlyOneOwnershipUpdateSucceeds(t *testing.T) { + testData := getContainerClient(t) + defer testData.Cleanup() + + cc, err := container.NewClientFromConnectionString(testData.ConnectionString, testData.ContainerName, nil) + require.NoError(t, err) + + store, err := checkpoints.NewBlobStore(cc, nil) + require.NoError(t, err) + + // we're going to make multiple calls to the blob store but only _one_ should succeed + // since it's "first one in wins" + claimsCh := make(chan []azeventhubs.Ownership, 20) + + ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) + defer cancel() + + ownerships, err := store.ClaimOwnership(ctx, []azeventhubs.Ownership{ + {ConsumerGroup: azeventhubs.DefaultConsumerGroup, EventHubName: "name", FullyQualifiedNamespace: "ns", PartitionID: "0", OwnerID: "ownerID"}, + }, nil) + require.NoError(t, err) + require.Equal(t, "0", ownerships[0].PartitionID) + require.NotNil(t, ownerships[0].ETag) + + t.Logf("Starting %d goroutines to claim ownership without an etag", cap(claimsCh)) + + // attempt to claim the same partition from multiple goroutines. Only _one_ of the + // goroutines should walk away thinking it claimed the partition. + for i := 0; i < cap(claimsCh); i++ { + go func() { + + ownerships, err := store.ClaimOwnership(ctx, ownerships, nil) + + if err != nil { + claimsCh <- nil + require.NoError(t, err) + } else { + claimsCh <- ownerships + } + }() + } + + claimed := map[string]bool{} + numFailedClaims := 0 + + for i := 0; i < cap(claimsCh); i++ { + claims := <-claimsCh + + if claims == nil { + numFailedClaims++ + continue + } + + for _, claim := range claims { + require.False(t, claimed[claim.PartitionID], fmt.Sprintf("Partition ID %s was claimed more than once", claim.PartitionID)) + require.NotNil(t, claim.ETag) + claimed[claim.PartitionID] = true + } + } + + require.Equal(t, cap(claimsCh)-1, numFailedClaims, fmt.Sprintf("One of the 1/%d wins and the rest all fail to claim", cap(claimsCh))) +} + func getContainerClient(t *testing.T) struct { ConnectionString string ContainerName string diff --git a/sdk/messaging/azeventhubs/consumer_client_internal_test.go b/sdk/messaging/azeventhubs/consumer_client_internal_test.go index dedd628be219..50a2d06ae62b 100644 --- a/sdk/messaging/azeventhubs/consumer_client_internal_test.go +++ b/sdk/messaging/azeventhubs/consumer_client_internal_test.go @@ -126,7 +126,7 @@ func TestConsumerClient_Recovery(t *testing.T) { require.NoError(t, err) require.EqualValues(t, 1, len(events)) - t.Logf("[%s] Received seq:%d, offset:%d", sr.PartitionID, events[0].SequenceNumber, *events[0].Offset) + t.Logf("[%s] Received seq:%d, offset:%d", sr.PartitionID, events[0].SequenceNumber, events[0].Offset) require.Equal(t, fmt.Sprintf("event 1 for partition %s", sr.PartitionID), string(events[0].Body)) }(i, sr) diff --git a/sdk/messaging/azeventhubs/consumer_client_unit_test.go b/sdk/messaging/azeventhubs/consumer_client_unit_test.go index 900e46d4d37f..1d91ff164280 100644 --- a/sdk/messaging/azeventhubs/consumer_client_unit_test.go +++ b/sdk/messaging/azeventhubs/consumer_client_unit_test.go @@ -49,42 +49,46 @@ func TestUnitNewConsumerClient(t *testing.T) { func TestUnit_getOffsetExpression(t *testing.T) { t.Run("Valid", func(t *testing.T) { - expr, err := getOffsetExpression(StartPosition{}) + expr, err := getStartExpression(StartPosition{}) require.NoError(t, err) require.Equal(t, "amqp.annotation.x-opt-offset > '@latest'", expr) - expr, err = getOffsetExpression(StartPosition{Earliest: to.Ptr(true)}) + expr, err = getStartExpression(StartPosition{Earliest: to.Ptr(true)}) require.NoError(t, err) require.Equal(t, "amqp.annotation.x-opt-offset > '-1'", expr) - expr, err = getOffsetExpression(StartPosition{Latest: to.Ptr(true)}) + expr, err = getStartExpression(StartPosition{Latest: to.Ptr(true)}) require.NoError(t, err) require.Equal(t, "amqp.annotation.x-opt-offset > '@latest'", expr) - expr, err = getOffsetExpression(StartPosition{Offset: to.Ptr(int64(101))}) + expr, err = getStartExpression(StartPosition{Latest: to.Ptr(true), Inclusive: true}) + require.NoError(t, err) + require.Equal(t, "amqp.annotation.x-opt-offset >= '@latest'", expr) + + expr, err = getStartExpression(StartPosition{Offset: to.Ptr(int64(101))}) require.NoError(t, err) require.Equal(t, "amqp.annotation.x-opt-offset > '101'", expr) - expr, err = getOffsetExpression(StartPosition{Offset: to.Ptr(int64(101)), Inclusive: true}) + expr, err = getStartExpression(StartPosition{Offset: to.Ptr(int64(101)), Inclusive: true}) require.NoError(t, err) require.Equal(t, "amqp.annotation.x-opt-offset >= '101'", expr) - expr, err = getOffsetExpression(StartPosition{SequenceNumber: to.Ptr(int64(202))}) + expr, err = getStartExpression(StartPosition{SequenceNumber: to.Ptr(int64(202))}) require.NoError(t, err) require.Equal(t, "amqp.annotation.x-opt-sequence-number > '202'", expr) - expr, err = getOffsetExpression(StartPosition{SequenceNumber: to.Ptr(int64(202)), Inclusive: true}) + expr, err = getStartExpression(StartPosition{SequenceNumber: to.Ptr(int64(202)), Inclusive: true}) require.NoError(t, err) require.Equal(t, "amqp.annotation.x-opt-sequence-number >= '202'", expr) enqueueTime, err := time.Parse(time.RFC3339, "2020-01-01T01:02:03Z") require.NoError(t, err) - expr, err = getOffsetExpression(StartPosition{EnqueuedTime: &enqueueTime}) + expr, err = getStartExpression(StartPosition{EnqueuedTime: &enqueueTime}) require.NoError(t, err) require.Equal(t, "amqp.annotation.x-opt-enqueued-time > '1577840523000'", expr) - expr, err = getOffsetExpression(StartPosition{EnqueuedTime: &enqueueTime, Inclusive: true}) + expr, err = getStartExpression(StartPosition{EnqueuedTime: &enqueueTime, Inclusive: true}) require.NoError(t, err) require.Equal(t, "amqp.annotation.x-opt-enqueued-time >= '1577840523000'", expr) }) @@ -93,28 +97,28 @@ func TestUnit_getOffsetExpression(t *testing.T) { enqueueTime, err := time.Parse(time.RFC3339, "2020-01-01T01:02:03Z") require.NoError(t, err) - expr, err := getOffsetExpression(StartPosition{ + expr, err := getStartExpression(StartPosition{ EnqueuedTime: &enqueueTime, Offset: to.Ptr[int64](101), }) require.EqualError(t, err, "only a single start point can be set: Earliest, EnqueuedTime, Latest, Offset, or SequenceNumber") require.Empty(t, expr) - expr, err = getOffsetExpression(StartPosition{ + expr, err = getStartExpression(StartPosition{ Offset: to.Ptr[int64](202), Latest: to.Ptr(true), }) require.EqualError(t, err, "only a single start point can be set: Earliest, EnqueuedTime, Latest, Offset, or SequenceNumber") require.Empty(t, expr) - expr, err = getOffsetExpression(StartPosition{ + expr, err = getStartExpression(StartPosition{ Latest: to.Ptr(true), SequenceNumber: to.Ptr[int64](202), }) require.EqualError(t, err, "only a single start point can be set: Earliest, EnqueuedTime, Latest, Offset, or SequenceNumber") require.Empty(t, expr) - expr, err = getOffsetExpression(StartPosition{ + expr, err = getStartExpression(StartPosition{ SequenceNumber: to.Ptr[int64](202), Earliest: to.Ptr(true), }) diff --git a/sdk/messaging/azeventhubs/event_data.go b/sdk/messaging/azeventhubs/event_data.go index 9300aa51f7c6..00b89a3ca0e1 100644 --- a/sdk/messaging/azeventhubs/event_data.go +++ b/sdk/messaging/azeventhubs/event_data.go @@ -10,7 +10,7 @@ import ( "github.com/Azure/azure-sdk-for-go/sdk/azcore/to" "github.com/Azure/azure-sdk-for-go/sdk/messaging/azeventhubs/internal/eh" - "github.com/Azure/azure-sdk-for-go/sdk/messaging/azeventhubs/internal/go-amqp" + "github.com/Azure/go-amqp" ) // EventData is an event that can be sent, using the ProducerClient, to an Event Hub. @@ -52,7 +52,7 @@ type ReceivedEventData struct { PartitionKey *string // Offset is the offset of the event. - Offset *int64 + Offset int64 // RawAMQPMessage is the AMQP message, as received by the client. This can be useful to get access // to properties that are not exposed by ReceivedEventData such as payloads encoded into the @@ -177,7 +177,7 @@ func updateFromAMQPAnnotations(src *amqp.Message, dest *ReceivedEventData) error case offsetNumberAnnotation: if offsetStr, ok := v.(string); ok { if offset, err := strconv.ParseInt(offsetStr, 10, 64); err == nil { - dest.Offset = &offset + dest.Offset = offset continue } } diff --git a/sdk/messaging/azeventhubs/event_data_batch.go b/sdk/messaging/azeventhubs/event_data_batch.go index a73e7145df92..edc6517b90b5 100644 --- a/sdk/messaging/azeventhubs/event_data_batch.go +++ b/sdk/messaging/azeventhubs/event_data_batch.go @@ -11,7 +11,7 @@ import ( "github.com/Azure/azure-sdk-for-go/sdk/internal/uuid" "github.com/Azure/azure-sdk-for-go/sdk/messaging/azeventhubs/internal" "github.com/Azure/azure-sdk-for-go/sdk/messaging/azeventhubs/internal/amqpwrap" - "github.com/Azure/azure-sdk-for-go/sdk/messaging/azeventhubs/internal/go-amqp" + "github.com/Azure/go-amqp" ) // ErrEventDataTooLarge is returned when a message cannot fit into a batch when using the [azeventhubs.EventDataBatch.AddEventData] function. diff --git a/sdk/messaging/azeventhubs/event_data_batch_unit_test.go b/sdk/messaging/azeventhubs/event_data_batch_unit_test.go index 23224e5e8104..4144f09a3635 100644 --- a/sdk/messaging/azeventhubs/event_data_batch_unit_test.go +++ b/sdk/messaging/azeventhubs/event_data_batch_unit_test.go @@ -10,8 +10,8 @@ import ( "github.com/Azure/azure-sdk-for-go/sdk/azcore/to" "github.com/Azure/azure-sdk-for-go/sdk/messaging/azeventhubs/internal/amqpwrap" - "github.com/Azure/azure-sdk-for-go/sdk/messaging/azeventhubs/internal/go-amqp" "github.com/Azure/azure-sdk-for-go/sdk/messaging/azeventhubs/internal/mock" + "github.com/Azure/go-amqp" "github.com/golang/mock/gomock" "github.com/stretchr/testify/require" ) diff --git a/sdk/messaging/azeventhubs/event_data_test.go b/sdk/messaging/azeventhubs/event_data_test.go index bbc25e4cdcdd..0c58c9bde4ea 100644 --- a/sdk/messaging/azeventhubs/event_data_test.go +++ b/sdk/messaging/azeventhubs/event_data_test.go @@ -8,7 +8,7 @@ import ( "time" "github.com/Azure/azure-sdk-for-go/sdk/azcore/to" - "github.com/Azure/azure-sdk-for-go/sdk/messaging/azeventhubs/internal/go-amqp" + "github.com/Azure/go-amqp" "github.com/stretchr/testify/require" ) @@ -20,7 +20,7 @@ func TestEventData_Annotations(t *testing.T) { require.Empty(t, re.Body) require.Nil(t, re.EnqueuedTime) require.Equal(t, int64(0), re.SequenceNumber) - require.Nil(t, re.Offset) + require.Zero(t, re.Offset) require.Nil(t, re.PartitionKey) }) @@ -99,7 +99,7 @@ func TestEventData_newReceivedEventData(t *testing.T) { SystemProperties: map[string]any{ "hello": "world", }, - Offset: to.Ptr[int64](102), + Offset: int64(102), PartitionKey: to.Ptr("partition key"), RawAMQPMessage: &AMQPAnnotatedMessage{ Properties: &AMQPAnnotatedMessageProperties{ diff --git a/sdk/messaging/azeventhubs/example_checkpoint_migration_test.go b/sdk/messaging/azeventhubs/example_checkpoint_migration_test.go index 2692d47c1fe4..937c364a8ae6 100644 --- a/sdk/messaging/azeventhubs/example_checkpoint_migration_test.go +++ b/sdk/messaging/azeventhubs/example_checkpoint_migration_test.go @@ -102,7 +102,7 @@ func Example_migrateCheckpoints() { newCheckpoint.Offset = &offset newCheckpoint.SequenceNumber = &oldCheckpoint.Checkpoint.SequenceNumber - if err := newCheckpointStore.UpdateCheckpoint(context.Background(), newCheckpoint, nil); err != nil { + if err := newCheckpointStore.SetCheckpoint(context.Background(), newCheckpoint, nil); err != nil { panic(err) } } diff --git a/sdk/messaging/azeventhubs/example_consuming_with_checkpoints_test.go b/sdk/messaging/azeventhubs/example_consuming_with_checkpoints_test.go index 1e4243cbafc1..c02ad5804ddd 100644 --- a/sdk/messaging/azeventhubs/example_consuming_with_checkpoints_test.go +++ b/sdk/messaging/azeventhubs/example_consuming_with_checkpoints_test.go @@ -136,7 +136,7 @@ func processEventsForPartition(partitionClient *azeventhubs.ProcessorPartitionCl // Updates the checkpoint with the latest event received. If processing needs to restart // it will restart from this point, automatically. - if err := partitionClient.UpdateCheckpoint(context.TODO(), events[len(events)-1]); err != nil { + if err := partitionClient.UpdateCheckpoint(context.TODO(), events[len(events)-1], nil); err != nil { return err } } @@ -154,7 +154,7 @@ func shutdownPartitionResources(partitionClient *azeventhubs.ProcessorPartitionC defer partitionClient.Close(context.TODO()) } -func createClientsForExample(eventHubConnectionString, eventHubName, storageConnectionString, storageContainerName string) (*azeventhubs.ConsumerClient, *checkpoints.BlobStore, error) { +func createClientsForExample(eventHubConnectionString, eventHubName, storageConnectionString, storageContainerName string) (*azeventhubs.ConsumerClient, azeventhubs.CheckpointStore, error) { // NOTE: the storageContainerName must exist before the checkpoint store can be used. azBlobContainerClient, err := container.NewClientFromConnectionString(storageConnectionString, storageContainerName, nil) diff --git a/sdk/messaging/azeventhubs/go.mod b/sdk/messaging/azeventhubs/go.mod index e158f2a2713d..db6ebc2cd1d6 100644 --- a/sdk/messaging/azeventhubs/go.mod +++ b/sdk/messaging/azeventhubs/go.mod @@ -8,10 +8,11 @@ require ( github.com/Azure/azure-sdk-for-go/sdk/internal v1.2.0 github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/eventhub/armeventhub v1.0.0 github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.0.0 + github.com/Azure/go-amqp v1.0.0 github.com/golang/mock v1.6.0 github.com/joho/godotenv v1.4.0 github.com/stretchr/testify v1.7.1 - nhooyr.io/websocket v1.8.7 + nhooyr.io/websocket v1.8.7 ) require ( diff --git a/sdk/messaging/azeventhubs/go.sum b/sdk/messaging/azeventhubs/go.sum index 20d483a3af2e..a09abd6c3dc0 100644 --- a/sdk/messaging/azeventhubs/go.sum +++ b/sdk/messaging/azeventhubs/go.sum @@ -10,6 +10,8 @@ github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/eventhub/armeventhub v1.0. github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/eventhub/armeventhub v1.0.0/go.mod h1:Y3gnVwfaz8h6L1YHar+NfWORtBoVUSB5h4GlGkdeF7Q= github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.0.0 h1:u/LLAOFgsMv7HmNL4Qufg58y+qElGOt5qv0z1mURkRY= github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.0.0/go.mod h1:2e8rMJtl2+2j+HXbTBwnyGpm5Nou7KhvSfxOq8JpTag= +github.com/Azure/go-amqp v1.0.0 h1:QfCugi1M+4F2JDTRgVnRw7PYXLXZ9hmqk3+9+oJh3OA= +github.com/Azure/go-amqp v1.0.0/go.mod h1:+bg0x3ce5+Q3ahCEXnCsGG3ETpDQe3MEVnOuT2ywPwc= github.com/AzureAD/microsoft-authentication-library-for-go v0.5.1 h1:BWe8a+f/t+7KY7zH2mqygeUD0t8hNFXe08p1Pb3/jKE= github.com/AzureAD/microsoft-authentication-library-for-go v0.5.1/go.mod h1:Vt9sXTKwMyGcOxSmLDMnGPgqsUg7m8pe215qMLrDXw4= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= diff --git a/sdk/messaging/azeventhubs/inmemory_checkpoint_store_test.go b/sdk/messaging/azeventhubs/inmemory_checkpoint_store_test.go index be8978f9c292..44aacfa626d0 100644 --- a/sdk/messaging/azeventhubs/inmemory_checkpoint_store_test.go +++ b/sdk/messaging/azeventhubs/inmemory_checkpoint_store_test.go @@ -23,7 +23,7 @@ func Test_InMemoryCheckpointStore_Checkpoints(t *testing.T) { require.Empty(t, checkpoints) for i := int64(0); i < 5; i++ { - err = store.UpdateCheckpoint(context.Background(), Checkpoint{ + err = store.SetCheckpoint(context.Background(), Checkpoint{ FullyQualifiedNamespace: "ns", EventHubName: "eh", ConsumerGroup: "cg", @@ -206,13 +206,18 @@ func (cps *testCheckpointStore) ClaimOwnership(ctx context.Context, partitionOwn current, exists := cps.ownerships[key] - if exists && po.ETag != nil && *current.ETag != *po.ETag { - // can't own it, didn't have the expected etag - return nil, nil + if exists { + if po.ETag == nil { + panic("Ownership blob exists, we should have claimed it using an etag") + } + + if *po.ETag != *current.ETag { + // can't own it, didn't have the expected etag + return nil, nil + } } newOwnership := po - uuid, err := uuid.New() if err != nil { @@ -264,7 +269,7 @@ func (cps *testCheckpointStore) ListOwnership(ctx context.Context, fullyQualifie return ownerships, nil } -func (cps *testCheckpointStore) UpdateCheckpoint(ctx context.Context, checkpoint Checkpoint, options *UpdateCheckpointOptions) error { +func (cps *testCheckpointStore) SetCheckpoint(ctx context.Context, checkpoint Checkpoint, options *SetCheckpointOptions) error { cps.checkpointsMu.Lock() defer cps.checkpointsMu.Unlock() diff --git a/sdk/messaging/azeventhubs/internal/amqp_fakes.go b/sdk/messaging/azeventhubs/internal/amqp_fakes.go index 9f354a0f19dd..a64783a7f207 100644 --- a/sdk/messaging/azeventhubs/internal/amqp_fakes.go +++ b/sdk/messaging/azeventhubs/internal/amqp_fakes.go @@ -7,7 +7,7 @@ import ( "context" "github.com/Azure/azure-sdk-for-go/sdk/messaging/azeventhubs/internal/amqpwrap" - "github.com/Azure/azure-sdk-for-go/sdk/messaging/azeventhubs/internal/go-amqp" + "github.com/Azure/go-amqp" ) type FakeNSForPartClient struct { diff --git a/sdk/messaging/azeventhubs/internal/amqpwrap/amqpwrap.go b/sdk/messaging/azeventhubs/internal/amqpwrap/amqpwrap.go index dda9958c591e..c1b3524b7ed7 100644 --- a/sdk/messaging/azeventhubs/internal/amqpwrap/amqpwrap.go +++ b/sdk/messaging/azeventhubs/internal/amqpwrap/amqpwrap.go @@ -10,7 +10,7 @@ import ( "errors" "time" - "github.com/Azure/azure-sdk-for-go/sdk/messaging/azeventhubs/internal/go-amqp" + "github.com/Azure/go-amqp" ) // AMQPReceiver is implemented by *amqp.Receiver diff --git a/sdk/messaging/azeventhubs/internal/amqpwrap/mock_amqp_test.go b/sdk/messaging/azeventhubs/internal/amqpwrap/mock_amqp_test.go index f32dd94aee1e..6f48c0d524e5 100644 --- a/sdk/messaging/azeventhubs/internal/amqpwrap/mock_amqp_test.go +++ b/sdk/messaging/azeventhubs/internal/amqpwrap/mock_amqp_test.go @@ -12,7 +12,7 @@ import ( context "context" reflect "reflect" - go_amqp "github.com/Azure/azure-sdk-for-go/sdk/messaging/azeventhubs/internal/go-amqp" + go_amqp "github.com/Azure/go-amqp" gomock "github.com/golang/mock/gomock" ) diff --git a/sdk/messaging/azeventhubs/internal/amqpwrap/rpc.go b/sdk/messaging/azeventhubs/internal/amqpwrap/rpc.go index 12bab2b2fa88..0a7b7a132ff9 100644 --- a/sdk/messaging/azeventhubs/internal/amqpwrap/rpc.go +++ b/sdk/messaging/azeventhubs/internal/amqpwrap/rpc.go @@ -6,7 +6,7 @@ package amqpwrap import ( "context" - "github.com/Azure/azure-sdk-for-go/sdk/messaging/azeventhubs/internal/go-amqp" + "github.com/Azure/go-amqp" ) // RPCResponse is the simplified response structure from an RPC like call diff --git a/sdk/messaging/azeventhubs/internal/cbs.go b/sdk/messaging/azeventhubs/internal/cbs.go index e428ef9056ba..4d41921d35fd 100644 --- a/sdk/messaging/azeventhubs/internal/cbs.go +++ b/sdk/messaging/azeventhubs/internal/cbs.go @@ -11,7 +11,7 @@ import ( "github.com/Azure/azure-sdk-for-go/sdk/messaging/azeventhubs/internal/amqpwrap" "github.com/Azure/azure-sdk-for-go/sdk/messaging/azeventhubs/internal/auth" "github.com/Azure/azure-sdk-for-go/sdk/messaging/azeventhubs/internal/exported" - "github.com/Azure/azure-sdk-for-go/sdk/messaging/azeventhubs/internal/go-amqp" + "github.com/Azure/go-amqp" ) const ( diff --git a/sdk/messaging/azeventhubs/internal/cbs_test.go b/sdk/messaging/azeventhubs/internal/cbs_test.go index 13a28559fcff..baa589a96a0e 100644 --- a/sdk/messaging/azeventhubs/internal/cbs_test.go +++ b/sdk/messaging/azeventhubs/internal/cbs_test.go @@ -9,8 +9,8 @@ import ( "testing" "github.com/Azure/azure-sdk-for-go/sdk/messaging/azeventhubs/internal/auth" - "github.com/Azure/azure-sdk-for-go/sdk/messaging/azeventhubs/internal/go-amqp" "github.com/Azure/azure-sdk-for-go/sdk/messaging/azeventhubs/internal/mock" + "github.com/Azure/go-amqp" "github.com/golang/mock/gomock" "github.com/stretchr/testify/require" ) diff --git a/sdk/messaging/azeventhubs/internal/eh/stress/deploy.ps1 b/sdk/messaging/azeventhubs/internal/eh/stress/deploy.ps1 index 2abdb8722ec9..30bb9a04a7be 100644 --- a/sdk/messaging/azeventhubs/internal/eh/stress/deploy.ps1 +++ b/sdk/messaging/azeventhubs/internal/eh/stress/deploy.ps1 @@ -4,12 +4,12 @@ Set-Location $PSScriptRoot function deployUsingLocalAddons() { $azureSDKToolsRoot="" $stressTestAddonsFolder = "$azureSDKToolsRoot/tools/stress-cluster/cluster/kubernetes/stress-test-addons" - $clusterResourceGroup = " set -ex; mkdir -p "$DEBUG_SHARE"; - /app/stress "{{.Stress.testTarget}}" "-rounds" "{{.Stress.rounds}}" "-prefetch" "{{.Stress.prefetch}}" "{{.Stress.verbose}}" "-sleepAfter" "{{.Stress.sleepAfter}}" | tee "${DEBUG_SHARE}/{{ .Stress.Scenario }}.log"; + /app/stress "{{.Stress.testTarget}}" "-rounds" "{{.Stress.rounds}}" "-prefetch" "{{.Stress.prefetch}}" "{{.Stress.verbose}}" "-sleepAfter" "{{.Stress.sleepAfter}}" 2>&1 | tee -a "${DEBUG_SHARE}/{{ .Stress.Scenario }}-`date +%s`.log"; # Pulls the image on pod start, always. We tend to push to the same image and tag over and over again # when iterating, so this is a must. imagePullPolicy: Always @@ -33,8 +33,8 @@ spec: # just uses 'limits' for both. resources: limits: - memory: "1.5Gi" - cpu: "1" + memory: "0.5Gi" + cpu: "0.5" {{- include "stress-test-addons.container-env" . | nindent 6 }} {{- end -}} diff --git a/sdk/messaging/azeventhubs/internal/eh/stress/tests/processor_stress_tester.go b/sdk/messaging/azeventhubs/internal/eh/stress/tests/processor_stress_tester.go index a6d2398cb66a..9e9a48032059 100644 --- a/sdk/messaging/azeventhubs/internal/eh/stress/tests/processor_stress_tester.go +++ b/sdk/messaging/azeventhubs/internal/eh/stress/tests/processor_stress_tester.go @@ -285,7 +285,7 @@ func (inf *processorStressTest) receiveForever(ctx context.Context, partClient * if len(events) > 0 { // we're okay, let's update our checkpoint - if err := partClient.UpdateCheckpoint(ctx, events[len(events)-1]); err != nil { + if err := partClient.UpdateCheckpoint(ctx, events[len(events)-1], nil); err != nil { logger("Fatal error updating checkpoint: %s", err) inf.TC.TrackException(err) panic(err) diff --git a/sdk/messaging/azeventhubs/internal/eh/stress/tests/shared.go b/sdk/messaging/azeventhubs/internal/eh/stress/tests/shared.go index 4f291a73c28c..5e5e210c9245 100644 --- a/sdk/messaging/azeventhubs/internal/eh/stress/tests/shared.go +++ b/sdk/messaging/azeventhubs/internal/eh/stress/tests/shared.go @@ -318,7 +318,7 @@ func initCheckpointStore(ctx context.Context, containerName string, testData *st newCheckpoint.SequenceNumber = &partProps.LastEnqueuedSequenceNumber } - if err = cps.UpdateCheckpoint(ctx, newCheckpoint, nil); err != nil { + if err = cps.SetCheckpoint(ctx, newCheckpoint, nil); err != nil { return nil, err } diff --git a/sdk/messaging/azeventhubs/internal/errors.go b/sdk/messaging/azeventhubs/internal/errors.go index b0b08b0c57fc..71d77e52c7eb 100644 --- a/sdk/messaging/azeventhubs/internal/errors.go +++ b/sdk/messaging/azeventhubs/internal/errors.go @@ -15,7 +15,7 @@ import ( "github.com/Azure/azure-sdk-for-go/sdk/messaging/azeventhubs/internal/amqpwrap" "github.com/Azure/azure-sdk-for-go/sdk/messaging/azeventhubs/internal/exported" - "github.com/Azure/azure-sdk-for-go/sdk/messaging/azeventhubs/internal/go-amqp" + "github.com/Azure/go-amqp" ) type errNonRetriable struct { @@ -139,12 +139,16 @@ var amqpConditionsToRecoveryKind = map[amqp.ErrCond]RecoveryKind{ amqp.ErrCondInternalError: RecoveryKindConn, // "amqp:internal-error" // No recovery possible - this operation is non retriable. + + // ErrCondResourceLimitExceeded comes back if the entity is actually full. + amqp.ErrCondResourceLimitExceeded: RecoveryKindFatal, // "amqp:resource-limit-exceeded" amqp.ErrCondMessageSizeExceeded: RecoveryKindFatal, // "amqp:link:message-size-exceeded" amqp.ErrCondUnauthorizedAccess: RecoveryKindFatal, // creds are bad amqp.ErrCondNotFound: RecoveryKindFatal, // "amqp:not-found" amqp.ErrCondNotAllowed: RecoveryKindFatal, // "amqp:not-allowed" amqp.ErrCond("com.microsoft:entity-disabled"): RecoveryKindFatal, // entity is disabled in the portal amqp.ErrCond("com.microsoft:session-cannot-be-locked"): RecoveryKindFatal, + amqp.ErrCond("com.microsoft:argument-out-of-range"): RecoveryKindFatal, // asked for a partition ID that doesn't exist errorConditionLockLost: RecoveryKindFatal, } diff --git a/sdk/messaging/azeventhubs/internal/errors_test.go b/sdk/messaging/azeventhubs/internal/errors_test.go index b7b35dbc95ed..b85fd1f768fb 100644 --- a/sdk/messaging/azeventhubs/internal/errors_test.go +++ b/sdk/messaging/azeventhubs/internal/errors_test.go @@ -12,7 +12,7 @@ import ( "github.com/Azure/azure-sdk-for-go/sdk/azidentity" "github.com/Azure/azure-sdk-for-go/sdk/messaging/azeventhubs/internal/amqpwrap" "github.com/Azure/azure-sdk-for-go/sdk/messaging/azeventhubs/internal/exported" - "github.com/Azure/azure-sdk-for-go/sdk/messaging/azeventhubs/internal/go-amqp" + "github.com/Azure/go-amqp" "github.com/stretchr/testify/require" ) @@ -44,6 +44,7 @@ func TestGetRecoveryKind(t *testing.T) { require.Equal(t, GetRecoveryKind(context.Canceled), RecoveryKindFatal) require.Equal(t, GetRecoveryKind(RPCError{Resp: &amqpwrap.RPCResponse{Code: http.StatusUnauthorized}}), RecoveryKindFatal) require.Equal(t, GetRecoveryKind(RPCError{Resp: &amqpwrap.RPCResponse{Code: http.StatusNotFound}}), RecoveryKindFatal) + require.Equal(t, GetRecoveryKind(&amqp.Error{Condition: amqp.ErrCondResourceLimitExceeded}), RecoveryKindFatal) } func Test_TransformError(t *testing.T) { diff --git a/sdk/messaging/azeventhubs/internal/go-amqp/conn.go b/sdk/messaging/azeventhubs/internal/go-amqp/conn.go deleted file mode 100644 index 519f9d4cc5de..000000000000 --- a/sdk/messaging/azeventhubs/internal/go-amqp/conn.go +++ /dev/null @@ -1,1135 +0,0 @@ -// Copyright (C) 2017 Kale Blankenship -// Portions Copyright (c) Microsoft Corporation - -package amqp - -import ( - "bytes" - "context" - "crypto/tls" - "errors" - "fmt" - "math" - "net" - "net/url" - "sync" - "time" - - "github.com/Azure/azure-sdk-for-go/sdk/messaging/azeventhubs/internal/go-amqp/internal/bitmap" - "github.com/Azure/azure-sdk-for-go/sdk/messaging/azeventhubs/internal/go-amqp/internal/buffer" - "github.com/Azure/azure-sdk-for-go/sdk/messaging/azeventhubs/internal/go-amqp/internal/debug" - "github.com/Azure/azure-sdk-for-go/sdk/messaging/azeventhubs/internal/go-amqp/internal/encoding" - "github.com/Azure/azure-sdk-for-go/sdk/messaging/azeventhubs/internal/go-amqp/internal/frames" - "github.com/Azure/azure-sdk-for-go/sdk/messaging/azeventhubs/internal/go-amqp/internal/shared" -) - -// Default connection options -const ( - defaultIdleTimeout = 1 * time.Minute - defaultMaxFrameSize = 65536 - defaultMaxSessions = 65536 - defaultWriteTimeout = 30 * time.Second -) - -// ConnOptions contains the optional settings for configuring an AMQP connection. -type ConnOptions struct { - // ContainerID sets the container-id to use when opening the connection. - // - // A container ID will be randomly generated if this option is not used. - ContainerID string - - // HostName sets the hostname sent in the AMQP - // Open frame and TLS ServerName (if not otherwise set). - HostName string - - // IdleTimeout specifies the maximum period between - // receiving frames from the peer. - // - // Specify a value less than zero to disable idle timeout. - // - // Default: 1 minute (60000000000). - IdleTimeout time.Duration - - // MaxFrameSize sets the maximum frame size that - // the connection will accept. - // - // Must be 512 or greater. - // - // Default: 512. - MaxFrameSize uint32 - - // MaxSessions sets the maximum number of channels. - // The value must be greater than zero. - // - // Default: 65535. - MaxSessions uint16 - - // Properties sets an entry in the connection properties map sent to the server. - Properties map[string]any - - // SASLType contains the specified SASL authentication mechanism. - SASLType SASLType - - // TLSConfig sets the tls.Config to be used during - // TLS negotiation. - // - // This option is for advanced usage, in most scenarios - // providing a URL scheme of "amqps://" is sufficient. - TLSConfig *tls.Config - - // WriteTimeout controls the write deadline when writing AMQP frames to the - // underlying net.Conn and no caller provided context.Context is available or - // the context contains no deadline (e.g. context.Background()). - // The timeout is set per write. - // - // Setting to a value less than zero means no timeout is set, so writes - // defer to the underlying behavior of net.Conn with no write deadline. - // - // Default: 30s - WriteTimeout time.Duration - - // test hook - dialer dialer -} - -// Dial connects to an AMQP server. -// -// If the addr includes a scheme, it must be "amqp", "amqps", or "amqp+ssl". -// If no port is provided, 5672 will be used for "amqp" and 5671 for "amqps" or "amqp+ssl". -// -// If username and password information is not empty it's used as SASL PLAIN -// credentials, equal to passing ConnSASLPlain option. -// -// opts: pass nil to accept the default values. -func Dial(ctx context.Context, addr string, opts *ConnOptions) (*Conn, error) { - c, err := dialConn(ctx, addr, opts) - if err != nil { - return nil, err - } - err = c.start(ctx) - if err != nil { - return nil, err - } - return c, nil -} - -// NewConn establishes a new AMQP client connection over conn. -// opts: pass nil to accept the default values. -func NewConn(ctx context.Context, conn net.Conn, opts *ConnOptions) (*Conn, error) { - c, err := newConn(conn, opts) - if err != nil { - return nil, err - } - err = c.start(ctx) - if err != nil { - return nil, err - } - return c, nil -} - -// Conn is an AMQP connection. -type Conn struct { - net net.Conn // underlying connection - dialer dialer // used for testing purposes, it allows faking dialing TCP/TLS endpoints - writeTimeout time.Duration // controls write deadline in absense of a context - - // TLS - tlsNegotiation bool // negotiate TLS - tlsComplete bool // TLS negotiation complete - tlsConfig *tls.Config // TLS config, default used if nil (ServerName set to Client.hostname) - - // SASL - saslHandlers map[encoding.Symbol]stateFunc // map of supported handlers keyed by SASL mechanism, SASL not negotiated if nil - saslComplete bool // SASL negotiation complete; internal *except* for SASL auth methods - - // local settings - maxFrameSize uint32 // max frame size to accept - channelMax uint16 // maximum number of channels to allow - hostname string // hostname of remote server (set explicitly or parsed from URL) - idleTimeout time.Duration // maximum period between receiving frames - properties map[encoding.Symbol]any // additional properties sent upon connection open - containerID string // set explicitly or randomly generated - - // peer settings - peerIdleTimeout time.Duration // maximum period between sending frames - peerMaxFrameSize uint32 // maximum frame size peer will accept - - // conn state - done chan struct{} // indicates the connection has terminated - doneErr error // contains the error state returned from Close(); DO NOT TOUCH outside of conn.go until done has been closed! - - // connReader and connWriter management - rxtxExit chan struct{} // signals connReader and connWriter to exit - closeOnce sync.Once // ensures that close() is only called once - - // session tracking - channels *bitmap.Bitmap - sessionsByChannel map[uint16]*Session - sessionsByChannelMu sync.RWMutex - - abandonedSessionsMu sync.Mutex - abandonedSessions []*Session - - // connReader - rxBuf buffer.Buffer // incoming bytes buffer - rxDone chan struct{} // closed when connReader exits - rxErr error // contains last error reading from c.net; DO NOT TOUCH outside of connReader until rxDone has been closed! - - // connWriter - txFrame chan frameEnvelope // AMQP frames to be sent by connWriter - txBuf buffer.Buffer // buffer for marshaling frames before transmitting - txDone chan struct{} // closed when connWriter exits - txErr error // contains last error writing to c.net; DO NOT TOUCH outside of connWriter until txDone has been closed! -} - -// used to abstract the underlying dialer for testing purposes -type dialer interface { - NetDialerDial(ctx context.Context, c *Conn, host, port string) error - TLSDialWithDialer(ctx context.Context, c *Conn, host, port string) error -} - -// implements the dialer interface -type defaultDialer struct{} - -func (defaultDialer) NetDialerDial(ctx context.Context, c *Conn, host, port string) (err error) { - dialer := &net.Dialer{} - c.net, err = dialer.DialContext(ctx, "tcp", net.JoinHostPort(host, port)) - return -} - -func (defaultDialer) TLSDialWithDialer(ctx context.Context, c *Conn, host, port string) (err error) { - dialer := &tls.Dialer{Config: c.tlsConfig} - c.net, err = dialer.DialContext(ctx, "tcp", net.JoinHostPort(host, port)) - return -} - -func dialConn(ctx context.Context, addr string, opts *ConnOptions) (*Conn, error) { - u, err := url.Parse(addr) - if err != nil { - return nil, err - } - host, port := u.Hostname(), u.Port() - if port == "" { - port = "5672" - if u.Scheme == "amqps" || u.Scheme == "amqp+ssl" { - port = "5671" - } - } - - var cp ConnOptions - if opts != nil { - cp = *opts - } - - // prepend SASL credentials when the user/pass segment is not empty - if u.User != nil { - pass, _ := u.User.Password() - cp.SASLType = SASLTypePlain(u.User.Username(), pass) - } - - if cp.HostName == "" { - cp.HostName = host - } - - c, err := newConn(nil, &cp) - if err != nil { - return nil, err - } - - switch u.Scheme { - case "amqp", "": - err = c.dialer.NetDialerDial(ctx, c, host, port) - case "amqps", "amqp+ssl": - c.initTLSConfig() - c.tlsNegotiation = false - err = c.dialer.TLSDialWithDialer(ctx, c, host, port) - default: - err = fmt.Errorf("unsupported scheme %q", u.Scheme) - } - - if err != nil { - return nil, err - } - return c, nil -} - -func newConn(netConn net.Conn, opts *ConnOptions) (*Conn, error) { - c := &Conn{ - dialer: defaultDialer{}, - net: netConn, - maxFrameSize: defaultMaxFrameSize, - peerMaxFrameSize: defaultMaxFrameSize, - channelMax: defaultMaxSessions - 1, // -1 because channel-max starts at zero - idleTimeout: defaultIdleTimeout, - containerID: shared.RandString(40), - done: make(chan struct{}), - rxtxExit: make(chan struct{}), - rxDone: make(chan struct{}), - txFrame: make(chan frameEnvelope), - txDone: make(chan struct{}), - sessionsByChannel: map[uint16]*Session{}, - writeTimeout: defaultWriteTimeout, - } - - // apply options - if opts == nil { - opts = &ConnOptions{} - } - - if opts.WriteTimeout > 0 { - c.writeTimeout = opts.WriteTimeout - } else if opts.WriteTimeout < 0 { - c.writeTimeout = 0 - } - if opts.ContainerID != "" { - c.containerID = opts.ContainerID - } - if opts.HostName != "" { - c.hostname = opts.HostName - } - if opts.IdleTimeout > 0 { - c.idleTimeout = opts.IdleTimeout - } else if opts.IdleTimeout < 0 { - c.idleTimeout = 0 - } - if opts.MaxFrameSize > 0 && opts.MaxFrameSize < 512 { - return nil, fmt.Errorf("invalid MaxFrameSize value %d", opts.MaxFrameSize) - } else if opts.MaxFrameSize > 512 { - c.maxFrameSize = opts.MaxFrameSize - } - if opts.MaxSessions > 0 { - c.channelMax = opts.MaxSessions - } - if opts.SASLType != nil { - if err := opts.SASLType(c); err != nil { - return nil, err - } - } - if opts.Properties != nil { - c.properties = make(map[encoding.Symbol]any) - for key, val := range opts.Properties { - c.properties[encoding.Symbol(key)] = val - } - } - if opts.TLSConfig != nil { - c.tlsConfig = opts.TLSConfig.Clone() - } - if opts.dialer != nil { - c.dialer = opts.dialer - } - return c, nil -} - -func (c *Conn) initTLSConfig() { - // create a new config if not already set - if c.tlsConfig == nil { - c.tlsConfig = new(tls.Config) - } - - // TLS config must have ServerName or InsecureSkipVerify set - if c.tlsConfig.ServerName == "" && !c.tlsConfig.InsecureSkipVerify { - c.tlsConfig.ServerName = c.hostname - } -} - -// start establishes the connection and begins multiplexing network IO. -// It is an error to call Start() on a connection that's been closed. -func (c *Conn) start(ctx context.Context) (err error) { - // if the context has a deadline or is cancellable, start the interruptor goroutine. - // this will close the underlying net.Conn in response to the context. - - if ctx.Done() != nil { - done := make(chan struct{}) - interruptRes := make(chan error, 1) - - defer func() { - close(done) - if ctxErr := <-interruptRes; ctxErr != nil { - // return context error to caller - err = ctxErr - } - }() - - go func() { - select { - case <-ctx.Done(): - c.closeDuringStart() - interruptRes <- ctx.Err() - case <-done: - interruptRes <- nil - } - }() - } - - if err = c.startImpl(ctx); err != nil { - return err - } - - // we can't create the channel bitmap until the connection has been established. - // this is because our peer can tell us the max channels they support. - c.channels = bitmap.New(uint32(c.channelMax)) - - go c.connWriter() - go c.connReader() - - return -} - -func (c *Conn) startImpl(ctx context.Context) error { - // set connection establishment deadline as required - if deadline, ok := ctx.Deadline(); ok && !deadline.IsZero() { - _ = c.net.SetDeadline(deadline) - - // remove connection establishment deadline - defer func() { - _ = c.net.SetDeadline(time.Time{}) - }() - } - - // run connection establishment state machine - for state := c.negotiateProto; state != nil; { - var err error - state, err = state(ctx) - // check if err occurred - if err != nil { - c.closeDuringStart() - return err - } - } - - return nil -} - -// Close closes the connection. -func (c *Conn) Close() error { - c.close() - - // wait until the reader/writer goroutines have exited before proceeding. - // this is to prevent a race between calling Close() and a reader/writer - // goroutine calling close() due to a terminal error. - <-c.txDone - <-c.rxDone - - var connErr *ConnError - if errors.As(c.doneErr, &connErr) && connErr.RemoteErr == nil && connErr.inner == nil { - // an empty ConnectionError means the connection was closed by the caller - return nil - } - - // there was an error during shut-down or connReader/connWriter - // experienced a terminal error - return c.doneErr -} - -// close is called once, either from Close() or when connReader/connWriter exits -func (c *Conn) close() { - c.closeOnce.Do(func() { - defer close(c.done) - - close(c.rxtxExit) - - // wait for writing to stop, allows it to send the final close frame - <-c.txDone - - closeErr := c.net.Close() - - // check rxDone after closing net, otherwise may block - // for up to c.idleTimeout - <-c.rxDone - - if errors.Is(c.rxErr, net.ErrClosed) { - // this is the expected error when the connection is closed, swallow it - c.rxErr = nil - } - - if c.txErr == nil && c.rxErr == nil && closeErr == nil { - // if there are no errors, it means user initiated close() and we shut down cleanly - c.doneErr = &ConnError{} - } else if amqpErr, ok := c.rxErr.(*Error); ok { - // we experienced a peer-initiated close that contained an Error. return it - c.doneErr = &ConnError{RemoteErr: amqpErr} - } else if c.txErr != nil { - // c.txErr is already wrapped in a ConnError - c.doneErr = c.txErr - } else if c.rxErr != nil { - c.doneErr = &ConnError{inner: c.rxErr} - } else { - c.doneErr = &ConnError{inner: closeErr} - } - }) -} - -// closeDuringStart is a special close to be used only during startup (i.e. c.start() and any of its children) -func (c *Conn) closeDuringStart() { - c.closeOnce.Do(func() { - c.net.Close() - }) -} - -// NewSession starts a new session on the connection. -// - ctx controls waiting for the peer to acknowledge the session -// - opts contains optional values, pass nil to accept the defaults -// -// If the context's deadline expires or is cancelled before the operation -// completes, an error is returned. If the Session was successfully -// created, it will be cleaned up in future calls to NewSession. -func (c *Conn) NewSession(ctx context.Context, opts *SessionOptions) (*Session, error) { - // clean up any abandoned sessions first - if err := c.freeAbandonedSessions(ctx); err != nil { - return nil, err - } - - session, err := c.newSession(opts) - if err != nil { - return nil, err - } - - if err := session.begin(ctx); err != nil { - c.abandonSession(session) - return nil, err - } - - return session, nil -} - -func (c *Conn) freeAbandonedSessions(ctx context.Context) error { - c.abandonedSessionsMu.Lock() - defer c.abandonedSessionsMu.Unlock() - - debug.Log(3, "TX (Conn %p): cleaning up %d abandoned sessions", c, len(c.abandonedSessions)) - - for _, s := range c.abandonedSessions { - fr := frames.PerformEnd{} - if err := s.txFrameAndWait(ctx, &fr); err != nil { - return err - } - } - - c.abandonedSessions = nil - return nil -} - -func (c *Conn) newSession(opts *SessionOptions) (*Session, error) { - c.sessionsByChannelMu.Lock() - defer c.sessionsByChannelMu.Unlock() - - // create the next session to allocate - // note that channel always start at 0 - channel, ok := c.channels.Next() - if !ok { - if err := c.Close(); err != nil { - return nil, err - } - return nil, &ConnError{inner: fmt.Errorf("reached connection channel max (%d)", c.channelMax)} - } - session := newSession(c, uint16(channel), opts) - c.sessionsByChannel[session.channel] = session - - return session, nil -} - -func (c *Conn) deleteSession(s *Session) { - c.sessionsByChannelMu.Lock() - defer c.sessionsByChannelMu.Unlock() - - delete(c.sessionsByChannel, s.channel) - c.channels.Remove(uint32(s.channel)) -} - -func (c *Conn) abandonSession(s *Session) { - c.abandonedSessionsMu.Lock() - defer c.abandonedSessionsMu.Unlock() - c.abandonedSessions = append(c.abandonedSessions, s) -} - -// connReader reads from the net.Conn, decodes frames, and either handles -// them here as appropriate or sends them to the session.rx channel. -func (c *Conn) connReader() { - defer func() { - close(c.rxDone) - c.close() - }() - - var sessionsByRemoteChannel = make(map[uint16]*Session) - var err error - for { - if err != nil { - debug.Log(1, "RX (connReader %p): terminal error: %v", c, err) - c.rxErr = err - return - } - - var fr frames.Frame - fr, err = c.readFrame() - if err != nil { - continue - } - - debug.Log(1, "RX (connReader %p): %s", c, fr) - - var ( - session *Session - ok bool - ) - - switch body := fr.Body.(type) { - // Server initiated close. - case *frames.PerformClose: - // connWriter will send the close performative ack on its way out. - // it's a SHOULD though, not a MUST. - if body.Error == nil { - return - } - err = body.Error - continue - - // RemoteChannel should be used when frame is Begin - case *frames.PerformBegin: - if body.RemoteChannel == nil { - // since we only support remotely-initiated sessions, this is an error - // TODO: it would be ideal to not have this kill the connection - err = fmt.Errorf("%T: nil RemoteChannel", fr.Body) - continue - } - c.sessionsByChannelMu.RLock() - session, ok = c.sessionsByChannel[*body.RemoteChannel] - c.sessionsByChannelMu.RUnlock() - if !ok { - // this can happen if NewSession() exits due to the context expiring/cancelled - // before the begin ack is received. - err = fmt.Errorf("unexpected remote channel number %d", *body.RemoteChannel) - continue - } - - session.remoteChannel = fr.Channel - sessionsByRemoteChannel[fr.Channel] = session - - case *frames.PerformEnd: - session, ok = sessionsByRemoteChannel[fr.Channel] - if !ok { - err = fmt.Errorf("%T: didn't find channel %d in sessionsByRemoteChannel (PerformEnd)", fr.Body, fr.Channel) - continue - } - // we MUST remove the remote channel from our map as soon as we receive - // the ack (i.e. before passing it on to the session mux) on the session - // ending since the numbers are recycled. - delete(sessionsByRemoteChannel, fr.Channel) - c.deleteSession(session) - - default: - // pass on performative to the correct session - session, ok = sessionsByRemoteChannel[fr.Channel] - if !ok { - err = fmt.Errorf("%T: didn't find channel %d in sessionsByRemoteChannel", fr.Body, fr.Channel) - continue - } - } - - q := session.rxQ.Acquire() - q.Enqueue(fr.Body) - session.rxQ.Release(q) - debug.Log(2, "RX (connReader %p): mux frame to Session (%p): %s", c, session, fr) - } -} - -// readFrame reads a complete frame from c.net. -// it assumes that any read deadline has already been applied. -// used externally by SASL only. -func (c *Conn) readFrame() (frames.Frame, error) { - switch { - // Cheaply reuse free buffer space when fully read. - case c.rxBuf.Len() == 0: - c.rxBuf.Reset() - - // Prevent excessive/unbounded growth by shifting data to beginning of buffer. - case int64(c.rxBuf.Size()) > int64(c.maxFrameSize): - c.rxBuf.Reclaim() - } - - var ( - currentHeader frames.Header // keep track of the current header, for frames split across multiple TCP packets - frameInProgress bool // true if in the middle of receiving data for currentHeader - ) - - for { - // need to read more if buf doesn't contain the complete frame - // or there's not enough in buf to parse the header - if frameInProgress || c.rxBuf.Len() < frames.HeaderSize { - // we MUST reset the idle timeout before each read from net.Conn - if c.idleTimeout > 0 { - _ = c.net.SetReadDeadline(time.Now().Add(c.idleTimeout)) - } - err := c.rxBuf.ReadFromOnce(c.net) - if err != nil { - return frames.Frame{}, err - } - } - - // read more if buf doesn't contain enough to parse the header - if c.rxBuf.Len() < frames.HeaderSize { - continue - } - - // parse the header if a frame isn't in progress - if !frameInProgress { - var err error - currentHeader, err = frames.ParseHeader(&c.rxBuf) - if err != nil { - return frames.Frame{}, err - } - frameInProgress = true - } - - // check size is reasonable - if currentHeader.Size > math.MaxInt32 { // make max size configurable - return frames.Frame{}, errors.New("payload too large") - } - - bodySize := int64(currentHeader.Size - frames.HeaderSize) - - // the full frame hasn't been received, keep reading - if int64(c.rxBuf.Len()) < bodySize { - continue - } - frameInProgress = false - - // check if body is empty (keepalive) - if bodySize == 0 { - debug.Log(3, "RX (connReader %p): received keep-alive frame", c) - continue - } - - // parse the frame - b, ok := c.rxBuf.Next(bodySize) - if !ok { - return frames.Frame{}, fmt.Errorf("buffer EOF; requested bytes: %d, actual size: %d", bodySize, c.rxBuf.Len()) - } - - parsedBody, err := frames.ParseBody(buffer.New(b)) - if err != nil { - return frames.Frame{}, err - } - - return frames.Frame{Channel: currentHeader.Channel, Body: parsedBody}, nil - } -} - -// frameEnvelope is used when sending a frame to connWriter to be written to net.Conn -type frameEnvelope struct { - Ctx context.Context - Frame frames.Frame - - // optional channel that is closed on successful write to net.Conn or contains the write error - // NOTE: use a buffered channel of size 1 when populating - Sent chan error -} - -func (c *Conn) connWriter() { - defer func() { - close(c.txDone) - c.close() - }() - - var ( - // keepalives are sent at a rate of 1/2 idle timeout - keepaliveInterval = c.peerIdleTimeout / 2 - // 0 disables keepalives - keepalivesEnabled = keepaliveInterval > 0 - // set if enable, nil if not; nil channels block forever - keepalive <-chan time.Time - ) - - if keepalivesEnabled { - ticker := time.NewTicker(keepaliveInterval) - defer ticker.Stop() - keepalive = ticker.C - } - - var err error - for { - if err != nil { - debug.Log(1, "TX (connWriter %p): terminal error: %v", c, err) - c.txErr = err - return - } - - select { - // frame write request - case env := <-c.txFrame: - timeout, ctxErr := c.getWriteTimeout(env.Ctx) - if ctxErr != nil { - debug.Log(1, "TX (connWriter %p) deadline exceeded: %s", c, env.Frame) - if env.Sent != nil { - env.Sent <- ctxErr - } - continue - } - - debug.Log(1, "TX (connWriter %p) timeout %s: %s", c, timeout, env.Frame) - err = c.writeFrame(timeout, env.Frame) - if env.Sent != nil { - if err == nil { - close(env.Sent) - } else { - env.Sent <- err - } - } - - // keepalive timer - case <-keepalive: - debug.Log(3, "TX (connWriter %p): sending keep-alive frame", c) - _ = c.net.SetWriteDeadline(time.Now().Add(c.writeTimeout)) - if _, err = c.net.Write(keepaliveFrame); err != nil { - err = &ConnError{inner: err} - } - // It would be slightly more efficient in terms of network - // resources to reset the timer each time a frame is sent. - // However, keepalives are small (8 bytes) and the interval - // is usually on the order of minutes. It does not seem - // worth it to add extra operations in the write path to - // avoid. (To properly reset a timer it needs to be stopped, - // possibly drained, then reset.) - - // connection complete - case <-c.rxtxExit: - // send close performative. note that the spec says we - // SHOULD wait for the ack but we don't HAVE to, in order - // to be resilient to bad actors etc. so we just send - // the close performative and exit. - fr := frames.Frame{ - Type: frames.TypeAMQP, - Body: &frames.PerformClose{}, - } - debug.Log(1, "TX (connWriter %p): %s", c, fr) - c.txErr = c.writeFrame(c.writeTimeout, fr) - return - } - } -} - -// writeFrame writes a frame to the network. -// used externally by SASL only. -// - timeout - the write deadline to set. zero means no deadline -// -// errors are wrapped in a ConnError as they can be returned to outside callers. -func (c *Conn) writeFrame(timeout time.Duration, fr frames.Frame) error { - // writeFrame into txBuf - c.txBuf.Reset() - err := frames.Write(&c.txBuf, fr) - if err != nil { - return &ConnError{inner: err} - } - - // validate the frame isn't exceeding peer's max frame size - requiredFrameSize := c.txBuf.Len() - if uint64(requiredFrameSize) > uint64(c.peerMaxFrameSize) { - return &ConnError{inner: fmt.Errorf("%T frame size %d larger than peer's max frame size %d", fr, requiredFrameSize, c.peerMaxFrameSize)} - } - - if timeout == 0 { - _ = c.net.SetWriteDeadline(time.Time{}) - } else if timeout > 0 { - _ = c.net.SetWriteDeadline(time.Now().Add(timeout)) - } - - // write to network - n, err := c.net.Write(c.txBuf.Bytes()) - if l := c.txBuf.Len(); n > 0 && n < l && err != nil { - debug.Log(1, "TX (writeFrame %p): wrote %d bytes less than len %d: %v", c, n, l, err) - } - if err != nil { - err = &ConnError{inner: err} - } - return err -} - -// writeProtoHeader writes an AMQP protocol header to the -// network -func (c *Conn) writeProtoHeader(pID protoID) error { - _, err := c.net.Write([]byte{'A', 'M', 'Q', 'P', byte(pID), 1, 0, 0}) - return err -} - -// keepaliveFrame is an AMQP frame with no body, used for keepalives -var keepaliveFrame = []byte{0x00, 0x00, 0x00, 0x08, 0x02, 0x00, 0x00, 0x00} - -// SendFrame is used by sessions and links to send frames across the network. -// - ctx is used to provide the write deadline -// - fr is the frame to write to net.Conn -// - sent is the optional channel that will contain the error if the write fails -func (c *Conn) sendFrame(ctx context.Context, fr frames.Frame, sent chan error) { - select { - case c.txFrame <- frameEnvelope{Ctx: ctx, Frame: fr, Sent: sent}: - debug.Log(2, "TX (Conn %p): mux frame to connWriter: %s", c, fr) - case <-c.done: - if sent != nil { - sent <- c.doneErr - } - } -} - -// stateFunc is a state in a state machine. -// -// The state is advanced by returning the next state. -// The state machine concludes when nil is returned. -type stateFunc func(context.Context) (stateFunc, error) - -// negotiateProto determines which proto to negotiate next. -// used externally by SASL only. -func (c *Conn) negotiateProto(ctx context.Context) (stateFunc, error) { - // in the order each must be negotiated - switch { - case c.tlsNegotiation && !c.tlsComplete: - return c.exchangeProtoHeader(protoTLS) - case c.saslHandlers != nil && !c.saslComplete: - return c.exchangeProtoHeader(protoSASL) - default: - return c.exchangeProtoHeader(protoAMQP) - } -} - -type protoID uint8 - -// protocol IDs received in protoHeaders -const ( - protoAMQP protoID = 0x0 - protoTLS protoID = 0x2 - protoSASL protoID = 0x3 -) - -// exchangeProtoHeader performs the round trip exchange of protocol -// headers, validation, and returns the protoID specific next state. -func (c *Conn) exchangeProtoHeader(pID protoID) (stateFunc, error) { - // write the proto header - if err := c.writeProtoHeader(pID); err != nil { - return nil, err - } - - // read response header - p, err := c.readProtoHeader() - if err != nil { - return nil, err - } - - if pID != p.ProtoID { - return nil, fmt.Errorf("unexpected protocol header %#00x, expected %#00x", p.ProtoID, pID) - } - - // go to the proto specific state - switch pID { - case protoAMQP: - return c.openAMQP, nil - case protoTLS: - return c.startTLS, nil - case protoSASL: - return c.negotiateSASL, nil - default: - return nil, fmt.Errorf("unknown protocol ID %#02x", p.ProtoID) - } -} - -// readProtoHeader reads a protocol header packet from c.rxProto. -func (c *Conn) readProtoHeader() (protoHeader, error) { - const protoHeaderSize = 8 - - // only read from the network once our buffer has been exhausted. - // TODO: this preserves existing behavior as some tests rely on this - // implementation detail (it lets you replay a stream of bytes). we - // might want to consider removing this and fixing the tests as the - // protocol doesn't actually work this way. - if c.rxBuf.Len() == 0 { - for { - err := c.rxBuf.ReadFromOnce(c.net) - if err != nil { - return protoHeader{}, err - } - - // read more if buf doesn't contain enough to parse the header - if c.rxBuf.Len() >= protoHeaderSize { - break - } - } - } - - buf, ok := c.rxBuf.Next(protoHeaderSize) - if !ok { - return protoHeader{}, errors.New("invalid protoHeader") - } - // bounds check hint to compiler; see golang.org/issue/14808 - _ = buf[protoHeaderSize-1] - - if !bytes.Equal(buf[:4], []byte{'A', 'M', 'Q', 'P'}) { - return protoHeader{}, fmt.Errorf("unexpected protocol %q", buf[:4]) - } - - p := protoHeader{ - ProtoID: protoID(buf[4]), - Major: buf[5], - Minor: buf[6], - Revision: buf[7], - } - - if p.Major != 1 || p.Minor != 0 || p.Revision != 0 { - return protoHeader{}, fmt.Errorf("unexpected protocol version %d.%d.%d", p.Major, p.Minor, p.Revision) - } - - return p, nil -} - -// startTLS wraps the conn with TLS and returns to Client.negotiateProto -func (c *Conn) startTLS(ctx context.Context) (stateFunc, error) { - c.initTLSConfig() - - _ = c.net.SetReadDeadline(time.Time{}) // clear timeout - - // wrap existing net.Conn and perform TLS handshake - tlsConn := tls.Client(c.net, c.tlsConfig) - if err := tlsConn.HandshakeContext(ctx); err != nil { - return nil, err - } - - // swap net.Conn - c.net = tlsConn - c.tlsComplete = true - - // go to next protocol - return c.negotiateProto, nil -} - -// openAMQP round trips the AMQP open performative -func (c *Conn) openAMQP(ctx context.Context) (stateFunc, error) { - // send open frame - open := &frames.PerformOpen{ - ContainerID: c.containerID, - Hostname: c.hostname, - MaxFrameSize: c.maxFrameSize, - ChannelMax: c.channelMax, - IdleTimeout: c.idleTimeout / 2, // per spec, advertise half our idle timeout - Properties: c.properties, - } - fr := frames.Frame{ - Type: frames.TypeAMQP, - Body: open, - Channel: 0, - } - debug.Log(1, "TX (openAMQP %p): %s", c, fr) - timeout, err := c.getWriteTimeout(ctx) - if err != nil { - return nil, err - } - if err = c.writeFrame(timeout, fr); err != nil { - return nil, err - } - - // get the response - fr, err = c.readSingleFrame() - if err != nil { - return nil, err - } - debug.Log(1, "RX (openAMQP %p): %s", c, fr) - o, ok := fr.Body.(*frames.PerformOpen) - if !ok { - return nil, fmt.Errorf("openAMQP: unexpected frame type %T", fr.Body) - } - - // update peer settings - if o.MaxFrameSize > 0 { - c.peerMaxFrameSize = o.MaxFrameSize - } - if o.IdleTimeout > 0 { - // TODO: reject very small idle timeouts - c.peerIdleTimeout = o.IdleTimeout - } - if o.ChannelMax < c.channelMax { - c.channelMax = o.ChannelMax - } - - // connection established, exit state machine - return nil, nil -} - -// negotiateSASL returns the SASL handler for the first matched -// mechanism specified by the server -func (c *Conn) negotiateSASL(context.Context) (stateFunc, error) { - // read mechanisms frame - fr, err := c.readSingleFrame() - if err != nil { - return nil, err - } - debug.Log(1, "RX (negotiateSASL %p): %s", c, fr) - sm, ok := fr.Body.(*frames.SASLMechanisms) - if !ok { - return nil, fmt.Errorf("negotiateSASL: unexpected frame type %T", fr.Body) - } - - // return first match in c.saslHandlers based on order received - for _, mech := range sm.Mechanisms { - if state, ok := c.saslHandlers[mech]; ok { - return state, nil - } - } - - // no match - return nil, fmt.Errorf("no supported auth mechanism (%v)", sm.Mechanisms) // TODO: send "auth not supported" frame? -} - -// saslOutcome processes the SASL outcome frame and return Client.negotiateProto -// on success. -// -// SASL handlers return this stateFunc when the mechanism specific negotiation -// has completed. -// used externally by SASL only. -func (c *Conn) saslOutcome(context.Context) (stateFunc, error) { - // read outcome frame - fr, err := c.readSingleFrame() - if err != nil { - return nil, err - } - debug.Log(1, "RX (saslOutcome %p): %s", c, fr) - so, ok := fr.Body.(*frames.SASLOutcome) - if !ok { - return nil, fmt.Errorf("saslOutcome: unexpected frame type %T", fr.Body) - } - - // check if auth succeeded - if so.Code != encoding.CodeSASLOK { - return nil, fmt.Errorf("SASL PLAIN auth failed with code %#00x: %s", so.Code, so.AdditionalData) // implement Stringer for so.Code - } - - // return to c.negotiateProto - c.saslComplete = true - return c.negotiateProto, nil -} - -// readSingleFrame is used during connection establishment to read a single frame. -// -// After setup, conn.connReader handles incoming frames. -func (c *Conn) readSingleFrame() (frames.Frame, error) { - fr, err := c.readFrame() - if err != nil { - return frames.Frame{}, err - } - - return fr, nil -} - -// getWriteTimeout returns the timeout as calculated from the context's deadline -// or the default write timeout if the context has no deadline. -// if the context has timed out or was cancelled, an error is returned. -func (c *Conn) getWriteTimeout(ctx context.Context) (time.Duration, error) { - if deadline, ok := ctx.Deadline(); ok { - until := time.Until(deadline) - if until <= 0 { - return 0, context.DeadlineExceeded - } - return until, nil - } - return c.writeTimeout, nil -} - -type protoHeader struct { - ProtoID protoID - Major uint8 - Minor uint8 - Revision uint8 -} diff --git a/sdk/messaging/azeventhubs/internal/go-amqp/const.go b/sdk/messaging/azeventhubs/internal/go-amqp/const.go deleted file mode 100644 index fee0b5041525..000000000000 --- a/sdk/messaging/azeventhubs/internal/go-amqp/const.go +++ /dev/null @@ -1,96 +0,0 @@ -// Copyright (C) 2017 Kale Blankenship -// Portions Copyright (c) Microsoft Corporation - -package amqp - -import "github.com/Azure/azure-sdk-for-go/sdk/messaging/azeventhubs/internal/go-amqp/internal/encoding" - -// Sender Settlement Modes -const ( - // Sender will send all deliveries initially unsettled to the receiver. - SenderSettleModeUnsettled SenderSettleMode = encoding.SenderSettleModeUnsettled - - // Sender will send all deliveries settled to the receiver. - SenderSettleModeSettled SenderSettleMode = encoding.SenderSettleModeSettled - - // Sender MAY send a mixture of settled and unsettled deliveries to the receiver. - SenderSettleModeMixed SenderSettleMode = encoding.SenderSettleModeMixed -) - -// SenderSettleMode specifies how the sender will settle messages. -type SenderSettleMode = encoding.SenderSettleMode - -func senderSettleModeValue(m *SenderSettleMode) SenderSettleMode { - if m == nil { - return SenderSettleModeMixed - } - return *m -} - -// Receiver Settlement Modes -const ( - // Receiver is the first to consider the message as settled. - // Once the corresponding disposition frame is sent, the message - // is considered to be settled. - ReceiverSettleModeFirst ReceiverSettleMode = encoding.ReceiverSettleModeFirst - - // Receiver is the second to consider the message as settled. - // Once the corresponding disposition frame is sent, the settlement - // is considered in-flight and the message will not be considered as - // settled until the sender replies acknowledging the settlement. - ReceiverSettleModeSecond ReceiverSettleMode = encoding.ReceiverSettleModeSecond -) - -// ReceiverSettleMode specifies how the receiver will settle messages. -type ReceiverSettleMode = encoding.ReceiverSettleMode - -func receiverSettleModeValue(m *ReceiverSettleMode) ReceiverSettleMode { - if m == nil { - return ReceiverSettleModeFirst - } - return *m -} - -// Durability Policies -const ( - // No terminus state is retained durably. - DurabilityNone Durability = encoding.DurabilityNone - - // Only the existence and configuration of the terminus is - // retained durably. - DurabilityConfiguration Durability = encoding.DurabilityConfiguration - - // In addition to the existence and configuration of the - // terminus, the unsettled state for durable messages is - // retained durably. - DurabilityUnsettledState Durability = encoding.DurabilityUnsettledState -) - -// Durability specifies the durability of a link. -type Durability = encoding.Durability - -// Expiry Policies -const ( - // The expiry timer starts when terminus is detached. - ExpiryPolicyLinkDetach ExpiryPolicy = encoding.ExpiryLinkDetach - - // The expiry timer starts when the most recently - // associated session is ended. - ExpiryPolicySessionEnd ExpiryPolicy = encoding.ExpirySessionEnd - - // The expiry timer starts when most recently associated - // connection is closed. - ExpiryPolicyConnectionClose ExpiryPolicy = encoding.ExpiryConnectionClose - - // The terminus never expires. - ExpiryPolicyNever ExpiryPolicy = encoding.ExpiryNever -) - -// ExpiryPolicy specifies when the expiry timer of a terminus -// starts counting down from the timeout value. -// -// If the link is subsequently re-attached before the terminus is expired, -// then the count down is aborted. If the conditions for the -// terminus-expiry-policy are subsequently re-met, the expiry timer restarts -// from its originally configured timeout value. -type ExpiryPolicy = encoding.ExpiryPolicy diff --git a/sdk/messaging/azeventhubs/internal/go-amqp/creditor.go b/sdk/messaging/azeventhubs/internal/go-amqp/creditor.go deleted file mode 100644 index 184702bca7d2..000000000000 --- a/sdk/messaging/azeventhubs/internal/go-amqp/creditor.go +++ /dev/null @@ -1,119 +0,0 @@ -// Copyright (c) Microsoft Corporation - -package amqp - -import ( - "context" - "errors" - "sync" -) - -type creditor struct { - mu sync.Mutex - - // future values for the next flow frame. - pendingDrain bool - creditsToAdd uint32 - - // drained is set when a drain is active and we're waiting - // for the corresponding flow from the remote. - drained chan struct{} -} - -var ( - errLinkDraining = errors.New("link is currently draining, no credits can be added") - errAlreadyDraining = errors.New("drain already in process") -) - -// EndDrain ends the current drain, unblocking any active Drain calls. -func (mc *creditor) EndDrain() { - mc.mu.Lock() - defer mc.mu.Unlock() - - if mc.drained != nil { - close(mc.drained) - mc.drained = nil - } -} - -// FlowBits gets gets the proper values for the next flow frame -// and resets the internal state. -// Returns: -// -// (drain: true, credits: 0) if a flow is needed (drain) -// (drain: false, credits > 0) if a flow is needed (issue credit) -// (drain: false, credits == 0) if no flow needed. -func (mc *creditor) FlowBits(currentCredits uint32) (bool, uint32) { - mc.mu.Lock() - defer mc.mu.Unlock() - - drain := mc.pendingDrain - var credits uint32 - - if mc.pendingDrain { - // only send one drain request - mc.pendingDrain = false - } - - // either: - // drain is true (ie, we're going to send a drain frame, and the credits for it should be 0) - // mc.creditsToAdd == 0 (no flow frame needed, no new credits are being issued) - if drain || mc.creditsToAdd == 0 { - credits = 0 - } else { - credits = mc.creditsToAdd + currentCredits - } - - mc.creditsToAdd = 0 - - return drain, credits -} - -// Drain initiates a drain and blocks until EndDrain is called. -// If the context's deadline expires or is cancelled before the operation -// completes, the drain might not have happened. -func (mc *creditor) Drain(ctx context.Context, r *Receiver) error { - mc.mu.Lock() - - if mc.drained != nil { - mc.mu.Unlock() - return errAlreadyDraining - } - - mc.drained = make(chan struct{}) - // use a local copy to avoid racing with EndDrain() - drained := mc.drained - mc.pendingDrain = true - - mc.mu.Unlock() - - // cause mux() to check our flow conditions. - select { - case r.receiverReady <- struct{}{}: - default: - } - - // send drain, wait for responding flow frame - select { - case <-drained: - return nil - case <-r.l.done: - return r.l.doneErr - case <-ctx.Done(): - return ctx.Err() - } -} - -// IssueCredit queues up additional credits to be requested at the next -// call of FlowBits() -func (mc *creditor) IssueCredit(credits uint32) error { - mc.mu.Lock() - defer mc.mu.Unlock() - - if mc.drained != nil { - return errLinkDraining - } - - mc.creditsToAdd += credits - return nil -} diff --git a/sdk/messaging/azeventhubs/internal/go-amqp/errors.go b/sdk/messaging/azeventhubs/internal/go-amqp/errors.go deleted file mode 100644 index 515a7c36bca3..000000000000 --- a/sdk/messaging/azeventhubs/internal/go-amqp/errors.go +++ /dev/null @@ -1,107 +0,0 @@ -// Copyright (C) 2017 Kale Blankenship -// Portions Copyright (c) Microsoft Corporation - -package amqp - -import ( - "github.com/Azure/azure-sdk-for-go/sdk/messaging/azeventhubs/internal/go-amqp/internal/encoding" -) - -// ErrCond is an AMQP defined error condition. -// See http://docs.oasis-open.org/amqp/core/v1.0/os/amqp-core-transport-v1.0-os.html#type-amqp-error for info on their meaning. -type ErrCond = encoding.ErrCond - -// Error Conditions -const ( - // AMQP Errors - ErrCondDecodeError ErrCond = "amqp:decode-error" - ErrCondFrameSizeTooSmall ErrCond = "amqp:frame-size-too-small" - ErrCondIllegalState ErrCond = "amqp:illegal-state" - ErrCondInternalError ErrCond = "amqp:internal-error" - ErrCondInvalidField ErrCond = "amqp:invalid-field" - ErrCondNotAllowed ErrCond = "amqp:not-allowed" - ErrCondNotFound ErrCond = "amqp:not-found" - ErrCondNotImplemented ErrCond = "amqp:not-implemented" - ErrCondPreconditionFailed ErrCond = "amqp:precondition-failed" - ErrCondResourceDeleted ErrCond = "amqp:resource-deleted" - ErrCondResourceLimitExceeded ErrCond = "amqp:resource-limit-exceeded" - ErrCondResourceLocked ErrCond = "amqp:resource-locked" - ErrCondUnauthorizedAccess ErrCond = "amqp:unauthorized-access" - - // Connection Errors - ErrCondConnectionForced ErrCond = "amqp:connection:forced" - ErrCondConnectionRedirect ErrCond = "amqp:connection:redirect" - ErrCondFramingError ErrCond = "amqp:connection:framing-error" - - // Session Errors - ErrCondErrantLink ErrCond = "amqp:session:errant-link" - ErrCondHandleInUse ErrCond = "amqp:session:handle-in-use" - ErrCondUnattachedHandle ErrCond = "amqp:session:unattached-handle" - ErrCondWindowViolation ErrCond = "amqp:session:window-violation" - - // Link Errors - ErrCondDetachForced ErrCond = "amqp:link:detach-forced" - ErrCondLinkRedirect ErrCond = "amqp:link:redirect" - ErrCondMessageSizeExceeded ErrCond = "amqp:link:message-size-exceeded" - ErrCondStolen ErrCond = "amqp:link:stolen" - ErrCondTransferLimitExceeded ErrCond = "amqp:link:transfer-limit-exceeded" -) - -// Error is an AMQP error. -type Error = encoding.Error - -// LinkError is returned by methods on Sender/Receiver when the link has closed. -type LinkError struct { - // RemoteErr contains any error information provided by the peer if the peer detached the link. - RemoteErr *Error - - inner error -} - -// Error implements the error interface for LinkError. -func (e *LinkError) Error() string { - if e.RemoteErr == nil && e.inner == nil { - return "amqp: link closed" - } else if e.RemoteErr != nil { - return e.RemoteErr.Error() - } - return e.inner.Error() -} - -// ConnError is returned by methods on Conn and propagated to Session and Senders/Receivers -// when the connection has been closed. -type ConnError struct { - // RemoteErr contains any error information provided by the peer if the peer closed the AMQP connection. - RemoteErr *Error - - inner error -} - -// Error implements the error interface for ConnectionError. -func (e *ConnError) Error() string { - if e.RemoteErr == nil && e.inner == nil { - return "amqp: connection closed" - } else if e.RemoteErr != nil { - return e.RemoteErr.Error() - } - return e.inner.Error() -} - -// SessionError is returned by methods on Session and propagated to Senders/Receivers -// when the session has been closed. -type SessionError struct { - // RemoteErr contains any error information provided by the peer if the peer closed the session. - RemoteErr *Error - - inner error -} - -// Error implements the error interface for SessionError. -func (e *SessionError) Error() string { - if e.RemoteErr == nil && e.inner == nil { - return "amqp: session closed" - } else if e.RemoteErr != nil { - return e.RemoteErr.Error() - } - return e.inner.Error() -} diff --git a/sdk/messaging/azeventhubs/internal/go-amqp/internal/bitmap/bitmap.go b/sdk/messaging/azeventhubs/internal/go-amqp/internal/bitmap/bitmap.go deleted file mode 100644 index d4d682e9199e..000000000000 --- a/sdk/messaging/azeventhubs/internal/go-amqp/internal/bitmap/bitmap.go +++ /dev/null @@ -1,99 +0,0 @@ -// Copyright (C) 2017 Kale Blankenship -// Portions Copyright (c) Microsoft Corporation - -package bitmap - -import ( - "math/bits" -) - -// bitmap is a lazily initialized bitmap -type Bitmap struct { - max uint32 - bits []uint64 -} - -func New(max uint32) *Bitmap { - return &Bitmap{max: max} -} - -// add sets n in the bitmap. -// -// bits will be expanded as needed. -// -// If n is greater than max, the call has no effect. -func (b *Bitmap) Add(n uint32) { - if n > b.max { - return - } - - var ( - idx = n / 64 - offset = n % 64 - ) - - if l := len(b.bits); int(idx) >= l { - b.bits = append(b.bits, make([]uint64, int(idx)-l+1)...) - } - - b.bits[idx] |= 1 << offset -} - -// remove clears n from the bitmap. -// -// If n is not set or greater than max the call has not effect. -func (b *Bitmap) Remove(n uint32) { - var ( - idx = n / 64 - offset = n % 64 - ) - - if int(idx) >= len(b.bits) { - return - } - - b.bits[idx] &= ^uint64(1 << offset) -} - -// next sets and returns the lowest unset bit in the bitmap. -// -// bits will be expanded if necessary. -// -// If there are no unset bits below max, the second return -// value will be false. -func (b *Bitmap) Next() (uint32, bool) { - // find the first unset bit - for i, v := range b.bits { - // skip if all bits are set - if v == ^uint64(0) { - continue - } - - var ( - offset = bits.TrailingZeros64(^v) // invert and count zeroes - next = uint32(i*64 + offset) - ) - - // check if in bounds - if next > b.max { - return next, false - } - - // set bit - b.bits[i] |= 1 << uint32(offset) - return next, true - } - - // no unset bits in the current slice, - // check if the full range has been allocated - if uint64(len(b.bits)*64) > uint64(b.max) { - return 0, false - } - - // full range not allocated, append entry with first - // bit set - b.bits = append(b.bits, 1) - - // return the value of the first bit - return uint32(len(b.bits)-1) * 64, true -} diff --git a/sdk/messaging/azeventhubs/internal/go-amqp/internal/buffer/buffer.go b/sdk/messaging/azeventhubs/internal/go-amqp/internal/buffer/buffer.go deleted file mode 100644 index b82e5fab76a6..000000000000 --- a/sdk/messaging/azeventhubs/internal/go-amqp/internal/buffer/buffer.go +++ /dev/null @@ -1,180 +0,0 @@ -// Copyright (C) 2017 Kale Blankenship -// Portions Copyright (c) Microsoft Corporation - -package buffer - -import ( - "encoding/binary" - "io" -) - -// buffer is similar to bytes.Buffer but specialized for this package -type Buffer struct { - b []byte - i int -} - -func New(b []byte) *Buffer { - return &Buffer{b: b} -} - -func (b *Buffer) Next(n int64) ([]byte, bool) { - if b.readCheck(n) { - buf := b.b[b.i:len(b.b)] - b.i = len(b.b) - return buf, false - } - - buf := b.b[b.i : b.i+int(n)] - b.i += int(n) - return buf, true -} - -func (b *Buffer) Skip(n int) { - b.i += n -} - -func (b *Buffer) Reset() { - b.b = b.b[:0] - b.i = 0 -} - -// reclaim shifts used buffer space to the beginning of the -// underlying slice. -func (b *Buffer) Reclaim() { - l := b.Len() - copy(b.b[:l], b.b[b.i:]) - b.b = b.b[:l] - b.i = 0 -} - -func (b *Buffer) readCheck(n int64) bool { - return int64(b.i)+n > int64(len(b.b)) -} - -func (b *Buffer) ReadByte() (byte, error) { - if b.readCheck(1) { - return 0, io.EOF - } - - byte_ := b.b[b.i] - b.i++ - return byte_, nil -} - -func (b *Buffer) PeekByte() (byte, error) { - if b.readCheck(1) { - return 0, io.EOF - } - - return b.b[b.i], nil -} - -func (b *Buffer) ReadUint16() (uint16, error) { - if b.readCheck(2) { - return 0, io.EOF - } - - n := binary.BigEndian.Uint16(b.b[b.i:]) - b.i += 2 - return n, nil -} - -func (b *Buffer) ReadUint32() (uint32, error) { - if b.readCheck(4) { - return 0, io.EOF - } - - n := binary.BigEndian.Uint32(b.b[b.i:]) - b.i += 4 - return n, nil -} - -func (b *Buffer) ReadUint64() (uint64, error) { - if b.readCheck(8) { - return 0, io.EOF - } - - n := binary.BigEndian.Uint64(b.b[b.i : b.i+8]) - b.i += 8 - return n, nil -} - -func (b *Buffer) ReadFromOnce(r io.Reader) error { - const minRead = 512 - - l := len(b.b) - if cap(b.b)-l < minRead { - total := l * 2 - if total == 0 { - total = minRead - } - new := make([]byte, l, total) - copy(new, b.b) - b.b = new - } - - n, err := r.Read(b.b[l:cap(b.b)]) - b.b = b.b[:l+n] - return err -} - -func (b *Buffer) Append(p []byte) { - b.b = append(b.b, p...) -} - -func (b *Buffer) AppendByte(bb byte) { - b.b = append(b.b, bb) -} - -func (b *Buffer) AppendString(s string) { - b.b = append(b.b, s...) -} - -func (b *Buffer) Len() int { - return len(b.b) - b.i -} - -func (b *Buffer) Size() int { - return b.i -} - -func (b *Buffer) Bytes() []byte { - return b.b[b.i:] -} - -func (b *Buffer) Detach() []byte { - temp := b.b - b.b = nil - b.i = 0 - return temp -} - -func (b *Buffer) AppendUint16(n uint16) { - b.b = append(b.b, - byte(n>>8), - byte(n), - ) -} - -func (b *Buffer) AppendUint32(n uint32) { - b.b = append(b.b, - byte(n>>24), - byte(n>>16), - byte(n>>8), - byte(n), - ) -} - -func (b *Buffer) AppendUint64(n uint64) { - b.b = append(b.b, - byte(n>>56), - byte(n>>48), - byte(n>>40), - byte(n>>32), - byte(n>>24), - byte(n>>16), - byte(n>>8), - byte(n), - ) -} diff --git a/sdk/messaging/azeventhubs/internal/go-amqp/internal/debug/debug.go b/sdk/messaging/azeventhubs/internal/go-amqp/internal/debug/debug.go deleted file mode 100644 index 3e6821e1f723..000000000000 --- a/sdk/messaging/azeventhubs/internal/go-amqp/internal/debug/debug.go +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (C) 2017 Kale Blankenship -// Portions Copyright (c) Microsoft Corporation - -//go:build !debug -// +build !debug - -package debug - -// dummy functions used when debugging is not enabled - -// Log writes the formatted string to stderr. -// Level indicates the verbosity of the messages to log. -// The greater the value, the more verbose messages will be logged. -func Log(_ int, _ string, _ ...any) {} - -// Assert panics if the specified condition is false. -func Assert(bool) {} - -// Assert panics with the provided message if the specified condition is false. -func Assertf(bool, string, ...any) {} diff --git a/sdk/messaging/azeventhubs/internal/go-amqp/internal/debug/debug_debug.go b/sdk/messaging/azeventhubs/internal/go-amqp/internal/debug/debug_debug.go deleted file mode 100644 index 96d53768a5c9..000000000000 --- a/sdk/messaging/azeventhubs/internal/go-amqp/internal/debug/debug_debug.go +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright (C) 2017 Kale Blankenship -// Portions Copyright (c) Microsoft Corporation - -//go:build debug -// +build debug - -package debug - -import ( - "fmt" - "log" - "os" - "strconv" -) - -var ( - debugLevel = 1 - logger = log.New(os.Stderr, "", log.Lmicroseconds) -) - -func init() { - level, err := strconv.Atoi(os.Getenv("DEBUG_LEVEL")) - if err != nil { - return - } - - debugLevel = level -} - -// Log writes the formatted string to stderr. -// Level indicates the verbosity of the messages to log. -// The greater the value, the more verbose messages will be logged. -func Log(level int, format string, v ...any) { - if level <= debugLevel { - logger.Printf(format, v...) - } -} - -// Assert panics if the specified condition is false. -func Assert(condition bool) { - if !condition { - panic("assertion failed!") - } -} - -// Assert panics with the provided message if the specified condition is false. -func Assertf(condition bool, msg string, v ...any) { - if !condition { - panic(fmt.Sprintf(msg, v...)) - } -} diff --git a/sdk/messaging/azeventhubs/internal/go-amqp/internal/encoding/decode.go b/sdk/messaging/azeventhubs/internal/go-amqp/internal/encoding/decode.go deleted file mode 100644 index 1de2be5f70a9..000000000000 --- a/sdk/messaging/azeventhubs/internal/go-amqp/internal/encoding/decode.go +++ /dev/null @@ -1,1150 +0,0 @@ -// Copyright (C) 2017 Kale Blankenship -// Portions Copyright (c) Microsoft Corporation - -package encoding - -import ( - "encoding/binary" - "errors" - "fmt" - "math" - "reflect" - "time" - - "github.com/Azure/azure-sdk-for-go/sdk/messaging/azeventhubs/internal/go-amqp/internal/buffer" -) - -// unmarshaler is fulfilled by types that can unmarshal -// themselves from AMQP data. -type unmarshaler interface { - Unmarshal(r *buffer.Buffer) error -} - -// unmarshal decodes AMQP encoded data into i. -// -// The decoding method is based on the type of i. -// -// If i implements unmarshaler, i.Unmarshal() will be called. -// -// Pointers to primitive types will be decoded via the appropriate read[Type] function. -// -// If i is a pointer to a pointer (**Type), it will be dereferenced and a new instance -// of (*Type) is allocated via reflection. -// -// Common map types (map[string]string, map[Symbol]any, and -// map[any]any), will be decoded via conversion to the mapStringAny, -// mapSymbolAny, and mapAnyAny types. -func Unmarshal(r *buffer.Buffer, i any) error { - if tryReadNull(r) { - return nil - } - - switch t := i.(type) { - case *int: - val, err := readInt(r) - if err != nil { - return err - } - *t = val - case *int8: - val, err := readSbyte(r) - if err != nil { - return err - } - *t = val - case *int16: - val, err := readShort(r) - if err != nil { - return err - } - *t = val - case *int32: - val, err := readInt32(r) - if err != nil { - return err - } - *t = val - case *int64: - val, err := readLong(r) - if err != nil { - return err - } - *t = val - case *uint64: - val, err := readUlong(r) - if err != nil { - return err - } - *t = val - case *uint32: - val, err := readUint32(r) - if err != nil { - return err - } - *t = val - case **uint32: // fastpath for uint32 pointer fields - val, err := readUint32(r) - if err != nil { - return err - } - *t = &val - case *uint16: - val, err := readUshort(r) - if err != nil { - return err - } - *t = val - case *uint8: - val, err := ReadUbyte(r) - if err != nil { - return err - } - *t = val - case *float32: - val, err := readFloat(r) - if err != nil { - return err - } - *t = val - case *float64: - val, err := readDouble(r) - if err != nil { - return err - } - *t = val - case *string: - val, err := ReadString(r) - if err != nil { - return err - } - *t = val - case *Symbol: - s, err := ReadString(r) - if err != nil { - return err - } - *t = Symbol(s) - case *[]byte: - val, err := readBinary(r) - if err != nil { - return err - } - *t = val - case *bool: - b, err := readBool(r) - if err != nil { - return err - } - *t = b - case *time.Time: - ts, err := readTimestamp(r) - if err != nil { - return err - } - *t = ts - case *[]int8: - return (*arrayInt8)(t).Unmarshal(r) - case *[]uint16: - return (*arrayUint16)(t).Unmarshal(r) - case *[]int16: - return (*arrayInt16)(t).Unmarshal(r) - case *[]uint32: - return (*arrayUint32)(t).Unmarshal(r) - case *[]int32: - return (*arrayInt32)(t).Unmarshal(r) - case *[]uint64: - return (*arrayUint64)(t).Unmarshal(r) - case *[]int64: - return (*arrayInt64)(t).Unmarshal(r) - case *[]float32: - return (*arrayFloat)(t).Unmarshal(r) - case *[]float64: - return (*arrayDouble)(t).Unmarshal(r) - case *[]bool: - return (*arrayBool)(t).Unmarshal(r) - case *[]string: - return (*arrayString)(t).Unmarshal(r) - case *[]Symbol: - return (*arraySymbol)(t).Unmarshal(r) - case *[][]byte: - return (*arrayBinary)(t).Unmarshal(r) - case *[]time.Time: - return (*arrayTimestamp)(t).Unmarshal(r) - case *[]UUID: - return (*arrayUUID)(t).Unmarshal(r) - case *[]any: - return (*list)(t).Unmarshal(r) - case *map[any]any: - return (*mapAnyAny)(t).Unmarshal(r) - case *map[string]any: - return (*mapStringAny)(t).Unmarshal(r) - case *map[Symbol]any: - return (*mapSymbolAny)(t).Unmarshal(r) - case *DeliveryState: - type_, _, err := PeekMessageType(r.Bytes()) - if err != nil { - return err - } - - switch AMQPType(type_) { - case TypeCodeStateAccepted: - *t = new(StateAccepted) - case TypeCodeStateModified: - *t = new(StateModified) - case TypeCodeStateReceived: - *t = new(StateReceived) - case TypeCodeStateRejected: - *t = new(StateRejected) - case TypeCodeStateReleased: - *t = new(StateReleased) - default: - return fmt.Errorf("unexpected type %d for deliveryState", type_) - } - return Unmarshal(r, *t) - - case *any: - v, err := ReadAny(r) - if err != nil { - return err - } - *t = v - - case unmarshaler: - return t.Unmarshal(r) - default: - // handle **T - v := reflect.Indirect(reflect.ValueOf(i)) - - // can't unmarshal into a non-pointer - if v.Kind() != reflect.Ptr { - return fmt.Errorf("unable to unmarshal %T", i) - } - - // if nil pointer, allocate a new value to - // unmarshal into - if v.IsNil() { - v.Set(reflect.New(v.Type().Elem())) - } - - return Unmarshal(r, v.Interface()) - } - return nil -} - -// unmarshalComposite is a helper for use in a composite's unmarshal() function. -// -// The composite from r will be unmarshaled into zero or more fields. An error -// will be returned if typ does not match the decoded type. -func UnmarshalComposite(r *buffer.Buffer, type_ AMQPType, fields ...UnmarshalField) error { - cType, numFields, err := readCompositeHeader(r) - if err != nil { - return err - } - - // check type matches expectation - if cType != type_ { - return fmt.Errorf("invalid header %#0x for %#0x", cType, type_) - } - - // Validate the field count is less than or equal to the number of fields - // provided. Fields may be omitted by the sender if they are not set. - if numFields > int64(len(fields)) { - return fmt.Errorf("invalid field count %d for %#0x", numFields, type_) - } - - for i, field := range fields[:numFields] { - // If the field is null and handleNull is set, call it. - if tryReadNull(r) { - if field.HandleNull != nil { - err = field.HandleNull() - if err != nil { - return err - } - } - continue - } - - // Unmarshal each of the received fields. - err = Unmarshal(r, field.Field) - if err != nil { - return fmt.Errorf("unmarshaling field %d: %v", i, err) - } - } - - // check and call handleNull for the remaining fields - for _, field := range fields[numFields:] { - if field.HandleNull != nil { - err = field.HandleNull() - if err != nil { - return err - } - } - } - - return nil -} - -// unmarshalField is a struct that contains a field to be unmarshaled into. -// -// An optional nullHandler can be set. If the composite field being unmarshaled -// is null and handleNull is not nil, nullHandler will be called. -type UnmarshalField struct { - Field any - HandleNull NullHandler -} - -// nullHandler is a function to be called when a composite's field -// is null. -type NullHandler func() error - -func readType(r *buffer.Buffer) (AMQPType, error) { - n, err := r.ReadByte() - return AMQPType(n), err -} - -func peekType(r *buffer.Buffer) (AMQPType, error) { - n, err := r.PeekByte() - return AMQPType(n), err -} - -// readCompositeHeader reads and consumes the composite header from r. -func readCompositeHeader(r *buffer.Buffer) (_ AMQPType, fields int64, _ error) { - type_, err := readType(r) - if err != nil { - return 0, 0, err - } - - // compsites always start with 0x0 - if type_ != 0 { - return 0, 0, fmt.Errorf("invalid composite header %#02x", type_) - } - - // next, the composite type is encoded as an AMQP uint8 - v, err := readUlong(r) - if err != nil { - return 0, 0, err - } - - // fields are represented as a list - fields, err = readListHeader(r) - - return AMQPType(v), fields, err -} - -func readListHeader(r *buffer.Buffer) (length int64, _ error) { - type_, err := readType(r) - if err != nil { - return 0, err - } - - listLength := r.Len() - - switch type_ { - case TypeCodeList0: - return 0, nil - case TypeCodeList8: - buf, ok := r.Next(2) - if !ok { - return 0, errors.New("invalid length") - } - _ = buf[1] - - size := int(buf[0]) - if size > listLength-1 { - return 0, errors.New("invalid length") - } - length = int64(buf[1]) - case TypeCodeList32: - buf, ok := r.Next(8) - if !ok { - return 0, errors.New("invalid length") - } - _ = buf[7] - - size := int(binary.BigEndian.Uint32(buf[:4])) - if size > listLength-4 { - return 0, errors.New("invalid length") - } - length = int64(binary.BigEndian.Uint32(buf[4:8])) - default: - return 0, fmt.Errorf("type code %#02x is not a recognized list type", type_) - } - - return length, nil -} - -func readArrayHeader(r *buffer.Buffer) (length int64, _ error) { - type_, err := readType(r) - if err != nil { - return 0, err - } - - arrayLength := r.Len() - - switch type_ { - case TypeCodeArray8: - buf, ok := r.Next(2) - if !ok { - return 0, errors.New("invalid length") - } - _ = buf[1] - - size := int(buf[0]) - if size > arrayLength-1 { - return 0, errors.New("invalid length") - } - length = int64(buf[1]) - case TypeCodeArray32: - buf, ok := r.Next(8) - if !ok { - return 0, errors.New("invalid length") - } - _ = buf[7] - - size := binary.BigEndian.Uint32(buf[:4]) - if int(size) > arrayLength-4 { - return 0, fmt.Errorf("invalid length for type %02x", type_) - } - length = int64(binary.BigEndian.Uint32(buf[4:8])) - default: - return 0, fmt.Errorf("type code %#02x is not a recognized array type", type_) - } - return length, nil -} - -func ReadString(r *buffer.Buffer) (string, error) { - type_, err := readType(r) - if err != nil { - return "", err - } - - var length int64 - switch type_ { - case TypeCodeStr8, TypeCodeSym8: - n, err := r.ReadByte() - if err != nil { - return "", err - } - length = int64(n) - case TypeCodeStr32, TypeCodeSym32: - buf, ok := r.Next(4) - if !ok { - return "", fmt.Errorf("invalid length for type %#02x", type_) - } - length = int64(binary.BigEndian.Uint32(buf)) - default: - return "", fmt.Errorf("type code %#02x is not a recognized string type", type_) - } - - buf, ok := r.Next(length) - if !ok { - return "", errors.New("invalid length") - } - return string(buf), nil -} - -func readBinary(r *buffer.Buffer) ([]byte, error) { - type_, err := readType(r) - if err != nil { - return nil, err - } - - var length int64 - switch type_ { - case TypeCodeVbin8: - n, err := r.ReadByte() - if err != nil { - return nil, err - } - length = int64(n) - case TypeCodeVbin32: - buf, ok := r.Next(4) - if !ok { - return nil, fmt.Errorf("invalid length for type %#02x", type_) - } - length = int64(binary.BigEndian.Uint32(buf)) - default: - return nil, fmt.Errorf("type code %#02x is not a recognized binary type", type_) - } - - if length == 0 { - // An empty value and a nil value are distinct, - // ensure that the returned value is not nil in this case. - return make([]byte, 0), nil - } - - buf, ok := r.Next(length) - if !ok { - return nil, errors.New("invalid length") - } - return append([]byte(nil), buf...), nil -} - -func ReadAny(r *buffer.Buffer) (any, error) { - if tryReadNull(r) { - return nil, nil - } - - type_, err := peekType(r) - if err != nil { - return nil, errors.New("invalid length") - } - - switch type_ { - // composite - case 0x0: - return readComposite(r) - - // bool - case TypeCodeBool, TypeCodeBoolTrue, TypeCodeBoolFalse: - return readBool(r) - - // uint - case TypeCodeUbyte: - return ReadUbyte(r) - case TypeCodeUshort: - return readUshort(r) - case TypeCodeUint, - TypeCodeSmallUint, - TypeCodeUint0: - return readUint32(r) - case TypeCodeUlong, - TypeCodeSmallUlong, - TypeCodeUlong0: - return readUlong(r) - - // int - case TypeCodeByte: - return readSbyte(r) - case TypeCodeShort: - return readShort(r) - case TypeCodeInt, - TypeCodeSmallint: - return readInt32(r) - case TypeCodeLong, - TypeCodeSmalllong: - return readLong(r) - - // floating point - case TypeCodeFloat: - return readFloat(r) - case TypeCodeDouble: - return readDouble(r) - - // binary - case TypeCodeVbin8, TypeCodeVbin32: - return readBinary(r) - - // strings - case TypeCodeStr8, TypeCodeStr32: - return ReadString(r) - case TypeCodeSym8, TypeCodeSym32: - // symbols currently decoded as string to avoid - // exposing symbol type in message, this may need - // to change if users need to distinguish strings - // from symbols - return ReadString(r) - - // timestamp - case TypeCodeTimestamp: - return readTimestamp(r) - - // UUID - case TypeCodeUUID: - return readUUID(r) - - // arrays - case TypeCodeArray8, TypeCodeArray32: - return readAnyArray(r) - - // lists - case TypeCodeList0, TypeCodeList8, TypeCodeList32: - return readAnyList(r) - - // maps - case TypeCodeMap8: - return readAnyMap(r) - case TypeCodeMap32: - return readAnyMap(r) - - // TODO: implement - case TypeCodeDecimal32: - return nil, errors.New("decimal32 not implemented") - case TypeCodeDecimal64: - return nil, errors.New("decimal64 not implemented") - case TypeCodeDecimal128: - return nil, errors.New("decimal128 not implemented") - case TypeCodeChar: - return nil, errors.New("char not implemented") - default: - return nil, fmt.Errorf("unknown type %#02x", type_) - } -} - -func readAnyMap(r *buffer.Buffer) (any, error) { - var m map[any]any - err := (*mapAnyAny)(&m).Unmarshal(r) - if err != nil { - return nil, err - } - - if len(m) == 0 { - return m, nil - } - - stringKeys := true -Loop: - for key := range m { - switch key.(type) { - case string: - case Symbol: - default: - stringKeys = false - break Loop - } - } - - if stringKeys { - mm := make(map[string]any, len(m)) - for key, value := range m { - switch key := key.(type) { - case string: - mm[key] = value - case Symbol: - mm[string(key)] = value - } - } - return mm, nil - } - - return m, nil -} - -func readAnyList(r *buffer.Buffer) (any, error) { - var a []any - err := (*list)(&a).Unmarshal(r) - return a, err -} - -func readAnyArray(r *buffer.Buffer) (any, error) { - // get the array type - buf := r.Bytes() - if len(buf) < 1 { - return nil, errors.New("invalid length") - } - - var typeIdx int - switch AMQPType(buf[0]) { - case TypeCodeArray8: - typeIdx = 3 - case TypeCodeArray32: - typeIdx = 9 - default: - return nil, fmt.Errorf("invalid array type %02x", buf[0]) - } - if len(buf) < typeIdx+1 { - return nil, errors.New("invalid length") - } - - switch AMQPType(buf[typeIdx]) { - case TypeCodeByte: - var a []int8 - err := (*arrayInt8)(&a).Unmarshal(r) - return a, err - case TypeCodeUbyte: - var a ArrayUByte - err := a.Unmarshal(r) - return a, err - case TypeCodeUshort: - var a []uint16 - err := (*arrayUint16)(&a).Unmarshal(r) - return a, err - case TypeCodeShort: - var a []int16 - err := (*arrayInt16)(&a).Unmarshal(r) - return a, err - case TypeCodeUint0, TypeCodeSmallUint, TypeCodeUint: - var a []uint32 - err := (*arrayUint32)(&a).Unmarshal(r) - return a, err - case TypeCodeSmallint, TypeCodeInt: - var a []int32 - err := (*arrayInt32)(&a).Unmarshal(r) - return a, err - case TypeCodeUlong0, TypeCodeSmallUlong, TypeCodeUlong: - var a []uint64 - err := (*arrayUint64)(&a).Unmarshal(r) - return a, err - case TypeCodeSmalllong, TypeCodeLong: - var a []int64 - err := (*arrayInt64)(&a).Unmarshal(r) - return a, err - case TypeCodeFloat: - var a []float32 - err := (*arrayFloat)(&a).Unmarshal(r) - return a, err - case TypeCodeDouble: - var a []float64 - err := (*arrayDouble)(&a).Unmarshal(r) - return a, err - case TypeCodeBool, TypeCodeBoolTrue, TypeCodeBoolFalse: - var a []bool - err := (*arrayBool)(&a).Unmarshal(r) - return a, err - case TypeCodeStr8, TypeCodeStr32: - var a []string - err := (*arrayString)(&a).Unmarshal(r) - return a, err - case TypeCodeSym8, TypeCodeSym32: - var a []Symbol - err := (*arraySymbol)(&a).Unmarshal(r) - return a, err - case TypeCodeVbin8, TypeCodeVbin32: - var a [][]byte - err := (*arrayBinary)(&a).Unmarshal(r) - return a, err - case TypeCodeTimestamp: - var a []time.Time - err := (*arrayTimestamp)(&a).Unmarshal(r) - return a, err - case TypeCodeUUID: - var a []UUID - err := (*arrayUUID)(&a).Unmarshal(r) - return a, err - default: - return nil, fmt.Errorf("array decoding not implemented for %#02x", buf[typeIdx]) - } -} - -func readComposite(r *buffer.Buffer) (any, error) { - buf := r.Bytes() - - if len(buf) < 2 { - return nil, errors.New("invalid length for composite") - } - - // compsites start with 0x0 - if AMQPType(buf[0]) != 0x0 { - return nil, fmt.Errorf("invalid composite header %#02x", buf[0]) - } - - var compositeType uint64 - switch AMQPType(buf[1]) { - case TypeCodeSmallUlong: - if len(buf) < 3 { - return nil, errors.New("invalid length for smallulong") - } - compositeType = uint64(buf[2]) - case TypeCodeUlong: - if len(buf) < 10 { - return nil, errors.New("invalid length for ulong") - } - compositeType = binary.BigEndian.Uint64(buf[2:]) - } - - if compositeType > math.MaxUint8 { - // try as described type - var dt DescribedType - err := dt.Unmarshal(r) - return dt, err - } - - switch AMQPType(compositeType) { - // Error - case TypeCodeError: - t := new(Error) - err := t.Unmarshal(r) - return t, err - - // Lifetime Policies - case TypeCodeDeleteOnClose: - t := DeleteOnClose - err := t.Unmarshal(r) - return t, err - case TypeCodeDeleteOnNoMessages: - t := DeleteOnNoMessages - err := t.Unmarshal(r) - return t, err - case TypeCodeDeleteOnNoLinks: - t := DeleteOnNoLinks - err := t.Unmarshal(r) - return t, err - case TypeCodeDeleteOnNoLinksOrMessages: - t := DeleteOnNoLinksOrMessages - err := t.Unmarshal(r) - return t, err - - // Delivery States - case TypeCodeStateAccepted: - t := new(StateAccepted) - err := t.Unmarshal(r) - return t, err - case TypeCodeStateModified: - t := new(StateModified) - err := t.Unmarshal(r) - return t, err - case TypeCodeStateReceived: - t := new(StateReceived) - err := t.Unmarshal(r) - return t, err - case TypeCodeStateRejected: - t := new(StateRejected) - err := t.Unmarshal(r) - return t, err - case TypeCodeStateReleased: - t := new(StateReleased) - err := t.Unmarshal(r) - return t, err - - case TypeCodeOpen, - TypeCodeBegin, - TypeCodeAttach, - TypeCodeFlow, - TypeCodeTransfer, - TypeCodeDisposition, - TypeCodeDetach, - TypeCodeEnd, - TypeCodeClose, - TypeCodeSource, - TypeCodeTarget, - TypeCodeMessageHeader, - TypeCodeDeliveryAnnotations, - TypeCodeMessageAnnotations, - TypeCodeMessageProperties, - TypeCodeApplicationProperties, - TypeCodeApplicationData, - TypeCodeAMQPSequence, - TypeCodeAMQPValue, - TypeCodeFooter, - TypeCodeSASLMechanism, - TypeCodeSASLInit, - TypeCodeSASLChallenge, - TypeCodeSASLResponse, - TypeCodeSASLOutcome: - return nil, fmt.Errorf("readComposite unmarshal not implemented for %#02x", compositeType) - - default: - // try as described type - var dt DescribedType - err := dt.Unmarshal(r) - return dt, err - } -} - -func readTimestamp(r *buffer.Buffer) (time.Time, error) { - type_, err := readType(r) - if err != nil { - return time.Time{}, err - } - - if type_ != TypeCodeTimestamp { - return time.Time{}, fmt.Errorf("invalid type for timestamp %02x", type_) - } - - n, err := r.ReadUint64() - ms := int64(n) - return time.Unix(ms/1000, (ms%1000)*1000000).UTC(), err -} - -func readInt(r *buffer.Buffer) (int, error) { - type_, err := peekType(r) - if err != nil { - return 0, err - } - - switch type_ { - // Unsigned - case TypeCodeUbyte: - n, err := ReadUbyte(r) - return int(n), err - case TypeCodeUshort: - n, err := readUshort(r) - return int(n), err - case TypeCodeUint0, TypeCodeSmallUint, TypeCodeUint: - n, err := readUint32(r) - return int(n), err - case TypeCodeUlong0, TypeCodeSmallUlong, TypeCodeUlong: - n, err := readUlong(r) - return int(n), err - - // Signed - case TypeCodeByte: - n, err := readSbyte(r) - return int(n), err - case TypeCodeShort: - n, err := readShort(r) - return int(n), err - case TypeCodeSmallint, TypeCodeInt: - n, err := readInt32(r) - return int(n), err - case TypeCodeSmalllong, TypeCodeLong: - n, err := readLong(r) - return int(n), err - default: - return 0, fmt.Errorf("type code %#02x is not a recognized number type", type_) - } -} - -func readLong(r *buffer.Buffer) (int64, error) { - type_, err := readType(r) - if err != nil { - return 0, err - } - - switch type_ { - case TypeCodeSmalllong: - n, err := r.ReadByte() - return int64(int8(n)), err - case TypeCodeLong: - n, err := r.ReadUint64() - return int64(n), err - default: - return 0, fmt.Errorf("invalid type for uint32 %02x", type_) - } -} - -func readInt32(r *buffer.Buffer) (int32, error) { - type_, err := readType(r) - if err != nil { - return 0, err - } - - switch type_ { - case TypeCodeSmallint: - n, err := r.ReadByte() - return int32(int8(n)), err - case TypeCodeInt: - n, err := r.ReadUint32() - return int32(n), err - default: - return 0, fmt.Errorf("invalid type for int32 %02x", type_) - } -} - -func readShort(r *buffer.Buffer) (int16, error) { - type_, err := readType(r) - if err != nil { - return 0, err - } - - if type_ != TypeCodeShort { - return 0, fmt.Errorf("invalid type for short %02x", type_) - } - - n, err := r.ReadUint16() - return int16(n), err -} - -func readSbyte(r *buffer.Buffer) (int8, error) { - type_, err := readType(r) - if err != nil { - return 0, err - } - - if type_ != TypeCodeByte { - return 0, fmt.Errorf("invalid type for int8 %02x", type_) - } - - n, err := r.ReadByte() - return int8(n), err -} - -func ReadUbyte(r *buffer.Buffer) (uint8, error) { - type_, err := readType(r) - if err != nil { - return 0, err - } - - if type_ != TypeCodeUbyte { - return 0, fmt.Errorf("invalid type for ubyte %02x", type_) - } - - return r.ReadByte() -} - -func readUshort(r *buffer.Buffer) (uint16, error) { - type_, err := readType(r) - if err != nil { - return 0, err - } - - if type_ != TypeCodeUshort { - return 0, fmt.Errorf("invalid type for ushort %02x", type_) - } - - return r.ReadUint16() -} - -func readUint32(r *buffer.Buffer) (uint32, error) { - type_, err := readType(r) - if err != nil { - return 0, err - } - - switch type_ { - case TypeCodeUint0: - return 0, nil - case TypeCodeSmallUint: - n, err := r.ReadByte() - return uint32(n), err - case TypeCodeUint: - return r.ReadUint32() - default: - return 0, fmt.Errorf("invalid type for uint32 %02x", type_) - } -} - -func readUlong(r *buffer.Buffer) (uint64, error) { - type_, err := readType(r) - if err != nil { - return 0, err - } - - switch type_ { - case TypeCodeUlong0: - return 0, nil - case TypeCodeSmallUlong: - n, err := r.ReadByte() - return uint64(n), err - case TypeCodeUlong: - return r.ReadUint64() - default: - return 0, fmt.Errorf("invalid type for uint32 %02x", type_) - } -} - -func readFloat(r *buffer.Buffer) (float32, error) { - type_, err := readType(r) - if err != nil { - return 0, err - } - - if type_ != TypeCodeFloat { - return 0, fmt.Errorf("invalid type for float32 %02x", type_) - } - - bits, err := r.ReadUint32() - return math.Float32frombits(bits), err -} - -func readDouble(r *buffer.Buffer) (float64, error) { - type_, err := readType(r) - if err != nil { - return 0, err - } - - if type_ != TypeCodeDouble { - return 0, fmt.Errorf("invalid type for float64 %02x", type_) - } - - bits, err := r.ReadUint64() - return math.Float64frombits(bits), err -} - -func readBool(r *buffer.Buffer) (bool, error) { - type_, err := readType(r) - if err != nil { - return false, err - } - - switch type_ { - case TypeCodeBool: - b, err := r.ReadByte() - return b != 0, err - case TypeCodeBoolTrue: - return true, nil - case TypeCodeBoolFalse: - return false, nil - default: - return false, fmt.Errorf("type code %#02x is not a recognized bool type", type_) - } -} - -func readUint(r *buffer.Buffer) (value uint64, _ error) { - type_, err := readType(r) - if err != nil { - return 0, err - } - - switch type_ { - case TypeCodeUint0, TypeCodeUlong0: - return 0, nil - case TypeCodeUbyte, TypeCodeSmallUint, TypeCodeSmallUlong: - n, err := r.ReadByte() - return uint64(n), err - case TypeCodeUshort: - n, err := r.ReadUint16() - return uint64(n), err - case TypeCodeUint: - n, err := r.ReadUint32() - return uint64(n), err - case TypeCodeUlong: - return r.ReadUint64() - default: - return 0, fmt.Errorf("type code %#02x is not a recognized number type", type_) - } -} - -func readUUID(r *buffer.Buffer) (UUID, error) { - var uuid UUID - - type_, err := readType(r) - if err != nil { - return uuid, err - } - - if type_ != TypeCodeUUID { - return uuid, fmt.Errorf("type code %#00x is not a UUID", type_) - } - - buf, ok := r.Next(16) - if !ok { - return uuid, errors.New("invalid length") - } - copy(uuid[:], buf) - - return uuid, nil -} - -func readMapHeader(r *buffer.Buffer) (count uint32, _ error) { - type_, err := readType(r) - if err != nil { - return 0, err - } - - length := r.Len() - - switch type_ { - case TypeCodeMap8: - buf, ok := r.Next(2) - if !ok { - return 0, errors.New("invalid length") - } - _ = buf[1] - - size := int(buf[0]) - if size > length-1 { - return 0, errors.New("invalid length") - } - count = uint32(buf[1]) - case TypeCodeMap32: - buf, ok := r.Next(8) - if !ok { - return 0, errors.New("invalid length") - } - _ = buf[7] - - size := int(binary.BigEndian.Uint32(buf[:4])) - if size > length-4 { - return 0, errors.New("invalid length") - } - count = binary.BigEndian.Uint32(buf[4:8]) - default: - return 0, fmt.Errorf("invalid map type %#02x", type_) - } - - if int(count) > r.Len() { - return 0, errors.New("invalid length") - } - return count, nil -} diff --git a/sdk/messaging/azeventhubs/internal/go-amqp/internal/encoding/encode.go b/sdk/messaging/azeventhubs/internal/go-amqp/internal/encoding/encode.go deleted file mode 100644 index 1103c84f2b26..000000000000 --- a/sdk/messaging/azeventhubs/internal/go-amqp/internal/encoding/encode.go +++ /dev/null @@ -1,573 +0,0 @@ -// Copyright (C) 2017 Kale Blankenship -// Portions Copyright (c) Microsoft Corporation - -package encoding - -import ( - "encoding/binary" - "errors" - "fmt" - "math" - "time" - "unicode/utf8" - - "github.com/Azure/azure-sdk-for-go/sdk/messaging/azeventhubs/internal/go-amqp/internal/buffer" -) - -type marshaler interface { - Marshal(*buffer.Buffer) error -} - -func Marshal(wr *buffer.Buffer, i any) error { - switch t := i.(type) { - case nil: - wr.AppendByte(byte(TypeCodeNull)) - case bool: - if t { - wr.AppendByte(byte(TypeCodeBoolTrue)) - } else { - wr.AppendByte(byte(TypeCodeBoolFalse)) - } - case *bool: - if *t { - wr.AppendByte(byte(TypeCodeBoolTrue)) - } else { - wr.AppendByte(byte(TypeCodeBoolFalse)) - } - case uint: - writeUint64(wr, uint64(t)) - case *uint: - writeUint64(wr, uint64(*t)) - case uint64: - writeUint64(wr, t) - case *uint64: - writeUint64(wr, *t) - case uint32: - writeUint32(wr, t) - case *uint32: - writeUint32(wr, *t) - case uint16: - wr.AppendByte(byte(TypeCodeUshort)) - wr.AppendUint16(t) - case *uint16: - wr.AppendByte(byte(TypeCodeUshort)) - wr.AppendUint16(*t) - case uint8: - wr.Append([]byte{ - byte(TypeCodeUbyte), - t, - }) - case *uint8: - wr.Append([]byte{ - byte(TypeCodeUbyte), - *t, - }) - case int: - writeInt64(wr, int64(t)) - case *int: - writeInt64(wr, int64(*t)) - case int8: - wr.Append([]byte{ - byte(TypeCodeByte), - uint8(t), - }) - case *int8: - wr.Append([]byte{ - byte(TypeCodeByte), - uint8(*t), - }) - case int16: - wr.AppendByte(byte(TypeCodeShort)) - wr.AppendUint16(uint16(t)) - case *int16: - wr.AppendByte(byte(TypeCodeShort)) - wr.AppendUint16(uint16(*t)) - case int32: - writeInt32(wr, t) - case *int32: - writeInt32(wr, *t) - case int64: - writeInt64(wr, t) - case *int64: - writeInt64(wr, *t) - case float32: - writeFloat(wr, t) - case *float32: - writeFloat(wr, *t) - case float64: - writeDouble(wr, t) - case *float64: - writeDouble(wr, *t) - case string: - return writeString(wr, t) - case *string: - return writeString(wr, *t) - case []byte: - return WriteBinary(wr, t) - case *[]byte: - return WriteBinary(wr, *t) - case map[any]any: - return writeMap(wr, t) - case *map[any]any: - return writeMap(wr, *t) - case map[string]any: - return writeMap(wr, t) - case *map[string]any: - return writeMap(wr, *t) - case map[Symbol]any: - return writeMap(wr, t) - case *map[Symbol]any: - return writeMap(wr, *t) - case Unsettled: - return writeMap(wr, t) - case *Unsettled: - return writeMap(wr, *t) - case time.Time: - writeTimestamp(wr, t) - case *time.Time: - writeTimestamp(wr, *t) - case []int8: - return arrayInt8(t).Marshal(wr) - case *[]int8: - return arrayInt8(*t).Marshal(wr) - case []uint16: - return arrayUint16(t).Marshal(wr) - case *[]uint16: - return arrayUint16(*t).Marshal(wr) - case []int16: - return arrayInt16(t).Marshal(wr) - case *[]int16: - return arrayInt16(*t).Marshal(wr) - case []uint32: - return arrayUint32(t).Marshal(wr) - case *[]uint32: - return arrayUint32(*t).Marshal(wr) - case []int32: - return arrayInt32(t).Marshal(wr) - case *[]int32: - return arrayInt32(*t).Marshal(wr) - case []uint64: - return arrayUint64(t).Marshal(wr) - case *[]uint64: - return arrayUint64(*t).Marshal(wr) - case []int64: - return arrayInt64(t).Marshal(wr) - case *[]int64: - return arrayInt64(*t).Marshal(wr) - case []float32: - return arrayFloat(t).Marshal(wr) - case *[]float32: - return arrayFloat(*t).Marshal(wr) - case []float64: - return arrayDouble(t).Marshal(wr) - case *[]float64: - return arrayDouble(*t).Marshal(wr) - case []bool: - return arrayBool(t).Marshal(wr) - case *[]bool: - return arrayBool(*t).Marshal(wr) - case []string: - return arrayString(t).Marshal(wr) - case *[]string: - return arrayString(*t).Marshal(wr) - case []Symbol: - return arraySymbol(t).Marshal(wr) - case *[]Symbol: - return arraySymbol(*t).Marshal(wr) - case [][]byte: - return arrayBinary(t).Marshal(wr) - case *[][]byte: - return arrayBinary(*t).Marshal(wr) - case []time.Time: - return arrayTimestamp(t).Marshal(wr) - case *[]time.Time: - return arrayTimestamp(*t).Marshal(wr) - case []UUID: - return arrayUUID(t).Marshal(wr) - case *[]UUID: - return arrayUUID(*t).Marshal(wr) - case []any: - return list(t).Marshal(wr) - case *[]any: - return list(*t).Marshal(wr) - case marshaler: - return t.Marshal(wr) - default: - return fmt.Errorf("marshal not implemented for %T", i) - } - return nil -} - -func writeInt32(wr *buffer.Buffer, n int32) { - if n < 128 && n >= -128 { - wr.Append([]byte{ - byte(TypeCodeSmallint), - byte(n), - }) - return - } - - wr.AppendByte(byte(TypeCodeInt)) - wr.AppendUint32(uint32(n)) -} - -func writeInt64(wr *buffer.Buffer, n int64) { - if n < 128 && n >= -128 { - wr.Append([]byte{ - byte(TypeCodeSmalllong), - byte(n), - }) - return - } - - wr.AppendByte(byte(TypeCodeLong)) - wr.AppendUint64(uint64(n)) -} - -func writeUint32(wr *buffer.Buffer, n uint32) { - if n == 0 { - wr.AppendByte(byte(TypeCodeUint0)) - return - } - - if n < 256 { - wr.Append([]byte{ - byte(TypeCodeSmallUint), - byte(n), - }) - return - } - - wr.AppendByte(byte(TypeCodeUint)) - wr.AppendUint32(n) -} - -func writeUint64(wr *buffer.Buffer, n uint64) { - if n == 0 { - wr.AppendByte(byte(TypeCodeUlong0)) - return - } - - if n < 256 { - wr.Append([]byte{ - byte(TypeCodeSmallUlong), - byte(n), - }) - return - } - - wr.AppendByte(byte(TypeCodeUlong)) - wr.AppendUint64(n) -} - -func writeFloat(wr *buffer.Buffer, f float32) { - wr.AppendByte(byte(TypeCodeFloat)) - wr.AppendUint32(math.Float32bits(f)) -} - -func writeDouble(wr *buffer.Buffer, f float64) { - wr.AppendByte(byte(TypeCodeDouble)) - wr.AppendUint64(math.Float64bits(f)) -} - -func writeTimestamp(wr *buffer.Buffer, t time.Time) { - wr.AppendByte(byte(TypeCodeTimestamp)) - ms := t.UnixNano() / int64(time.Millisecond) - wr.AppendUint64(uint64(ms)) -} - -// marshalField is a field to be marshaled -type MarshalField struct { - Value any // value to be marshaled, use pointers to avoid interface conversion overhead - Omit bool // indicates that this field should be omitted (set to null) -} - -// marshalComposite is a helper for us in a composite's marshal() function. -// -// The returned bytes include the composite header and fields. Fields with -// omit set to true will be encoded as null or omitted altogether if there are -// no non-null fields after them. -func MarshalComposite(wr *buffer.Buffer, code AMQPType, fields []MarshalField) error { - // lastSetIdx is the last index to have a non-omitted field. - // start at -1 as it's possible to have no fields in a composite - lastSetIdx := -1 - - // marshal each field into it's index in rawFields, - // null fields are skipped, leaving the index nil. - for i, f := range fields { - if f.Omit { - continue - } - lastSetIdx = i - } - - // write header only - if lastSetIdx == -1 { - wr.Append([]byte{ - 0x0, - byte(TypeCodeSmallUlong), - byte(code), - byte(TypeCodeList0), - }) - return nil - } - - // write header - WriteDescriptor(wr, code) - - // write fields - wr.AppendByte(byte(TypeCodeList32)) - - // write temp size, replace later - sizeIdx := wr.Len() - wr.Append([]byte{0, 0, 0, 0}) - preFieldLen := wr.Len() - - // field count - wr.AppendUint32(uint32(lastSetIdx + 1)) - - // write null to each index up to lastSetIdx - for _, f := range fields[:lastSetIdx+1] { - if f.Omit { - wr.AppendByte(byte(TypeCodeNull)) - continue - } - err := Marshal(wr, f.Value) - if err != nil { - return err - } - } - - // fix size - size := uint32(wr.Len() - preFieldLen) - buf := wr.Bytes() - binary.BigEndian.PutUint32(buf[sizeIdx:], size) - - return nil -} - -func WriteDescriptor(wr *buffer.Buffer, code AMQPType) { - wr.Append([]byte{ - 0x0, - byte(TypeCodeSmallUlong), - byte(code), - }) -} - -func writeString(wr *buffer.Buffer, str string) error { - if !utf8.ValidString(str) { - return errors.New("not a valid UTF-8 string") - } - l := len(str) - - switch { - // Str8 - case l < 256: - wr.Append([]byte{ - byte(TypeCodeStr8), - byte(l), - }) - wr.AppendString(str) - return nil - - // Str32 - case uint(l) < math.MaxUint32: - wr.AppendByte(byte(TypeCodeStr32)) - wr.AppendUint32(uint32(l)) - wr.AppendString(str) - return nil - - default: - return errors.New("too long") - } -} - -func WriteBinary(wr *buffer.Buffer, bin []byte) error { - l := len(bin) - - switch { - // List8 - case l < 256: - wr.Append([]byte{ - byte(TypeCodeVbin8), - byte(l), - }) - wr.Append(bin) - return nil - - // List32 - case uint(l) < math.MaxUint32: - wr.AppendByte(byte(TypeCodeVbin32)) - wr.AppendUint32(uint32(l)) - wr.Append(bin) - return nil - - default: - return errors.New("too long") - } -} - -func writeMap(wr *buffer.Buffer, m any) error { - startIdx := wr.Len() - wr.Append([]byte{ - byte(TypeCodeMap32), // type - 0, 0, 0, 0, // size placeholder - 0, 0, 0, 0, // length placeholder - }) - - var pairs int - switch m := m.(type) { - case map[any]any: - pairs = len(m) * 2 - for key, val := range m { - err := Marshal(wr, key) - if err != nil { - return err - } - err = Marshal(wr, val) - if err != nil { - return err - } - } - case map[string]any: - pairs = len(m) * 2 - for key, val := range m { - err := writeString(wr, key) - if err != nil { - return err - } - err = Marshal(wr, val) - if err != nil { - return err - } - } - case map[Symbol]any: - pairs = len(m) * 2 - for key, val := range m { - err := key.Marshal(wr) - if err != nil { - return err - } - err = Marshal(wr, val) - if err != nil { - return err - } - } - case Unsettled: - pairs = len(m) * 2 - for key, val := range m { - err := writeString(wr, key) - if err != nil { - return err - } - err = Marshal(wr, val) - if err != nil { - return err - } - } - case Filter: - pairs = len(m) * 2 - for key, val := range m { - err := key.Marshal(wr) - if err != nil { - return err - } - err = val.Marshal(wr) - if err != nil { - return err - } - } - case Annotations: - pairs = len(m) * 2 - for key, val := range m { - switch key := key.(type) { - case string: - err := Symbol(key).Marshal(wr) - if err != nil { - return err - } - case Symbol: - err := key.Marshal(wr) - if err != nil { - return err - } - case int64: - writeInt64(wr, key) - case int: - writeInt64(wr, int64(key)) - default: - return fmt.Errorf("unsupported Annotations key type %T", key) - } - - err := Marshal(wr, val) - if err != nil { - return err - } - } - default: - return fmt.Errorf("unsupported map type %T", m) - } - - if uint(pairs) > math.MaxUint32-4 { - return errors.New("map contains too many elements") - } - - // overwrite placeholder size and length - bytes := wr.Bytes()[startIdx+1 : startIdx+9] - _ = bytes[7] // bounds check hint - - length := wr.Len() - startIdx - 1 - 4 // -1 for type, -4 for length - binary.BigEndian.PutUint32(bytes[:4], uint32(length)) - binary.BigEndian.PutUint32(bytes[4:8], uint32(pairs)) - - return nil -} - -// type length sizes -const ( - array8TLSize = 2 - array32TLSize = 5 -) - -func writeArrayHeader(wr *buffer.Buffer, length, typeSize int, type_ AMQPType) { - size := length * typeSize - - // array type - if size+array8TLSize <= math.MaxUint8 { - wr.Append([]byte{ - byte(TypeCodeArray8), // type - byte(size + array8TLSize), // size - byte(length), // length - byte(type_), // element type - }) - } else { - wr.AppendByte(byte(TypeCodeArray32)) //type - wr.AppendUint32(uint32(size + array32TLSize)) // size - wr.AppendUint32(uint32(length)) // length - wr.AppendByte(byte(type_)) // element type - } -} - -func writeVariableArrayHeader(wr *buffer.Buffer, length, elementsSizeTotal int, type_ AMQPType) { - // 0xA_ == 1, 0xB_ == 4 - // http://docs.oasis-open.org/amqp/core/v1.0/os/amqp-core-types-v1.0-os.html#doc-idp82960 - elementTypeSize := 1 - if type_&0xf0 == 0xb0 { - elementTypeSize = 4 - } - - size := elementsSizeTotal + (length * elementTypeSize) // size excluding array length - if size+array8TLSize <= math.MaxUint8 { - wr.Append([]byte{ - byte(TypeCodeArray8), // type - byte(size + array8TLSize), // size - byte(length), // length - byte(type_), // element type - }) - } else { - wr.AppendByte(byte(TypeCodeArray32)) // type - wr.AppendUint32(uint32(size + array32TLSize)) // size - wr.AppendUint32(uint32(length)) // length - wr.AppendByte(byte(type_)) // element type - } -} diff --git a/sdk/messaging/azeventhubs/internal/go-amqp/internal/encoding/types.go b/sdk/messaging/azeventhubs/internal/go-amqp/internal/encoding/types.go deleted file mode 100644 index 5196d49b4d4c..000000000000 --- a/sdk/messaging/azeventhubs/internal/go-amqp/internal/encoding/types.go +++ /dev/null @@ -1,2155 +0,0 @@ -// Copyright (C) 2017 Kale Blankenship -// Portions Copyright (c) Microsoft Corporation - -package encoding - -import ( - "encoding/binary" - "encoding/hex" - "errors" - "fmt" - "math" - "reflect" - "time" - "unicode/utf8" - - "github.com/Azure/azure-sdk-for-go/sdk/messaging/azeventhubs/internal/go-amqp/internal/buffer" -) - -type AMQPType uint8 - -// Type codes -const ( - TypeCodeNull AMQPType = 0x40 - - // Bool - TypeCodeBool AMQPType = 0x56 // boolean with the octet 0x00 being false and octet 0x01 being true - TypeCodeBoolTrue AMQPType = 0x41 - TypeCodeBoolFalse AMQPType = 0x42 - - // Unsigned - TypeCodeUbyte AMQPType = 0x50 // 8-bit unsigned integer (1) - TypeCodeUshort AMQPType = 0x60 // 16-bit unsigned integer in network byte order (2) - TypeCodeUint AMQPType = 0x70 // 32-bit unsigned integer in network byte order (4) - TypeCodeSmallUint AMQPType = 0x52 // unsigned integer value in the range 0 to 255 inclusive (1) - TypeCodeUint0 AMQPType = 0x43 // the uint value 0 (0) - TypeCodeUlong AMQPType = 0x80 // 64-bit unsigned integer in network byte order (8) - TypeCodeSmallUlong AMQPType = 0x53 // unsigned long value in the range 0 to 255 inclusive (1) - TypeCodeUlong0 AMQPType = 0x44 // the ulong value 0 (0) - - // Signed - TypeCodeByte AMQPType = 0x51 // 8-bit two's-complement integer (1) - TypeCodeShort AMQPType = 0x61 // 16-bit two's-complement integer in network byte order (2) - TypeCodeInt AMQPType = 0x71 // 32-bit two's-complement integer in network byte order (4) - TypeCodeSmallint AMQPType = 0x54 // 8-bit two's-complement integer (1) - TypeCodeLong AMQPType = 0x81 // 64-bit two's-complement integer in network byte order (8) - TypeCodeSmalllong AMQPType = 0x55 // 8-bit two's-complement integer - - // Decimal - TypeCodeFloat AMQPType = 0x72 // IEEE 754-2008 binary32 (4) - TypeCodeDouble AMQPType = 0x82 // IEEE 754-2008 binary64 (8) - TypeCodeDecimal32 AMQPType = 0x74 // IEEE 754-2008 decimal32 using the Binary Integer Decimal encoding (4) - TypeCodeDecimal64 AMQPType = 0x84 // IEEE 754-2008 decimal64 using the Binary Integer Decimal encoding (8) - TypeCodeDecimal128 AMQPType = 0x94 // IEEE 754-2008 decimal128 using the Binary Integer Decimal encoding (16) - - // Other - TypeCodeChar AMQPType = 0x73 // a UTF-32BE encoded Unicode character (4) - TypeCodeTimestamp AMQPType = 0x83 // 64-bit two's-complement integer representing milliseconds since the unix epoch - TypeCodeUUID AMQPType = 0x98 // UUID as defined in section 4.1.2 of RFC-4122 - - // Variable Length - TypeCodeVbin8 AMQPType = 0xa0 // up to 2^8 - 1 octets of binary data (1 + variable) - TypeCodeVbin32 AMQPType = 0xb0 // up to 2^32 - 1 octets of binary data (4 + variable) - TypeCodeStr8 AMQPType = 0xa1 // up to 2^8 - 1 octets worth of UTF-8 Unicode (with no byte order mark) (1 + variable) - TypeCodeStr32 AMQPType = 0xb1 // up to 2^32 - 1 octets worth of UTF-8 Unicode (with no byte order mark) (4 +variable) - TypeCodeSym8 AMQPType = 0xa3 // up to 2^8 - 1 seven bit ASCII characters representing a symbolic value (1 + variable) - TypeCodeSym32 AMQPType = 0xb3 // up to 2^32 - 1 seven bit ASCII characters representing a symbolic value (4 + variable) - - // Compound - TypeCodeList0 AMQPType = 0x45 // the empty list (i.e. the list with no elements) (0) - TypeCodeList8 AMQPType = 0xc0 // up to 2^8 - 1 list elements with total size less than 2^8 octets (1 + compound) - TypeCodeList32 AMQPType = 0xd0 // up to 2^32 - 1 list elements with total size less than 2^32 octets (4 + compound) - TypeCodeMap8 AMQPType = 0xc1 // up to 2^8 - 1 octets of encoded map data (1 + compound) - TypeCodeMap32 AMQPType = 0xd1 // up to 2^32 - 1 octets of encoded map data (4 + compound) - TypeCodeArray8 AMQPType = 0xe0 // up to 2^8 - 1 array elements with total size less than 2^8 octets (1 + array) - TypeCodeArray32 AMQPType = 0xf0 // up to 2^32 - 1 array elements with total size less than 2^32 octets (4 + array) - - // Composites - TypeCodeOpen AMQPType = 0x10 - TypeCodeBegin AMQPType = 0x11 - TypeCodeAttach AMQPType = 0x12 - TypeCodeFlow AMQPType = 0x13 - TypeCodeTransfer AMQPType = 0x14 - TypeCodeDisposition AMQPType = 0x15 - TypeCodeDetach AMQPType = 0x16 - TypeCodeEnd AMQPType = 0x17 - TypeCodeClose AMQPType = 0x18 - - TypeCodeSource AMQPType = 0x28 - TypeCodeTarget AMQPType = 0x29 - TypeCodeError AMQPType = 0x1d - - TypeCodeMessageHeader AMQPType = 0x70 - TypeCodeDeliveryAnnotations AMQPType = 0x71 - TypeCodeMessageAnnotations AMQPType = 0x72 - TypeCodeMessageProperties AMQPType = 0x73 - TypeCodeApplicationProperties AMQPType = 0x74 - TypeCodeApplicationData AMQPType = 0x75 - TypeCodeAMQPSequence AMQPType = 0x76 - TypeCodeAMQPValue AMQPType = 0x77 - TypeCodeFooter AMQPType = 0x78 - - TypeCodeStateReceived AMQPType = 0x23 - TypeCodeStateAccepted AMQPType = 0x24 - TypeCodeStateRejected AMQPType = 0x25 - TypeCodeStateReleased AMQPType = 0x26 - TypeCodeStateModified AMQPType = 0x27 - - TypeCodeSASLMechanism AMQPType = 0x40 - TypeCodeSASLInit AMQPType = 0x41 - TypeCodeSASLChallenge AMQPType = 0x42 - TypeCodeSASLResponse AMQPType = 0x43 - TypeCodeSASLOutcome AMQPType = 0x44 - - TypeCodeDeleteOnClose AMQPType = 0x2b - TypeCodeDeleteOnNoLinks AMQPType = 0x2c - TypeCodeDeleteOnNoMessages AMQPType = 0x2d - TypeCodeDeleteOnNoLinksOrMessages AMQPType = 0x2e -) - -// Durability Policies -const ( - // No terminus state is retained durably. - DurabilityNone Durability = 0 - - // Only the existence and configuration of the terminus is - // retained durably. - DurabilityConfiguration Durability = 1 - - // In addition to the existence and configuration of the - // terminus, the unsettled state for durable messages is - // retained durably. - DurabilityUnsettledState Durability = 2 -) - -// Durability specifies the durability of a link. -type Durability uint32 - -func (d *Durability) String() string { - if d == nil { - return "" - } - - switch *d { - case DurabilityNone: - return "none" - case DurabilityConfiguration: - return "configuration" - case DurabilityUnsettledState: - return "unsettled-state" - default: - return fmt.Sprintf("unknown durability %d", *d) - } -} - -func (d Durability) Marshal(wr *buffer.Buffer) error { - return Marshal(wr, uint32(d)) -} - -func (d *Durability) Unmarshal(r *buffer.Buffer) error { - return Unmarshal(r, (*uint32)(d)) -} - -// Expiry Policies -const ( - // The expiry timer starts when terminus is detached. - ExpiryLinkDetach ExpiryPolicy = "link-detach" - - // The expiry timer starts when the most recently - // associated session is ended. - ExpirySessionEnd ExpiryPolicy = "session-end" - - // The expiry timer starts when most recently associated - // connection is closed. - ExpiryConnectionClose ExpiryPolicy = "connection-close" - - // The terminus never expires. - ExpiryNever ExpiryPolicy = "never" -) - -// ExpiryPolicy specifies when the expiry timer of a terminus -// starts counting down from the timeout value. -// -// If the link is subsequently re-attached before the terminus is expired, -// then the count down is aborted. If the conditions for the -// terminus-expiry-policy are subsequently re-met, the expiry timer restarts -// from its originally configured timeout value. -type ExpiryPolicy Symbol - -func ValidateExpiryPolicy(e ExpiryPolicy) error { - switch e { - case ExpiryLinkDetach, - ExpirySessionEnd, - ExpiryConnectionClose, - ExpiryNever: - return nil - default: - return fmt.Errorf("unknown expiry-policy %q", e) - } -} - -func (e ExpiryPolicy) Marshal(wr *buffer.Buffer) error { - return Symbol(e).Marshal(wr) -} - -func (e *ExpiryPolicy) Unmarshal(r *buffer.Buffer) error { - err := Unmarshal(r, (*Symbol)(e)) - if err != nil { - return err - } - return ValidateExpiryPolicy(*e) -} - -func (e *ExpiryPolicy) String() string { - if e == nil { - return "" - } - return string(*e) -} - -// Sender Settlement Modes -const ( - // Sender will send all deliveries initially unsettled to the receiver. - SenderSettleModeUnsettled SenderSettleMode = 0 - - // Sender will send all deliveries settled to the receiver. - SenderSettleModeSettled SenderSettleMode = 1 - - // Sender MAY send a mixture of settled and unsettled deliveries to the receiver. - SenderSettleModeMixed SenderSettleMode = 2 -) - -// SenderSettleMode specifies how the sender will settle messages. -type SenderSettleMode uint8 - -func (m SenderSettleMode) Ptr() *SenderSettleMode { - return &m -} - -func (m *SenderSettleMode) String() string { - if m == nil { - return "" - } - - switch *m { - case SenderSettleModeUnsettled: - return "unsettled" - - case SenderSettleModeSettled: - return "settled" - - case SenderSettleModeMixed: - return "mixed" - - default: - return fmt.Sprintf("unknown sender mode %d", uint8(*m)) - } -} - -func (m SenderSettleMode) Marshal(wr *buffer.Buffer) error { - return Marshal(wr, uint8(m)) -} - -func (m *SenderSettleMode) Unmarshal(r *buffer.Buffer) error { - n, err := ReadUbyte(r) - *m = SenderSettleMode(n) - return err -} - -// Receiver Settlement Modes -const ( - // Receiver will spontaneously settle all incoming transfers. - ReceiverSettleModeFirst ReceiverSettleMode = 0 - - // Receiver will only settle after sending the disposition to the - // sender and receiving a disposition indicating settlement of - // the delivery from the sender. - ReceiverSettleModeSecond ReceiverSettleMode = 1 -) - -// ReceiverSettleMode specifies how the receiver will settle messages. -type ReceiverSettleMode uint8 - -func (m ReceiverSettleMode) Ptr() *ReceiverSettleMode { - return &m -} - -func (m *ReceiverSettleMode) String() string { - if m == nil { - return "" - } - - switch *m { - case ReceiverSettleModeFirst: - return "first" - - case ReceiverSettleModeSecond: - return "second" - - default: - return fmt.Sprintf("unknown receiver mode %d", uint8(*m)) - } -} - -func (m ReceiverSettleMode) Marshal(wr *buffer.Buffer) error { - return Marshal(wr, uint8(m)) -} - -func (m *ReceiverSettleMode) Unmarshal(r *buffer.Buffer) error { - n, err := ReadUbyte(r) - *m = ReceiverSettleMode(n) - return err -} - -type Role bool - -const ( - RoleSender Role = false - RoleReceiver Role = true -) - -func (rl Role) String() string { - if rl { - return "Receiver" - } - return "Sender" -} - -func (rl *Role) Unmarshal(r *buffer.Buffer) error { - b, err := readBool(r) - *rl = Role(b) - return err -} - -func (rl Role) Marshal(wr *buffer.Buffer) error { - return Marshal(wr, (bool)(rl)) -} - -type SASLCode uint8 - -// SASL Codes -const ( - CodeSASLOK SASLCode = iota // Connection authentication succeeded. - CodeSASLAuth // Connection authentication failed due to an unspecified problem with the supplied credentials. - CodeSASLSysPerm // Connection authentication failed due to a system error that is unlikely to be corrected without intervention. -) - -func (s SASLCode) Marshal(wr *buffer.Buffer) error { - return Marshal(wr, uint8(s)) -} - -func (s *SASLCode) Unmarshal(r *buffer.Buffer) error { - n, err := ReadUbyte(r) - *s = SASLCode(n) - return err -} - -// DeliveryState encapsulates the various concrete delivery states. -// http://docs.oasis-open.org/amqp/core/v1.0/os/amqp-core-messaging-v1.0-os.html#section-delivery-state -// TODO: http://docs.oasis-open.org/amqp/core/v1.0/os/amqp-core-transactions-v1.0-os.html#type-declared -type DeliveryState interface { - deliveryState() // marker method -} - -type Unsettled map[string]DeliveryState - -func (u Unsettled) Marshal(wr *buffer.Buffer) error { - return writeMap(wr, u) -} - -func (u *Unsettled) Unmarshal(r *buffer.Buffer) error { - count, err := readMapHeader(r) - if err != nil { - return err - } - - m := make(Unsettled, count/2) - for i := uint32(0); i < count; i += 2 { - key, err := ReadString(r) - if err != nil { - return err - } - var value DeliveryState - err = Unmarshal(r, &value) - if err != nil { - return err - } - m[key] = value - } - *u = m - return nil -} - -type Filter map[Symbol]*DescribedType - -func (f Filter) Marshal(wr *buffer.Buffer) error { - return writeMap(wr, f) -} - -func (f *Filter) Unmarshal(r *buffer.Buffer) error { - count, err := readMapHeader(r) - if err != nil { - return err - } - - m := make(Filter, count/2) - for i := uint32(0); i < count; i += 2 { - key, err := ReadString(r) - if err != nil { - return err - } - var value DescribedType - err = Unmarshal(r, &value) - if err != nil { - return err - } - m[Symbol(key)] = &value - } - *f = m - return nil -} - -// peekMessageType reads the message type without -// modifying any data. -func PeekMessageType(buf []byte) (uint8, uint8, error) { - if len(buf) < 3 { - return 0, 0, errors.New("invalid message") - } - - if buf[0] != 0 { - return 0, 0, fmt.Errorf("invalid composite header %02x", buf[0]) - } - - // copied from readUlong to avoid allocations - t := AMQPType(buf[1]) - if t == TypeCodeUlong0 { - return 0, 2, nil - } - - if t == TypeCodeSmallUlong { - if len(buf[2:]) == 0 { - return 0, 0, errors.New("invalid ulong") - } - return buf[2], 3, nil - } - - if t != TypeCodeUlong { - return 0, 0, fmt.Errorf("invalid type for uint32 %02x", t) - } - - if len(buf[2:]) < 8 { - return 0, 0, errors.New("invalid ulong") - } - v := binary.BigEndian.Uint64(buf[2:10]) - - return uint8(v), 10, nil -} - -func tryReadNull(r *buffer.Buffer) bool { - if r.Len() > 0 && AMQPType(r.Bytes()[0]) == TypeCodeNull { - r.Skip(1) - return true - } - return false -} - -// Annotations keys must be of type string, int, or int64. -// -// String keys are encoded as AMQP Symbols. -type Annotations map[any]any - -func (a Annotations) Marshal(wr *buffer.Buffer) error { - return writeMap(wr, a) -} - -func (a *Annotations) Unmarshal(r *buffer.Buffer) error { - count, err := readMapHeader(r) - if err != nil { - return err - } - - m := make(Annotations, count/2) - for i := uint32(0); i < count; i += 2 { - key, err := ReadAny(r) - if err != nil { - return err - } - value, err := ReadAny(r) - if err != nil { - return err - } - m[key] = value - } - *a = m - return nil -} - -// ErrCond is one of the error conditions defined in the AMQP spec. -type ErrCond string - -func (ec ErrCond) Marshal(wr *buffer.Buffer) error { - return (Symbol)(ec).Marshal(wr) -} - -func (ec *ErrCond) Unmarshal(r *buffer.Buffer) error { - s, err := ReadString(r) - *ec = ErrCond(s) - return err -} - -/* - - - - - - -*/ - -// Error is an AMQP error. -type Error struct { - // A symbolic value indicating the error condition. - Condition ErrCond - - // descriptive text about the error condition - // - // This text supplies any supplementary details not indicated by the condition field. - // This text can be logged as an aid to resolving issues. - Description string - - // map carrying information about the error condition - Info map[string]any -} - -func (e *Error) Marshal(wr *buffer.Buffer) error { - return MarshalComposite(wr, TypeCodeError, []MarshalField{ - {Value: &e.Condition, Omit: false}, - {Value: &e.Description, Omit: e.Description == ""}, - {Value: e.Info, Omit: len(e.Info) == 0}, - }) -} - -func (e *Error) Unmarshal(r *buffer.Buffer) error { - return UnmarshalComposite(r, TypeCodeError, []UnmarshalField{ - {Field: &e.Condition, HandleNull: func() error { return errors.New("Error.Condition is required") }}, - {Field: &e.Description}, - {Field: &e.Info}, - }...) -} - -func (e *Error) String() string { - if e == nil { - return "*Error(nil)" - } - return fmt.Sprintf("*Error{Condition: %s, Description: %s, Info: %v}", - e.Condition, - e.Description, - e.Info, - ) -} - -func (e *Error) Error() string { - return e.String() -} - -/* - - - - - -*/ - -type StateReceived struct { - // When sent by the sender this indicates the first section of the message - // (with section-number 0 being the first section) for which data can be resent. - // Data from sections prior to the given section cannot be retransmitted for - // this delivery. - // - // When sent by the receiver this indicates the first section of the message - // for which all data might not yet have been received. - SectionNumber uint32 - - // When sent by the sender this indicates the first byte of the encoded section - // data of the section given by section-number for which data can be resent - // (with section-offset 0 being the first byte). Bytes from the same section - // prior to the given offset section cannot be retransmitted for this delivery. - // - // When sent by the receiver this indicates the first byte of the given section - // which has not yet been received. Note that if a receiver has received all of - // section number X (which contains N bytes of data), but none of section number - // X + 1, then it can indicate this by sending either Received(section-number=X, - // section-offset=N) or Received(section-number=X+1, section-offset=0). The state - // Received(section-number=0, section-offset=0) indicates that no message data - // at all has been transferred. - SectionOffset uint64 -} - -func (sr *StateReceived) deliveryState() {} - -func (sr *StateReceived) Marshal(wr *buffer.Buffer) error { - return MarshalComposite(wr, TypeCodeStateReceived, []MarshalField{ - {Value: &sr.SectionNumber, Omit: false}, - {Value: &sr.SectionOffset, Omit: false}, - }) -} - -func (sr *StateReceived) Unmarshal(r *buffer.Buffer) error { - return UnmarshalComposite(r, TypeCodeStateReceived, []UnmarshalField{ - {Field: &sr.SectionNumber, HandleNull: func() error { return errors.New("StateReceiver.SectionNumber is required") }}, - {Field: &sr.SectionOffset, HandleNull: func() error { return errors.New("StateReceiver.SectionOffset is required") }}, - }...) -} - -/* - - - -*/ - -type StateAccepted struct{} - -func (sr *StateAccepted) deliveryState() {} - -func (sa *StateAccepted) Marshal(wr *buffer.Buffer) error { - return MarshalComposite(wr, TypeCodeStateAccepted, nil) -} - -func (sa *StateAccepted) Unmarshal(r *buffer.Buffer) error { - return UnmarshalComposite(r, TypeCodeStateAccepted) -} - -func (sa *StateAccepted) String() string { - return "Accepted" -} - -/* - - - - -*/ - -type StateRejected struct { - Error *Error -} - -func (sr *StateRejected) deliveryState() {} - -func (sr *StateRejected) Marshal(wr *buffer.Buffer) error { - return MarshalComposite(wr, TypeCodeStateRejected, []MarshalField{ - {Value: sr.Error, Omit: sr.Error == nil}, - }) -} - -func (sr *StateRejected) Unmarshal(r *buffer.Buffer) error { - return UnmarshalComposite(r, TypeCodeStateRejected, - UnmarshalField{Field: &sr.Error}, - ) -} - -func (sr *StateRejected) String() string { - return fmt.Sprintf("Rejected{Error: %v}", sr.Error) -} - -/* - - - -*/ - -type StateReleased struct{} - -func (sr *StateReleased) deliveryState() {} - -func (sr *StateReleased) Marshal(wr *buffer.Buffer) error { - return MarshalComposite(wr, TypeCodeStateReleased, nil) -} - -func (sr *StateReleased) Unmarshal(r *buffer.Buffer) error { - return UnmarshalComposite(r, TypeCodeStateReleased) -} - -func (sr *StateReleased) String() string { - return "Released" -} - -/* - - - - - - -*/ - -type StateModified struct { - // count the transfer as an unsuccessful delivery attempt - // - // If the delivery-failed flag is set, any messages modified - // MUST have their delivery-count incremented. - DeliveryFailed bool - - // prevent redelivery - // - // If the undeliverable-here is set, then any messages released MUST NOT - // be redelivered to the modifying link endpoint. - UndeliverableHere bool - - // message attributes - // Map containing attributes to combine with the existing message-annotations - // held in the message's header section. Where the existing message-annotations - // of the message contain an entry with the same key as an entry in this field, - // the value in this field associated with that key replaces the one in the - // existing headers; where the existing message-annotations has no such value, - // the value in this map is added. - MessageAnnotations Annotations -} - -func (sr *StateModified) deliveryState() {} - -func (sm *StateModified) Marshal(wr *buffer.Buffer) error { - return MarshalComposite(wr, TypeCodeStateModified, []MarshalField{ - {Value: &sm.DeliveryFailed, Omit: !sm.DeliveryFailed}, - {Value: &sm.UndeliverableHere, Omit: !sm.UndeliverableHere}, - {Value: sm.MessageAnnotations, Omit: sm.MessageAnnotations == nil}, - }) -} - -func (sm *StateModified) Unmarshal(r *buffer.Buffer) error { - return UnmarshalComposite(r, TypeCodeStateModified, []UnmarshalField{ - {Field: &sm.DeliveryFailed}, - {Field: &sm.UndeliverableHere}, - {Field: &sm.MessageAnnotations}, - }...) -} - -func (sm *StateModified) String() string { - return fmt.Sprintf("Modified{DeliveryFailed: %t, UndeliverableHere: %t, MessageAnnotations: %v}", sm.DeliveryFailed, sm.UndeliverableHere, sm.MessageAnnotations) -} - -// symbol is an AMQP symbolic string. -type Symbol string - -func (s Symbol) Marshal(wr *buffer.Buffer) error { - l := len(s) - switch { - // Sym8 - case l < 256: - wr.Append([]byte{ - byte(TypeCodeSym8), - byte(l), - }) - wr.AppendString(string(s)) - - // Sym32 - case uint(l) < math.MaxUint32: - wr.AppendByte(uint8(TypeCodeSym32)) - wr.AppendUint32(uint32(l)) - wr.AppendString(string(s)) - default: - return errors.New("too long") - } - return nil -} - -type Milliseconds time.Duration - -func (m Milliseconds) Marshal(wr *buffer.Buffer) error { - writeUint32(wr, uint32(m/Milliseconds(time.Millisecond))) - return nil -} - -func (m *Milliseconds) Unmarshal(r *buffer.Buffer) error { - n, err := readUint(r) - *m = Milliseconds(time.Duration(n) * time.Millisecond) - return err -} - -// mapAnyAny is used to decode AMQP maps who's keys are undefined or -// inconsistently typed. -type mapAnyAny map[any]any - -func (m mapAnyAny) Marshal(wr *buffer.Buffer) error { - return writeMap(wr, map[any]any(m)) -} - -func (m *mapAnyAny) Unmarshal(r *buffer.Buffer) error { - count, err := readMapHeader(r) - if err != nil { - return err - } - - mm := make(mapAnyAny, count/2) - for i := uint32(0); i < count; i += 2 { - key, err := ReadAny(r) - if err != nil { - return err - } - value, err := ReadAny(r) - if err != nil { - return err - } - - // https://golang.org/ref/spec#Map_types: - // The comparison operators == and != must be fully defined - // for operands of the key type; thus the key type must not - // be a function, map, or slice. - switch reflect.ValueOf(key).Kind() { - case reflect.Slice, reflect.Func, reflect.Map: - return errors.New("invalid map key") - } - - mm[key] = value - } - *m = mm - return nil -} - -// mapStringAny is used to decode AMQP maps that have string keys -type mapStringAny map[string]any - -func (m mapStringAny) Marshal(wr *buffer.Buffer) error { - return writeMap(wr, map[string]any(m)) -} - -func (m *mapStringAny) Unmarshal(r *buffer.Buffer) error { - count, err := readMapHeader(r) - if err != nil { - return err - } - - mm := make(mapStringAny, count/2) - for i := uint32(0); i < count; i += 2 { - key, err := ReadString(r) - if err != nil { - return err - } - value, err := ReadAny(r) - if err != nil { - return err - } - mm[key] = value - } - *m = mm - - return nil -} - -// mapStringAny is used to decode AMQP maps that have Symbol keys -type mapSymbolAny map[Symbol]any - -func (m mapSymbolAny) Marshal(wr *buffer.Buffer) error { - return writeMap(wr, map[Symbol]any(m)) -} - -func (m *mapSymbolAny) Unmarshal(r *buffer.Buffer) error { - count, err := readMapHeader(r) - if err != nil { - return err - } - - mm := make(mapSymbolAny, count/2) - for i := uint32(0); i < count; i += 2 { - key, err := ReadString(r) - if err != nil { - return err - } - value, err := ReadAny(r) - if err != nil { - return err - } - mm[Symbol(key)] = value - } - *m = mm - return nil -} - -// UUID is a 128 bit identifier as defined in RFC 4122. -type UUID [16]byte - -// String returns the hex encoded representation described in RFC 4122, Section 3. -func (u UUID) String() string { - var buf [36]byte - hex.Encode(buf[:8], u[:4]) - buf[8] = '-' - hex.Encode(buf[9:13], u[4:6]) - buf[13] = '-' - hex.Encode(buf[14:18], u[6:8]) - buf[18] = '-' - hex.Encode(buf[19:23], u[8:10]) - buf[23] = '-' - hex.Encode(buf[24:], u[10:]) - return string(buf[:]) -} - -func (u UUID) Marshal(wr *buffer.Buffer) error { - wr.AppendByte(byte(TypeCodeUUID)) - wr.Append(u[:]) - return nil -} - -func (u *UUID) Unmarshal(r *buffer.Buffer) error { - un, err := readUUID(r) - *u = un - return err -} - -type LifetimePolicy uint8 - -const ( - DeleteOnClose = LifetimePolicy(TypeCodeDeleteOnClose) - DeleteOnNoLinks = LifetimePolicy(TypeCodeDeleteOnNoLinks) - DeleteOnNoMessages = LifetimePolicy(TypeCodeDeleteOnNoMessages) - DeleteOnNoLinksOrMessages = LifetimePolicy(TypeCodeDeleteOnNoLinksOrMessages) -) - -func (p LifetimePolicy) Marshal(wr *buffer.Buffer) error { - wr.Append([]byte{ - 0x0, - byte(TypeCodeSmallUlong), - byte(p), - byte(TypeCodeList0), - }) - return nil -} - -func (p *LifetimePolicy) Unmarshal(r *buffer.Buffer) error { - typ, fields, err := readCompositeHeader(r) - if err != nil { - return err - } - if fields != 0 { - return fmt.Errorf("invalid size %d for lifetime-policy", fields) - } - *p = LifetimePolicy(typ) - return nil -} - -type DescribedType struct { - Descriptor any - Value any -} - -func (t DescribedType) Marshal(wr *buffer.Buffer) error { - wr.AppendByte(0x0) // descriptor constructor - err := Marshal(wr, t.Descriptor) - if err != nil { - return err - } - return Marshal(wr, t.Value) -} - -func (t *DescribedType) Unmarshal(r *buffer.Buffer) error { - b, err := r.ReadByte() - if err != nil { - return err - } - - if b != 0x0 { - return fmt.Errorf("invalid described type header %02x", b) - } - - err = Unmarshal(r, &t.Descriptor) - if err != nil { - return err - } - return Unmarshal(r, &t.Value) -} - -func (t DescribedType) String() string { - return fmt.Sprintf("DescribedType{descriptor: %v, value: %v}", - t.Descriptor, - t.Value, - ) -} - -// SLICES - -// ArrayUByte allows encoding []uint8/[]byte as an array -// rather than binary data. -type ArrayUByte []uint8 - -func (a ArrayUByte) Marshal(wr *buffer.Buffer) error { - const typeSize = 1 - - writeArrayHeader(wr, len(a), typeSize, TypeCodeUbyte) - wr.Append(a) - - return nil -} - -func (a *ArrayUByte) Unmarshal(r *buffer.Buffer) error { - length, err := readArrayHeader(r) - if err != nil { - return err - } - - type_, err := readType(r) - if err != nil { - return err - } - if type_ != TypeCodeUbyte { - return fmt.Errorf("invalid type for []uint16 %02x", type_) - } - - buf, ok := r.Next(length) - if !ok { - return fmt.Errorf("invalid length %d", length) - } - *a = append([]byte(nil), buf...) - - return nil -} - -type arrayInt8 []int8 - -func (a arrayInt8) Marshal(wr *buffer.Buffer) error { - const typeSize = 1 - - writeArrayHeader(wr, len(a), typeSize, TypeCodeByte) - - for _, value := range a { - wr.AppendByte(uint8(value)) - } - - return nil -} - -func (a *arrayInt8) Unmarshal(r *buffer.Buffer) error { - length, err := readArrayHeader(r) - if err != nil { - return err - } - - type_, err := readType(r) - if err != nil { - return err - } - if type_ != TypeCodeByte { - return fmt.Errorf("invalid type for []uint16 %02x", type_) - } - - buf, ok := r.Next(length) - if !ok { - return fmt.Errorf("invalid length %d", length) - } - - aa := (*a)[:0] - if int64(cap(aa)) < length { - aa = make([]int8, length) - } else { - aa = aa[:length] - } - - for i, value := range buf { - aa[i] = int8(value) - } - - *a = aa - return nil -} - -type arrayUint16 []uint16 - -func (a arrayUint16) Marshal(wr *buffer.Buffer) error { - const typeSize = 2 - - writeArrayHeader(wr, len(a), typeSize, TypeCodeUshort) - - for _, element := range a { - wr.AppendUint16(element) - } - - return nil -} - -func (a *arrayUint16) Unmarshal(r *buffer.Buffer) error { - length, err := readArrayHeader(r) - if err != nil { - return err - } - - type_, err := readType(r) - if err != nil { - return err - } - if type_ != TypeCodeUshort { - return fmt.Errorf("invalid type for []uint16 %02x", type_) - } - - const typeSize = 2 - buf, ok := r.Next(length * typeSize) - if !ok { - return fmt.Errorf("invalid length %d", length) - } - - aa := (*a)[:0] - if int64(cap(aa)) < length { - aa = make([]uint16, length) - } else { - aa = aa[:length] - } - - var bufIdx int - for i := range aa { - aa[i] = binary.BigEndian.Uint16(buf[bufIdx:]) - bufIdx += 2 - } - - *a = aa - return nil -} - -type arrayInt16 []int16 - -func (a arrayInt16) Marshal(wr *buffer.Buffer) error { - const typeSize = 2 - - writeArrayHeader(wr, len(a), typeSize, TypeCodeShort) - - for _, element := range a { - wr.AppendUint16(uint16(element)) - } - - return nil -} - -func (a *arrayInt16) Unmarshal(r *buffer.Buffer) error { - length, err := readArrayHeader(r) - if err != nil { - return err - } - - type_, err := readType(r) - if err != nil { - return err - } - if type_ != TypeCodeShort { - return fmt.Errorf("invalid type for []uint16 %02x", type_) - } - - const typeSize = 2 - buf, ok := r.Next(length * typeSize) - if !ok { - return fmt.Errorf("invalid length %d", length) - } - - aa := (*a)[:0] - if int64(cap(aa)) < length { - aa = make([]int16, length) - } else { - aa = aa[:length] - } - - var bufIdx int - for i := range aa { - aa[i] = int16(binary.BigEndian.Uint16(buf[bufIdx : bufIdx+2])) - bufIdx += 2 - } - - *a = aa - return nil -} - -type arrayUint32 []uint32 - -func (a arrayUint32) Marshal(wr *buffer.Buffer) error { - var ( - typeSize = 1 - TypeCode = TypeCodeSmallUint - ) - for _, n := range a { - if n > math.MaxUint8 { - typeSize = 4 - TypeCode = TypeCodeUint - break - } - } - - writeArrayHeader(wr, len(a), typeSize, TypeCode) - - if TypeCode == TypeCodeUint { - for _, element := range a { - wr.AppendUint32(element) - } - } else { - for _, element := range a { - wr.AppendByte(byte(element)) - } - } - - return nil -} - -func (a *arrayUint32) Unmarshal(r *buffer.Buffer) error { - length, err := readArrayHeader(r) - if err != nil { - return err - } - - aa := (*a)[:0] - - type_, err := readType(r) - if err != nil { - return err - } - switch type_ { - case TypeCodeUint0: - if int64(cap(aa)) < length { - aa = make([]uint32, length) - } else { - aa = aa[:length] - for i := range aa { - aa[i] = 0 - } - } - case TypeCodeSmallUint: - buf, ok := r.Next(length) - if !ok { - return errors.New("invalid length") - } - - if int64(cap(aa)) < length { - aa = make([]uint32, length) - } else { - aa = aa[:length] - } - - for i, n := range buf { - aa[i] = uint32(n) - } - case TypeCodeUint: - const typeSize = 4 - buf, ok := r.Next(length * typeSize) - if !ok { - return fmt.Errorf("invalid length %d", length) - } - - if int64(cap(aa)) < length { - aa = make([]uint32, length) - } else { - aa = aa[:length] - } - - var bufIdx int - for i := range aa { - aa[i] = binary.BigEndian.Uint32(buf[bufIdx : bufIdx+4]) - bufIdx += 4 - } - default: - return fmt.Errorf("invalid type for []uint32 %02x", type_) - } - - *a = aa - return nil -} - -type arrayInt32 []int32 - -func (a arrayInt32) Marshal(wr *buffer.Buffer) error { - var ( - typeSize = 1 - TypeCode = TypeCodeSmallint - ) - for _, n := range a { - if n > math.MaxInt8 { - typeSize = 4 - TypeCode = TypeCodeInt - break - } - } - - writeArrayHeader(wr, len(a), typeSize, TypeCode) - - if TypeCode == TypeCodeInt { - for _, element := range a { - wr.AppendUint32(uint32(element)) - } - } else { - for _, element := range a { - wr.AppendByte(byte(element)) - } - } - - return nil -} - -func (a *arrayInt32) Unmarshal(r *buffer.Buffer) error { - length, err := readArrayHeader(r) - if err != nil { - return err - } - - aa := (*a)[:0] - - type_, err := readType(r) - if err != nil { - return err - } - switch type_ { - case TypeCodeSmallint: - buf, ok := r.Next(length) - if !ok { - return errors.New("invalid length") - } - - if int64(cap(aa)) < length { - aa = make([]int32, length) - } else { - aa = aa[:length] - } - - for i, n := range buf { - aa[i] = int32(int8(n)) - } - case TypeCodeInt: - const typeSize = 4 - buf, ok := r.Next(length * typeSize) - if !ok { - return fmt.Errorf("invalid length %d", length) - } - - if int64(cap(aa)) < length { - aa = make([]int32, length) - } else { - aa = aa[:length] - } - - var bufIdx int - for i := range aa { - aa[i] = int32(binary.BigEndian.Uint32(buf[bufIdx:])) - bufIdx += 4 - } - default: - return fmt.Errorf("invalid type for []int32 %02x", type_) - } - - *a = aa - return nil -} - -type arrayUint64 []uint64 - -func (a arrayUint64) Marshal(wr *buffer.Buffer) error { - var ( - typeSize = 1 - TypeCode = TypeCodeSmallUlong - ) - for _, n := range a { - if n > math.MaxUint8 { - typeSize = 8 - TypeCode = TypeCodeUlong - break - } - } - - writeArrayHeader(wr, len(a), typeSize, TypeCode) - - if TypeCode == TypeCodeUlong { - for _, element := range a { - wr.AppendUint64(element) - } - } else { - for _, element := range a { - wr.AppendByte(byte(element)) - } - } - - return nil -} - -func (a *arrayUint64) Unmarshal(r *buffer.Buffer) error { - length, err := readArrayHeader(r) - if err != nil { - return err - } - - aa := (*a)[:0] - - type_, err := readType(r) - if err != nil { - return err - } - switch type_ { - case TypeCodeUlong0: - if int64(cap(aa)) < length { - aa = make([]uint64, length) - } else { - aa = aa[:length] - for i := range aa { - aa[i] = 0 - } - } - case TypeCodeSmallUlong: - buf, ok := r.Next(length) - if !ok { - return errors.New("invalid length") - } - - if int64(cap(aa)) < length { - aa = make([]uint64, length) - } else { - aa = aa[:length] - } - - for i, n := range buf { - aa[i] = uint64(n) - } - case TypeCodeUlong: - const typeSize = 8 - buf, ok := r.Next(length * typeSize) - if !ok { - return errors.New("invalid length") - } - - if int64(cap(aa)) < length { - aa = make([]uint64, length) - } else { - aa = aa[:length] - } - - var bufIdx int - for i := range aa { - aa[i] = binary.BigEndian.Uint64(buf[bufIdx : bufIdx+8]) - bufIdx += 8 - } - default: - return fmt.Errorf("invalid type for []uint64 %02x", type_) - } - - *a = aa - return nil -} - -type arrayInt64 []int64 - -func (a arrayInt64) Marshal(wr *buffer.Buffer) error { - var ( - typeSize = 1 - TypeCode = TypeCodeSmalllong - ) - for _, n := range a { - if n > math.MaxInt8 { - typeSize = 8 - TypeCode = TypeCodeLong - break - } - } - - writeArrayHeader(wr, len(a), typeSize, TypeCode) - - if TypeCode == TypeCodeLong { - for _, element := range a { - wr.AppendUint64(uint64(element)) - } - } else { - for _, element := range a { - wr.AppendByte(byte(element)) - } - } - - return nil -} - -func (a *arrayInt64) Unmarshal(r *buffer.Buffer) error { - length, err := readArrayHeader(r) - if err != nil { - return err - } - - aa := (*a)[:0] - - type_, err := readType(r) - if err != nil { - return err - } - switch type_ { - case TypeCodeSmalllong: - buf, ok := r.Next(length) - if !ok { - return errors.New("invalid length") - } - - if int64(cap(aa)) < length { - aa = make([]int64, length) - } else { - aa = aa[:length] - } - - for i, n := range buf { - aa[i] = int64(int8(n)) - } - case TypeCodeLong: - const typeSize = 8 - buf, ok := r.Next(length * typeSize) - if !ok { - return errors.New("invalid length") - } - - if int64(cap(aa)) < length { - aa = make([]int64, length) - } else { - aa = aa[:length] - } - - var bufIdx int - for i := range aa { - aa[i] = int64(binary.BigEndian.Uint64(buf[bufIdx:])) - bufIdx += 8 - } - default: - return fmt.Errorf("invalid type for []uint64 %02x", type_) - } - - *a = aa - return nil -} - -type arrayFloat []float32 - -func (a arrayFloat) Marshal(wr *buffer.Buffer) error { - const typeSize = 4 - - writeArrayHeader(wr, len(a), typeSize, TypeCodeFloat) - - for _, element := range a { - wr.AppendUint32(math.Float32bits(element)) - } - - return nil -} - -func (a *arrayFloat) Unmarshal(r *buffer.Buffer) error { - length, err := readArrayHeader(r) - if err != nil { - return err - } - - type_, err := readType(r) - if err != nil { - return err - } - if type_ != TypeCodeFloat { - return fmt.Errorf("invalid type for []float32 %02x", type_) - } - - const typeSize = 4 - buf, ok := r.Next(length * typeSize) - if !ok { - return fmt.Errorf("invalid length %d", length) - } - - aa := (*a)[:0] - if int64(cap(aa)) < length { - aa = make([]float32, length) - } else { - aa = aa[:length] - } - - var bufIdx int - for i := range aa { - bits := binary.BigEndian.Uint32(buf[bufIdx:]) - aa[i] = math.Float32frombits(bits) - bufIdx += typeSize - } - - *a = aa - return nil -} - -type arrayDouble []float64 - -func (a arrayDouble) Marshal(wr *buffer.Buffer) error { - const typeSize = 8 - - writeArrayHeader(wr, len(a), typeSize, TypeCodeDouble) - - for _, element := range a { - wr.AppendUint64(math.Float64bits(element)) - } - - return nil -} - -func (a *arrayDouble) Unmarshal(r *buffer.Buffer) error { - length, err := readArrayHeader(r) - if err != nil { - return err - } - - type_, err := readType(r) - if err != nil { - return err - } - if type_ != TypeCodeDouble { - return fmt.Errorf("invalid type for []float64 %02x", type_) - } - - const typeSize = 8 - buf, ok := r.Next(length * typeSize) - if !ok { - return fmt.Errorf("invalid length %d", length) - } - - aa := (*a)[:0] - if int64(cap(aa)) < length { - aa = make([]float64, length) - } else { - aa = aa[:length] - } - - var bufIdx int - for i := range aa { - bits := binary.BigEndian.Uint64(buf[bufIdx:]) - aa[i] = math.Float64frombits(bits) - bufIdx += typeSize - } - - *a = aa - return nil -} - -type arrayBool []bool - -func (a arrayBool) Marshal(wr *buffer.Buffer) error { - const typeSize = 1 - - writeArrayHeader(wr, len(a), typeSize, TypeCodeBool) - - for _, element := range a { - value := byte(0) - if element { - value = 1 - } - wr.AppendByte(value) - } - - return nil -} - -func (a *arrayBool) Unmarshal(r *buffer.Buffer) error { - length, err := readArrayHeader(r) - if err != nil { - return err - } - - aa := (*a)[:0] - if int64(cap(aa)) < length { - aa = make([]bool, length) - } else { - aa = aa[:length] - } - - type_, err := readType(r) - if err != nil { - return err - } - switch type_ { - case TypeCodeBool: - buf, ok := r.Next(length) - if !ok { - return errors.New("invalid length") - } - - for i, value := range buf { - if value == 0 { - aa[i] = false - } else { - aa[i] = true - } - } - - case TypeCodeBoolTrue: - for i := range aa { - aa[i] = true - } - case TypeCodeBoolFalse: - for i := range aa { - aa[i] = false - } - default: - return fmt.Errorf("invalid type for []bool %02x", type_) - } - - *a = aa - return nil -} - -type arrayString []string - -func (a arrayString) Marshal(wr *buffer.Buffer) error { - var ( - elementType = TypeCodeStr8 - elementsSizeTotal int - ) - for _, element := range a { - if !utf8.ValidString(element) { - return errors.New("not a valid UTF-8 string") - } - - elementsSizeTotal += len(element) - - if len(element) > math.MaxUint8 { - elementType = TypeCodeStr32 - } - } - - writeVariableArrayHeader(wr, len(a), elementsSizeTotal, elementType) - - if elementType == TypeCodeStr32 { - for _, element := range a { - wr.AppendUint32(uint32(len(element))) - wr.AppendString(element) - } - } else { - for _, element := range a { - wr.AppendByte(byte(len(element))) - wr.AppendString(element) - } - } - - return nil -} - -func (a *arrayString) Unmarshal(r *buffer.Buffer) error { - length, err := readArrayHeader(r) - if err != nil { - return err - } - - const typeSize = 2 // assume all strings are at least 2 bytes - if length*typeSize > int64(r.Len()) { - return fmt.Errorf("invalid length %d", length) - } - - aa := (*a)[:0] - if int64(cap(aa)) < length { - aa = make([]string, length) - } else { - aa = aa[:length] - } - - type_, err := readType(r) - if err != nil { - return err - } - switch type_ { - case TypeCodeStr8: - for i := range aa { - size, err := r.ReadByte() - if err != nil { - return err - } - - buf, ok := r.Next(int64(size)) - if !ok { - return errors.New("invalid length") - } - - aa[i] = string(buf) - } - case TypeCodeStr32: - for i := range aa { - buf, ok := r.Next(4) - if !ok { - return errors.New("invalid length") - } - size := int64(binary.BigEndian.Uint32(buf)) - - buf, ok = r.Next(size) - if !ok { - return errors.New("invalid length") - } - aa[i] = string(buf) - } - default: - return fmt.Errorf("invalid type for []string %02x", type_) - } - - *a = aa - return nil -} - -type arraySymbol []Symbol - -func (a arraySymbol) Marshal(wr *buffer.Buffer) error { - var ( - elementType = TypeCodeSym8 - elementsSizeTotal int - ) - for _, element := range a { - elementsSizeTotal += len(element) - - if len(element) > math.MaxUint8 { - elementType = TypeCodeSym32 - } - } - - writeVariableArrayHeader(wr, len(a), elementsSizeTotal, elementType) - - if elementType == TypeCodeSym32 { - for _, element := range a { - wr.AppendUint32(uint32(len(element))) - wr.AppendString(string(element)) - } - } else { - for _, element := range a { - wr.AppendByte(byte(len(element))) - wr.AppendString(string(element)) - } - } - - return nil -} - -func (a *arraySymbol) Unmarshal(r *buffer.Buffer) error { - length, err := readArrayHeader(r) - if err != nil { - return err - } - - const typeSize = 2 // assume all symbols are at least 2 bytes - if length*typeSize > int64(r.Len()) { - return fmt.Errorf("invalid length %d", length) - } - - aa := (*a)[:0] - if int64(cap(aa)) < length { - aa = make([]Symbol, length) - } else { - aa = aa[:length] - } - - type_, err := readType(r) - if err != nil { - return err - } - switch type_ { - case TypeCodeSym8: - for i := range aa { - size, err := r.ReadByte() - if err != nil { - return err - } - - buf, ok := r.Next(int64(size)) - if !ok { - return errors.New("invalid length") - } - aa[i] = Symbol(buf) - } - case TypeCodeSym32: - for i := range aa { - buf, ok := r.Next(4) - if !ok { - return errors.New("invalid length") - } - size := int64(binary.BigEndian.Uint32(buf)) - - buf, ok = r.Next(size) - if !ok { - return errors.New("invalid length") - } - aa[i] = Symbol(buf) - } - default: - return fmt.Errorf("invalid type for []Symbol %02x", type_) - } - - *a = aa - return nil -} - -type arrayBinary [][]byte - -func (a arrayBinary) Marshal(wr *buffer.Buffer) error { - var ( - elementType = TypeCodeVbin8 - elementsSizeTotal int - ) - for _, element := range a { - elementsSizeTotal += len(element) - - if len(element) > math.MaxUint8 { - elementType = TypeCodeVbin32 - } - } - - writeVariableArrayHeader(wr, len(a), elementsSizeTotal, elementType) - - if elementType == TypeCodeVbin32 { - for _, element := range a { - wr.AppendUint32(uint32(len(element))) - wr.Append(element) - } - } else { - for _, element := range a { - wr.AppendByte(byte(len(element))) - wr.Append(element) - } - } - - return nil -} - -func (a *arrayBinary) Unmarshal(r *buffer.Buffer) error { - length, err := readArrayHeader(r) - if err != nil { - return err - } - - const typeSize = 2 // assume all binary is at least 2 bytes - if length*typeSize > int64(r.Len()) { - return fmt.Errorf("invalid length %d", length) - } - - aa := (*a)[:0] - if int64(cap(aa)) < length { - aa = make([][]byte, length) - } else { - aa = aa[:length] - } - - type_, err := readType(r) - if err != nil { - return err - } - switch type_ { - case TypeCodeVbin8: - for i := range aa { - size, err := r.ReadByte() - if err != nil { - return err - } - - buf, ok := r.Next(int64(size)) - if !ok { - return fmt.Errorf("invalid length %d", length) - } - aa[i] = append([]byte(nil), buf...) - } - case TypeCodeVbin32: - for i := range aa { - buf, ok := r.Next(4) - if !ok { - return errors.New("invalid length") - } - size := binary.BigEndian.Uint32(buf) - - buf, ok = r.Next(int64(size)) - if !ok { - return errors.New("invalid length") - } - aa[i] = append([]byte(nil), buf...) - } - default: - return fmt.Errorf("invalid type for [][]byte %02x", type_) - } - - *a = aa - return nil -} - -type arrayTimestamp []time.Time - -func (a arrayTimestamp) Marshal(wr *buffer.Buffer) error { - const typeSize = 8 - - writeArrayHeader(wr, len(a), typeSize, TypeCodeTimestamp) - - for _, element := range a { - ms := element.UnixNano() / int64(time.Millisecond) - wr.AppendUint64(uint64(ms)) - } - - return nil -} - -func (a *arrayTimestamp) Unmarshal(r *buffer.Buffer) error { - length, err := readArrayHeader(r) - if err != nil { - return err - } - - type_, err := readType(r) - if err != nil { - return err - } - if type_ != TypeCodeTimestamp { - return fmt.Errorf("invalid type for []time.Time %02x", type_) - } - - const typeSize = 8 - buf, ok := r.Next(length * typeSize) - if !ok { - return fmt.Errorf("invalid length %d", length) - } - - aa := (*a)[:0] - if int64(cap(aa)) < length { - aa = make([]time.Time, length) - } else { - aa = aa[:length] - } - - var bufIdx int - for i := range aa { - ms := int64(binary.BigEndian.Uint64(buf[bufIdx:])) - bufIdx += typeSize - aa[i] = time.Unix(ms/1000, (ms%1000)*1000000).UTC() - } - - *a = aa - return nil -} - -type arrayUUID []UUID - -func (a arrayUUID) Marshal(wr *buffer.Buffer) error { - const typeSize = 16 - - writeArrayHeader(wr, len(a), typeSize, TypeCodeUUID) - - for _, element := range a { - wr.Append(element[:]) - } - - return nil -} - -func (a *arrayUUID) Unmarshal(r *buffer.Buffer) error { - length, err := readArrayHeader(r) - if err != nil { - return err - } - - type_, err := readType(r) - if err != nil { - return err - } - if type_ != TypeCodeUUID { - return fmt.Errorf("invalid type for []UUID %#02x", type_) - } - - const typeSize = 16 - buf, ok := r.Next(length * typeSize) - if !ok { - return fmt.Errorf("invalid length %d", length) - } - - aa := (*a)[:0] - if int64(cap(aa)) < length { - aa = make([]UUID, length) - } else { - aa = aa[:length] - } - - var bufIdx int - for i := range aa { - copy(aa[i][:], buf[bufIdx:bufIdx+16]) - bufIdx += 16 - } - - *a = aa - return nil -} - -// LIST - -type list []any - -func (l list) Marshal(wr *buffer.Buffer) error { - length := len(l) - - // type - if length == 0 { - wr.AppendByte(byte(TypeCodeList0)) - return nil - } - wr.AppendByte(byte(TypeCodeList32)) - - // size - sizeIdx := wr.Len() - wr.Append([]byte{0, 0, 0, 0}) - - // length - wr.AppendUint32(uint32(length)) - - for _, element := range l { - err := Marshal(wr, element) - if err != nil { - return err - } - } - - // overwrite size - binary.BigEndian.PutUint32(wr.Bytes()[sizeIdx:], uint32(wr.Len()-(sizeIdx+4))) - - return nil -} - -func (l *list) Unmarshal(r *buffer.Buffer) error { - length, err := readListHeader(r) - if err != nil { - return err - } - - // assume that all types are at least 1 byte - if length > int64(r.Len()) { - return fmt.Errorf("invalid length %d", length) - } - - ll := *l - if int64(cap(ll)) < length { - ll = make([]any, length) - } else { - ll = ll[:length] - } - - for i := range ll { - ll[i], err = ReadAny(r) - if err != nil { - return err - } - } - - *l = ll - return nil -} - -// multiSymbol can decode a single symbol or an array. -type MultiSymbol []Symbol - -func (ms MultiSymbol) Marshal(wr *buffer.Buffer) error { - return Marshal(wr, []Symbol(ms)) -} - -func (ms *MultiSymbol) Unmarshal(r *buffer.Buffer) error { - type_, err := peekType(r) - if err != nil { - return err - } - - if type_ == TypeCodeSym8 || type_ == TypeCodeSym32 { - s, err := ReadString(r) - if err != nil { - return err - } - - *ms = []Symbol{Symbol(s)} - return nil - } - - return Unmarshal(r, (*[]Symbol)(ms)) -} diff --git a/sdk/messaging/azeventhubs/internal/go-amqp/internal/frames/frames.go b/sdk/messaging/azeventhubs/internal/go-amqp/internal/frames/frames.go deleted file mode 100644 index 63491582a85d..000000000000 --- a/sdk/messaging/azeventhubs/internal/go-amqp/internal/frames/frames.go +++ /dev/null @@ -1,1543 +0,0 @@ -// Copyright (C) 2017 Kale Blankenship -// Portions Copyright (c) Microsoft Corporation - -package frames - -import ( - "errors" - "fmt" - "strconv" - "time" - - "github.com/Azure/azure-sdk-for-go/sdk/messaging/azeventhubs/internal/go-amqp/internal/buffer" - "github.com/Azure/azure-sdk-for-go/sdk/messaging/azeventhubs/internal/go-amqp/internal/encoding" -) - -// Type contains the values for a frame's type. -type Type uint8 - -const ( - TypeAMQP Type = 0x0 - TypeSASL Type = 0x1 -) - -// String implements the fmt.Stringer interface for type Type. -func (t Type) String() string { - if t == 0 { - return "AMQP" - } - return "SASL" -} - -/* - - - - - - - - - - - - - - - - -*/ -type Source struct { - // the address of the source - // - // The address of the source MUST NOT be set when sent on a attach frame sent by - // the receiving link endpoint where the dynamic flag is set to true (that is where - // the receiver is requesting the sender to create an addressable node). - // - // The address of the source MUST be set when sent on a attach frame sent by the - // sending link endpoint where the dynamic flag is set to true (that is where the - // sender has created an addressable node at the request of the receiver and is now - // communicating the address of that created node). The generated name of the address - // SHOULD include the link name and the container-id of the remote container to allow - // for ease of identification. - Address string - - // indicates the durability of the terminus - // - // Indicates what state of the terminus will be retained durably: the state of durable - // messages, only existence and configuration of the terminus, or no state at all. - // - // 0: none - // 1: configuration - // 2: unsettled-state - Durable encoding.Durability - - // the expiry policy of the source - // - // link-detach: The expiry timer starts when terminus is detached. - // session-end: The expiry timer starts when the most recently associated session is - // ended. - // connection-close: The expiry timer starts when most recently associated connection - // is closed. - // never: The terminus never expires. - ExpiryPolicy encoding.ExpiryPolicy - - // duration that an expiring source will be retained - // - // The source starts expiring as indicated by the expiry-policy. - Timeout uint32 // seconds - - // request dynamic creation of a remote node - // - // When set to true by the receiving link endpoint, this field constitutes a request - // for the sending peer to dynamically create a node at the source. In this case the - // address field MUST NOT be set. - // - // When set to true by the sending link endpoint this field indicates creation of a - // dynamically created node. In this case the address field will contain the address - // of the created node. The generated address SHOULD include the link name and other - // available information on the initiator of the request (such as the remote - // container-id) in some recognizable form for ease of traceability. - Dynamic bool - - // properties of the dynamically created node - // - // If the dynamic field is not set to true this field MUST be left unset. - // - // When set by the receiving link endpoint, this field contains the desired - // properties of the node the receiver wishes to be created. When set by the - // sending link endpoint this field contains the actual properties of the - // dynamically created node. See subsection 3.5.9 for standard node properties. - // http://www.amqp.org/specification/1.0/node-properties - // - // lifetime-policy: The lifetime of a dynamically generated node. - // Definitionally, the lifetime will never be less than the lifetime - // of the link which caused its creation, however it is possible to - // extend the lifetime of dynamically created node using a lifetime - // policy. The value of this entry MUST be of a type which provides - // the lifetime-policy archetype. The following standard - // lifetime-policies are defined below: delete-on-close, - // delete-on-no-links, delete-on-no-messages or - // delete-on-no-links-or-messages. - // supported-dist-modes: The distribution modes that the node supports. - // The value of this entry MUST be one or more symbols which are valid - // distribution-modes. That is, the value MUST be of the same type as - // would be valid in a field defined with the following attributes: - // type="symbol" multiple="true" requires="distribution-mode" - DynamicNodeProperties map[encoding.Symbol]any // TODO: implement custom type with validation - - // the distribution mode of the link - // - // This field MUST be set by the sending end of the link if the endpoint supports more - // than one distribution-mode. This field MAY be set by the receiving end of the link - // to indicate a preference when a node supports multiple distribution modes. - DistributionMode encoding.Symbol - - // a set of predicates to filter the messages admitted onto the link - // - // The receiving endpoint sets its desired filter, the sending endpoint sets the filter - // actually in place (including any filters defaulted at the node). The receiving - // endpoint MUST check that the filter in place meets its needs and take responsibility - // for detaching if it does not. - Filter encoding.Filter - - // default outcome for unsettled transfers - // - // Indicates the outcome to be used for transfers that have not reached a terminal - // state at the receiver when the transfer is settled, including when the source - // is destroyed. The value MUST be a valid outcome (e.g., released or rejected). - DefaultOutcome any - - // descriptors for the outcomes that can be chosen on this link - // - // The values in this field are the symbolic descriptors of the outcomes that can - // be chosen on this link. This field MAY be empty, indicating that the default-outcome - // will be assumed for all message transfers (if the default-outcome is not set, and no - // outcomes are provided, then the accepted outcome MUST be supported by the source). - // - // When present, the values MUST be a symbolic descriptor of a valid outcome, - // e.g., "amqp:accepted:list". - Outcomes encoding.MultiSymbol - - // the extension capabilities the sender supports/desires - // - // http://www.amqp.org/specification/1.0/source-capabilities - Capabilities encoding.MultiSymbol -} - -func (s *Source) Marshal(wr *buffer.Buffer) error { - return encoding.MarshalComposite(wr, encoding.TypeCodeSource, []encoding.MarshalField{ - {Value: &s.Address, Omit: s.Address == ""}, - {Value: &s.Durable, Omit: s.Durable == encoding.DurabilityNone}, - {Value: &s.ExpiryPolicy, Omit: s.ExpiryPolicy == "" || s.ExpiryPolicy == encoding.ExpirySessionEnd}, - {Value: &s.Timeout, Omit: s.Timeout == 0}, - {Value: &s.Dynamic, Omit: !s.Dynamic}, - {Value: s.DynamicNodeProperties, Omit: len(s.DynamicNodeProperties) == 0}, - {Value: &s.DistributionMode, Omit: s.DistributionMode == ""}, - {Value: s.Filter, Omit: len(s.Filter) == 0}, - {Value: &s.DefaultOutcome, Omit: s.DefaultOutcome == nil}, - {Value: &s.Outcomes, Omit: len(s.Outcomes) == 0}, - {Value: &s.Capabilities, Omit: len(s.Capabilities) == 0}, - }) -} - -func (s *Source) Unmarshal(r *buffer.Buffer) error { - return encoding.UnmarshalComposite(r, encoding.TypeCodeSource, []encoding.UnmarshalField{ - {Field: &s.Address}, - {Field: &s.Durable}, - {Field: &s.ExpiryPolicy, HandleNull: func() error { s.ExpiryPolicy = encoding.ExpirySessionEnd; return nil }}, - {Field: &s.Timeout}, - {Field: &s.Dynamic}, - {Field: &s.DynamicNodeProperties}, - {Field: &s.DistributionMode}, - {Field: &s.Filter}, - {Field: &s.DefaultOutcome}, - {Field: &s.Outcomes}, - {Field: &s.Capabilities}, - }...) -} - -func (s Source) String() string { - return fmt.Sprintf("source{Address: %s, Durable: %d, ExpiryPolicy: %s, Timeout: %d, "+ - "Dynamic: %t, DynamicNodeProperties: %v, DistributionMode: %s, Filter: %v, DefaultOutcome: %v "+ - "Outcomes: %v, Capabilities: %v}", - s.Address, - s.Durable, - s.ExpiryPolicy, - s.Timeout, - s.Dynamic, - s.DynamicNodeProperties, - s.DistributionMode, - s.Filter, - s.DefaultOutcome, - s.Outcomes, - s.Capabilities, - ) -} - -/* - - - - - - - - - - - - -*/ -type Target struct { - // the address of the target - // - // The address of the target MUST NOT be set when sent on a attach frame sent by - // the sending link endpoint where the dynamic flag is set to true (that is where - // the sender is requesting the receiver to create an addressable node). - // - // The address of the source MUST be set when sent on a attach frame sent by the - // receiving link endpoint where the dynamic flag is set to true (that is where - // the receiver has created an addressable node at the request of the sender and - // is now communicating the address of that created node). The generated name of - // the address SHOULD include the link name and the container-id of the remote - // container to allow for ease of identification. - Address string - - // indicates the durability of the terminus - // - // Indicates what state of the terminus will be retained durably: the state of durable - // messages, only existence and configuration of the terminus, or no state at all. - // - // 0: none - // 1: configuration - // 2: unsettled-state - Durable encoding.Durability - - // the expiry policy of the target - // - // link-detach: The expiry timer starts when terminus is detached. - // session-end: The expiry timer starts when the most recently associated session is - // ended. - // connection-close: The expiry timer starts when most recently associated connection - // is closed. - // never: The terminus never expires. - ExpiryPolicy encoding.ExpiryPolicy - - // duration that an expiring target will be retained - // - // The target starts expiring as indicated by the expiry-policy. - Timeout uint32 // seconds - - // request dynamic creation of a remote node - // - // When set to true by the sending link endpoint, this field constitutes a request - // for the receiving peer to dynamically create a node at the target. In this case - // the address field MUST NOT be set. - // - // When set to true by the receiving link endpoint this field indicates creation of - // a dynamically created node. In this case the address field will contain the - // address of the created node. The generated address SHOULD include the link name - // and other available information on the initiator of the request (such as the - // remote container-id) in some recognizable form for ease of traceability. - Dynamic bool - - // properties of the dynamically created node - // - // If the dynamic field is not set to true this field MUST be left unset. - // - // When set by the sending link endpoint, this field contains the desired - // properties of the node the sender wishes to be created. When set by the - // receiving link endpoint this field contains the actual properties of the - // dynamically created node. See subsection 3.5.9 for standard node properties. - // http://www.amqp.org/specification/1.0/node-properties - // - // lifetime-policy: The lifetime of a dynamically generated node. - // Definitionally, the lifetime will never be less than the lifetime - // of the link which caused its creation, however it is possible to - // extend the lifetime of dynamically created node using a lifetime - // policy. The value of this entry MUST be of a type which provides - // the lifetime-policy archetype. The following standard - // lifetime-policies are defined below: delete-on-close, - // delete-on-no-links, delete-on-no-messages or - // delete-on-no-links-or-messages. - // supported-dist-modes: The distribution modes that the node supports. - // The value of this entry MUST be one or more symbols which are valid - // distribution-modes. That is, the value MUST be of the same type as - // would be valid in a field defined with the following attributes: - // type="symbol" multiple="true" requires="distribution-mode" - DynamicNodeProperties map[encoding.Symbol]any // TODO: implement custom type with validation - - // the extension capabilities the sender supports/desires - // - // http://www.amqp.org/specification/1.0/target-capabilities - Capabilities encoding.MultiSymbol -} - -func (t *Target) Marshal(wr *buffer.Buffer) error { - return encoding.MarshalComposite(wr, encoding.TypeCodeTarget, []encoding.MarshalField{ - {Value: &t.Address, Omit: t.Address == ""}, - {Value: &t.Durable, Omit: t.Durable == encoding.DurabilityNone}, - {Value: &t.ExpiryPolicy, Omit: t.ExpiryPolicy == "" || t.ExpiryPolicy == encoding.ExpirySessionEnd}, - {Value: &t.Timeout, Omit: t.Timeout == 0}, - {Value: &t.Dynamic, Omit: !t.Dynamic}, - {Value: t.DynamicNodeProperties, Omit: len(t.DynamicNodeProperties) == 0}, - {Value: &t.Capabilities, Omit: len(t.Capabilities) == 0}, - }) -} - -func (t *Target) Unmarshal(r *buffer.Buffer) error { - return encoding.UnmarshalComposite(r, encoding.TypeCodeTarget, []encoding.UnmarshalField{ - {Field: &t.Address}, - {Field: &t.Durable}, - {Field: &t.ExpiryPolicy, HandleNull: func() error { t.ExpiryPolicy = encoding.ExpirySessionEnd; return nil }}, - {Field: &t.Timeout}, - {Field: &t.Dynamic}, - {Field: &t.DynamicNodeProperties}, - {Field: &t.Capabilities}, - }...) -} - -func (t Target) String() string { - return fmt.Sprintf("source{Address: %s, Durable: %d, ExpiryPolicy: %s, Timeout: %d, "+ - "Dynamic: %t, DynamicNodeProperties: %v, Capabilities: %v}", - t.Address, - t.Durable, - t.ExpiryPolicy, - t.Timeout, - t.Dynamic, - t.DynamicNodeProperties, - t.Capabilities, - ) -} - -// frame is the decoded representation of a frame -type Frame struct { - Type Type // AMQP/SASL - Channel uint16 // channel this frame is for - Body FrameBody // body of the frame -} - -// String implements the fmt.Stringer interface for type Frame. -func (f Frame) String() string { - return fmt.Sprintf("Frame{Type: %s, Channel: %d, Body: %s}", f.Type, f.Channel, f.Body) -} - -// frameBody adds some type safety to frame encoding -type FrameBody interface { - frameBody() -} - -/* - - - - - - - - - - - - - -*/ - -type PerformOpen struct { - ContainerID string // required - Hostname string - MaxFrameSize uint32 // default: 4294967295 - ChannelMax uint16 // default: 65535 - IdleTimeout time.Duration // from milliseconds - OutgoingLocales encoding.MultiSymbol - IncomingLocales encoding.MultiSymbol - OfferedCapabilities encoding.MultiSymbol - DesiredCapabilities encoding.MultiSymbol - Properties map[encoding.Symbol]any -} - -func (o *PerformOpen) frameBody() {} - -func (o *PerformOpen) Marshal(wr *buffer.Buffer) error { - return encoding.MarshalComposite(wr, encoding.TypeCodeOpen, []encoding.MarshalField{ - {Value: &o.ContainerID, Omit: false}, - {Value: &o.Hostname, Omit: o.Hostname == ""}, - {Value: &o.MaxFrameSize, Omit: o.MaxFrameSize == 4294967295}, - {Value: &o.ChannelMax, Omit: o.ChannelMax == 65535}, - {Value: (*encoding.Milliseconds)(&o.IdleTimeout), Omit: o.IdleTimeout == 0}, - {Value: &o.OutgoingLocales, Omit: len(o.OutgoingLocales) == 0}, - {Value: &o.IncomingLocales, Omit: len(o.IncomingLocales) == 0}, - {Value: &o.OfferedCapabilities, Omit: len(o.OfferedCapabilities) == 0}, - {Value: &o.DesiredCapabilities, Omit: len(o.DesiredCapabilities) == 0}, - {Value: o.Properties, Omit: len(o.Properties) == 0}, - }) -} - -func (o *PerformOpen) Unmarshal(r *buffer.Buffer) error { - return encoding.UnmarshalComposite(r, encoding.TypeCodeOpen, []encoding.UnmarshalField{ - {Field: &o.ContainerID, HandleNull: func() error { return errors.New("Open.ContainerID is required") }}, - {Field: &o.Hostname}, - {Field: &o.MaxFrameSize, HandleNull: func() error { o.MaxFrameSize = 4294967295; return nil }}, - {Field: &o.ChannelMax, HandleNull: func() error { o.ChannelMax = 65535; return nil }}, - {Field: (*encoding.Milliseconds)(&o.IdleTimeout)}, - {Field: &o.OutgoingLocales}, - {Field: &o.IncomingLocales}, - {Field: &o.OfferedCapabilities}, - {Field: &o.DesiredCapabilities}, - {Field: &o.Properties}, - }...) -} - -func (o *PerformOpen) String() string { - return fmt.Sprintf("Open{ContainerID : %s, Hostname: %s, MaxFrameSize: %d, "+ - "ChannelMax: %d, IdleTimeout: %v, "+ - "OutgoingLocales: %v, IncomingLocales: %v, "+ - "OfferedCapabilities: %v, DesiredCapabilities: %v, "+ - "Properties: %v}", - o.ContainerID, - o.Hostname, - o.MaxFrameSize, - o.ChannelMax, - o.IdleTimeout, - o.OutgoingLocales, - o.IncomingLocales, - o.OfferedCapabilities, - o.DesiredCapabilities, - o.Properties, - ) -} - -/* - - - - - - - - - - - - - -*/ -type PerformBegin struct { - // the remote channel for this session - // If a session is locally initiated, the remote-channel MUST NOT be set. - // When an endpoint responds to a remotely initiated session, the remote-channel - // MUST be set to the channel on which the remote session sent the begin. - RemoteChannel *uint16 - - // the transfer-id of the first transfer id the sender will send - NextOutgoingID uint32 // required, sequence number http://www.ietf.org/rfc/rfc1982.txt - - // the initial incoming-window of the sender - IncomingWindow uint32 // required - - // the initial outgoing-window of the sender - OutgoingWindow uint32 // required - - // the maximum handle value that can be used on the session - // The handle-max value is the highest handle value that can be - // used on the session. A peer MUST NOT attempt to attach a link - // using a handle value outside the range that its partner can handle. - // A peer that receives a handle outside the supported range MUST - // close the connection with the framing-error error-code. - HandleMax uint32 // default 4294967295 - - // the extension capabilities the sender supports - // http://www.amqp.org/specification/1.0/session-capabilities - OfferedCapabilities encoding.MultiSymbol - - // the extension capabilities the sender can use if the receiver supports them - // The sender MUST NOT attempt to use any capability other than those it - // has declared in desired-capabilities field. - DesiredCapabilities encoding.MultiSymbol - - // session properties - // http://www.amqp.org/specification/1.0/session-properties - Properties map[encoding.Symbol]any -} - -func (b *PerformBegin) frameBody() {} - -func (b *PerformBegin) String() string { - return fmt.Sprintf("Begin{RemoteChannel: %v, NextOutgoingID: %d, IncomingWindow: %d, "+ - "OutgoingWindow: %d, HandleMax: %d, OfferedCapabilities: %v, DesiredCapabilities: %v, "+ - "Properties: %v}", - formatUint16Ptr(b.RemoteChannel), - b.NextOutgoingID, - b.IncomingWindow, - b.OutgoingWindow, - b.HandleMax, - b.OfferedCapabilities, - b.DesiredCapabilities, - b.Properties, - ) -} - -func formatUint16Ptr(p *uint16) string { - if p == nil { - return "" - } - return strconv.FormatUint(uint64(*p), 10) -} - -func (b *PerformBegin) Marshal(wr *buffer.Buffer) error { - return encoding.MarshalComposite(wr, encoding.TypeCodeBegin, []encoding.MarshalField{ - {Value: b.RemoteChannel, Omit: b.RemoteChannel == nil}, - {Value: &b.NextOutgoingID, Omit: false}, - {Value: &b.IncomingWindow, Omit: false}, - {Value: &b.OutgoingWindow, Omit: false}, - {Value: &b.HandleMax, Omit: b.HandleMax == 4294967295}, - {Value: &b.OfferedCapabilities, Omit: len(b.OfferedCapabilities) == 0}, - {Value: &b.DesiredCapabilities, Omit: len(b.DesiredCapabilities) == 0}, - {Value: b.Properties, Omit: b.Properties == nil}, - }) -} - -func (b *PerformBegin) Unmarshal(r *buffer.Buffer) error { - return encoding.UnmarshalComposite(r, encoding.TypeCodeBegin, []encoding.UnmarshalField{ - {Field: &b.RemoteChannel}, - {Field: &b.NextOutgoingID, HandleNull: func() error { return errors.New("Begin.NextOutgoingID is required") }}, - {Field: &b.IncomingWindow, HandleNull: func() error { return errors.New("Begin.IncomingWindow is required") }}, - {Field: &b.OutgoingWindow, HandleNull: func() error { return errors.New("Begin.OutgoingWindow is required") }}, - {Field: &b.HandleMax, HandleNull: func() error { b.HandleMax = 4294967295; return nil }}, - {Field: &b.OfferedCapabilities}, - {Field: &b.DesiredCapabilities}, - {Field: &b.Properties}, - }...) -} - -/* - - - - - - - - - - - - - - - - - - - -*/ -type PerformAttach struct { - // the name of the link - // - // This name uniquely identifies the link from the container of the source - // to the container of the target node, e.g., if the container of the source - // node is A, and the container of the target node is B, the link MAY be - // globally identified by the (ordered) tuple (A,B,). - Name string // required - - // the handle for the link while attached - // - // The numeric handle assigned by the the peer as a shorthand to refer to the - // link in all performatives that reference the link until the it is detached. - // - // The handle MUST NOT be used for other open links. An attempt to attach using - // a handle which is already associated with a link MUST be responded to with - // an immediate close carrying a handle-in-use session-error. - // - // To make it easier to monitor AMQP link attach frames, it is RECOMMENDED that - // implementations always assign the lowest available handle to this field. - // - // The two endpoints MAY potentially use different handles to refer to the same link. - // Link handles MAY be reused once a link is closed for both send and receive. - Handle uint32 // required - - // role of the link endpoint - // - // The role being played by the peer, i.e., whether the peer is the sender or the - // receiver of messages on the link. - Role encoding.Role - - // settlement policy for the sender - // - // The delivery settlement policy for the sender. When set at the receiver this - // indicates the desired value for the settlement mode at the sender. When set - // at the sender this indicates the actual settlement mode in use. The sender - // SHOULD respect the receiver's desired settlement mode if the receiver initiates - // the attach exchange and the sender supports the desired mode. - // - // 0: unsettled - The sender will send all deliveries initially unsettled to the receiver. - // 1: settled - The sender will send all deliveries settled to the receiver. - // 2: mixed - The sender MAY send a mixture of settled and unsettled deliveries to the receiver. - SenderSettleMode *encoding.SenderSettleMode - - // the settlement policy of the receiver - // - // The delivery settlement policy for the receiver. When set at the sender this - // indicates the desired value for the settlement mode at the receiver. - // When set at the receiver this indicates the actual settlement mode in use. - // The receiver SHOULD respect the sender's desired settlement mode if the sender - // initiates the attach exchange and the receiver supports the desired mode. - // - // 0: first - The receiver will spontaneously settle all incoming transfers. - // 1: second - The receiver will only settle after sending the disposition to - // the sender and receiving a disposition indicating settlement of - // the delivery from the sender. - ReceiverSettleMode *encoding.ReceiverSettleMode - - // the source for messages - // - // If no source is specified on an outgoing link, then there is no source currently - // attached to the link. A link with no source will never produce outgoing messages. - Source *Source - - // the target for messages - // - // If no target is specified on an incoming link, then there is no target currently - // attached to the link. A link with no target will never permit incoming messages. - Target *Target - - // unsettled delivery state - // - // This is used to indicate any unsettled delivery states when a suspended link is - // resumed. The map is keyed by delivery-tag with values indicating the delivery state. - // The local and remote delivery states for a given delivery-tag MUST be compared to - // resolve any in-doubt deliveries. If necessary, deliveries MAY be resent, or resumed - // based on the outcome of this comparison. See subsection 2.6.13. - // - // If the local unsettled map is too large to be encoded within a frame of the agreed - // maximum frame size then the session MAY be ended with the frame-size-too-small error. - // The endpoint SHOULD make use of the ability to send an incomplete unsettled map - // (see below) to avoid sending an error. - // - // The unsettled map MUST NOT contain null valued keys. - // - // When reattaching (as opposed to resuming), the unsettled map MUST be null. - Unsettled encoding.Unsettled - - // If set to true this field indicates that the unsettled map provided is not complete. - // When the map is incomplete the recipient of the map cannot take the absence of a - // delivery tag from the map as evidence of settlement. On receipt of an incomplete - // unsettled map a sending endpoint MUST NOT send any new deliveries (i.e. deliveries - // where resume is not set to true) to its partner (and a receiving endpoint which sent - // an incomplete unsettled map MUST detach with an error on receiving a transfer which - // does not have the resume flag set to true). - // - // Note that if this flag is set to true then the endpoints MUST detach and reattach at - // least once in order to send new deliveries. This flag can be useful when there are - // too many entries in the unsettled map to fit within a single frame. An endpoint can - // attach, resume, settle, and detach until enough unsettled state has been cleared for - // an attach where this flag is set to false. - IncompleteUnsettled bool // default: false - - // the sender's initial value for delivery-count - // - // This MUST NOT be null if role is sender, and it is ignored if the role is receiver. - InitialDeliveryCount uint32 // sequence number - - // the maximum message size supported by the link endpoint - // - // This field indicates the maximum message size supported by the link endpoint. - // Any attempt to deliver a message larger than this results in a message-size-exceeded - // link-error. If this field is zero or unset, there is no maximum size imposed by the - // link endpoint. - MaxMessageSize uint64 - - // the extension capabilities the sender supports - // http://www.amqp.org/specification/1.0/link-capabilities - OfferedCapabilities encoding.MultiSymbol - - // the extension capabilities the sender can use if the receiver supports them - // - // The sender MUST NOT attempt to use any capability other than those it - // has declared in desired-capabilities field. - DesiredCapabilities encoding.MultiSymbol - - // link properties - // http://www.amqp.org/specification/1.0/link-properties - Properties map[encoding.Symbol]any -} - -func (a *PerformAttach) frameBody() {} - -func (a PerformAttach) String() string { - return fmt.Sprintf("Attach{Name: %s, Handle: %d, Role: %s, SenderSettleMode: %s, ReceiverSettleMode: %s, "+ - "Source: %v, Target: %v, Unsettled: %v, IncompleteUnsettled: %t, InitialDeliveryCount: %d, MaxMessageSize: %d, "+ - "OfferedCapabilities: %v, DesiredCapabilities: %v, Properties: %v}", - a.Name, - a.Handle, - a.Role, - a.SenderSettleMode, - a.ReceiverSettleMode, - a.Source, - a.Target, - a.Unsettled, - a.IncompleteUnsettled, - a.InitialDeliveryCount, - a.MaxMessageSize, - a.OfferedCapabilities, - a.DesiredCapabilities, - a.Properties, - ) -} - -func (a *PerformAttach) Marshal(wr *buffer.Buffer) error { - return encoding.MarshalComposite(wr, encoding.TypeCodeAttach, []encoding.MarshalField{ - {Value: &a.Name, Omit: false}, - {Value: &a.Handle, Omit: false}, - {Value: &a.Role, Omit: false}, - {Value: a.SenderSettleMode, Omit: a.SenderSettleMode == nil}, - {Value: a.ReceiverSettleMode, Omit: a.ReceiverSettleMode == nil}, - {Value: a.Source, Omit: a.Source == nil}, - {Value: a.Target, Omit: a.Target == nil}, - {Value: a.Unsettled, Omit: len(a.Unsettled) == 0}, - {Value: &a.IncompleteUnsettled, Omit: !a.IncompleteUnsettled}, - {Value: &a.InitialDeliveryCount, Omit: a.Role == encoding.RoleReceiver}, - {Value: &a.MaxMessageSize, Omit: a.MaxMessageSize == 0}, - {Value: &a.OfferedCapabilities, Omit: len(a.OfferedCapabilities) == 0}, - {Value: &a.DesiredCapabilities, Omit: len(a.DesiredCapabilities) == 0}, - {Value: a.Properties, Omit: len(a.Properties) == 0}, - }) -} - -func (a *PerformAttach) Unmarshal(r *buffer.Buffer) error { - return encoding.UnmarshalComposite(r, encoding.TypeCodeAttach, []encoding.UnmarshalField{ - {Field: &a.Name, HandleNull: func() error { return errors.New("Attach.Name is required") }}, - {Field: &a.Handle, HandleNull: func() error { return errors.New("Attach.Handle is required") }}, - {Field: &a.Role, HandleNull: func() error { return errors.New("Attach.Role is required") }}, - {Field: &a.SenderSettleMode}, - {Field: &a.ReceiverSettleMode}, - {Field: &a.Source}, - {Field: &a.Target}, - {Field: &a.Unsettled}, - {Field: &a.IncompleteUnsettled}, - {Field: &a.InitialDeliveryCount}, - {Field: &a.MaxMessageSize}, - {Field: &a.OfferedCapabilities}, - {Field: &a.DesiredCapabilities}, - {Field: &a.Properties}, - }...) -} - -/* - - - - - - - - - - - - - - - - -*/ -type PerformFlow struct { - // Identifies the expected transfer-id of the next incoming transfer frame. - // This value MUST be set if the peer has received the begin frame for the - // session, and MUST NOT be set if it has not. See subsection 2.5.6 for more details. - NextIncomingID *uint32 // sequence number - - // Defines the maximum number of incoming transfer frames that the endpoint - // can currently receive. See subsection 2.5.6 for more details. - IncomingWindow uint32 // required - - // The transfer-id that will be assigned to the next outgoing transfer frame. - // See subsection 2.5.6 for more details. - NextOutgoingID uint32 // sequence number - - // Defines the maximum number of outgoing transfer frames that the endpoint - // could potentially currently send, if it was not constrained by restrictions - // imposed by its peer's incoming-window. See subsection 2.5.6 for more details. - OutgoingWindow uint32 - - // If set, indicates that the flow frame carries flow state information for the local - // link endpoint associated with the given handle. If not set, the flow frame is - // carrying only information pertaining to the session endpoint. - // - // If set to a handle that is not currently associated with an attached link, - // the recipient MUST respond by ending the session with an unattached-handle - // session error. - Handle *uint32 - - // The delivery-count is initialized by the sender when a link endpoint is created, - // and is incremented whenever a message is sent. Only the sender MAY independently - // modify this field. The receiver's value is calculated based on the last known - // value from the sender and any subsequent messages received on the link. Note that, - // despite its name, the delivery-count is not a count but a sequence number - // initialized at an arbitrary point by the sender. - // - // When the handle field is not set, this field MUST NOT be set. - // - // When the handle identifies that the flow state is being sent from the sender link - // endpoint to receiver link endpoint this field MUST be set to the current - // delivery-count of the link endpoint. - // - // When the flow state is being sent from the receiver endpoint to the sender endpoint - // this field MUST be set to the last known value of the corresponding sending endpoint. - // In the event that the receiving link endpoint has not yet seen the initial attach - // frame from the sender this field MUST NOT be set. - DeliveryCount *uint32 // sequence number - - // the current maximum number of messages that can be received - // - // The current maximum number of messages that can be handled at the receiver endpoint - // of the link. Only the receiver endpoint can independently set this value. The sender - // endpoint sets this to the last known value seen from the receiver. - // See subsection 2.6.7 for more details. - // - // When the handle field is not set, this field MUST NOT be set. - LinkCredit *uint32 - - // the number of available messages - // - // The number of messages awaiting credit at the link sender endpoint. Only the sender - // can independently set this value. The receiver sets this to the last known value seen - // from the sender. See subsection 2.6.7 for more details. - // - // When the handle field is not set, this field MUST NOT be set. - Available *uint32 - - // indicates drain mode - // - // When flow state is sent from the sender to the receiver, this field contains the - // actual drain mode of the sender. When flow state is sent from the receiver to the - // sender, this field contains the desired drain mode of the receiver. - // See subsection 2.6.7 for more details. - // - // When the handle field is not set, this field MUST NOT be set. - Drain bool - - // request state from partner - // - // If set to true then the receiver SHOULD send its state at the earliest convenient - // opportunity. - // - // If set to true, and the handle field is not set, then the sender only requires - // session endpoint state to be echoed, however, the receiver MAY fulfil this requirement - // by sending a flow performative carrying link-specific state (since any such flow also - // carries session state). - // - // If a sender makes multiple requests for the same state before the receiver can reply, - // the receiver MAY send only one flow in return. - // - // Note that if a peer responds to echo requests with flows which themselves have the - // echo field set to true, an infinite loop could result if its partner adopts the same - // policy (therefore such a policy SHOULD be avoided). - Echo bool - - // link state properties - // http://www.amqp.org/specification/1.0/link-state-properties - Properties map[encoding.Symbol]any -} - -func (f *PerformFlow) frameBody() {} - -func (f *PerformFlow) String() string { - return fmt.Sprintf("Flow{NextIncomingID: %s, IncomingWindow: %d, NextOutgoingID: %d, OutgoingWindow: %d, "+ - "Handle: %s, DeliveryCount: %s, LinkCredit: %s, Available: %s, Drain: %t, Echo: %t, Properties: %+v}", - formatUint32Ptr(f.NextIncomingID), - f.IncomingWindow, - f.NextOutgoingID, - f.OutgoingWindow, - formatUint32Ptr(f.Handle), - formatUint32Ptr(f.DeliveryCount), - formatUint32Ptr(f.LinkCredit), - formatUint32Ptr(f.Available), - f.Drain, - f.Echo, - f.Properties, - ) -} - -func formatUint32Ptr(p *uint32) string { - if p == nil { - return "" - } - return strconv.FormatUint(uint64(*p), 10) -} - -func (f *PerformFlow) Marshal(wr *buffer.Buffer) error { - return encoding.MarshalComposite(wr, encoding.TypeCodeFlow, []encoding.MarshalField{ - {Value: f.NextIncomingID, Omit: f.NextIncomingID == nil}, - {Value: &f.IncomingWindow, Omit: false}, - {Value: &f.NextOutgoingID, Omit: false}, - {Value: &f.OutgoingWindow, Omit: false}, - {Value: f.Handle, Omit: f.Handle == nil}, - {Value: f.DeliveryCount, Omit: f.DeliveryCount == nil}, - {Value: f.LinkCredit, Omit: f.LinkCredit == nil}, - {Value: f.Available, Omit: f.Available == nil}, - {Value: &f.Drain, Omit: !f.Drain}, - {Value: &f.Echo, Omit: !f.Echo}, - {Value: f.Properties, Omit: len(f.Properties) == 0}, - }) -} - -func (f *PerformFlow) Unmarshal(r *buffer.Buffer) error { - return encoding.UnmarshalComposite(r, encoding.TypeCodeFlow, []encoding.UnmarshalField{ - {Field: &f.NextIncomingID}, - {Field: &f.IncomingWindow, HandleNull: func() error { return errors.New("Flow.IncomingWindow is required") }}, - {Field: &f.NextOutgoingID, HandleNull: func() error { return errors.New("Flow.NextOutgoingID is required") }}, - {Field: &f.OutgoingWindow, HandleNull: func() error { return errors.New("Flow.OutgoingWindow is required") }}, - {Field: &f.Handle}, - {Field: &f.DeliveryCount}, - {Field: &f.LinkCredit}, - {Field: &f.Available}, - {Field: &f.Drain}, - {Field: &f.Echo}, - {Field: &f.Properties}, - }...) -} - -/* - - - - - - - - - - - - - - - - -*/ -type PerformTransfer struct { - // Specifies the link on which the message is transferred. - Handle uint32 // required - - // The delivery-id MUST be supplied on the first transfer of a multi-transfer - // delivery. On continuation transfers the delivery-id MAY be omitted. It is - // an error if the delivery-id on a continuation transfer differs from the - // delivery-id on the first transfer of a delivery. - DeliveryID *uint32 // sequence number - - // Uniquely identifies the delivery attempt for a given message on this link. - // This field MUST be specified for the first transfer of a multi-transfer - // message and can only be omitted for continuation transfers. It is an error - // if the delivery-tag on a continuation transfer differs from the delivery-tag - // on the first transfer of a delivery. - DeliveryTag []byte // up to 32 bytes - - // This field MUST be specified for the first transfer of a multi-transfer message - // and can only be omitted for continuation transfers. It is an error if the - // message-format on a continuation transfer differs from the message-format on - // the first transfer of a delivery. - // - // The upper three octets of a message format code identify a particular message - // format. The lowest octet indicates the version of said message format. Any given - // version of a format is forwards compatible with all higher versions. - MessageFormat *uint32 - - // If not set on the first (or only) transfer for a (multi-transfer) delivery, - // then the settled flag MUST be interpreted as being false. For subsequent - // transfers in a multi-transfer delivery if the settled flag is left unset then - // it MUST be interpreted as true if and only if the value of the settled flag on - // any of the preceding transfers was true; if no preceding transfer was sent with - // settled being true then the value when unset MUST be taken as false. - // - // If the negotiated value for snd-settle-mode at attachment is settled, then this - // field MUST be true on at least one transfer frame for a delivery (i.e., the - // delivery MUST be settled at the sender at the point the delivery has been - // completely transferred). - // - // If the negotiated value for snd-settle-mode at attachment is unsettled, then this - // field MUST be false (or unset) on every transfer frame for a delivery (unless the - // delivery is aborted). - Settled bool - - // indicates that the message has more content - // - // Note that if both the more and aborted fields are set to true, the aborted flag - // takes precedence. That is, a receiver SHOULD ignore the value of the more field - // if the transfer is marked as aborted. A sender SHOULD NOT set the more flag to - // true if it also sets the aborted flag to true. - More bool - - // If first, this indicates that the receiver MUST settle the delivery once it has - // arrived without waiting for the sender to settle first. - // - // If second, this indicates that the receiver MUST NOT settle until sending its - // disposition to the sender and receiving a settled disposition from the sender. - // - // If not set, this value is defaulted to the value negotiated on link attach. - // - // If the negotiated link value is first, then it is illegal to set this field - // to second. - // - // If the message is being sent settled by the sender, the value of this field - // is ignored. - // - // The (implicit or explicit) value of this field does not form part of the - // transfer state, and is not retained if a link is suspended and subsequently resumed. - // - // 0: first - The receiver will spontaneously settle all incoming transfers. - // 1: second - The receiver will only settle after sending the disposition to - // the sender and receiving a disposition indicating settlement of - // the delivery from the sender. - ReceiverSettleMode *encoding.ReceiverSettleMode - - // the state of the delivery at the sender - // - // When set this informs the receiver of the state of the delivery at the sender. - // This is particularly useful when transfers of unsettled deliveries are resumed - // after resuming a link. Setting the state on the transfer can be thought of as - // being equivalent to sending a disposition immediately before the transfer - // performative, i.e., it is the state of the delivery (not the transfer) that - // existed at the point the frame was sent. - // - // Note that if the transfer performative (or an earlier disposition performative - // referring to the delivery) indicates that the delivery has attained a terminal - // state, then no future transfer or disposition sent by the sender can alter that - // terminal state. - State encoding.DeliveryState - - // indicates a resumed delivery - // - // If true, the resume flag indicates that the transfer is being used to reassociate - // an unsettled delivery from a dissociated link endpoint. See subsection 2.6.13 - // for more details. - // - // The receiver MUST ignore resumed deliveries that are not in its local unsettled map. - // The sender MUST NOT send resumed transfers for deliveries not in its local - // unsettled map. - // - // If a resumed delivery spans more than one transfer performative, then the resume - // flag MUST be set to true on the first transfer of the resumed delivery. For - // subsequent transfers for the same delivery the resume flag MAY be set to true, - // or MAY be omitted. - // - // In the case where the exchange of unsettled maps makes clear that all message - // data has been successfully transferred to the receiver, and that only the final - // state (and potentially settlement) at the sender needs to be conveyed, then a - // resumed delivery MAY carry no payload and instead act solely as a vehicle for - // carrying the terminal state of the delivery at the sender. - Resume bool - - // indicates that the message is aborted - // - // Aborted messages SHOULD be discarded by the recipient (any payload within the - // frame carrying the performative MUST be ignored). An aborted message is - // implicitly settled. - Aborted bool - - // batchable hint - // - // If true, then the issuer is hinting that there is no need for the peer to urgently - // communicate updated delivery state. This hint MAY be used to artificially increase - // the amount of batching an implementation uses when communicating delivery states, - // and thereby save bandwidth. - // - // If the message being delivered is too large to fit within a single frame, then the - // setting of batchable to true on any of the transfer performatives for the delivery - // is equivalent to setting batchable to true for all the transfer performatives for - // the delivery. - // - // The batchable value does not form part of the transfer state, and is not retained - // if a link is suspended and subsequently resumed. - Batchable bool - - Payload []byte - - // optional channel to indicate to sender that transfer has completed - // - // Settled=true: closed when the transferred on network. - // Settled=false: closed when the receiver has confirmed settlement. - Done chan encoding.DeliveryState -} - -func (t *PerformTransfer) frameBody() {} - -func (t PerformTransfer) String() string { - deliveryTag := "" - if t.DeliveryTag != nil { - deliveryTag = fmt.Sprintf("%X", t.DeliveryTag) - } - - return fmt.Sprintf("Transfer{Handle: %d, DeliveryID: %s, DeliveryTag: %s, MessageFormat: %s, "+ - "Settled: %t, More: %t, ReceiverSettleMode: %s, State: %v, Resume: %t, Aborted: %t, "+ - "Batchable: %t, Payload [size]: %d}", - t.Handle, - formatUint32Ptr(t.DeliveryID), - deliveryTag, - formatUint32Ptr(t.MessageFormat), - t.Settled, - t.More, - t.ReceiverSettleMode, - t.State, - t.Resume, - t.Aborted, - t.Batchable, - len(t.Payload), - ) -} - -func (t *PerformTransfer) Marshal(wr *buffer.Buffer) error { - err := encoding.MarshalComposite(wr, encoding.TypeCodeTransfer, []encoding.MarshalField{ - {Value: &t.Handle}, - {Value: t.DeliveryID, Omit: t.DeliveryID == nil}, - {Value: &t.DeliveryTag, Omit: len(t.DeliveryTag) == 0}, - {Value: t.MessageFormat, Omit: t.MessageFormat == nil}, - {Value: &t.Settled, Omit: !t.Settled}, - {Value: &t.More, Omit: !t.More}, - {Value: t.ReceiverSettleMode, Omit: t.ReceiverSettleMode == nil}, - {Value: t.State, Omit: t.State == nil}, - {Value: &t.Resume, Omit: !t.Resume}, - {Value: &t.Aborted, Omit: !t.Aborted}, - {Value: &t.Batchable, Omit: !t.Batchable}, - }) - if err != nil { - return err - } - - wr.Append(t.Payload) - return nil -} - -func (t *PerformTransfer) Unmarshal(r *buffer.Buffer) error { - err := encoding.UnmarshalComposite(r, encoding.TypeCodeTransfer, []encoding.UnmarshalField{ - {Field: &t.Handle, HandleNull: func() error { return errors.New("Transfer.Handle is required") }}, - {Field: &t.DeliveryID}, - {Field: &t.DeliveryTag}, - {Field: &t.MessageFormat}, - {Field: &t.Settled}, - {Field: &t.More}, - {Field: &t.ReceiverSettleMode}, - {Field: &t.State}, - {Field: &t.Resume}, - {Field: &t.Aborted}, - {Field: &t.Batchable}, - }...) - if err != nil { - return err - } - - t.Payload = append([]byte(nil), r.Bytes()...) - - return err -} - -/* - - - - - - - - - - - -*/ -type PerformDisposition struct { - // directionality of disposition - // - // The role identifies whether the disposition frame contains information about - // sending link endpoints or receiving link endpoints. - Role encoding.Role - - // lower bound of deliveries - // - // Identifies the lower bound of delivery-ids for the deliveries in this set. - First uint32 // required, sequence number - - // upper bound of deliveries - // - // Identifies the upper bound of delivery-ids for the deliveries in this set. - // If not set, this is taken to be the same as first. - Last *uint32 // sequence number - - // indicates deliveries are settled - // - // If true, indicates that the referenced deliveries are considered settled by - // the issuing endpoint. - Settled bool - - // indicates state of deliveries - // - // Communicates the state of all the deliveries referenced by this disposition. - State encoding.DeliveryState - - // batchable hint - // - // If true, then the issuer is hinting that there is no need for the peer to - // urgently communicate the impact of the updated delivery states. This hint - // MAY be used to artificially increase the amount of batching an implementation - // uses when communicating delivery states, and thereby save bandwidth. - Batchable bool -} - -func (d *PerformDisposition) frameBody() {} - -func (d PerformDisposition) String() string { - return fmt.Sprintf("Disposition{Role: %s, First: %d, Last: %s, Settled: %t, State: %v, Batchable: %t}", - d.Role, - d.First, - formatUint32Ptr(d.Last), - d.Settled, - d.State, - d.Batchable, - ) -} - -func (d *PerformDisposition) Marshal(wr *buffer.Buffer) error { - return encoding.MarshalComposite(wr, encoding.TypeCodeDisposition, []encoding.MarshalField{ - {Value: &d.Role, Omit: false}, - {Value: &d.First, Omit: false}, - {Value: d.Last, Omit: d.Last == nil}, - {Value: &d.Settled, Omit: !d.Settled}, - {Value: d.State, Omit: d.State == nil}, - {Value: &d.Batchable, Omit: !d.Batchable}, - }) -} - -func (d *PerformDisposition) Unmarshal(r *buffer.Buffer) error { - return encoding.UnmarshalComposite(r, encoding.TypeCodeDisposition, []encoding.UnmarshalField{ - {Field: &d.Role, HandleNull: func() error { return errors.New("Disposition.Role is required") }}, - {Field: &d.First, HandleNull: func() error { return errors.New("Disposition.Handle is required") }}, - {Field: &d.Last}, - {Field: &d.Settled}, - {Field: &d.State}, - {Field: &d.Batchable}, - }...) -} - -/* - - - - - - - - -*/ -type PerformDetach struct { - // the local handle of the link to be detached - Handle uint32 //required - - // if true then the sender has closed the link - Closed bool - - // error causing the detach - // - // If set, this field indicates that the link is being detached due to an error - // condition. The value of the field SHOULD contain details on the cause of the error. - Error *encoding.Error -} - -func (d *PerformDetach) frameBody() {} - -func (d PerformDetach) String() string { - return fmt.Sprintf("Detach{Handle: %d, Closed: %t, Error: %v}", - d.Handle, - d.Closed, - d.Error, - ) -} - -func (d *PerformDetach) Marshal(wr *buffer.Buffer) error { - return encoding.MarshalComposite(wr, encoding.TypeCodeDetach, []encoding.MarshalField{ - {Value: &d.Handle, Omit: false}, - {Value: &d.Closed, Omit: !d.Closed}, - {Value: d.Error, Omit: d.Error == nil}, - }) -} - -func (d *PerformDetach) Unmarshal(r *buffer.Buffer) error { - return encoding.UnmarshalComposite(r, encoding.TypeCodeDetach, []encoding.UnmarshalField{ - {Field: &d.Handle, HandleNull: func() error { return errors.New("Detach.Handle is required") }}, - {Field: &d.Closed}, - {Field: &d.Error}, - }...) -} - -/* - - - - - - -*/ -type PerformEnd struct { - // error causing the end - // - // If set, this field indicates that the session is being ended due to an error - // condition. The value of the field SHOULD contain details on the cause of the error. - Error *encoding.Error -} - -func (e *PerformEnd) frameBody() {} - -func (d PerformEnd) String() string { - return fmt.Sprintf("End{Error: %v}", d.Error) -} - -func (e *PerformEnd) Marshal(wr *buffer.Buffer) error { - return encoding.MarshalComposite(wr, encoding.TypeCodeEnd, []encoding.MarshalField{ - {Value: e.Error, Omit: e.Error == nil}, - }) -} - -func (e *PerformEnd) Unmarshal(r *buffer.Buffer) error { - return encoding.UnmarshalComposite(r, encoding.TypeCodeEnd, - encoding.UnmarshalField{Field: &e.Error}, - ) -} - -/* - - - - - - -*/ -type PerformClose struct { - // error causing the close - // - // If set, this field indicates that the session is being closed due to an error - // condition. The value of the field SHOULD contain details on the cause of the error. - Error *encoding.Error -} - -func (c *PerformClose) frameBody() {} - -func (c *PerformClose) Marshal(wr *buffer.Buffer) error { - return encoding.MarshalComposite(wr, encoding.TypeCodeClose, []encoding.MarshalField{ - {Value: c.Error, Omit: c.Error == nil}, - }) -} - -func (c *PerformClose) Unmarshal(r *buffer.Buffer) error { - return encoding.UnmarshalComposite(r, encoding.TypeCodeClose, - encoding.UnmarshalField{Field: &c.Error}, - ) -} - -func (c *PerformClose) String() string { - return fmt.Sprintf("Close{Error: %s}", c.Error) -} - -/* - - - - - - -*/ - -type SASLInit struct { - Mechanism encoding.Symbol - InitialResponse []byte - Hostname string -} - -func (si *SASLInit) frameBody() {} - -func (si *SASLInit) Marshal(wr *buffer.Buffer) error { - return encoding.MarshalComposite(wr, encoding.TypeCodeSASLInit, []encoding.MarshalField{ - {Value: &si.Mechanism, Omit: false}, - {Value: &si.InitialResponse, Omit: false}, - {Value: &si.Hostname, Omit: len(si.Hostname) == 0}, - }) -} - -func (si *SASLInit) Unmarshal(r *buffer.Buffer) error { - return encoding.UnmarshalComposite(r, encoding.TypeCodeSASLInit, []encoding.UnmarshalField{ - {Field: &si.Mechanism, HandleNull: func() error { return errors.New("saslInit.Mechanism is required") }}, - {Field: &si.InitialResponse}, - {Field: &si.Hostname}, - }...) -} - -func (si *SASLInit) String() string { - // Elide the InitialResponse as it may contain a plain text secret. - return fmt.Sprintf("SaslInit{Mechanism : %s, InitialResponse: ********, Hostname: %s}", - si.Mechanism, - si.Hostname, - ) -} - -/* - - - - -*/ - -type SASLMechanisms struct { - Mechanisms encoding.MultiSymbol -} - -func (sm *SASLMechanisms) frameBody() {} - -func (sm *SASLMechanisms) Marshal(wr *buffer.Buffer) error { - return encoding.MarshalComposite(wr, encoding.TypeCodeSASLMechanism, []encoding.MarshalField{ - {Value: &sm.Mechanisms, Omit: false}, - }) -} - -func (sm *SASLMechanisms) Unmarshal(r *buffer.Buffer) error { - return encoding.UnmarshalComposite(r, encoding.TypeCodeSASLMechanism, - encoding.UnmarshalField{Field: &sm.Mechanisms, HandleNull: func() error { return errors.New("saslMechanisms.Mechanisms is required") }}, - ) -} - -func (sm *SASLMechanisms) String() string { - return fmt.Sprintf("SaslMechanisms{Mechanisms : %v}", - sm.Mechanisms, - ) -} - -/* - - - - -*/ - -type SASLChallenge struct { - Challenge []byte -} - -func (sc *SASLChallenge) String() string { - return "Challenge{Challenge: ********}" -} - -func (sc *SASLChallenge) frameBody() {} - -func (sc *SASLChallenge) Marshal(wr *buffer.Buffer) error { - return encoding.MarshalComposite(wr, encoding.TypeCodeSASLChallenge, []encoding.MarshalField{ - {Value: &sc.Challenge, Omit: false}, - }) -} - -func (sc *SASLChallenge) Unmarshal(r *buffer.Buffer) error { - return encoding.UnmarshalComposite(r, encoding.TypeCodeSASLChallenge, []encoding.UnmarshalField{ - {Field: &sc.Challenge, HandleNull: func() error { return errors.New("saslChallenge.Challenge is required") }}, - }...) -} - -/* - - - - -*/ - -type SASLResponse struct { - Response []byte -} - -func (sr *SASLResponse) String() string { - return "Response{Response: ********}" -} - -func (sr *SASLResponse) frameBody() {} - -func (sr *SASLResponse) Marshal(wr *buffer.Buffer) error { - return encoding.MarshalComposite(wr, encoding.TypeCodeSASLResponse, []encoding.MarshalField{ - {Value: &sr.Response, Omit: false}, - }) -} - -func (sr *SASLResponse) Unmarshal(r *buffer.Buffer) error { - return encoding.UnmarshalComposite(r, encoding.TypeCodeSASLResponse, []encoding.UnmarshalField{ - {Field: &sr.Response, HandleNull: func() error { return errors.New("saslResponse.Response is required") }}, - }...) -} - -/* - - - - - -*/ - -type SASLOutcome struct { - Code encoding.SASLCode - AdditionalData []byte -} - -func (so *SASLOutcome) frameBody() {} - -func (so *SASLOutcome) Marshal(wr *buffer.Buffer) error { - return encoding.MarshalComposite(wr, encoding.TypeCodeSASLOutcome, []encoding.MarshalField{ - {Value: &so.Code, Omit: false}, - {Value: &so.AdditionalData, Omit: len(so.AdditionalData) == 0}, - }) -} - -func (so *SASLOutcome) Unmarshal(r *buffer.Buffer) error { - return encoding.UnmarshalComposite(r, encoding.TypeCodeSASLOutcome, []encoding.UnmarshalField{ - {Field: &so.Code, HandleNull: func() error { return errors.New("saslOutcome.AdditionalData is required") }}, - {Field: &so.AdditionalData}, - }...) -} - -func (so *SASLOutcome) String() string { - return fmt.Sprintf("SaslOutcome{Code : %v, AdditionalData: %v}", - so.Code, - so.AdditionalData, - ) -} diff --git a/sdk/messaging/azeventhubs/internal/go-amqp/internal/frames/parsing.go b/sdk/messaging/azeventhubs/internal/go-amqp/internal/frames/parsing.go deleted file mode 100644 index 0e03a52a23e3..000000000000 --- a/sdk/messaging/azeventhubs/internal/go-amqp/internal/frames/parsing.go +++ /dev/null @@ -1,162 +0,0 @@ -// Copyright (C) 2017 Kale Blankenship -// Portions Copyright (c) Microsoft Corporation - -package frames - -import ( - "encoding/binary" - "errors" - "fmt" - "math" - - "github.com/Azure/azure-sdk-for-go/sdk/messaging/azeventhubs/internal/go-amqp/internal/buffer" - "github.com/Azure/azure-sdk-for-go/sdk/messaging/azeventhubs/internal/go-amqp/internal/encoding" -) - -const HeaderSize = 8 - -// Frame structure: -// -// header (8 bytes) -// 0-3: SIZE (total size, at least 8 bytes for header, uint32) -// 4: DOFF (data offset,at least 2, count of 4 bytes words, uint8) -// 5: TYPE (frame type) -// 0x0: AMQP -// 0x1: SASL -// 6-7: type dependent (channel for AMQP) -// extended header (opt) -// body (opt) - -// Header in a structure appropriate for use with binary.Read() -type Header struct { - // size: an unsigned 32-bit integer that MUST contain the total frame size of the frame header, - // extended header, and frame body. The frame is malformed if the size is less than the size of - // the frame header (8 bytes). - Size uint32 - // doff: gives the position of the body within the frame. The value of the data offset is an - // unsigned, 8-bit integer specifying a count of 4-byte words. Due to the mandatory 8-byte - // frame header, the frame is malformed if the value is less than 2. - DataOffset uint8 - FrameType uint8 - Channel uint16 -} - -// ParseHeader reads the header from r and returns the result. -// -// No validation is done. -func ParseHeader(r *buffer.Buffer) (Header, error) { - buf, ok := r.Next(8) - if !ok { - return Header{}, errors.New("invalid frameHeader") - } - _ = buf[7] - - fh := Header{ - Size: binary.BigEndian.Uint32(buf[0:4]), - DataOffset: buf[4], - FrameType: buf[5], - Channel: binary.BigEndian.Uint16(buf[6:8]), - } - - if fh.Size < HeaderSize { - return fh, fmt.Errorf("received frame header with invalid size %d", fh.Size) - } - - if fh.DataOffset < 2 { - return fh, fmt.Errorf("received frame header with invalid data offset %d", fh.DataOffset) - } - - return fh, nil -} - -// ParseBody reads and unmarshals an AMQP frame. -func ParseBody(r *buffer.Buffer) (FrameBody, error) { - payload := r.Bytes() - - if r.Len() < 3 || payload[0] != 0 || encoding.AMQPType(payload[1]) != encoding.TypeCodeSmallUlong { - return nil, errors.New("invalid frame body header") - } - - switch pType := encoding.AMQPType(payload[2]); pType { - case encoding.TypeCodeOpen: - t := new(PerformOpen) - err := t.Unmarshal(r) - return t, err - case encoding.TypeCodeBegin: - t := new(PerformBegin) - err := t.Unmarshal(r) - return t, err - case encoding.TypeCodeAttach: - t := new(PerformAttach) - err := t.Unmarshal(r) - return t, err - case encoding.TypeCodeFlow: - t := new(PerformFlow) - err := t.Unmarshal(r) - return t, err - case encoding.TypeCodeTransfer: - t := new(PerformTransfer) - err := t.Unmarshal(r) - return t, err - case encoding.TypeCodeDisposition: - t := new(PerformDisposition) - err := t.Unmarshal(r) - return t, err - case encoding.TypeCodeDetach: - t := new(PerformDetach) - err := t.Unmarshal(r) - return t, err - case encoding.TypeCodeEnd: - t := new(PerformEnd) - err := t.Unmarshal(r) - return t, err - case encoding.TypeCodeClose: - t := new(PerformClose) - err := t.Unmarshal(r) - return t, err - case encoding.TypeCodeSASLMechanism: - t := new(SASLMechanisms) - err := t.Unmarshal(r) - return t, err - case encoding.TypeCodeSASLChallenge: - t := new(SASLChallenge) - err := t.Unmarshal(r) - return t, err - case encoding.TypeCodeSASLOutcome: - t := new(SASLOutcome) - err := t.Unmarshal(r) - return t, err - default: - return nil, fmt.Errorf("unknown performative type %02x", pType) - } -} - -// Write encodes fr into buf. -// split out from conn.WriteFrame for testing purposes. -func Write(buf *buffer.Buffer, fr Frame) error { - // write header - buf.Append([]byte{ - 0, 0, 0, 0, // size, overwrite later - 2, // doff, see frameHeader.DataOffset comment - uint8(fr.Type), // frame type - }) - buf.AppendUint16(fr.Channel) // channel - - // write AMQP frame body - err := encoding.Marshal(buf, fr.Body) - if err != nil { - return err - } - - // validate size - if uint(buf.Len()) > math.MaxUint32 { - return errors.New("frame too large") - } - - // retrieve raw bytes - bufBytes := buf.Bytes() - - // write correct size - binary.BigEndian.PutUint32(bufBytes, uint32(len(bufBytes))) - return nil -} diff --git a/sdk/messaging/azeventhubs/internal/go-amqp/internal/queue/queue.go b/sdk/messaging/azeventhubs/internal/go-amqp/internal/queue/queue.go deleted file mode 100644 index 45d6f5af9daf..000000000000 --- a/sdk/messaging/azeventhubs/internal/go-amqp/internal/queue/queue.go +++ /dev/null @@ -1,164 +0,0 @@ -// Copyright (c) Microsoft Corporation - -package queue - -import ( - "container/ring" -) - -// Holder provides synchronized access to a *Queue[T]. -type Holder[T any] struct { - // these channels work in tandem to provide exclusive access to the underlying *Queue[T]. - // each channel is created with a buffer size of one. - // empty behaves like a mutex when there's one or more messages in the queue. - // populated is like a semaphore when the queue is empty. - // the *Queue[T] is only ever in one channel. which channel depends on if it contains any items. - // the initial state is for empty to contain an empty queue. - empty chan *Queue[T] - populated chan *Queue[T] -} - -// NewHolder creates a new Holder[T] that contains the provided *Queue[T]. -func NewHolder[T any](q *Queue[T]) *Holder[T] { - h := &Holder[T]{ - empty: make(chan *Queue[T], 1), - populated: make(chan *Queue[T], 1), - } - h.Release(q) - return h -} - -// Acquire attempts to acquire the *Queue[T]. If the *Queue[T] has already been acquired the call blocks. -// When the *Queue[T] is no longer required, you MUST call Release() to relinquish acquisition. -func (h *Holder[T]) Acquire() *Queue[T] { - // the queue will be in only one of the channels, it doesn't matter which one - var q *Queue[T] - select { - case q = <-h.empty: - // empty queue - case q = <-h.populated: - // populated queue - } - return q -} - -// Wait returns a channel that's signaled when the *Queue[T] contains at least one item. -// When the *Queue[T] is no longer required, you MUST call Release() to relinquish acquisition. -func (h *Holder[T]) Wait() <-chan *Queue[T] { - return h.populated -} - -// Release returns the *Queue[T] back to the Holder[T]. -// Once the *Queue[T] has been released, it is no longer safe to call its methods. -func (h *Holder[T]) Release(q *Queue[T]) { - if q.Len() == 0 { - h.empty <- q - } else { - h.populated <- q - } -} - -// Len returns the length of the *Queue[T]. -func (h *Holder[T]) Len() int { - msgLen := 0 - select { - case q := <-h.empty: - h.empty <- q - case q := <-h.populated: - msgLen = q.Len() - h.populated <- q - } - return msgLen -} - -// Queue[T] is a segmented FIFO queue of Ts. -type Queue[T any] struct { - head *ring.Ring - tail *ring.Ring - size int -} - -// New creates a new instance of Queue[T]. -// - size is the size of each Queue segment -func New[T any](size int) *Queue[T] { - r := &ring.Ring{ - Value: &segment[T]{ - items: make([]*T, size), - }, - } - return &Queue[T]{ - head: r, - tail: r, - } -} - -// Enqueue adds the specified item to the end of the queue. -// If the current segment is full, a new segment is created. -func (q *Queue[T]) Enqueue(item T) { - for { - r := q.tail - seg := r.Value.(*segment[T]) - - if seg.tail < len(seg.items) { - seg.items[seg.tail] = &item - seg.tail++ - q.size++ - return - } - - // segment is full, can we advance? - if next := r.Next(); next != q.head { - q.tail = next - continue - } - - // no, add a new ring - r.Link(&ring.Ring{ - Value: &segment[T]{ - items: make([]*T, len(seg.items)), - }, - }) - - q.tail = r.Next() - } -} - -// Dequeue removes and returns the item from the front of the queue. -func (q *Queue[T]) Dequeue() *T { - r := q.head - seg := r.Value.(*segment[T]) - - if seg.tail == 0 { - // queue is empty - return nil - } - - // remove first item - item := seg.items[seg.head] - seg.items[seg.head] = nil - seg.head++ - q.size-- - - if seg.head == seg.tail { - // segment is now empty, reset indices - seg.head, seg.tail = 0, 0 - - // if we're not at the last ring, advance head to the next one - if q.head != q.tail { - q.head = r.Next() - } - } - - return item -} - -// Len returns the total count of enqueued items. -func (q *Queue[T]) Len() int { - return q.size -} - -type segment[T any] struct { - items []*T - head int - tail int -} diff --git a/sdk/messaging/azeventhubs/internal/go-amqp/internal/shared/shared.go b/sdk/messaging/azeventhubs/internal/go-amqp/internal/shared/shared.go deleted file mode 100644 index 867c1e932bf5..000000000000 --- a/sdk/messaging/azeventhubs/internal/go-amqp/internal/shared/shared.go +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright (c) Microsoft Corporation - -package shared - -import ( - "encoding/base64" - "math/rand" - "sync" - "time" -) - -// lockedRand provides a rand source that is safe for concurrent use. -type lockedRand struct { - mu sync.Mutex - src *rand.Rand -} - -func (r *lockedRand) Read(p []byte) (int, error) { - r.mu.Lock() - defer r.mu.Unlock() - return r.src.Read(p) -} - -// package scoped rand source to avoid any issues with seeding -// of the global source. -var pkgRand = &lockedRand{ - src: rand.New(rand.NewSource(time.Now().UnixNano())), -} - -// RandString returns a base64 encoded string of n bytes. -func RandString(n int) string { - b := make([]byte, n) - // from math/rand, cannot fail - _, _ = pkgRand.Read(b) - return base64.RawURLEncoding.EncodeToString(b) -} diff --git a/sdk/messaging/azeventhubs/internal/go-amqp/link.go b/sdk/messaging/azeventhubs/internal/go-amqp/link.go deleted file mode 100644 index 27a257c7ecb3..000000000000 --- a/sdk/messaging/azeventhubs/internal/go-amqp/link.go +++ /dev/null @@ -1,390 +0,0 @@ -// Copyright (C) 2017 Kale Blankenship -// Portions Copyright (c) Microsoft Corporation - -package amqp - -import ( - "context" - "errors" - "fmt" - "sync" - - "github.com/Azure/azure-sdk-for-go/sdk/messaging/azeventhubs/internal/go-amqp/internal/debug" - "github.com/Azure/azure-sdk-for-go/sdk/messaging/azeventhubs/internal/go-amqp/internal/encoding" - "github.com/Azure/azure-sdk-for-go/sdk/messaging/azeventhubs/internal/go-amqp/internal/frames" - "github.com/Azure/azure-sdk-for-go/sdk/messaging/azeventhubs/internal/go-amqp/internal/queue" - "github.com/Azure/azure-sdk-for-go/sdk/messaging/azeventhubs/internal/go-amqp/internal/shared" -) - -// linkKey uniquely identifies a link on a connection by name and direction. -// -// A link can be identified uniquely by the ordered tuple -// -// (source-container-id, target-container-id, name) -// -// On a single connection the container ID pairs can be abbreviated -// to a boolean flag indicating the direction of the link. -type linkKey struct { - name string - role encoding.Role // Local role: sender/receiver -} - -// link contains the common state and methods for sending and receiving links -type link struct { - key linkKey // Name and direction - handle uint32 // our handle - remoteHandle uint32 // remote's handle - dynamicAddr bool // request a dynamic link address from the server - - // frames destined for this link are added to this queue by Session.muxFrameToLink - rxQ *queue.Holder[frames.FrameBody] - - // used for gracefully closing link - close chan struct{} // signals a link's mux to shut down; DO NOT use this to check if a link has terminated, use done instead - closeOnce *sync.Once // closeOnce protects close from being closed multiple times - - done chan struct{} // closed when the link has terminated (mux exited); DO NOT wait on this from within a link's mux() as it will never trigger! - doneErr error // contains the mux error state; ONLY written to by the mux and MUST only be read from after done is closed! - closeErr error // contains the error state returned from closeLink(); ONLY closeLink() reads/writes this! - - session *Session // parent session - source *frames.Source // used for Receiver links - target *frames.Target // used for Sender links - properties map[encoding.Symbol]any // additional properties sent upon link attach - - // "The delivery-count is initialized by the sender when a link endpoint is created, - // and is incremented whenever a message is sent. Only the sender MAY independently - // modify this field. The receiver's value is calculated based on the last known - // value from the sender and any subsequent messages received on the link. Note that, - // despite its name, the delivery-count is not a count but a sequence number - // initialized at an arbitrary point by the sender." - deliveryCount uint32 - - // The current maximum number of messages that can be handled at the receiver endpoint of the link. Only the receiver endpoint - // can independently set this value. The sender endpoint sets this to the last known value seen from the receiver. - linkCredit uint32 - - senderSettleMode *SenderSettleMode - receiverSettleMode *ReceiverSettleMode - maxMessageSize uint64 - - closeInProgress bool // indicates that the detach performative has been sent -} - -func newLink(s *Session, r encoding.Role) link { - l := link{ - key: linkKey{shared.RandString(40), r}, - session: s, - close: make(chan struct{}), - closeOnce: &sync.Once{}, - done: make(chan struct{}), - } - - // set the segment size relative to respective window - var segmentSize int - if r == encoding.RoleReceiver { - segmentSize = int(s.incomingWindow) - } else { - segmentSize = int(s.outgoingWindow) - } - - l.rxQ = queue.NewHolder(queue.New[frames.FrameBody](segmentSize)) - return l -} - -// waitForFrame waits for an incoming frame to be queued. -// it returns the next frame from the queue, or an error. -// the error is either from the context or session.doneErr. -// not meant for consumption outside of link.go. -func (l *link) waitForFrame(ctx context.Context) (frames.FrameBody, error) { - select { - case <-ctx.Done(): - return nil, ctx.Err() - case <-l.session.done: - // session has terminated, no need to deallocate in this case - return nil, l.session.doneErr - case q := <-l.rxQ.Wait(): - // frame received - fr := q.Dequeue() - l.rxQ.Release(q) - return *fr, nil - } -} - -// attach sends the Attach performative to establish the link with its parent session. -// this is automatically called by the new*Link constructors. -func (l *link) attach(ctx context.Context, beforeAttach func(*frames.PerformAttach), afterAttach func(*frames.PerformAttach)) error { - if err := l.session.freeAbandonedLinks(ctx); err != nil { - return err - } - - // once the abandoned links have been cleaned up we can create our link - if err := l.session.allocateHandle(ctx, l); err != nil { - return err - } - - attach := &frames.PerformAttach{ - Name: l.key.name, - Handle: l.handle, - ReceiverSettleMode: l.receiverSettleMode, - SenderSettleMode: l.senderSettleMode, - MaxMessageSize: l.maxMessageSize, - Source: l.source, - Target: l.target, - Properties: l.properties, - } - - // link-specific configuration of the attach frame - beforeAttach(attach) - - if err := l.txFrameAndWait(ctx, attach); err != nil { - return err - } - - // wait for response - fr, err := l.waitForFrame(ctx) - if err != nil { - l.session.abandonLink(l) - return err - } - - resp, ok := fr.(*frames.PerformAttach) - if !ok { - debug.Log(1, "RX (link %p): unexpected attach response frame %T", l, fr) - if err := l.session.conn.Close(); err != nil { - return err - } - return &ConnError{inner: fmt.Errorf("unexpected attach response: %#v", fr)} - } - - // If the remote encounters an error during the attach it returns an Attach - // with no Source or Target. The remote then sends a Detach with an error. - // - // Note that if the application chooses not to create a terminus, the session - // endpoint will still create a link endpoint and issue an attach indicating - // that the link endpoint has no associated local terminus. In this case, the - // session endpoint MUST immediately detach the newly created link endpoint. - // - // http://docs.oasis-open.org/amqp/core/v1.0/csprd01/amqp-core-transport-v1.0-csprd01.html#doc-idp386144 - if resp.Source == nil && resp.Target == nil { - // wait for detach - fr, err := l.waitForFrame(ctx) - if err != nil { - // we timed out waiting for the peer to close the link, this really isn't an abandoned link. - // however, we still need to send the detach performative to ack the peer. - l.session.abandonLink(l) - return err - } - - detach, ok := fr.(*frames.PerformDetach) - if !ok { - if err := l.session.conn.Close(); err != nil { - return err - } - return &ConnError{inner: fmt.Errorf("unexpected frame while waiting for detach: %#v", fr)} - } - - // send return detach - fr = &frames.PerformDetach{ - Handle: l.handle, - Closed: true, - } - if err := l.txFrameAndWait(ctx, fr); err != nil { - return err - } - - if detach.Error == nil { - return fmt.Errorf("received detach with no error specified") - } - return detach.Error - } - - if l.maxMessageSize == 0 || resp.MaxMessageSize < l.maxMessageSize { - l.maxMessageSize = resp.MaxMessageSize - } - - // link-specific configuration post attach - afterAttach(resp) - - if err := l.setSettleModes(resp); err != nil { - // close the link as there's a mismatch on requested/supported settlement modes - dr := &frames.PerformDetach{ - Handle: l.handle, - Closed: true, - } - if err := l.txFrameAndWait(ctx, dr); err != nil { - return err - } - return err - } - - return nil -} - -// setSettleModes sets the settlement modes based on the resp frames.PerformAttach. -// -// If a settlement mode has been explicitly set locally and it was not honored by the -// server an error is returned. -func (l *link) setSettleModes(resp *frames.PerformAttach) error { - var ( - localRecvSettle = receiverSettleModeValue(l.receiverSettleMode) - respRecvSettle = receiverSettleModeValue(resp.ReceiverSettleMode) - ) - if l.receiverSettleMode != nil && localRecvSettle != respRecvSettle { - return fmt.Errorf("amqp: receiver settlement mode %q requested, received %q from server", l.receiverSettleMode, &respRecvSettle) - } - l.receiverSettleMode = &respRecvSettle - - var ( - localSendSettle = senderSettleModeValue(l.senderSettleMode) - respSendSettle = senderSettleModeValue(resp.SenderSettleMode) - ) - if l.senderSettleMode != nil && localSendSettle != respSendSettle { - return fmt.Errorf("amqp: sender settlement mode %q requested, received %q from server", l.senderSettleMode, &respSendSettle) - } - l.senderSettleMode = &respSendSettle - - return nil -} - -// muxHandleFrame processes fr based on type. -func (l *link) muxHandleFrame(fr frames.FrameBody) error { - switch fr := fr.(type) { - case *frames.PerformDetach: - if !fr.Closed { - l.closeWithError(ErrCondNotImplemented, fmt.Sprintf("non-closing detach not supported: %+v", fr)) - return nil - } - - // there are two possibilities: - // - this is the ack to a client-side Close() - // - the peer is closing the link so we must ack - - if l.closeInProgress { - // if the client-side close was initiated due to an error (l.closeWithError) - // then l.doneErr will already be set. in this case, return that error instead - // of an empty LinkError which indicates a clean client-side close. - if l.doneErr != nil { - return l.doneErr - } - return &LinkError{} - } - - dr := &frames.PerformDetach{ - Handle: l.handle, - Closed: true, - } - l.txFrame(context.Background(), dr, nil) - return &LinkError{RemoteErr: fr.Error} - - default: - debug.Log(1, "RX (link %p): unexpected frame: %s", l, fr) - l.closeWithError(ErrCondInternalError, fmt.Sprintf("link received unexpected frame %T", fr)) - return nil - } -} - -// Close closes the Sender and AMQP link. -func (l *link) closeLink(ctx context.Context) error { - var ctxErr error - l.closeOnce.Do(func() { - close(l.close) - - // once the mux has received the ack'ing detach performative, the mux will - // exit which deletes the link and closes l.done. - select { - case <-l.done: - l.closeErr = l.doneErr - case <-ctx.Done(): - // notify the caller that the close timed out/was cancelled. - // the mux will remain running and once the ack is received it will terminate. - ctxErr = ctx.Err() - - // record that the close timed out/was cancelled. - // subsequent calls to closeLink() will return this - debug.Log(1, "TX (link %p) closing %s: %v", l, l.key.name, ctxErr) - l.closeErr = &LinkError{inner: ctxErr} - } - }) - - if ctxErr != nil { - return ctxErr - } - - var linkErr *LinkError - if errors.As(l.closeErr, &linkErr) && linkErr.RemoteErr == nil && linkErr.inner == nil { - // an empty LinkError means the link was cleanly closed by the caller - return nil - } - return l.closeErr -} - -// closeWithError initiates closing the link with the specified AMQP error. -// the mux must continue to run until the ack'ing detach is received. -// l.doneErr is populated with a &LinkError{} containing an inner error constructed from the specified values -// - cnd is the AMQP error condition -// - desc is the error description -func (l *link) closeWithError(cnd ErrCond, desc string) { - amqpErr := &Error{Condition: cnd, Description: desc} - if l.closeInProgress { - debug.Log(3, "TX (link %p) close error already pending, discarding %v", l, amqpErr) - return - } - - dr := &frames.PerformDetach{ - Handle: l.handle, - Closed: true, - Error: amqpErr, - } - l.closeInProgress = true - l.doneErr = &LinkError{inner: fmt.Errorf("%s: %s", cnd, desc)} - l.txFrame(context.Background(), dr, nil) -} - -// txFrame sends the specified frame via the link's session. -// you MUST call this instead of session.txFrame() to ensure -// that frames are not sent during session shutdown. -func (l *link) txFrame(ctx context.Context, fr frames.FrameBody, sent chan error) { - // NOTE: there is no need to select on l.done as this is either - // called from a link's mux or before the mux has even started. - select { - case <-l.session.done: - if sent != nil { - sent <- l.session.doneErr - } - case <-l.session.endSent: - // we swallow this to prevent the link's mux from terminating. - // l.session.done will soon close so this is temporary. - return - case l.session.tx <- frameBodyEnvelope{Ctx: ctx, FrameBody: fr, Sent: sent}: - debug.Log(2, "TX (link %p): mux frame to Session (%p): %s", l, l.session, fr) - } -} - -// txFrame sends the specified frame via the link's session. -// you MUST call this instead of session.txFrame() to ensure -// that frames are not sent during session shutdown. -func (l *link) txFrameAndWait(ctx context.Context, fr frames.FrameBody) error { - // NOTE: there is no need to select on l.done as this is either - // called from a link's mux or before the mux has even started. - sent := make(chan error, 1) - select { - case <-l.session.done: - return l.session.doneErr - case <-l.session.endSent: - // we swallow this to prevent the link's mux from terminating. - // l.session.done will soon close so this is temporary. - return nil - case l.session.tx <- frameBodyEnvelope{Ctx: ctx, FrameBody: fr, Sent: sent}: - debug.Log(2, "TX (link %p): mux frame to Session (%p): %s", l, l.session, fr) - } - - select { - case err := <-sent: - return err - case <-l.done: - return l.doneErr - case <-l.session.done: - return l.session.doneErr - } -} diff --git a/sdk/messaging/azeventhubs/internal/go-amqp/link_options.go b/sdk/messaging/azeventhubs/internal/go-amqp/link_options.go deleted file mode 100644 index c4ba797007db..000000000000 --- a/sdk/messaging/azeventhubs/internal/go-amqp/link_options.go +++ /dev/null @@ -1,241 +0,0 @@ -// Copyright (C) 2017 Kale Blankenship -// Portions Copyright (c) Microsoft Corporation - -package amqp - -import ( - "github.com/Azure/azure-sdk-for-go/sdk/messaging/azeventhubs/internal/go-amqp/internal/encoding" -) - -type SenderOptions struct { - // Capabilities is the list of extension capabilities the sender supports. - Capabilities []string - - // Durability indicates what state of the sender will be retained durably. - // - // Default: DurabilityNone. - Durability Durability - - // DynamicAddress indicates a dynamic address is to be used. - // Any specified address will be ignored. - // - // Default: false. - DynamicAddress bool - - // ExpiryPolicy determines when the expiry timer of the sender starts counting - // down from the timeout value. If the link is subsequently re-attached before - // the timeout is reached, the count down is aborted. - // - // Default: ExpirySessionEnd. - ExpiryPolicy ExpiryPolicy - - // ExpiryTimeout is the duration in seconds that the sender will be retained. - // - // Default: 0. - ExpiryTimeout uint32 - - // Name sets the name of the link. - // - // Link names must be unique per-connection and direction. - // - // Default: randomly generated. - Name string - - // Properties sets an entry in the link properties map sent to the server. - Properties map[string]any - - // RequestedReceiverSettleMode sets the requested receiver settlement mode. - // - // If a settlement mode is explicitly set and the server does not - // honor it an error will be returned during link attachment. - // - // Default: Accept the settlement mode set by the server, commonly ModeFirst. - RequestedReceiverSettleMode *ReceiverSettleMode - - // SettlementMode sets the settlement mode in use by this sender. - // - // Default: ModeMixed. - SettlementMode *SenderSettleMode - - // SourceAddress specifies the source address for this sender. - SourceAddress string - - // TargetCapabilities is the list of extension capabilities the sender desires. - TargetCapabilities []string - - // TargetDurability indicates what state of the peer will be retained durably. - // - // Default: DurabilityNone. - TargetDurability Durability - - // TargetExpiryPolicy determines when the expiry timer of the peer starts counting - // down from the timeout value. If the link is subsequently re-attached before - // the timeout is reached, the count down is aborted. - // - // Default: ExpirySessionEnd. - TargetExpiryPolicy ExpiryPolicy - - // TargetExpiryTimeout is the duration in seconds that the peer will be retained. - // - // Default: 0. - TargetExpiryTimeout uint32 -} - -type ReceiverOptions struct { - // Capabilities is the list of extension capabilities the receiver supports. - Capabilities []string - - // Credit specifies the maximum number of unacknowledged messages - // the sender can transmit. Once this limit is reached, no more messages - // will arrive until messages are acknowledged and settled. - // - // As messages are settled, any available credit will automatically be issued. - // - // Setting this to -1 requires manual management of link credit. - // Credits can be added with IssueCredit(), and links can also be - // drained with DrainCredit(). - // This should only be enabled when complete control of the link's - // flow control is required. - // - // Default: 1. - Credit int32 - - // Durability indicates what state of the receiver will be retained durably. - // - // Default: DurabilityNone. - Durability Durability - - // DynamicAddress indicates a dynamic address is to be used. - // Any specified address will be ignored. - // - // Default: false. - DynamicAddress bool - - // ExpiryPolicy determines when the expiry timer of the sender starts counting - // down from the timeout value. If the link is subsequently re-attached before - // the timeout is reached, the count down is aborted. - // - // Default: ExpirySessionEnd. - ExpiryPolicy ExpiryPolicy - - // ExpiryTimeout is the duration in seconds that the sender will be retained. - // - // Default: 0. - ExpiryTimeout uint32 - - // Filters contains the desired filters for this receiver. - // If the peer cannot fulfill the filters the link will be detached. - Filters []LinkFilter - - // MaxMessageSize sets the maximum message size that can - // be received on the link. - // - // A size of zero indicates no limit. - // - // Default: 0. - MaxMessageSize uint64 - - // Name sets the name of the link. - // - // Link names must be unique per-connection and direction. - // - // Default: randomly generated. - Name string - - // Properties sets an entry in the link properties map sent to the server. - Properties map[string]any - - // RequestedSenderSettleMode sets the requested sender settlement mode. - // - // If a settlement mode is explicitly set and the server does not - // honor it an error will be returned during link attachment. - // - // Default: Accept the settlement mode set by the server, commonly ModeMixed. - RequestedSenderSettleMode *SenderSettleMode - - // SettlementMode sets the settlement mode in use by this receiver. - // - // Default: ModeFirst. - SettlementMode *ReceiverSettleMode - - // TargetAddress specifies the target address for this receiver. - TargetAddress string - - // SourceCapabilities is the list of extension capabilities the receiver desires. - SourceCapabilities []string - - // SourceDurability indicates what state of the peer will be retained durably. - // - // Default: DurabilityNone. - SourceDurability Durability - - // SourceExpiryPolicy determines when the expiry timer of the peer starts counting - // down from the timeout value. If the link is subsequently re-attached before - // the timeout is reached, the count down is aborted. - // - // Default: ExpirySessionEnd. - SourceExpiryPolicy ExpiryPolicy - - // SourceExpiryTimeout is the duration in seconds that the peer will be retained. - // - // Default: 0. - SourceExpiryTimeout uint32 -} - -// LinkFilter is an advanced API for setting non-standard source filters. -// Please file an issue or open a PR if a standard filter is missing from this -// library. -// -// The name is the key for the filter map. It will be encoded as an AMQP symbol type. -// -// The code is the descriptor of the described type value. The domain-id and descriptor-id -// should be concatenated together. If 0 is passed as the code, the name will be used as -// the descriptor. -// -// The value is the value of the descriped types. Acceptable types for value are specific -// to the filter. -// -// Example: -// -// The standard selector-filter is defined as: -// -// -// -// In this case the name is "apache.org:selector-filter:string" and the code is -// 0x0000468C00000004. -// -// LinkSourceFilter("apache.org:selector-filter:string", 0x0000468C00000004, exampleValue) -// -// References: -// -// http://docs.oasis-open.org/amqp/core/v1.0/os/amqp-core-messaging-v1.0-os.html#type-filter-set -// http://docs.oasis-open.org/amqp/core/v1.0/os/amqp-core-types-v1.0-os.html#section-descriptor-values -type LinkFilter func(encoding.Filter) - -// NewLinkFilter creates a new LinkFilter with the specified values. -// Any preexisting link filter with the same name will be updated with the new code and value. -func NewLinkFilter(name string, code uint64, value any) LinkFilter { - return func(f encoding.Filter) { - var descriptor any - if code != 0 { - descriptor = code - } else { - descriptor = encoding.Symbol(name) - } - f[encoding.Symbol(name)] = &encoding.DescribedType{ - Descriptor: descriptor, - Value: value, - } - } -} - -// NewSelectorFilter creates a new selector filter (apache.org:selector-filter:string) with the specified filter value. -// Any preexisting selector filter will be updated with the new filter value. -func NewSelectorFilter(filter string) LinkFilter { - return NewLinkFilter(selectorFilter, selectorFilterCode, filter) -} - -const ( - selectorFilter = "apache.org:selector-filter:string" - selectorFilterCode = uint64(0x0000468C00000004) -) diff --git a/sdk/messaging/azeventhubs/internal/go-amqp/message.go b/sdk/messaging/azeventhubs/internal/go-amqp/message.go deleted file mode 100644 index 20df597b6dc6..000000000000 --- a/sdk/messaging/azeventhubs/internal/go-amqp/message.go +++ /dev/null @@ -1,492 +0,0 @@ -// Copyright (C) 2017 Kale Blankenship -// Portions Copyright (c) Microsoft Corporation - -package amqp - -import ( - "fmt" - "time" - - "github.com/Azure/azure-sdk-for-go/sdk/messaging/azeventhubs/internal/go-amqp/internal/buffer" - "github.com/Azure/azure-sdk-for-go/sdk/messaging/azeventhubs/internal/go-amqp/internal/encoding" -) - -// Message is an AMQP message. -type Message struct { - // Message format code. - // - // The upper three octets of a message format code identify a particular message - // format. The lowest octet indicates the version of said message format. Any - // given version of a format is forwards compatible with all higher versions. - Format uint32 - - // The DeliveryTag can be up to 32 octets of binary data. - // Note that when mode one is enabled there will be no delivery tag. - DeliveryTag []byte - - // The header section carries standard delivery details about the transfer - // of a message through the AMQP network. - Header *MessageHeader - // If the header section is omitted the receiver MUST assume the appropriate - // default values (or the meaning implied by no value being set) for the - // fields within the header unless other target or node specific defaults - // have otherwise been set. - - // The delivery-annotations section is used for delivery-specific non-standard - // properties at the head of the message. Delivery annotations convey information - // from the sending peer to the receiving peer. - DeliveryAnnotations Annotations - // If the recipient does not understand the annotation it cannot be acted upon - // and its effects (such as any implied propagation) cannot be acted upon. - // Annotations might be specific to one implementation, or common to multiple - // implementations. The capabilities negotiated on link attach and on the source - // and target SHOULD be used to establish which annotations a peer supports. A - // registry of defined annotations and their meanings is maintained [AMQPDELANN]. - // The symbolic key "rejected" is reserved for the use of communicating error - // information regarding rejected messages. Any values associated with the - // "rejected" key MUST be of type error. - // - // If the delivery-annotations section is omitted, it is equivalent to a - // delivery-annotations section containing an empty map of annotations. - - // The message-annotations section is used for properties of the message which - // are aimed at the infrastructure. - Annotations Annotations - // The message-annotations section is used for properties of the message which - // are aimed at the infrastructure and SHOULD be propagated across every - // delivery step. Message annotations convey information about the message. - // Intermediaries MUST propagate the annotations unless the annotations are - // explicitly augmented or modified (e.g., by the use of the modified outcome). - // - // The capabilities negotiated on link attach and on the source and target can - // be used to establish which annotations a peer understands; however, in a - // network of AMQP intermediaries it might not be possible to know if every - // intermediary will understand the annotation. Note that for some annotations - // it might not be necessary for the intermediary to understand their purpose, - // i.e., they could be used purely as an attribute which can be filtered on. - // - // A registry of defined annotations and their meanings is maintained [AMQPMESSANN]. - // - // If the message-annotations section is omitted, it is equivalent to a - // message-annotations section containing an empty map of annotations. - - // The properties section is used for a defined set of standard properties of - // the message. - Properties *MessageProperties - // The properties section is part of the bare message; therefore, - // if retransmitted by an intermediary, it MUST remain unaltered. - - // The application-properties section is a part of the bare message used for - // structured application data. Intermediaries can use the data within this - // structure for the purposes of filtering or routing. - ApplicationProperties map[string]any - // The keys of this map are restricted to be of type string (which excludes - // the possibility of a null key) and the values are restricted to be of - // simple types only, that is, excluding map, list, and array types. - - // Data payloads. - // A data section contains opaque binary data. - Data [][]byte - - // Value payload. - // An amqp-value section contains a single AMQP value. - Value any - - // Sequence will contain AMQP sequence sections from the body of the message. - // An amqp-sequence section contains an AMQP sequence. - Sequence [][]any - - // The footer section is used for details about the message or delivery which - // can only be calculated or evaluated once the whole bare message has been - // constructed or seen (for example message hashes, HMACs, signatures and - // encryption details). - Footer Annotations - - deliveryID uint32 // used when sending disposition - settled bool // whether transfer was settled by sender -} - -// NewMessage returns a *Message with data as the payload. -// -// This constructor is intended as a helper for basic Messages with a -// single data payload. It is valid to construct a Message directly for -// more complex usages. -func NewMessage(data []byte) *Message { - return &Message{ - Data: [][]byte{data}, - } -} - -// GetData returns the first []byte from the Data field -// or nil if Data is empty. -func (m *Message) GetData() []byte { - if len(m.Data) < 1 { - return nil - } - return m.Data[0] -} - -// MarshalBinary encodes the message into binary form. -func (m *Message) MarshalBinary() ([]byte, error) { - buf := &buffer.Buffer{} - err := m.Marshal(buf) - return buf.Detach(), err -} - -func (m *Message) Marshal(wr *buffer.Buffer) error { - if m.Header != nil { - err := m.Header.Marshal(wr) - if err != nil { - return err - } - } - - if m.DeliveryAnnotations != nil { - encoding.WriteDescriptor(wr, encoding.TypeCodeDeliveryAnnotations) - err := encoding.Marshal(wr, m.DeliveryAnnotations) - if err != nil { - return err - } - } - - if m.Annotations != nil { - encoding.WriteDescriptor(wr, encoding.TypeCodeMessageAnnotations) - err := encoding.Marshal(wr, m.Annotations) - if err != nil { - return err - } - } - - if m.Properties != nil { - err := encoding.Marshal(wr, m.Properties) - if err != nil { - return err - } - } - - if m.ApplicationProperties != nil { - encoding.WriteDescriptor(wr, encoding.TypeCodeApplicationProperties) - err := encoding.Marshal(wr, m.ApplicationProperties) - if err != nil { - return err - } - } - - for _, data := range m.Data { - encoding.WriteDescriptor(wr, encoding.TypeCodeApplicationData) - err := encoding.WriteBinary(wr, data) - if err != nil { - return err - } - } - - if m.Value != nil { - encoding.WriteDescriptor(wr, encoding.TypeCodeAMQPValue) - err := encoding.Marshal(wr, m.Value) - if err != nil { - return err - } - } - - if m.Sequence != nil { - // the body can basically be one of three different types (value, data or sequence). - // When it's sequence it's actually _several_ sequence sections, one for each sub-array. - for _, v := range m.Sequence { - encoding.WriteDescriptor(wr, encoding.TypeCodeAMQPSequence) - err := encoding.Marshal(wr, v) - if err != nil { - return err - } - } - } - - if m.Footer != nil { - encoding.WriteDescriptor(wr, encoding.TypeCodeFooter) - err := encoding.Marshal(wr, m.Footer) - if err != nil { - return err - } - } - - return nil -} - -// UnmarshalBinary decodes the message from binary form. -func (m *Message) UnmarshalBinary(data []byte) error { - buf := buffer.New(data) - return m.Unmarshal(buf) -} - -func (m *Message) Unmarshal(r *buffer.Buffer) error { - // loop, decoding sections until bytes have been consumed - for r.Len() > 0 { - // determine type - type_, headerLength, err := encoding.PeekMessageType(r.Bytes()) - if err != nil { - return err - } - - var ( - section any - // section header is read from r before - // unmarshaling section is set to true - discardHeader = true - ) - switch encoding.AMQPType(type_) { - - case encoding.TypeCodeMessageHeader: - discardHeader = false - section = &m.Header - - case encoding.TypeCodeDeliveryAnnotations: - section = &m.DeliveryAnnotations - - case encoding.TypeCodeMessageAnnotations: - section = &m.Annotations - - case encoding.TypeCodeMessageProperties: - discardHeader = false - section = &m.Properties - - case encoding.TypeCodeApplicationProperties: - section = &m.ApplicationProperties - - case encoding.TypeCodeApplicationData: - r.Skip(int(headerLength)) - - var data []byte - err = encoding.Unmarshal(r, &data) - if err != nil { - return err - } - - m.Data = append(m.Data, data) - continue - - case encoding.TypeCodeAMQPSequence: - r.Skip(int(headerLength)) - - var data []any - err = encoding.Unmarshal(r, &data) - if err != nil { - return err - } - - m.Sequence = append(m.Sequence, data) - continue - - case encoding.TypeCodeFooter: - section = &m.Footer - - case encoding.TypeCodeAMQPValue: - section = &m.Value - - default: - return fmt.Errorf("unknown message section %#02x", type_) - } - - if discardHeader { - r.Skip(int(headerLength)) - } - - err = encoding.Unmarshal(r, section) - if err != nil { - return err - } - } - return nil -} - -/* - - - - - - - - -*/ - -// MessageHeader carries standard delivery details about the transfer -// of a message. -type MessageHeader struct { - Durable bool - Priority uint8 - TTL time.Duration // from milliseconds - FirstAcquirer bool - DeliveryCount uint32 -} - -func (h *MessageHeader) Marshal(wr *buffer.Buffer) error { - return encoding.MarshalComposite(wr, encoding.TypeCodeMessageHeader, []encoding.MarshalField{ - {Value: &h.Durable, Omit: !h.Durable}, - {Value: &h.Priority, Omit: h.Priority == 4}, - {Value: (*encoding.Milliseconds)(&h.TTL), Omit: h.TTL == 0}, - {Value: &h.FirstAcquirer, Omit: !h.FirstAcquirer}, - {Value: &h.DeliveryCount, Omit: h.DeliveryCount == 0}, - }) -} - -func (h *MessageHeader) Unmarshal(r *buffer.Buffer) error { - return encoding.UnmarshalComposite(r, encoding.TypeCodeMessageHeader, []encoding.UnmarshalField{ - {Field: &h.Durable}, - {Field: &h.Priority, HandleNull: func() error { h.Priority = 4; return nil }}, - {Field: (*encoding.Milliseconds)(&h.TTL)}, - {Field: &h.FirstAcquirer}, - {Field: &h.DeliveryCount}, - }...) -} - -/* - - - - - - - - - - - - - - - - -*/ - -// MessageProperties is the defined set of properties for AMQP messages. -type MessageProperties struct { - // Message-id, if set, uniquely identifies a message within the message system. - // The message producer is usually responsible for setting the message-id in - // such a way that it is assured to be globally unique. A broker MAY discard a - // message as a duplicate if the value of the message-id matches that of a - // previously received message sent to the same node. - // - // The value is restricted to the following types - // - uint64, UUID, []byte, or string - MessageID any - - // The identity of the user responsible for producing the message. - // The client sets this value, and it MAY be authenticated by intermediaries. - UserID []byte - - // The to field identifies the node that is the intended destination of the message. - // On any given transfer this might not be the node at the receiving end of the link. - To *string - - // A common field for summary information about the message content and purpose. - Subject *string - - // The address of the node to send replies to. - ReplyTo *string - - // This is a client-specific id that can be used to mark or identify messages - // between clients. - // - // The value is restricted to the following types - // - uint64, UUID, []byte, or string - CorrelationID any - - // The RFC-2046 [RFC2046] MIME type for the message's application-data section - // (body). As per RFC-2046 [RFC2046] this can contain a charset parameter defining - // the character encoding used: e.g., 'text/plain; charset="utf-8"'. - // - // For clarity, as per section 7.2.1 of RFC-2616 [RFC2616], where the content type - // is unknown the content-type SHOULD NOT be set. This allows the recipient the - // opportunity to determine the actual type. Where the section is known to be truly - // opaque binary data, the content-type SHOULD be set to application/octet-stream. - // - // When using an application-data section with a section code other than data, - // content-type SHOULD NOT be set. - ContentType *string - - // The content-encoding property is used as a modifier to the content-type. - // When present, its value indicates what additional content encodings have been - // applied to the application-data, and thus what decoding mechanisms need to be - // applied in order to obtain the media-type referenced by the content-type header - // field. - // - // Content-encoding is primarily used to allow a document to be compressed without - // losing the identity of its underlying content type. - // - // Content-encodings are to be interpreted as per section 3.5 of RFC 2616 [RFC2616]. - // Valid content-encodings are registered at IANA [IANAHTTPPARAMS]. - // - // The content-encoding MUST NOT be set when the application-data section is other - // than data. The binary representation of all other application-data section types - // is defined completely in terms of the AMQP type system. - // - // Implementations MUST NOT use the identity encoding. Instead, implementations - // SHOULD NOT set this property. Implementations SHOULD NOT use the compress encoding, - // except as to remain compatible with messages originally sent with other protocols, - // e.g. HTTP or SMTP. - // - // Implementations SHOULD NOT specify multiple content-encoding values except as to - // be compatible with messages originally sent with other protocols, e.g. HTTP or SMTP. - ContentEncoding *string - - // An absolute time when this message is considered to be expired. - AbsoluteExpiryTime *time.Time - - // An absolute time when this message was created. - CreationTime *time.Time - - // Identifies the group the message belongs to. - GroupID *string - - // The relative position of this message within its group. - // - // The value is defined as a RFC-1982 sequence number - GroupSequence *uint32 - - // This is a client-specific id that is used so that client can send replies to this - // message to a specific group. - ReplyToGroupID *string -} - -func (p *MessageProperties) Marshal(wr *buffer.Buffer) error { - return encoding.MarshalComposite(wr, encoding.TypeCodeMessageProperties, []encoding.MarshalField{ - {Value: p.MessageID, Omit: p.MessageID == nil}, - {Value: &p.UserID, Omit: len(p.UserID) == 0}, - {Value: p.To, Omit: p.To == nil}, - {Value: p.Subject, Omit: p.Subject == nil}, - {Value: p.ReplyTo, Omit: p.ReplyTo == nil}, - {Value: p.CorrelationID, Omit: p.CorrelationID == nil}, - {Value: (*encoding.Symbol)(p.ContentType), Omit: p.ContentType == nil}, - {Value: (*encoding.Symbol)(p.ContentEncoding), Omit: p.ContentEncoding == nil}, - {Value: p.AbsoluteExpiryTime, Omit: p.AbsoluteExpiryTime == nil}, - {Value: p.CreationTime, Omit: p.CreationTime == nil}, - {Value: p.GroupID, Omit: p.GroupID == nil}, - {Value: p.GroupSequence, Omit: p.GroupSequence == nil}, - {Value: p.ReplyToGroupID, Omit: p.ReplyToGroupID == nil}, - }) -} - -func (p *MessageProperties) Unmarshal(r *buffer.Buffer) error { - return encoding.UnmarshalComposite(r, encoding.TypeCodeMessageProperties, []encoding.UnmarshalField{ - {Field: &p.MessageID}, - {Field: &p.UserID}, - {Field: &p.To}, - {Field: &p.Subject}, - {Field: &p.ReplyTo}, - {Field: &p.CorrelationID}, - {Field: &p.ContentType}, - {Field: &p.ContentEncoding}, - {Field: &p.AbsoluteExpiryTime}, - {Field: &p.CreationTime}, - {Field: &p.GroupID}, - {Field: &p.GroupSequence}, - {Field: &p.ReplyToGroupID}, - }...) -} - -// Annotations keys must be of type string, int, or int64. -// -// String keys are encoded as AMQP Symbols. -type Annotations = encoding.Annotations - -// UUID is a 128 bit identifier as defined in RFC 4122. -type UUID = encoding.UUID diff --git a/sdk/messaging/azeventhubs/internal/go-amqp/receiver.go b/sdk/messaging/azeventhubs/internal/go-amqp/receiver.go deleted file mode 100644 index 88da28bac3ca..000000000000 --- a/sdk/messaging/azeventhubs/internal/go-amqp/receiver.go +++ /dev/null @@ -1,897 +0,0 @@ -// Copyright (C) 2017 Kale Blankenship -// Portions Copyright (c) Microsoft Corporation - -package amqp - -import ( - "bytes" - "context" - "errors" - "fmt" - "sync" - - "github.com/Azure/azure-sdk-for-go/sdk/messaging/azeventhubs/internal/go-amqp/internal/buffer" - "github.com/Azure/azure-sdk-for-go/sdk/messaging/azeventhubs/internal/go-amqp/internal/debug" - "github.com/Azure/azure-sdk-for-go/sdk/messaging/azeventhubs/internal/go-amqp/internal/encoding" - "github.com/Azure/azure-sdk-for-go/sdk/messaging/azeventhubs/internal/go-amqp/internal/frames" - "github.com/Azure/azure-sdk-for-go/sdk/messaging/azeventhubs/internal/go-amqp/internal/queue" -) - -// Default link options -const ( - defaultLinkCredit = 1 -) - -// Receiver receives messages on a single AMQP link. -type Receiver struct { - l link - - // message receiving - receiverReady chan struct{} // receiver sends on this when mux is paused to indicate it can handle more messages - messagesQ *queue.Holder[Message] // used to send completed messages to receiver - txDisposition chan frameBodyEnvelope // used to funnel disposition frames through the mux - - unsettledMessages map[string]struct{} // used to keep track of messages being handled downstream - unsettledMessagesLock sync.RWMutex // lock to protect concurrent access to unsettledMessages - msgBuf buffer.Buffer // buffered bytes for current message - more bool // if true, buf contains a partial message - msg Message // current message being decoded - - settlementCount uint32 // the count of settled messages - settlementCountMu sync.Mutex // must be held when accessing settlementCount - - autoSendFlow bool // automatically send flow frames as credit becomes available - inFlight inFlight // used to track message disposition when rcv-settle-mode == second - creditor creditor // manages credits via calls to IssueCredit/DrainCredit -} - -// IssueCredit adds credits to be requested in the next flow request. -// Attempting to issue more credit than the receiver's max credit as -// specified in ReceiverOptions.MaxCredit will result in an error. -func (r *Receiver) IssueCredit(credit uint32) error { - if r.autoSendFlow { - return errors.New("issueCredit can only be used with receiver links using manual credit management") - } - - if err := r.creditor.IssueCredit(credit); err != nil { - return err - } - - // cause mux() to check our flow conditions. - select { - case r.receiverReady <- struct{}{}: - default: - } - - return nil -} - -// Prefetched returns the next message that is stored in the Receiver's -// prefetch cache. It does NOT wait for the remote sender to send messages -// and returns immediately if the prefetch cache is empty. To receive from the -// prefetch and wait for messages from the remote Sender use `Receive`. -// -// Once a message is received, and if the sender is configured in any mode other -// than SenderSettleModeSettled, you *must* take an action on the message by calling -// one of the following: AcceptMessage, RejectMessage, ReleaseMessage, ModifyMessage. -func (r *Receiver) Prefetched() *Message { - select { - case r.receiverReady <- struct{}{}: - default: - } - - // non-blocking receive to ensure buffered messages are - // delivered regardless of whether the link has been closed. - q := r.messagesQ.Acquire() - msg := q.Dequeue() - r.messagesQ.Release(q) - - if msg == nil { - return nil - } - - debug.Log(3, "RX (Receiver %p): prefetched delivery ID %d", r, msg.deliveryID) - - if msg.settled { - r.onSettlement(1) - } - - return msg -} - -// ReceiveOptions contains any optional values for the Receiver.Receive method. -type ReceiveOptions struct { - // for future expansion -} - -// Receive returns the next message from the sender. -// Blocks until a message is received, ctx completes, or an error occurs. -// -// Once a message is received, and if the sender is configured in any mode other -// than SenderSettleModeSettled, you *must* take an action on the message by calling -// one of the following: AcceptMessage, RejectMessage, ReleaseMessage, ModifyMessage. -func (r *Receiver) Receive(ctx context.Context, opts *ReceiveOptions) (*Message, error) { - if msg := r.Prefetched(); msg != nil { - return msg, nil - } - - // wait for the next message - select { - case q := <-r.messagesQ.Wait(): - msg := q.Dequeue() - debug.Assert(msg != nil) - debug.Log(3, "RX (Receiver %p): received delivery ID %d", r, msg.deliveryID) - r.messagesQ.Release(q) - if msg.settled { - r.onSettlement(1) - } - return msg, nil - case <-r.l.done: - // if the link receives messages and is then closed between the above call to r.Prefetched() - // and this select statement, the order of selecting r.messages and r.l.done is undefined. - // however, once r.l.done is closed the link cannot receive any more messages. so be sure to - // drain any that might have trickled in within this window. - if msg := r.Prefetched(); msg != nil { - return msg, nil - } - return nil, r.l.doneErr - case <-ctx.Done(): - return nil, ctx.Err() - } -} - -// Accept notifies the server that the message has been accepted and does not require redelivery. -// - ctx controls waiting for the peer to acknowledge the disposition -// - msg is the message to accept -// -// If the context's deadline expires or is cancelled before the operation -// completes, the message's disposition is in an unknown state. -func (r *Receiver) AcceptMessage(ctx context.Context, msg *Message) error { - return r.messageDisposition(ctx, msg, &encoding.StateAccepted{}) -} - -// Reject notifies the server that the message is invalid. -// - ctx controls waiting for the peer to acknowledge the disposition -// - msg is the message to reject -// - e is an optional rejection error -// -// If the context's deadline expires or is cancelled before the operation -// completes, the message's disposition is in an unknown state. -func (r *Receiver) RejectMessage(ctx context.Context, msg *Message, e *Error) error { - return r.messageDisposition(ctx, msg, &encoding.StateRejected{Error: e}) -} - -// Release releases the message back to the server. The message may be redelivered to this or another consumer. -// - ctx controls waiting for the peer to acknowledge the disposition -// - msg is the message to release -// -// If the context's deadline expires or is cancelled before the operation -// completes, the message's disposition is in an unknown state. -func (r *Receiver) ReleaseMessage(ctx context.Context, msg *Message) error { - return r.messageDisposition(ctx, msg, &encoding.StateReleased{}) -} - -// Modify notifies the server that the message was not acted upon and should be modifed. -// - ctx controls waiting for the peer to acknowledge the disposition -// - msg is the message to modify -// - options contains the optional settings to modify -// -// If the context's deadline expires or is cancelled before the operation -// completes, the message's disposition is in an unknown state. -func (r *Receiver) ModifyMessage(ctx context.Context, msg *Message, options *ModifyMessageOptions) error { - if options == nil { - options = &ModifyMessageOptions{} - } - return r.messageDisposition(ctx, - msg, &encoding.StateModified{ - DeliveryFailed: options.DeliveryFailed, - UndeliverableHere: options.UndeliverableHere, - MessageAnnotations: options.Annotations, - }) -} - -// ModifyMessageOptions contains the optional parameters to ModifyMessage. -type ModifyMessageOptions struct { - // DeliveryFailed indicates that the server must consider this an - // unsuccessful delivery attempt and increment the delivery count. - DeliveryFailed bool - - // UndeliverableHere indicates that the server must not redeliver - // the message to this link. - UndeliverableHere bool - - // Annotations is an optional annotation map to be merged - // with the existing message annotations, overwriting existing keys - // if necessary. - Annotations Annotations -} - -// Address returns the link's address. -func (r *Receiver) Address() string { - if r.l.source == nil { - return "" - } - return r.l.source.Address -} - -// LinkName returns associated link name or an empty string if link is not defined. -func (r *Receiver) LinkName() string { - return r.l.key.name -} - -// LinkSourceFilterValue retrieves the specified link source filter value or nil if it doesn't exist. -func (r *Receiver) LinkSourceFilterValue(name string) any { - if r.l.source == nil { - return nil - } - filter, ok := r.l.source.Filter[encoding.Symbol(name)] - if !ok { - return nil - } - return filter.Value -} - -// Close closes the Receiver and AMQP link. -// - ctx controls waiting for the peer to acknowledge the close -// -// If the context's deadline expires or is cancelled before the operation -// completes, an error is returned. However, the operation will continue to -// execute in the background. Subsequent calls will return a *LinkError -// that contains the context's error message. -func (r *Receiver) Close(ctx context.Context) error { - return r.l.closeLink(ctx) -} - -// sendDisposition sends a disposition frame to the peer -func (r *Receiver) sendDisposition(ctx context.Context, first uint32, last *uint32, state encoding.DeliveryState) error { - fr := &frames.PerformDisposition{ - Role: encoding.RoleReceiver, - First: first, - Last: last, - Settled: r.l.receiverSettleMode == nil || *r.l.receiverSettleMode == ReceiverSettleModeFirst, - State: state, - } - - sent := make(chan error, 1) - select { - case r.txDisposition <- frameBodyEnvelope{Ctx: ctx, FrameBody: fr, Sent: sent}: - debug.Log(2, "TX (Receiver %p): mux txDisposition %s", r, fr) - case <-r.l.done: - return r.l.doneErr - } - - select { - case err := <-sent: - return err - case <-r.l.done: - return r.l.doneErr - } -} - -func (r *Receiver) messageDisposition(ctx context.Context, msg *Message, state encoding.DeliveryState) error { - if msg.settled { - return nil - } - - // NOTE: we MUST add to the in-flight map before sending the disposition. if not, it's possible - // to receive the ack'ing disposition frame *before* the in-flight map has been updated which - // will cause the below <-wait to never trigger. - - var wait chan error - if r.l.receiverSettleMode != nil && *r.l.receiverSettleMode == ReceiverSettleModeSecond { - debug.Log(3, "TX (Receiver %p): delivery ID %d is in flight", r, msg.deliveryID) - wait = r.inFlight.add(msg) - } - - if err := r.sendDisposition(ctx, msg.deliveryID, nil, state); err != nil { - return err - } - - if wait == nil { - // mode first, there will be no settlement ack - r.deleteUnsettled(msg) - r.onSettlement(1) - return nil - } - - select { - case err := <-wait: - // err has three possibilities - // - nil, meaning the peer acknowledged the settlement - // - an *Error, meaning the peer rejected the message with a provided error - // - a non-AMQP error. this comes from calls to inFlight.clear() during mux unwind. - // only for the first two cases is the message considered settled - - if amqpErr := (&Error{}); err == nil || errors.As(err, &amqpErr) { - debug.Log(3, "RX (Receiver %p): delivery ID %d has been settled", r, msg.deliveryID) - // we've received confirmation of disposition - return err - } - - debug.Log(3, "RX (Receiver %p): error settling delivery ID %d: %v", r, msg.deliveryID, err) - return err - - case <-ctx.Done(): - // didn't receive the ack in the time allotted, leave message as unsettled - // TODO: if the ack arrives later, we need to remove the message from the unsettled map and reclaim the credit - return ctx.Err() - } -} - -// onSettlement is to be called after message settlement. -// - count is the number of messages that were settled -func (r *Receiver) onSettlement(count uint32) { - if !r.autoSendFlow { - return - } - - r.settlementCountMu.Lock() - r.settlementCount += count - r.settlementCountMu.Unlock() - - select { - case r.receiverReady <- struct{}{}: - // woke up - default: - // wake pending - } -} - -func (r *Receiver) addUnsettled(msg *Message) { - r.unsettledMessagesLock.Lock() - r.unsettledMessages[string(msg.DeliveryTag)] = struct{}{} - r.unsettledMessagesLock.Unlock() -} - -func (r *Receiver) deleteUnsettled(msg *Message) { - r.unsettledMessagesLock.Lock() - delete(r.unsettledMessages, string(msg.DeliveryTag)) - r.unsettledMessagesLock.Unlock() -} - -func (r *Receiver) countUnsettled() int { - r.unsettledMessagesLock.RLock() - count := len(r.unsettledMessages) - r.unsettledMessagesLock.RUnlock() - return count -} - -func newReceiver(source string, session *Session, opts *ReceiverOptions) (*Receiver, error) { - l := newLink(session, encoding.RoleReceiver) - l.source = &frames.Source{Address: source} - l.target = new(frames.Target) - l.linkCredit = defaultLinkCredit - r := &Receiver{ - l: l, - autoSendFlow: true, - receiverReady: make(chan struct{}, 1), - txDisposition: make(chan frameBodyEnvelope), - } - - r.messagesQ = queue.NewHolder(queue.New[Message](int(session.incomingWindow))) - - if opts == nil { - return r, nil - } - - for _, v := range opts.Capabilities { - r.l.target.Capabilities = append(r.l.target.Capabilities, encoding.Symbol(v)) - } - if opts.Credit > 0 { - r.l.linkCredit = uint32(opts.Credit) - } else if opts.Credit < 0 { - r.l.linkCredit = 0 - r.autoSendFlow = false - } - if opts.Durability > DurabilityUnsettledState { - return nil, fmt.Errorf("invalid Durability %d", opts.Durability) - } - r.l.target.Durable = opts.Durability - if opts.DynamicAddress { - r.l.source.Address = "" - r.l.dynamicAddr = opts.DynamicAddress - } - if opts.ExpiryPolicy != "" { - if err := encoding.ValidateExpiryPolicy(opts.ExpiryPolicy); err != nil { - return nil, err - } - r.l.target.ExpiryPolicy = opts.ExpiryPolicy - } - r.l.target.Timeout = opts.ExpiryTimeout - if opts.Filters != nil { - r.l.source.Filter = make(encoding.Filter) - for _, f := range opts.Filters { - f(r.l.source.Filter) - } - } - if opts.MaxMessageSize > 0 { - r.l.maxMessageSize = opts.MaxMessageSize - } - if opts.Name != "" { - r.l.key.name = opts.Name - } - if opts.Properties != nil { - r.l.properties = make(map[encoding.Symbol]any) - for k, v := range opts.Properties { - if k == "" { - return nil, errors.New("link property key must not be empty") - } - r.l.properties[encoding.Symbol(k)] = v - } - } - if opts.RequestedSenderSettleMode != nil { - if rsm := *opts.RequestedSenderSettleMode; rsm > SenderSettleModeMixed { - return nil, fmt.Errorf("invalid RequestedSenderSettleMode %d", rsm) - } - r.l.senderSettleMode = opts.RequestedSenderSettleMode - } - if opts.SettlementMode != nil { - if rsm := *opts.SettlementMode; rsm > ReceiverSettleModeSecond { - return nil, fmt.Errorf("invalid SettlementMode %d", rsm) - } - r.l.receiverSettleMode = opts.SettlementMode - } - r.l.target.Address = opts.TargetAddress - for _, v := range opts.SourceCapabilities { - r.l.source.Capabilities = append(r.l.source.Capabilities, encoding.Symbol(v)) - } - if opts.SourceDurability != DurabilityNone { - r.l.source.Durable = opts.SourceDurability - } - if opts.SourceExpiryPolicy != ExpiryPolicySessionEnd { - r.l.source.ExpiryPolicy = opts.SourceExpiryPolicy - } - if opts.SourceExpiryTimeout != 0 { - r.l.source.Timeout = opts.SourceExpiryTimeout - } - return r, nil -} - -// attach sends the Attach performative to establish the link with its parent session. -// this is automatically called by the new*Link constructors. -func (r *Receiver) attach(ctx context.Context) error { - if err := r.l.attach(ctx, func(pa *frames.PerformAttach) { - pa.Role = encoding.RoleReceiver - if pa.Source == nil { - pa.Source = new(frames.Source) - } - pa.Source.Dynamic = r.l.dynamicAddr - }, func(pa *frames.PerformAttach) { - if r.l.source == nil { - r.l.source = new(frames.Source) - } - // if dynamic address requested, copy assigned name to address - if r.l.dynamicAddr && pa.Source != nil { - r.l.source.Address = pa.Source.Address - } - // deliveryCount is a sequence number, must initialize to sender's initial sequence number - r.l.deliveryCount = pa.InitialDeliveryCount - r.unsettledMessages = map[string]struct{}{} - // copy the received filter values - if pa.Source != nil { - r.l.source.Filter = pa.Source.Filter - } - }); err != nil { - return err - } - - return nil -} - -func nop() {} - -type receiverTestHooks struct { - MuxStart func() - MuxSelect func() -} - -func (r *Receiver) mux(hooks receiverTestHooks) { - if hooks.MuxSelect == nil { - hooks.MuxSelect = nop - } - if hooks.MuxStart == nil { - hooks.MuxStart = nop - } - - defer func() { - // unblock any in flight message dispositions - r.inFlight.clear(r.l.doneErr) - - if !r.autoSendFlow { - // unblock any pending drain requests - r.creditor.EndDrain() - } - - close(r.l.done) - }() - - hooks.MuxStart() - - if r.autoSendFlow { - r.l.doneErr = r.muxFlow(r.l.linkCredit, false) - } - - for { - msgLen := r.messagesQ.Len() - - r.settlementCountMu.Lock() - // counter that accumulates the settled delivery count. - // once the threshold has been reached, the counter is - // reset and a flow frame is sent. - previousSettlementCount := r.settlementCount - if previousSettlementCount >= r.l.linkCredit { - r.settlementCount = 0 - } - r.settlementCountMu.Unlock() - - // once we have pending credit equal to or greater than our available credit, reclaim it. - // we do this instead of settlementCount > 0 to prevent flow frames from being too chatty. - // NOTE: we compare the settlementCount against the current link credit instead of some - // fixed threshold to ensure credit is reclaimed in cases where the number of unsettled - // messages remains high for whatever reason. - if r.autoSendFlow && previousSettlementCount > 0 && previousSettlementCount >= r.l.linkCredit { - debug.Log(1, "RX (Receiver %p) (auto): source: %q, inflight: %d, linkCredit: %d, deliveryCount: %d, messages: %d, unsettled: %d, settlementCount: %d, settleMode: %s", - r, r.l.source.Address, r.inFlight.len(), r.l.linkCredit, r.l.deliveryCount, msgLen, r.countUnsettled(), previousSettlementCount, r.l.receiverSettleMode.String()) - r.l.doneErr = r.creditor.IssueCredit(previousSettlementCount) - } else if r.l.linkCredit == 0 { - debug.Log(1, "RX (Receiver %p) (pause): source: %q, inflight: %d, linkCredit: %d, deliveryCount: %d, messages: %d, unsettled: %d, settlementCount: %d, settleMode: %s", - r, r.l.source.Address, r.inFlight.len(), r.l.linkCredit, r.l.deliveryCount, msgLen, r.countUnsettled(), previousSettlementCount, r.l.receiverSettleMode.String()) - } - - if r.l.doneErr != nil { - return - } - - drain, credits := r.creditor.FlowBits(r.l.linkCredit) - if drain || credits > 0 { - debug.Log(1, "RX (Receiver %p) (flow): source: %q, inflight: %d, curLinkCredit: %d, newLinkCredit: %d, drain: %v, deliveryCount: %d, messages: %d, unsettled: %d, settlementCount: %d, settleMode: %s", - r, r.l.source.Address, r.inFlight.len(), r.l.linkCredit, credits, drain, r.l.deliveryCount, msgLen, r.countUnsettled(), previousSettlementCount, r.l.receiverSettleMode.String()) - - // send a flow frame. - r.l.doneErr = r.muxFlow(credits, drain) - } - - if r.l.doneErr != nil { - return - } - - txDisposition := r.txDisposition - closed := r.l.close - if r.l.closeInProgress { - // swap out channel so it no longer triggers - closed = nil - - // disable sending of disposition frames once closing is in progress. - // this is to prevent races between mux shutdown and clearing of - // any in-flight dispositions. - txDisposition = nil - } - - hooks.MuxSelect() - - select { - case q := <-r.l.rxQ.Wait(): - // populated queue - fr := *q.Dequeue() - r.l.rxQ.Release(q) - - // if muxHandleFrame returns an error it means the mux must terminate. - // note that in the case of a client-side close due to an error, nil - // is returned in order to keep the mux running to ack the detach frame. - if err := r.muxHandleFrame(fr); err != nil { - r.l.doneErr = err - return - } - - case env := <-txDisposition: - r.l.txFrame(env.Ctx, env.FrameBody, env.Sent) - - case <-r.receiverReady: - continue - - case <-closed: - if r.l.closeInProgress { - // a client-side close due to protocol error is in progress - continue - } - - // receiver is being closed by the client - r.l.closeInProgress = true - fr := &frames.PerformDetach{ - Handle: r.l.handle, - Closed: true, - } - r.l.txFrame(context.Background(), fr, nil) - - case <-r.l.session.done: - r.l.doneErr = r.l.session.doneErr - return - } - } -} - -// muxFlow sends tr to the session mux. -// l.linkCredit will also be updated to `linkCredit` -func (r *Receiver) muxFlow(linkCredit uint32, drain bool) error { - var ( - deliveryCount = r.l.deliveryCount - ) - - fr := &frames.PerformFlow{ - Handle: &r.l.handle, - DeliveryCount: &deliveryCount, - LinkCredit: &linkCredit, // max number of messages, - Drain: drain, - } - - // Update credit. This must happen before entering loop below - // because incoming messages handled while waiting to transmit - // flow increment deliveryCount. This causes the credit to become - // out of sync with the server. - - if !drain { - // if we're draining we don't want to touch our internal credit - we're not changing it so any issued credits - // are still valid until drain completes, at which point they will be naturally zeroed. - r.l.linkCredit = linkCredit - } - - select { - case r.l.session.tx <- frameBodyEnvelope{Ctx: context.Background(), FrameBody: fr}: - debug.Log(2, "TX (Receiver %p): mux frame to Session (%p): %d, %s", r, r.l.session, r.l.session.channel, fr) - return nil - case <-r.l.close: - return nil - case <-r.l.session.done: - return r.l.session.doneErr - } -} - -// muxHandleFrame processes fr based on type. -func (r *Receiver) muxHandleFrame(fr frames.FrameBody) error { - debug.Log(2, "RX (Receiver %p): %s", r, fr) - switch fr := fr.(type) { - // message frame - case *frames.PerformTransfer: - r.muxReceive(*fr) - - // flow control frame - case *frames.PerformFlow: - if !fr.Echo { - // if the 'drain' flag has been set in the frame sent to the _receiver_ then - // we signal whomever is waiting (the service has seen and acknowledged our drain) - if fr.Drain && !r.autoSendFlow { - r.l.linkCredit = 0 // we have no active credits at this point. - r.creditor.EndDrain() - } - return nil - } - - var ( - // copy because sent by pointer below; prevent race - linkCredit = r.l.linkCredit - deliveryCount = r.l.deliveryCount - ) - - // send flow - resp := &frames.PerformFlow{ - Handle: &r.l.handle, - DeliveryCount: &deliveryCount, - LinkCredit: &linkCredit, // max number of messages - } - - select { - case r.l.session.tx <- frameBodyEnvelope{Ctx: context.Background(), FrameBody: resp}: - debug.Log(2, "TX (Receiver %p): mux frame to Session (%p): %d, %s", r, r.l.session, r.l.session.channel, resp) - case <-r.l.close: - return nil - case <-r.l.session.done: - return r.l.session.doneErr - } - - case *frames.PerformDisposition: - // Unblock receivers waiting for message disposition - // bubble disposition error up to the receiver - var dispositionError error - if state, ok := fr.State.(*encoding.StateRejected); ok { - // state.Error isn't required to be filled out. For instance if you dead letter a message - // you will get a rejected response that doesn't contain an error. - if state.Error != nil { - dispositionError = state.Error - } - } - // removal from the in-flight map will also remove the message from the unsettled map - count := r.inFlight.remove(fr.First, fr.Last, dispositionError, func(msg *Message) { - r.deleteUnsettled(msg) - msg.settled = true - }) - r.onSettlement(count) - - default: - return r.l.muxHandleFrame(fr) - } - - return nil -} - -func (r *Receiver) muxReceive(fr frames.PerformTransfer) { - if !r.more { - // this is the first transfer of a message, - // record the delivery ID, message format, - // and delivery Tag - if fr.DeliveryID != nil { - r.msg.deliveryID = *fr.DeliveryID - } - if fr.MessageFormat != nil { - r.msg.Format = *fr.MessageFormat - } - r.msg.DeliveryTag = fr.DeliveryTag - - // these fields are required on first transfer of a message - if fr.DeliveryID == nil { - r.l.closeWithError(ErrCondNotAllowed, "received message without a delivery-id") - return - } - if fr.MessageFormat == nil { - r.l.closeWithError(ErrCondNotAllowed, "received message without a message-format") - return - } - if fr.DeliveryTag == nil { - r.l.closeWithError(ErrCondNotAllowed, "received message without a delivery-tag") - return - } - } else { - // this is a continuation of a multipart message - // some fields may be omitted on continuation transfers, - // but if they are included they must be consistent - // with the first. - - if fr.DeliveryID != nil && *fr.DeliveryID != r.msg.deliveryID { - msg := fmt.Sprintf( - "received continuation transfer with inconsistent delivery-id: %d != %d", - *fr.DeliveryID, r.msg.deliveryID, - ) - r.l.closeWithError(ErrCondNotAllowed, msg) - return - } - if fr.MessageFormat != nil && *fr.MessageFormat != r.msg.Format { - msg := fmt.Sprintf( - "received continuation transfer with inconsistent message-format: %d != %d", - *fr.MessageFormat, r.msg.Format, - ) - r.l.closeWithError(ErrCondNotAllowed, msg) - return - } - if fr.DeliveryTag != nil && !bytes.Equal(fr.DeliveryTag, r.msg.DeliveryTag) { - msg := fmt.Sprintf( - "received continuation transfer with inconsistent delivery-tag: %q != %q", - fr.DeliveryTag, r.msg.DeliveryTag, - ) - r.l.closeWithError(ErrCondNotAllowed, msg) - return - } - } - - // discard message if it's been aborted - if fr.Aborted { - r.msgBuf.Reset() - r.msg = Message{} - r.more = false - return - } - - // ensure maxMessageSize will not be exceeded - if r.l.maxMessageSize != 0 && uint64(r.msgBuf.Len())+uint64(len(fr.Payload)) > r.l.maxMessageSize { - r.l.closeWithError(ErrCondMessageSizeExceeded, fmt.Sprintf("received message larger than max size of %d", r.l.maxMessageSize)) - return - } - - // add the payload the the buffer - r.msgBuf.Append(fr.Payload) - - // mark as settled if at least one frame is settled - r.msg.settled = r.msg.settled || fr.Settled - - // save in-progress status - r.more = fr.More - - if fr.More { - return - } - - // last frame in message - err := r.msg.Unmarshal(&r.msgBuf) - if err != nil { - r.l.closeWithError(ErrCondInternalError, err.Error()) - return - } - - // send to receiver - if !r.msg.settled { - r.addUnsettled(&r.msg) - debug.Log(3, "RX (Receiver %p): add unsettled delivery ID %d", r, r.msg.deliveryID) - } - - q := r.messagesQ.Acquire() - q.Enqueue(r.msg) - msgLen := q.Len() - r.messagesQ.Release(q) - - // reset progress - r.msgBuf.Reset() - r.msg = Message{} - - // decrement link-credit after entire message received - r.l.deliveryCount++ - r.l.linkCredit-- - debug.Log(3, "RX (Receiver %p) link %s - deliveryCount: %d, linkCredit: %d, len(messages): %d", r, r.l.key.name, r.l.deliveryCount, r.l.linkCredit, msgLen) -} - -// inFlight tracks in-flight message dispositions allowing receivers -// to block waiting for the server to respond when an appropriate -// settlement mode is configured. -type inFlight struct { - mu sync.RWMutex - m map[uint32]inFlightInfo -} - -type inFlightInfo struct { - wait chan error - msg *Message -} - -func (f *inFlight) add(msg *Message) chan error { - wait := make(chan error, 1) - - f.mu.Lock() - if f.m == nil { - f.m = make(map[uint32]inFlightInfo) - } - - f.m[msg.deliveryID] = inFlightInfo{wait: wait, msg: msg} - f.mu.Unlock() - - return wait -} - -func (f *inFlight) remove(first uint32, last *uint32, err error, handler func(*Message)) uint32 { - f.mu.Lock() - - if f.m == nil { - f.mu.Unlock() - return 0 - } - - ll := first - if last != nil { - ll = *last - } - - count := uint32(0) - for i := first; i <= ll; i++ { - info, ok := f.m[i] - if ok { - handler(info.msg) - info.wait <- err - delete(f.m, i) - count++ - } - } - - f.mu.Unlock() - return count -} - -func (f *inFlight) clear(err error) { - f.mu.Lock() - for id, info := range f.m { - info.wait <- err - delete(f.m, id) - } - f.mu.Unlock() -} - -func (f *inFlight) len() int { - f.mu.RLock() - defer f.mu.RUnlock() - return len(f.m) -} diff --git a/sdk/messaging/azeventhubs/internal/go-amqp/sasl.go b/sdk/messaging/azeventhubs/internal/go-amqp/sasl.go deleted file mode 100644 index 11d185140dbf..000000000000 --- a/sdk/messaging/azeventhubs/internal/go-amqp/sasl.go +++ /dev/null @@ -1,262 +0,0 @@ -// Copyright (C) 2017 Kale Blankenship -// Portions Copyright (c) Microsoft Corporation - -package amqp - -import ( - "context" - "fmt" - - "github.com/Azure/azure-sdk-for-go/sdk/messaging/azeventhubs/internal/go-amqp/internal/debug" - "github.com/Azure/azure-sdk-for-go/sdk/messaging/azeventhubs/internal/go-amqp/internal/encoding" - "github.com/Azure/azure-sdk-for-go/sdk/messaging/azeventhubs/internal/go-amqp/internal/frames" -) - -// SASL Mechanisms -const ( - saslMechanismPLAIN encoding.Symbol = "PLAIN" - saslMechanismANONYMOUS encoding.Symbol = "ANONYMOUS" - saslMechanismEXTERNAL encoding.Symbol = "EXTERNAL" - saslMechanismXOAUTH2 encoding.Symbol = "XOAUTH2" -) - -// SASLType represents a SASL configuration to use during authentication. -type SASLType func(c *Conn) error - -// ConnSASLPlain enables SASL PLAIN authentication for the connection. -// -// SASL PLAIN transmits credentials in plain text and should only be used -// on TLS/SSL enabled connection. -func SASLTypePlain(username, password string) SASLType { - // TODO: how widely used is hostname? should it be supported - return func(c *Conn) error { - // make handlers map if no other mechanism has - if c.saslHandlers == nil { - c.saslHandlers = make(map[encoding.Symbol]stateFunc) - } - - // add the handler the the map - c.saslHandlers[saslMechanismPLAIN] = func(ctx context.Context) (stateFunc, error) { - // send saslInit with PLAIN payload - init := &frames.SASLInit{ - Mechanism: "PLAIN", - InitialResponse: []byte("\x00" + username + "\x00" + password), - Hostname: "", - } - fr := frames.Frame{ - Type: frames.TypeSASL, - Body: init, - } - debug.Log(1, "TX (ConnSASLPlain %p): %s", c, fr) - timeout, err := c.getWriteTimeout(ctx) - if err != nil { - return nil, err - } - if err = c.writeFrame(timeout, fr); err != nil { - return nil, err - } - - // go to c.saslOutcome to handle the server response - return c.saslOutcome, nil - } - return nil - } -} - -// ConnSASLAnonymous enables SASL ANONYMOUS authentication for the connection. -func SASLTypeAnonymous() SASLType { - return func(c *Conn) error { - // make handlers map if no other mechanism has - if c.saslHandlers == nil { - c.saslHandlers = make(map[encoding.Symbol]stateFunc) - } - - // add the handler the the map - c.saslHandlers[saslMechanismANONYMOUS] = func(ctx context.Context) (stateFunc, error) { - init := &frames.SASLInit{ - Mechanism: saslMechanismANONYMOUS, - InitialResponse: []byte("anonymous"), - } - fr := frames.Frame{ - Type: frames.TypeSASL, - Body: init, - } - debug.Log(1, "TX (ConnSASLAnonymous %p): %s", c, fr) - timeout, err := c.getWriteTimeout(ctx) - if err != nil { - return nil, err - } - if err = c.writeFrame(timeout, fr); err != nil { - return nil, err - } - - // go to c.saslOutcome to handle the server response - return c.saslOutcome, nil - } - return nil - } -} - -// ConnSASLExternal enables SASL EXTERNAL authentication for the connection. -// The value for resp is dependent on the type of authentication (empty string is common for TLS). -// See https://datatracker.ietf.org/doc/html/rfc4422#appendix-A for additional info. -func SASLTypeExternal(resp string) SASLType { - return func(c *Conn) error { - // make handlers map if no other mechanism has - if c.saslHandlers == nil { - c.saslHandlers = make(map[encoding.Symbol]stateFunc) - } - - // add the handler the the map - c.saslHandlers[saslMechanismEXTERNAL] = func(ctx context.Context) (stateFunc, error) { - init := &frames.SASLInit{ - Mechanism: saslMechanismEXTERNAL, - InitialResponse: []byte(resp), - } - fr := frames.Frame{ - Type: frames.TypeSASL, - Body: init, - } - debug.Log(1, "TX (ConnSASLExternal %p): %s", c, fr) - timeout, err := c.getWriteTimeout(ctx) - if err != nil { - return nil, err - } - if err = c.writeFrame(timeout, fr); err != nil { - return nil, err - } - - // go to c.saslOutcome to handle the server response - return c.saslOutcome, nil - } - return nil - } -} - -// ConnSASLXOAUTH2 enables SASL XOAUTH2 authentication for the connection. -// -// The saslMaxFrameSizeOverride parameter allows the limit that governs the maximum frame size this client will allow -// itself to generate to be raised for the sasl-init frame only. Set this when the size of the size of the SASL XOAUTH2 -// initial client response (which contains the username and bearer token) would otherwise breach the 512 byte min-max-frame-size -// (http://docs.oasis-open.org/amqp/core/v1.0/os/amqp-core-transport-v1.0-os.html#definition-MIN-MAX-FRAME-SIZE). Pass -1 -// to keep the default. -// -// SASL XOAUTH2 transmits the bearer in plain text and should only be used -// on TLS/SSL enabled connection. -func SASLTypeXOAUTH2(username, bearer string, saslMaxFrameSizeOverride uint32) SASLType { - return func(c *Conn) error { - // make handlers map if no other mechanism has - if c.saslHandlers == nil { - c.saslHandlers = make(map[encoding.Symbol]stateFunc) - } - - response, err := saslXOAUTH2InitialResponse(username, bearer) - if err != nil { - return err - } - - handler := saslXOAUTH2Handler{ - conn: c, - maxFrameSizeOverride: saslMaxFrameSizeOverride, - response: response, - } - // add the handler the the map - c.saslHandlers[saslMechanismXOAUTH2] = handler.init - return nil - } -} - -type saslXOAUTH2Handler struct { - conn *Conn - maxFrameSizeOverride uint32 - response []byte - errorResponse []byte // https://developers.google.com/gmail/imap/xoauth2-protocol#error_response -} - -func (s saslXOAUTH2Handler) init(ctx context.Context) (stateFunc, error) { - originalPeerMaxFrameSize := s.conn.peerMaxFrameSize - if s.maxFrameSizeOverride > s.conn.peerMaxFrameSize { - s.conn.peerMaxFrameSize = s.maxFrameSizeOverride - } - timeout, err := s.conn.getWriteTimeout(ctx) - if err != nil { - return nil, err - } - err = s.conn.writeFrame(timeout, frames.Frame{ - Type: frames.TypeSASL, - Body: &frames.SASLInit{ - Mechanism: saslMechanismXOAUTH2, - InitialResponse: s.response, - }, - }) - s.conn.peerMaxFrameSize = originalPeerMaxFrameSize - if err != nil { - return nil, err - } - - return s.step, nil -} - -func (s saslXOAUTH2Handler) step(ctx context.Context) (stateFunc, error) { - // read challenge or outcome frame - fr, err := s.conn.readFrame() - if err != nil { - return nil, err - } - - switch v := fr.Body.(type) { - case *frames.SASLOutcome: - // check if auth succeeded - if v.Code != encoding.CodeSASLOK { - return nil, fmt.Errorf("SASL XOAUTH2 auth failed with code %#00x: %s : %s", - v.Code, v.AdditionalData, s.errorResponse) - } - - // return to c.negotiateProto - s.conn.saslComplete = true - return s.conn.negotiateProto, nil - case *frames.SASLChallenge: - if s.errorResponse == nil { - s.errorResponse = v.Challenge - - timeout, err := s.conn.getWriteTimeout(ctx) - if err != nil { - return nil, err - } - - // The SASL protocol requires clients to send an empty response to this challenge. - err = s.conn.writeFrame(timeout, frames.Frame{ - Type: frames.TypeSASL, - Body: &frames.SASLResponse{ - Response: []byte{}, - }, - }) - if err != nil { - return nil, err - } - return s.step, nil - } else { - return nil, fmt.Errorf("SASL XOAUTH2 unexpected additional error response received during "+ - "exchange. Initial error response: %s, additional response: %s", s.errorResponse, v.Challenge) - } - default: - return nil, fmt.Errorf("sasl: unexpected frame type %T", fr.Body) - } -} - -func saslXOAUTH2InitialResponse(username string, bearer string) ([]byte, error) { - if len(bearer) == 0 { - return []byte{}, fmt.Errorf("unacceptable bearer token") - } - for _, char := range bearer { - if char < '\x20' || char > '\x7E' { - return []byte{}, fmt.Errorf("unacceptable bearer token") - } - } - for _, char := range username { - if char == '\x01' { - return []byte{}, fmt.Errorf("unacceptable username") - } - } - return []byte("user=" + username + "\x01auth=Bearer " + bearer + "\x01\x01"), nil -} diff --git a/sdk/messaging/azeventhubs/internal/go-amqp/sender.go b/sdk/messaging/azeventhubs/internal/go-amqp/sender.go deleted file mode 100644 index bb130ba17b2d..000000000000 --- a/sdk/messaging/azeventhubs/internal/go-amqp/sender.go +++ /dev/null @@ -1,476 +0,0 @@ -// Copyright (C) 2017 Kale Blankenship -// Portions Copyright (c) Microsoft Corporation - -package amqp - -import ( - "context" - "encoding/binary" - "errors" - "fmt" - "sync" - - "github.com/Azure/azure-sdk-for-go/sdk/messaging/azeventhubs/internal/go-amqp/internal/buffer" - "github.com/Azure/azure-sdk-for-go/sdk/messaging/azeventhubs/internal/go-amqp/internal/debug" - "github.com/Azure/azure-sdk-for-go/sdk/messaging/azeventhubs/internal/go-amqp/internal/encoding" - "github.com/Azure/azure-sdk-for-go/sdk/messaging/azeventhubs/internal/go-amqp/internal/frames" -) - -// Sender sends messages on a single AMQP link. -type Sender struct { - l link - transfers chan transferEnvelope // sender uses to send transfer frames - - mu sync.Mutex // protects buf and nextDeliveryTag - buf buffer.Buffer - nextDeliveryTag uint64 -} - -// LinkName() is the name of the link used for this Sender. -func (s *Sender) LinkName() string { - return s.l.key.name -} - -// MaxMessageSize is the maximum size of a single message. -func (s *Sender) MaxMessageSize() uint64 { - return s.l.maxMessageSize -} - -// SendOptions contains any optional values for the Sender.Send method. -type SendOptions struct { - // Indicates the message is to be sent as settled when settlement mode is SenderSettleModeMixed. - // If the settlement mode is SenderSettleModeUnsettled and Settled is true, an error is returned. - Settled bool -} - -// Send sends a Message. -// -// Blocks until the message is sent or an error occurs. If the peer is -// configured for receiver settlement mode second, the call also blocks -// until the peer confirms message settlement. -// -// - ctx controls waiting for the message to be sent and possibly confirmed -// - msg is the message to send -// - opts contains optional values, pass nil to accept the defaults -// -// If the context's deadline expires or is cancelled before the operation -// completes, the message is in an unknown state of transmission. -// -// Send is safe for concurrent use. Since only a single message can be -// sent on a link at a time, this is most useful when settlement confirmation -// has been requested (receiver settle mode is second). In this case, -// additional messages can be sent while the current goroutine is waiting -// for the confirmation. -func (s *Sender) Send(ctx context.Context, msg *Message, opts *SendOptions) error { - // check if the link is dead. while it's safe to call s.send - // in this case, this will avoid some allocations etc. - select { - case <-s.l.done: - return s.l.doneErr - default: - // link is still active - } - done, err := s.send(ctx, msg, opts) - if err != nil { - return err - } - - // wait for transfer to be confirmed - select { - case state := <-done: - if state, ok := state.(*encoding.StateRejected); ok { - if state.Error != nil { - return state.Error - } - return errors.New("the peer rejected the message without specifying an error") - } - return nil - case <-s.l.done: - return s.l.doneErr - case <-ctx.Done(): - // TODO: if the message is not settled and we never received a disposition, how can we consider the message as sent? - return ctx.Err() - } -} - -// send is separated from Send so that the mutex unlock can be deferred without -// locking the transfer confirmation that happens in Send. -func (s *Sender) send(ctx context.Context, msg *Message, opts *SendOptions) (chan encoding.DeliveryState, error) { - const ( - maxDeliveryTagLength = 32 - maxTransferFrameHeader = 66 // determined by calcMaxTransferFrameHeader - ) - if len(msg.DeliveryTag) > maxDeliveryTagLength { - return nil, fmt.Errorf("delivery tag is over the allowed %v bytes, len: %v", maxDeliveryTagLength, len(msg.DeliveryTag)) - } - - s.mu.Lock() - defer s.mu.Unlock() - - s.buf.Reset() - err := msg.Marshal(&s.buf) - if err != nil { - return nil, err - } - - if s.l.maxMessageSize != 0 && uint64(s.buf.Len()) > s.l.maxMessageSize { - return nil, fmt.Errorf("encoded message size exceeds max of %d", s.l.maxMessageSize) - } - - senderSettled := senderSettleModeValue(s.l.senderSettleMode) == SenderSettleModeSettled - if opts != nil { - if opts.Settled && senderSettleModeValue(s.l.senderSettleMode) == SenderSettleModeUnsettled { - return nil, errors.New("can't send message as settled when sender settlement mode is unsettled") - } else if opts.Settled { - senderSettled = true - } - } - - var ( - maxPayloadSize = int64(s.l.session.conn.peerMaxFrameSize) - maxTransferFrameHeader - ) - - deliveryTag := msg.DeliveryTag - if len(deliveryTag) == 0 { - // use uint64 encoded as []byte as deliveryTag - deliveryTag = make([]byte, 8) - binary.BigEndian.PutUint64(deliveryTag, s.nextDeliveryTag) - s.nextDeliveryTag++ - } - - fr := frames.PerformTransfer{ - Handle: s.l.handle, - DeliveryID: &needsDeliveryID, - DeliveryTag: deliveryTag, - MessageFormat: &msg.Format, - More: s.buf.Len() > 0, - } - - for fr.More { - buf, _ := s.buf.Next(maxPayloadSize) - fr.Payload = append([]byte(nil), buf...) - fr.More = s.buf.Len() > 0 - if !fr.More { - // SSM=settled: overrides RSM; no acks. - // SSM=unsettled: sender should wait for receiver to ack - // RSM=first: receiver considers it settled immediately, but must still send ack (SSM=unsettled only) - // RSM=second: receiver sends ack and waits for return ack from sender (SSM=unsettled only) - - // mark final transfer as settled when sender mode is settled - fr.Settled = senderSettled - - // set done on last frame - fr.Done = make(chan encoding.DeliveryState, 1) - } - - // NOTE: we MUST send a copy of fr here since we modify it post send - - sent := make(chan error, 1) - select { - case s.transfers <- transferEnvelope{Ctx: ctx, Frame: fr, Sent: sent}: - // frame was sent to our mux - case <-s.l.done: - return nil, s.l.doneErr - case <-ctx.Done(): - return nil, &Error{Condition: ErrCondTransferLimitExceeded, Description: fmt.Sprintf("credit limit exceeded for sending link %s", s.l.key.name)} - } - - select { - case err := <-sent: - if err != nil { - return nil, err - } - case <-s.l.done: - return nil, s.l.doneErr - } - - // clear values that are only required on first message - fr.DeliveryID = nil - fr.DeliveryTag = nil - fr.MessageFormat = nil - } - - return fr.Done, nil -} - -// Address returns the link's address. -func (s *Sender) Address() string { - if s.l.target == nil { - return "" - } - return s.l.target.Address -} - -// Close closes the Sender and AMQP link. -// - ctx controls waiting for the peer to acknowledge the close -// -// If the context's deadline expires or is cancelled before the operation -// completes, an error is returned. However, the operation will continue to -// execute in the background. Subsequent calls will return a *LinkError -// that contains the context's error message. -func (s *Sender) Close(ctx context.Context) error { - return s.l.closeLink(ctx) -} - -// newSendingLink creates a new sending link and attaches it to the session -func newSender(target string, session *Session, opts *SenderOptions) (*Sender, error) { - l := newLink(session, encoding.RoleSender) - l.target = &frames.Target{Address: target} - l.source = new(frames.Source) - s := &Sender{ - l: l, - } - - if opts == nil { - return s, nil - } - - for _, v := range opts.Capabilities { - s.l.source.Capabilities = append(s.l.source.Capabilities, encoding.Symbol(v)) - } - if opts.Durability > DurabilityUnsettledState { - return nil, fmt.Errorf("invalid Durability %d", opts.Durability) - } - s.l.source.Durable = opts.Durability - if opts.DynamicAddress { - s.l.target.Address = "" - s.l.dynamicAddr = opts.DynamicAddress - } - if opts.ExpiryPolicy != "" { - if err := encoding.ValidateExpiryPolicy(opts.ExpiryPolicy); err != nil { - return nil, err - } - s.l.source.ExpiryPolicy = opts.ExpiryPolicy - } - s.l.source.Timeout = opts.ExpiryTimeout - if opts.Name != "" { - s.l.key.name = opts.Name - } - if opts.Properties != nil { - s.l.properties = make(map[encoding.Symbol]any) - for k, v := range opts.Properties { - if k == "" { - return nil, errors.New("link property key must not be empty") - } - s.l.properties[encoding.Symbol(k)] = v - } - } - if opts.RequestedReceiverSettleMode != nil { - if rsm := *opts.RequestedReceiverSettleMode; rsm > ReceiverSettleModeSecond { - return nil, fmt.Errorf("invalid RequestedReceiverSettleMode %d", rsm) - } - s.l.receiverSettleMode = opts.RequestedReceiverSettleMode - } - if opts.SettlementMode != nil { - if ssm := *opts.SettlementMode; ssm > SenderSettleModeMixed { - return nil, fmt.Errorf("invalid SettlementMode %d", ssm) - } - s.l.senderSettleMode = opts.SettlementMode - } - s.l.source.Address = opts.SourceAddress - for _, v := range opts.TargetCapabilities { - s.l.target.Capabilities = append(s.l.target.Capabilities, encoding.Symbol(v)) - } - if opts.TargetDurability != DurabilityNone { - s.l.target.Durable = opts.TargetDurability - } - if opts.TargetExpiryPolicy != ExpiryPolicySessionEnd { - s.l.target.ExpiryPolicy = opts.TargetExpiryPolicy - } - if opts.TargetExpiryTimeout != 0 { - s.l.target.Timeout = opts.TargetExpiryTimeout - } - return s, nil -} - -func (s *Sender) attach(ctx context.Context) error { - if err := s.l.attach(ctx, func(pa *frames.PerformAttach) { - pa.Role = encoding.RoleSender - if pa.Target == nil { - pa.Target = new(frames.Target) - } - pa.Target.Dynamic = s.l.dynamicAddr - }, func(pa *frames.PerformAttach) { - if s.l.target == nil { - s.l.target = new(frames.Target) - } - - // if dynamic address requested, copy assigned name to address - if s.l.dynamicAddr && pa.Target != nil { - s.l.target.Address = pa.Target.Address - } - }); err != nil { - return err - } - - s.transfers = make(chan transferEnvelope) - - return nil -} - -type senderTestHooks struct { - MuxTransfer func() -} - -func (s *Sender) mux(hooks senderTestHooks) { - if hooks.MuxTransfer == nil { - hooks.MuxTransfer = nop - } - - defer func() { - close(s.l.done) - }() - -Loop: - for { - var outgoingTransfers chan transferEnvelope - if s.l.linkCredit > 0 { - debug.Log(1, "TX (Sender %p) (enable): target: %q, link credit: %d, deliveryCount: %d", s, s.l.target.Address, s.l.linkCredit, s.l.deliveryCount) - outgoingTransfers = s.transfers - } else { - debug.Log(1, "TX (Sender %p) (pause): target: %q, link credit: %d, deliveryCount: %d", s, s.l.target.Address, s.l.linkCredit, s.l.deliveryCount) - } - - closed := s.l.close - if s.l.closeInProgress { - // swap out channel so it no longer triggers - closed = nil - - // disable sending once closing is in progress. - // this prevents races with mux shutdown and - // the peer sending disposition frames. - outgoingTransfers = nil - } - - select { - // received frame - case q := <-s.l.rxQ.Wait(): - // populated queue - fr := *q.Dequeue() - s.l.rxQ.Release(q) - - // if muxHandleFrame returns an error it means the mux must terminate. - // note that in the case of a client-side close due to an error, nil - // is returned in order to keep the mux running to ack the detach frame. - if err := s.muxHandleFrame(fr); err != nil { - s.l.doneErr = err - return - } - - // send data - case env := <-outgoingTransfers: - hooks.MuxTransfer() - select { - case s.l.session.txTransfer <- env: - debug.Log(2, "TX (Sender %p): mux transfer to Session: %d, %s", s, s.l.session.channel, env.Frame) - // decrement link-credit after entire message transferred - if !env.Frame.More { - s.l.deliveryCount++ - s.l.linkCredit-- - // we are the sender and we keep track of the peer's link credit - debug.Log(3, "TX (Sender %p): link: %s, link credit: %d", s, s.l.key.name, s.l.linkCredit) - } - continue Loop - case <-s.l.close: - continue Loop - case <-s.l.session.done: - continue Loop - } - - case <-closed: - if s.l.closeInProgress { - // a client-side close due to protocol error is in progress - continue - } - - // sender is being closed by the client - s.l.closeInProgress = true - fr := &frames.PerformDetach{ - Handle: s.l.handle, - Closed: true, - } - s.l.txFrame(context.Background(), fr, nil) - - case <-s.l.session.done: - s.l.doneErr = s.l.session.doneErr - return - } - } -} - -// muxHandleFrame processes fr based on type. -// depending on the peer's RSM, it might return a disposition frame for sending -func (s *Sender) muxHandleFrame(fr frames.FrameBody) error { - debug.Log(2, "RX (Sender %p): %s", s, fr) - switch fr := fr.(type) { - // flow control frame - case *frames.PerformFlow: - // the sender's link-credit variable MUST be set according to this formula when flow information is given by the receiver: - // link-credit(snd) := delivery-count(rcv) + link-credit(rcv) - delivery-count(snd) - linkCredit := *fr.LinkCredit - s.l.deliveryCount - if fr.DeliveryCount != nil { - // DeliveryCount can be nil if the receiver hasn't processed - // the attach. That shouldn't be the case here, but it's - // what ActiveMQ does. - linkCredit += *fr.DeliveryCount - } - - s.l.linkCredit = linkCredit - - if !fr.Echo { - return nil - } - - var ( - // copy because sent by pointer below; prevent race - deliveryCount = s.l.deliveryCount - ) - - // send flow - resp := &frames.PerformFlow{ - Handle: &s.l.handle, - DeliveryCount: &deliveryCount, - LinkCredit: &linkCredit, // max number of messages - } - - select { - case s.l.session.tx <- frameBodyEnvelope{Ctx: context.Background(), FrameBody: resp}: - debug.Log(2, "TX (Sender %p): mux frame to Session (%p): %d, %s", s, s.l.session, s.l.session.channel, resp) - case <-s.l.close: - return nil - case <-s.l.session.done: - return s.l.session.doneErr - } - - case *frames.PerformDisposition: - if fr.Settled { - return nil - } - - // peer is in mode second, so we must send confirmation of disposition. - // NOTE: the ack must be sent through the session so it can close out - // the in-flight disposition. - dr := &frames.PerformDisposition{ - Role: encoding.RoleSender, - First: fr.First, - Last: fr.Last, - Settled: true, - } - - select { - case s.l.session.tx <- frameBodyEnvelope{Ctx: context.Background(), FrameBody: dr}: - debug.Log(2, "TX (Sender %p): mux frame to Session (%p): %d, %s", s, s.l.session, s.l.session.channel, dr) - case <-s.l.close: - return nil - case <-s.l.session.done: - return s.l.session.doneErr - } - - return nil - - default: - return s.l.muxHandleFrame(fr) - } - - return nil -} diff --git a/sdk/messaging/azeventhubs/internal/go-amqp/session.go b/sdk/messaging/azeventhubs/internal/go-amqp/session.go deleted file mode 100644 index 7a6cfd625441..000000000000 --- a/sdk/messaging/azeventhubs/internal/go-amqp/session.go +++ /dev/null @@ -1,792 +0,0 @@ -// Copyright (C) 2017 Kale Blankenship -// Portions Copyright (c) Microsoft Corporation - -package amqp - -import ( - "context" - "errors" - "fmt" - "math" - "sync" - - "github.com/Azure/azure-sdk-for-go/sdk/messaging/azeventhubs/internal/go-amqp/internal/bitmap" - "github.com/Azure/azure-sdk-for-go/sdk/messaging/azeventhubs/internal/go-amqp/internal/debug" - "github.com/Azure/azure-sdk-for-go/sdk/messaging/azeventhubs/internal/go-amqp/internal/encoding" - "github.com/Azure/azure-sdk-for-go/sdk/messaging/azeventhubs/internal/go-amqp/internal/frames" - "github.com/Azure/azure-sdk-for-go/sdk/messaging/azeventhubs/internal/go-amqp/internal/queue" -) - -// Default session options -const ( - defaultWindow = 5000 -) - -// SessionOptions contains the optional settings for configuring an AMQP session. -type SessionOptions struct { - // MaxLinks sets the maximum number of links (Senders/Receivers) - // allowed on the session. - // - // Minimum: 1. - // Default: 4294967295. - MaxLinks uint32 -} - -// Session is an AMQP session. -// -// A session multiplexes Receivers. -type Session struct { - channel uint16 // session's local channel - remoteChannel uint16 // session's remote channel, owned by conn.connReader - conn *Conn // underlying conn - tx chan frameBodyEnvelope // non-transfer frames to be sent; session must track disposition - txTransfer chan transferEnvelope // transfer frames to be sent; session must track disposition - - // frames destined for this session are added to this queue by conn.connReader - rxQ *queue.Holder[frames.FrameBody] - - // flow control - incomingWindow uint32 - outgoingWindow uint32 - needFlowCount uint32 - - handleMax uint32 - - // link management - linksMu sync.RWMutex // used to synchronize link handle allocation - linksByKey map[linkKey]*link // mapping of name+role link - handles *bitmap.Bitmap // allocated handles - - abandonedLinksMu sync.Mutex - abandonedLinks []*link - - // used for gracefully closing session - close chan struct{} // closed by calling Close(). it signals that the end performative should be sent - closeOnce sync.Once - - // part of internal public surface area - done chan struct{} // closed when the session has terminated (mux exited); DO NOT wait on this from within Session.mux() as it will never trigger! - endSent chan struct{} // closed when the end performative has been sent; once this is closed, links MUST NOT send any frames! - doneErr error // contains the mux error state; ONLY written to by the mux and MUST only be read from after done is closed! - closeErr error // contains the error state returned from Close(); ONLY Close() reads/writes this! -} - -func newSession(c *Conn, channel uint16, opts *SessionOptions) *Session { - s := &Session{ - conn: c, - channel: channel, - tx: make(chan frameBodyEnvelope), - txTransfer: make(chan transferEnvelope), - incomingWindow: defaultWindow, - outgoingWindow: defaultWindow, - handleMax: math.MaxUint32 - 1, - linksMu: sync.RWMutex{}, - linksByKey: make(map[linkKey]*link), - close: make(chan struct{}), - done: make(chan struct{}), - endSent: make(chan struct{}), - } - - if opts != nil { - if opts.MaxLinks != 0 { - // MaxLinks is the number of total links. - // handleMax is the max handle ID which starts - // at zero. so we decrement by one - s.handleMax = opts.MaxLinks - 1 - } - } - - // create handle map after options have been applied - s.handles = bitmap.New(s.handleMax) - - s.rxQ = queue.NewHolder(queue.New[frames.FrameBody](int(s.incomingWindow))) - - return s -} - -// waitForFrame waits for an incoming frame to be queued. -// it returns the next frame from the queue, or an error. -// the error is either from the context or conn.doneErr. -// not meant for consumption outside of session.go. -func (s *Session) waitForFrame(ctx context.Context) (frames.FrameBody, error) { - var q *queue.Queue[frames.FrameBody] - select { - case <-ctx.Done(): - return nil, ctx.Err() - case <-s.conn.done: - return nil, s.conn.doneErr - case q = <-s.rxQ.Wait(): - // populated queue - } - - fr := q.Dequeue() - s.rxQ.Release(q) - - return *fr, nil -} - -func (s *Session) begin(ctx context.Context) error { - // send Begin to server - begin := &frames.PerformBegin{ - NextOutgoingID: 0, - IncomingWindow: s.incomingWindow, - OutgoingWindow: s.outgoingWindow, - HandleMax: s.handleMax, - } - - if err := s.txFrameAndWait(ctx, begin); err != nil { - return err - } - - // wait for response - fr, err := s.waitForFrame(ctx) - if err != nil { - // if we exit before receiving the ack, our caller will clean up the channel. - // however, it does mean that the peer will now have assigned an outgoing - // channel ID that's not in use. - return err - } - - begin, ok := fr.(*frames.PerformBegin) - if !ok { - // this codepath is hard to hit (impossible?). if the response isn't a PerformBegin and we've not - // yet seen the remote channel number, the default clause in conn.connReader will protect us from that. - // if we have seen the remote channel number then it's likely the session.mux for that channel will - // either swallow the frame or blow up in some other way, both causing this call to hang. - // deallocate session on error. we can't call - // s.Close() as the session mux hasn't started yet. - debug.Log(1, "RX (Session %p): unexpected begin response frame %T", s, fr) - s.conn.deleteSession(s) - if err := s.conn.Close(); err != nil { - return err - } - return &ConnError{inner: fmt.Errorf("unexpected begin response: %#v", fr)} - } - - // start Session multiplexor - go s.mux(begin) - - return nil -} - -// Close closes the session. -// - ctx controls waiting for the peer to acknowledge the session is closed -// -// If the context's deadline expires or is cancelled before the operation -// completes, an error is returned. However, the operation will continue to -// execute in the background. Subsequent calls will return a *SessionError -// that contains the context's error message. -func (s *Session) Close(ctx context.Context) error { - var ctxErr error - s.closeOnce.Do(func() { - close(s.close) - - // once the mux has received the ack'ing end performative, the mux will - // exit which deletes the session and closes s.done. - select { - case <-s.done: - s.closeErr = s.doneErr - - case <-ctx.Done(): - // notify the caller that the close timed out/was cancelled. - // the mux will remain running and once the ack is received it will terminate. - ctxErr = ctx.Err() - - // record that the close timed out/was cancelled. - // subsequent calls to Close() will return this - debug.Log(1, "TX (Session %p) channel %d: %v", s, s.channel, ctxErr) - s.closeErr = &SessionError{inner: ctxErr} - } - }) - - if ctxErr != nil { - return ctxErr - } - - var sessionErr *SessionError - if errors.As(s.closeErr, &sessionErr) && sessionErr.RemoteErr == nil && sessionErr.inner == nil { - // an empty SessionError means the session was cleanly closed by the caller - return nil - } - return s.closeErr -} - -// txFrame sends a frame to the connWriter. -// - ctx is used to provide the write deadline -// - fr is the frame to write to net.Conn -// - sent is the optional channel that will contain the error if the write fails -func (s *Session) txFrame(ctx context.Context, fr frames.FrameBody, sent chan error) { - debug.Log(2, "TX (Session %p) mux frame to Conn (%p): %s", s, s.conn, fr) - s.conn.sendFrame(ctx, frames.Frame{ - Type: frames.TypeAMQP, - Channel: s.channel, - Body: fr, - }, sent) -} - -// txFrameAndWait sends a frame to the connWriter and waits for the write to complete -// - ctx is used to provide the write deadline -// - fr is the frame to write to net.Conn -func (s *Session) txFrameAndWait(ctx context.Context, fr frames.FrameBody) error { - sent := make(chan error, 1) - s.txFrame(ctx, fr, sent) - - select { - case err := <-sent: - return err - case <-s.conn.done: - return s.conn.doneErr - case <-s.done: - return s.doneErr - } -} - -// NewReceiver opens a new receiver link on the session. -// - ctx controls waiting for the peer to create a sending terminus -// - source is the name of the peer's sending terminus -// - opts contains optional values, pass nil to accept the defaults -// -// If the context's deadline expires or is cancelled before the operation -// completes, an error is returned. If the Receiver was successfully -// created, it will be cleaned up in future calls to NewReceiver. -func (s *Session) NewReceiver(ctx context.Context, source string, opts *ReceiverOptions) (*Receiver, error) { - r, err := newReceiver(source, s, opts) - if err != nil { - return nil, err - } - if err = r.attach(ctx); err != nil { - return nil, err - } - - go r.mux(receiverTestHooks{}) - - return r, nil -} - -// NewSender opens a new sender link on the session. -// - ctx controls waiting for the peer to create a receiver terminus -// - target is the name of the peer's receiver terminus -// - opts contains optional values, pass nil to accept the defaults -// -// If the context's deadline expires or is cancelled before the operation -// completes, an error is returned. If the Sender was successfully -// created, it will be cleaned up in future calls to NewSender. -func (s *Session) NewSender(ctx context.Context, target string, opts *SenderOptions) (*Sender, error) { - l, err := newSender(target, s, opts) - if err != nil { - return nil, err - } - if err = l.attach(ctx); err != nil { - return nil, err - } - - go l.mux(senderTestHooks{}) - - return l, nil -} - -func (s *Session) mux(remoteBegin *frames.PerformBegin) { - defer func() { - if s.doneErr == nil { - s.doneErr = &SessionError{} - } else if connErr := (&ConnError{}); !errors.As(s.doneErr, &connErr) { - // only wrap non-ConnError error types - var amqpErr *Error - if errors.As(s.doneErr, &amqpErr) { - s.doneErr = &SessionError{RemoteErr: amqpErr} - } else { - s.doneErr = &SessionError{inner: s.doneErr} - } - } - // Signal goroutines waiting on the session. - close(s.done) - }() - - var ( - links = make(map[uint32]*link) // mapping of remote handles to links - handlesByDeliveryID = make(map[uint32]uint32) // mapping of deliveryIDs to handles - deliveryIDByHandle = make(map[uint32]uint32) // mapping of handles to latest deliveryID - handlesByRemoteDeliveryID = make(map[uint32]uint32) // mapping of remote deliveryID to handles - - settlementByDeliveryID = make(map[uint32]chan encoding.DeliveryState) - - nextDeliveryID uint32 // tracks the next delivery ID for outgoing transfers - - // flow control values - nextOutgoingID uint32 - nextIncomingID = remoteBegin.NextOutgoingID - remoteIncomingWindow = remoteBegin.IncomingWindow - remoteOutgoingWindow = remoteBegin.OutgoingWindow - - closeInProgress bool // indicates the end performative has been sent - ) - - closeWithError := func(e1 *Error, e2 error) { - if closeInProgress { - debug.Log(3, "TX (Session %p): close already pending, discarding %v", s, e1) - return - } - - closeInProgress = true - s.doneErr = e2 - s.txFrame(context.Background(), &frames.PerformEnd{Error: e1}, nil) - close(s.endSent) - } - - for { - txTransfer := s.txTransfer - // disable txTransfer if flow control windows have been exceeded - if remoteIncomingWindow == 0 || s.outgoingWindow == 0 { - debug.Log(1, "TX (Session %p): disabling txTransfer - window exceeded. remoteIncomingWindow: %d outgoingWindow: %d", - s, remoteIncomingWindow, s.outgoingWindow) - txTransfer = nil - } - - tx := s.tx - closed := s.close - if closeInProgress { - // swap out channel so it no longer triggers - closed = nil - - // once the end performative is sent, we're not allowed to send any frames - tx = nil - txTransfer = nil - } - - // notes on client-side closing session - // when session is closed, we must keep the mux running until the ack'ing end performative - // has been received. during this window, the session is allowed to receive frames but cannot - // send them. - // client-side close happens either by user calling Session.Close() or due to mux initiated - // close due to a violation of some invariant (see sending &Error{} to s.close). in the case - // that both code paths have been triggered, we must be careful to preserve the error that - // triggered the mux initiated close so it can be surfaced to the caller. - - select { - // conn has completed, exit - case <-s.conn.done: - s.doneErr = s.conn.doneErr - return - - case <-closed: - if closeInProgress { - // a client-side close due to protocol error is in progress - continue - } - // session is being closed by the client - closeInProgress = true - s.txFrame(context.Background(), &frames.PerformEnd{}, nil) - close(s.endSent) - - // incoming frame - case q := <-s.rxQ.Wait(): - fr := *q.Dequeue() - s.rxQ.Release(q) - debug.Log(2, "RX (Session %p): %s", s, fr) - - switch body := fr.(type) { - // Disposition frames can reference transfers from more than one - // link. Send this frame to all of them. - case *frames.PerformDisposition: - start := body.First - end := start - if body.Last != nil { - end = *body.Last - } - for deliveryID := start; deliveryID <= end; deliveryID++ { - handles := handlesByDeliveryID - if body.Role == encoding.RoleSender { - handles = handlesByRemoteDeliveryID - } - - handle, ok := handles[deliveryID] - if !ok { - debug.Log(2, "RX (Session %p): role %s: didn't find deliveryID %d in handles map", s, body.Role, deliveryID) - continue - } - delete(handles, deliveryID) - - if body.Settled && body.Role == encoding.RoleReceiver { - // check if settlement confirmation was requested, if so - // confirm by closing channel - if done, ok := settlementByDeliveryID[deliveryID]; ok { - delete(settlementByDeliveryID, deliveryID) - select { - case done <- body.State: - default: - } - close(done) - } - } - - link, ok := links[handle] - if !ok { - closeWithError(&Error{ - Condition: ErrCondUnattachedHandle, - Description: "received disposition frame referencing a handle that's not in use", - }, fmt.Errorf("received disposition frame with unknown link handle %d", handle)) - continue - } - - s.muxFrameToLink(link, fr) - } - continue - case *frames.PerformFlow: - if body.NextIncomingID == nil { - // This is a protocol error: - // "[...] MUST be set if the peer has received - // the begin frame for the session" - closeWithError(&Error{ - Condition: ErrCondNotAllowed, - Description: "next-incoming-id not set after session established", - }, errors.New("protocol error: received flow without next-incoming-id after session established")) - continue - } - - // "When the endpoint receives a flow frame from its peer, - // it MUST update the next-incoming-id directly from the - // next-outgoing-id of the frame, and it MUST update the - // remote-outgoing-window directly from the outgoing-window - // of the frame." - nextIncomingID = body.NextOutgoingID - remoteOutgoingWindow = body.OutgoingWindow - - // "The remote-incoming-window is computed as follows: - // - // next-incoming-id(flow) + incoming-window(flow) - next-outgoing-id(endpoint) - // - // If the next-incoming-id field of the flow frame is not set, then remote-incoming-window is computed as follows: - // - // initial-outgoing-id(endpoint) + incoming-window(flow) - next-outgoing-id(endpoint)" - remoteIncomingWindow = body.IncomingWindow - nextOutgoingID - remoteIncomingWindow += *body.NextIncomingID - debug.Log(3, "RX (Session %p): flow - remoteOutgoingWindow: %d remoteIncomingWindow: %d nextOutgoingID: %d", s, remoteOutgoingWindow, remoteIncomingWindow, nextOutgoingID) - - // Send to link if handle is set - if body.Handle != nil { - link, ok := links[*body.Handle] - if !ok { - closeWithError(&Error{ - Condition: ErrCondUnattachedHandle, - Description: "received flow frame referencing a handle that's not in use", - }, fmt.Errorf("received flow frame with unknown link handle %d", body.Handle)) - continue - } - - s.muxFrameToLink(link, fr) - continue - } - - if body.Echo && !closeInProgress { - niID := nextIncomingID - resp := &frames.PerformFlow{ - NextIncomingID: &niID, - IncomingWindow: s.incomingWindow, - NextOutgoingID: nextOutgoingID, - OutgoingWindow: s.outgoingWindow, - } - s.txFrame(context.Background(), resp, nil) - } - - case *frames.PerformAttach: - // On Attach response link should be looked up by name, then added - // to the links map with the remote's handle contained in this - // attach frame. - // - // Note body.Role is the remote peer's role, we reverse for the local key. - s.linksMu.RLock() - link, linkOk := s.linksByKey[linkKey{name: body.Name, role: !body.Role}] - s.linksMu.RUnlock() - if !linkOk { - closeWithError(&Error{ - Condition: ErrCondNotAllowed, - Description: "received mismatched attach frame", - }, fmt.Errorf("protocol error: received mismatched attach frame %+v", body)) - continue - } - - link.remoteHandle = body.Handle - links[link.remoteHandle] = link - - s.muxFrameToLink(link, fr) - - case *frames.PerformTransfer: - s.needFlowCount++ - // "Upon receiving a transfer, the receiving endpoint will - // increment the next-incoming-id to match the implicit - // transfer-id of the incoming transfer plus one, as well - // as decrementing the remote-outgoing-window, and MAY - // (depending on policy) decrement its incoming-window." - nextIncomingID++ - // don't loop to intmax - if remoteOutgoingWindow > 0 { - remoteOutgoingWindow-- - } - link, ok := links[body.Handle] - if !ok { - closeWithError(&Error{ - Condition: ErrCondUnattachedHandle, - Description: "received transfer frame referencing a handle that's not in use", - }, fmt.Errorf("received transfer frame with unknown link handle %d", body.Handle)) - continue - } - - s.muxFrameToLink(link, fr) - - // if this message is received unsettled and link rcv-settle-mode == second, add to handlesByRemoteDeliveryID - if !body.Settled && body.DeliveryID != nil && link.receiverSettleMode != nil && *link.receiverSettleMode == ReceiverSettleModeSecond { - debug.Log(1, "RX (Session %p): adding handle to handlesByRemoteDeliveryID. delivery ID: %d", s, *body.DeliveryID) - handlesByRemoteDeliveryID[*body.DeliveryID] = body.Handle - } - - // Update peer's outgoing window if half has been consumed. - if s.needFlowCount >= s.incomingWindow/2 && !closeInProgress { - debug.Log(3, "RX (Session %p): channel %d: flow - s.needFlowCount(%d) >= s.incomingWindow(%d)/2\n", s, s.channel, s.needFlowCount, s.incomingWindow) - s.needFlowCount = 0 - nID := nextIncomingID - flow := &frames.PerformFlow{ - NextIncomingID: &nID, - IncomingWindow: s.incomingWindow, - NextOutgoingID: nextOutgoingID, - OutgoingWindow: s.outgoingWindow, - } - s.txFrame(context.Background(), flow, nil) - } - - case *frames.PerformDetach: - link, ok := links[body.Handle] - if !ok { - closeWithError(&Error{ - Condition: ErrCondUnattachedHandle, - Description: "received detach frame referencing a handle that's not in use", - }, fmt.Errorf("received detach frame with unknown link handle %d", body.Handle)) - continue - } - s.muxFrameToLink(link, fr) - - // we received a detach frame and sent it to the link. - // this was either the response to a client-side initiated - // detach or our peer detached us. either way, now that - // the link has processed the frame it's detached so we - // are safe to clean up its state. - delete(links, link.remoteHandle) - delete(deliveryIDByHandle, link.handle) - s.deallocateHandle(link) - - case *frames.PerformEnd: - // there are two possibilities: - // - this is the ack to a client-side Close() - // - the peer is ending the session so we must ack - - if closeInProgress { - return - } - - // peer detached us with an error, save it and send the ack - if body.Error != nil { - s.doneErr = body.Error - } - - fr := frames.PerformEnd{} - s.txFrame(context.Background(), &fr, nil) - - // per spec, when end is received, we're no longer allowed to receive frames - return - - default: - debug.Log(1, "RX (Session %p): unexpected frame: %s\n", s, body) - closeWithError(&Error{ - Condition: ErrCondInternalError, - Description: "session received unexpected frame", - }, fmt.Errorf("internal error: unexpected frame %T", body)) - } - - case env := <-txTransfer: - fr := &env.Frame - // record current delivery ID - var deliveryID uint32 - if fr.DeliveryID == &needsDeliveryID { - deliveryID = nextDeliveryID - fr.DeliveryID = &deliveryID - nextDeliveryID++ - deliveryIDByHandle[fr.Handle] = deliveryID - - // add to handleByDeliveryID if not sender-settled - if !fr.Settled { - handlesByDeliveryID[deliveryID] = fr.Handle - } - } else { - // if fr.DeliveryID is nil it must have been added - // to deliveryIDByHandle already - deliveryID = deliveryIDByHandle[fr.Handle] - } - - // log after the delivery ID has been assigned - debug.Log(2, "TX (Session %p): %d, %s", s, s.channel, fr) - - // frame has been sender-settled, remove from map - if fr.Settled { - delete(handlesByDeliveryID, deliveryID) - } - - s.txFrame(env.Ctx, fr, env.Sent) - if sendErr := <-env.Sent; sendErr != nil { - s.doneErr = sendErr - - // put the error back as our sender will read from this channel - env.Sent <- sendErr - return - } - - // if not settled, add done chan to map - if !fr.Settled && fr.Done != nil { - settlementByDeliveryID[deliveryID] = fr.Done - } else if fr.Done != nil { - // sender-settled, close done now that the transfer has been sent - close(fr.Done) - } - - // "Upon sending a transfer, the sending endpoint will increment - // its next-outgoing-id, decrement its remote-incoming-window, - // and MAY (depending on policy) decrement its outgoing-window." - nextOutgoingID++ - // don't decrement if we're at 0 or we could loop to int max - if remoteIncomingWindow != 0 { - remoteIncomingWindow-- - } - - case env := <-tx: - fr := env.FrameBody - debug.Log(2, "TX (Session %p): %d, %s", s, s.channel, fr) - switch fr := env.FrameBody.(type) { - case *frames.PerformDisposition: - if fr.Settled && fr.Role == encoding.RoleSender { - // sender with a peer that's in mode second; sending confirmation of disposition. - // disposition frames can reference a range of delivery IDs, although it's highly - // likely in this case there will only be one. - start := fr.First - end := start - if fr.Last != nil { - end = *fr.Last - } - for deliveryID := start; deliveryID <= end; deliveryID++ { - // send delivery state to the channel and close it to signal - // that the delivery has completed. - if done, ok := settlementByDeliveryID[deliveryID]; ok { - delete(settlementByDeliveryID, deliveryID) - select { - case done <- fr.State: - default: - } - close(done) - } - } - } - s.txFrame(env.Ctx, fr, env.Sent) - case *frames.PerformFlow: - niID := nextIncomingID - fr.NextIncomingID = &niID - fr.IncomingWindow = s.incomingWindow - fr.NextOutgoingID = nextOutgoingID - fr.OutgoingWindow = s.outgoingWindow - s.txFrame(context.Background(), fr, env.Sent) - case *frames.PerformTransfer: - panic("transfer frames must use txTransfer") - default: - s.txFrame(context.Background(), fr, env.Sent) - } - } - } -} - -func (s *Session) allocateHandle(ctx context.Context, l *link) error { - s.linksMu.Lock() - defer s.linksMu.Unlock() - - // Check if link name already exists, if so then an error should be returned - existing := s.linksByKey[l.key] - if existing != nil { - return fmt.Errorf("link with name '%v' already exists", l.key.name) - } - - next, ok := s.handles.Next() - if !ok { - if err := s.Close(ctx); err != nil { - return err - } - // handle numbers are zero-based, report the actual count - return &SessionError{inner: fmt.Errorf("reached session handle max (%d)", s.handleMax+1)} - } - - l.handle = next // allocate handle to the link - s.linksByKey[l.key] = l // add to mapping - - return nil -} - -func (s *Session) deallocateHandle(l *link) { - s.linksMu.Lock() - defer s.linksMu.Unlock() - - delete(s.linksByKey, l.key) - s.handles.Remove(l.handle) -} - -func (s *Session) abandonLink(l *link) { - s.abandonedLinksMu.Lock() - defer s.abandonedLinksMu.Unlock() - s.abandonedLinks = append(s.abandonedLinks, l) -} - -func (s *Session) freeAbandonedLinks(ctx context.Context) error { - s.abandonedLinksMu.Lock() - defer s.abandonedLinksMu.Unlock() - - debug.Log(3, "TX (Session %p): cleaning up %d abandoned links", s, len(s.abandonedLinks)) - - for _, l := range s.abandonedLinks { - dr := &frames.PerformDetach{ - Handle: l.handle, - Closed: true, - } - if err := s.txFrameAndWait(ctx, dr); err != nil { - return err - } - } - - s.abandonedLinks = nil - return nil -} - -func (s *Session) muxFrameToLink(l *link, fr frames.FrameBody) { - q := l.rxQ.Acquire() - q.Enqueue(fr) - l.rxQ.Release(q) - debug.Log(2, "RX (Session %p): mux frame to link (%p): %s, %s", s, l, l.key.name, fr) -} - -// transferEnvelope is used by senders to send transfer frames -type transferEnvelope struct { - Ctx context.Context - Frame frames.PerformTransfer - - // Sent is *never* nil as we use this for confirmation of sending - // NOTE: use a buffered channel of size 1 when populating - Sent chan error -} - -// frameBodyEnvelope is used by senders and receivers to send frames. -type frameBodyEnvelope struct { - Ctx context.Context - FrameBody frames.FrameBody - - // Sent *can* be nil depending on what frame is being sent. - // e.g. sending a disposition frame frame a receiver's settlement - // APIs will have a non-nil channel vs sending a flow frame - // NOTE: use a buffered channel of size 1 when populating - Sent chan error -} - -// the address of this var is a sentinel value indicating -// that a transfer frame is in need of a delivery ID -var needsDeliveryID uint32 diff --git a/sdk/messaging/azeventhubs/internal/links_test.go b/sdk/messaging/azeventhubs/internal/links_test.go index 50d9894bc9a9..40be4df96d74 100644 --- a/sdk/messaging/azeventhubs/internal/links_test.go +++ b/sdk/messaging/azeventhubs/internal/links_test.go @@ -13,8 +13,8 @@ import ( "github.com/Azure/azure-sdk-for-go/sdk/azcore/to" "github.com/Azure/azure-sdk-for-go/sdk/messaging/azeventhubs/internal/amqpwrap" "github.com/Azure/azure-sdk-for-go/sdk/messaging/azeventhubs/internal/exported" - "github.com/Azure/azure-sdk-for-go/sdk/messaging/azeventhubs/internal/go-amqp" "github.com/Azure/azure-sdk-for-go/sdk/messaging/azeventhubs/internal/test" + "github.com/Azure/go-amqp" "github.com/stretchr/testify/require" ) diff --git a/sdk/messaging/azeventhubs/internal/links_unit_test.go b/sdk/messaging/azeventhubs/internal/links_unit_test.go index f869135067c6..9f405f4ac011 100644 --- a/sdk/messaging/azeventhubs/internal/links_unit_test.go +++ b/sdk/messaging/azeventhubs/internal/links_unit_test.go @@ -9,9 +9,9 @@ import ( "testing" "github.com/Azure/azure-sdk-for-go/sdk/messaging/azeventhubs/internal/amqpwrap" - "github.com/Azure/azure-sdk-for-go/sdk/messaging/azeventhubs/internal/go-amqp" "github.com/Azure/azure-sdk-for-go/sdk/messaging/azeventhubs/internal/mock" "github.com/Azure/azure-sdk-for-go/sdk/messaging/azeventhubs/internal/test" + "github.com/Azure/go-amqp" "github.com/golang/mock/gomock" "github.com/stretchr/testify/require" ) diff --git a/sdk/messaging/azeventhubs/internal/mock/mock_amqp.go b/sdk/messaging/azeventhubs/internal/mock/mock_amqp.go index 4b67e349957a..400aa972eea2 100644 --- a/sdk/messaging/azeventhubs/internal/mock/mock_amqp.go +++ b/sdk/messaging/azeventhubs/internal/mock/mock_amqp.go @@ -13,7 +13,7 @@ import ( reflect "reflect" amqpwrap "github.com/Azure/azure-sdk-for-go/sdk/messaging/azeventhubs/internal/amqpwrap" - amqp "github.com/Azure/azure-sdk-for-go/sdk/messaging/azeventhubs/internal/go-amqp" + amqp "github.com/Azure/go-amqp" gomock "github.com/golang/mock/gomock" ) diff --git a/sdk/messaging/azeventhubs/internal/mock/mock_helpers.go b/sdk/messaging/azeventhubs/internal/mock/mock_helpers.go index 32577acb9db5..7ce47cd9c9d2 100644 --- a/sdk/messaging/azeventhubs/internal/mock/mock_helpers.go +++ b/sdk/messaging/azeventhubs/internal/mock/mock_helpers.go @@ -8,7 +8,7 @@ import ( "fmt" "time" - "github.com/Azure/azure-sdk-for-go/sdk/messaging/azeventhubs/internal/go-amqp" + "github.com/Azure/go-amqp" gomock "github.com/golang/mock/gomock" ) diff --git a/sdk/messaging/azeventhubs/internal/namespace.go b/sdk/messaging/azeventhubs/internal/namespace.go index 8f6b8dc34c8d..6fff62906bac 100644 --- a/sdk/messaging/azeventhubs/internal/namespace.go +++ b/sdk/messaging/azeventhubs/internal/namespace.go @@ -18,9 +18,9 @@ import ( "github.com/Azure/azure-sdk-for-go/sdk/messaging/azeventhubs/internal/amqpwrap" "github.com/Azure/azure-sdk-for-go/sdk/messaging/azeventhubs/internal/auth" "github.com/Azure/azure-sdk-for-go/sdk/messaging/azeventhubs/internal/exported" - "github.com/Azure/azure-sdk-for-go/sdk/messaging/azeventhubs/internal/go-amqp" "github.com/Azure/azure-sdk-for-go/sdk/messaging/azeventhubs/internal/sbauth" "github.com/Azure/azure-sdk-for-go/sdk/messaging/azeventhubs/internal/utils" + "github.com/Azure/go-amqp" ) var rootUserAgent = telemetry.Format("azeventhubs", Version) diff --git a/sdk/messaging/azeventhubs/internal/namespace_test.go b/sdk/messaging/azeventhubs/internal/namespace_test.go index 13973b73355a..5d0bd2615d74 100644 --- a/sdk/messaging/azeventhubs/internal/namespace_test.go +++ b/sdk/messaging/azeventhubs/internal/namespace_test.go @@ -16,9 +16,9 @@ import ( "github.com/Azure/azure-sdk-for-go/sdk/messaging/azeventhubs/internal/amqpwrap" "github.com/Azure/azure-sdk-for-go/sdk/messaging/azeventhubs/internal/auth" "github.com/Azure/azure-sdk-for-go/sdk/messaging/azeventhubs/internal/exported" - "github.com/Azure/azure-sdk-for-go/sdk/messaging/azeventhubs/internal/go-amqp" "github.com/Azure/azure-sdk-for-go/sdk/messaging/azeventhubs/internal/sbauth" "github.com/Azure/azure-sdk-for-go/sdk/messaging/azeventhubs/internal/test" + "github.com/Azure/go-amqp" "github.com/stretchr/testify/require" ) diff --git a/sdk/messaging/azeventhubs/internal/rpc.go b/sdk/messaging/azeventhubs/internal/rpc.go index 8d5bf1ff1765..ffad41d6dd15 100644 --- a/sdk/messaging/azeventhubs/internal/rpc.go +++ b/sdk/messaging/azeventhubs/internal/rpc.go @@ -14,7 +14,7 @@ import ( azlog "github.com/Azure/azure-sdk-for-go/sdk/internal/log" "github.com/Azure/azure-sdk-for-go/sdk/internal/uuid" "github.com/Azure/azure-sdk-for-go/sdk/messaging/azeventhubs/internal/amqpwrap" - "github.com/Azure/azure-sdk-for-go/sdk/messaging/azeventhubs/internal/go-amqp" + "github.com/Azure/go-amqp" ) const ( diff --git a/sdk/messaging/azeventhubs/internal/rpc_test.go b/sdk/messaging/azeventhubs/internal/rpc_test.go index cf39bd695c17..44c6affed55e 100644 --- a/sdk/messaging/azeventhubs/internal/rpc_test.go +++ b/sdk/messaging/azeventhubs/internal/rpc_test.go @@ -12,9 +12,9 @@ import ( "github.com/Azure/azure-sdk-for-go/sdk/internal/log" "github.com/Azure/azure-sdk-for-go/sdk/messaging/azeventhubs/internal/amqpwrap" - "github.com/Azure/azure-sdk-for-go/sdk/messaging/azeventhubs/internal/go-amqp" "github.com/Azure/azure-sdk-for-go/sdk/messaging/azeventhubs/internal/mock" "github.com/Azure/azure-sdk-for-go/sdk/messaging/azeventhubs/internal/test" + "github.com/Azure/go-amqp" "github.com/golang/mock/gomock" "github.com/stretchr/testify/require" ) diff --git a/sdk/messaging/azeventhubs/internal/test/test_helpers.go b/sdk/messaging/azeventhubs/internal/test/test_helpers.go index bfe1aa3c1bb0..97f7e5cfad83 100644 --- a/sdk/messaging/azeventhubs/internal/test/test_helpers.go +++ b/sdk/messaging/azeventhubs/internal/test/test_helpers.go @@ -40,6 +40,13 @@ func CaptureLogsForTest() func() []string { func CaptureLogsForTestWithChannel(messagesCh chan string) func() []string { setAzLogListener(func(e azlog.Event, s string) { + defer func() { + if err := recover(); err != nil { + fmt.Printf("FAILED SENDING MESSAGE (%s), message was: [%s] %s\n", err, e, s) + panic(err) + } + }() + messagesCh <- fmt.Sprintf("[%s] %s", e, s) }) diff --git a/sdk/messaging/azeventhubs/internal/utils/retrier_test.go b/sdk/messaging/azeventhubs/internal/utils/retrier_test.go index acae2d432949..cc3997bc3b06 100644 --- a/sdk/messaging/azeventhubs/internal/utils/retrier_test.go +++ b/sdk/messaging/azeventhubs/internal/utils/retrier_test.go @@ -14,7 +14,7 @@ import ( azlog "github.com/Azure/azure-sdk-for-go/sdk/internal/log" "github.com/Azure/azure-sdk-for-go/sdk/messaging/azeventhubs/internal/exported" - "github.com/Azure/azure-sdk-for-go/sdk/messaging/azeventhubs/internal/go-amqp" + "github.com/Azure/go-amqp" "github.com/stretchr/testify/require" ) diff --git a/sdk/messaging/azeventhubs/mgmt.go b/sdk/messaging/azeventhubs/mgmt.go index 333bf717d2a7..8c31e00bf198 100644 --- a/sdk/messaging/azeventhubs/mgmt.go +++ b/sdk/messaging/azeventhubs/mgmt.go @@ -13,7 +13,7 @@ import ( "github.com/Azure/azure-sdk-for-go/sdk/messaging/azeventhubs/internal" "github.com/Azure/azure-sdk-for-go/sdk/messaging/azeventhubs/internal/amqpwrap" "github.com/Azure/azure-sdk-for-go/sdk/messaging/azeventhubs/internal/eh" - "github.com/Azure/azure-sdk-for-go/sdk/messaging/azeventhubs/internal/go-amqp" + "github.com/Azure/go-amqp" ) // EventHubProperties represents properties of the Event Hub, like the number of partitions. diff --git a/sdk/messaging/azeventhubs/partition_client.go b/sdk/messaging/azeventhubs/partition_client.go index 8c5ab53fe8a3..238cb275babc 100644 --- a/sdk/messaging/azeventhubs/partition_client.go +++ b/sdk/messaging/azeventhubs/partition_client.go @@ -14,7 +14,7 @@ import ( "github.com/Azure/azure-sdk-for-go/sdk/messaging/azeventhubs/internal" "github.com/Azure/azure-sdk-for-go/sdk/messaging/azeventhubs/internal/amqpwrap" - "github.com/Azure/azure-sdk-for-go/sdk/messaging/azeventhubs/internal/go-amqp" + "github.com/Azure/go-amqp" ) // DefaultConsumerGroup is the name of the default consumer group in the Event Hubs service. @@ -184,7 +184,7 @@ func (pc *PartitionClient) ReceiveEvents(ctx context.Context, count int, options numEvents := len(events) lastSequenceNumber := events[numEvents-1].SequenceNumber - pc.offsetExpression = formatOffsetExpressionForSequence(">", lastSequenceNumber) + pc.offsetExpression = formatStartExpressionForSequence(">", lastSequenceNumber) log.Writef(EventConsumer, "%d Events received, moving sequence to %d", numEvents, lastSequenceNumber) return events, nil } @@ -274,7 +274,7 @@ func newPartitionClient(args partitionClientArgs, options *PartitionClientOption options = &PartitionClientOptions{} } - offsetExpr, err := getOffsetExpression(options.StartPosition) + offsetExpr, err := getStartExpression(options.StartPosition) if err != nil { return nil, err @@ -317,11 +317,11 @@ func getAllPrefetched(receiver amqpwrap.AMQPReceiver, max int) []*amqp.Message { return messages } -func getOffsetExpression(startPosition StartPosition) (string, error) { - lt := ">" +func getStartExpression(startPosition StartPosition) (string, error) { + gt := ">" if startPosition.Inclusive { - lt = ">=" + gt = ">=" } var errMultipleFieldsSet = errors.New("only a single start point can be set: Earliest, EnqueuedTime, Latest, Offset, or SequenceNumber") @@ -330,7 +330,7 @@ func getOffsetExpression(startPosition StartPosition) (string, error) { if startPosition.EnqueuedTime != nil { // time-based, non-inclusive - offsetExpr = fmt.Sprintf("amqp.annotation.x-opt-enqueued-time %s '%d'", lt, startPosition.EnqueuedTime.UnixMilli()) + offsetExpr = fmt.Sprintf("amqp.annotation.x-opt-enqueued-time %s '%d'", gt, startPosition.EnqueuedTime.UnixMilli()) } if startPosition.Offset != nil { @@ -340,7 +340,7 @@ func getOffsetExpression(startPosition StartPosition) (string, error) { return "", errMultipleFieldsSet } - offsetExpr = fmt.Sprintf("amqp.annotation.x-opt-offset %s '%d'", lt, *startPosition.Offset) + offsetExpr = fmt.Sprintf("amqp.annotation.x-opt-offset %s '%d'", gt, *startPosition.Offset) } if startPosition.Latest != nil && *startPosition.Latest { @@ -348,7 +348,7 @@ func getOffsetExpression(startPosition StartPosition) (string, error) { return "", errMultipleFieldsSet } - offsetExpr = "amqp.annotation.x-opt-offset > '@latest'" + offsetExpr = fmt.Sprintf("amqp.annotation.x-opt-offset %s '@latest'", gt) } if startPosition.SequenceNumber != nil { @@ -356,7 +356,7 @@ func getOffsetExpression(startPosition StartPosition) (string, error) { return "", errMultipleFieldsSet } - offsetExpr = formatOffsetExpressionForSequence(lt, *startPosition.SequenceNumber) + offsetExpr = formatStartExpressionForSequence(gt, *startPosition.SequenceNumber) } if startPosition.Earliest != nil && *startPosition.Earliest { @@ -375,6 +375,6 @@ func getOffsetExpression(startPosition StartPosition) (string, error) { return "amqp.annotation.x-opt-offset > '@latest'", nil } -func formatOffsetExpressionForSequence(op string, sequenceNumber int64) string { +func formatStartExpressionForSequence(op string, sequenceNumber int64) string { return fmt.Sprintf("amqp.annotation.x-opt-sequence-number %s '%d'", op, sequenceNumber) } diff --git a/sdk/messaging/azeventhubs/partition_client_unit_test.go b/sdk/messaging/azeventhubs/partition_client_unit_test.go index cbb570fadd8b..7560dbf7e209 100644 --- a/sdk/messaging/azeventhubs/partition_client_unit_test.go +++ b/sdk/messaging/azeventhubs/partition_client_unit_test.go @@ -10,8 +10,8 @@ import ( "time" "github.com/Azure/azure-sdk-for-go/sdk/messaging/azeventhubs/internal" - "github.com/Azure/azure-sdk-for-go/sdk/messaging/azeventhubs/internal/go-amqp" "github.com/Azure/azure-sdk-for-go/sdk/messaging/azeventhubs/internal/test" + "github.com/Azure/go-amqp" "github.com/stretchr/testify/require" ) diff --git a/sdk/messaging/azeventhubs/processor_load_balancer.go b/sdk/messaging/azeventhubs/processor_load_balancer.go index 419e227ee163..e708c6dd514b 100644 --- a/sdk/messaging/azeventhubs/processor_load_balancer.go +++ b/sdk/messaging/azeventhubs/processor_load_balancer.go @@ -8,7 +8,10 @@ import ( "fmt" "math" "math/rand" + "strings" "time" + + "github.com/Azure/azure-sdk-for-go/sdk/internal/log" ) type processorLoadBalancer struct { @@ -73,6 +76,7 @@ func (lb *processorLoadBalancer) LoadBalance(ctx context.Context, partitionIDs [ // - I have too many. We expect to have some stolen from us, but we'll maintain // ownership for now. claimMorePartitions = false + log.Writef(EventConsumer, "Owns %d/%d, no more needed", len(lbinfo.current), lbinfo.maxAllowed) } else if lbinfo.extraPartitionPossible && len(lbinfo.current) == lbinfo.maxAllowed-1 { // In the 'extraPartitionPossible' scenario, some consumers will have an extra partition // since things don't divide up evenly. We're one under the max, which means we _might_ @@ -81,6 +85,10 @@ func (lb *processorLoadBalancer) LoadBalance(ctx context.Context, partitionIDs [ // We will attempt to grab _one_ more but only if there are free partitions available // or if one of the consumers has more than the max allowed. claimMorePartitions = len(lbinfo.unownedOrExpired) > 0 || len(lbinfo.aboveMax) > 0 + log.Writef(EventConsumer, "Unowned/expired: %d, above max: %d, need to claim: %t", + len(lbinfo.unownedOrExpired), + len(lbinfo.aboveMax), + claimMorePartitions) } ownerships := lbinfo.current @@ -88,8 +96,10 @@ func (lb *processorLoadBalancer) LoadBalance(ctx context.Context, partitionIDs [ if claimMorePartitions { switch lb.strategy { case ProcessorStrategyGreedy: + log.Writef(EventConsumer, "Using greedy strategy to claim partitions") ownerships = lb.greedyLoadBalancer(ctx, lbinfo) case ProcessorStrategyBalanced: + log.Writef(EventConsumer, "Using balanced strategy to claim partitions") o := lb.balancedLoadBalancer(ctx, lbinfo) if o != nil { @@ -100,12 +110,34 @@ func (lb *processorLoadBalancer) LoadBalance(ctx context.Context, partitionIDs [ } } - return lb.checkpointStore.ClaimOwnership(ctx, ownerships, nil) + actual, err := lb.checkpointStore.ClaimOwnership(ctx, ownerships, nil) + + if err != nil { + return nil, err + } + + if log.Should(EventConsumer) { + log.Writef(EventConsumer, "[%0.5s] Asked for %s, got %s", lb.details.ClientID, partitionsForOwnerships(ownerships), partitionsForOwnerships(actual)) + } + + return actual, nil +} + +func partitionsForOwnerships(all []Ownership) string { + var parts []string + + for _, o := range all { + parts = append(parts, o.PartitionID) + } + + return strings.Join(parts, ",") } // getAvailablePartitions finds all partitions that are either completely unowned _or_ // their ownership is stale. func (lb *processorLoadBalancer) getAvailablePartitions(ctx context.Context, partitionIDs []string) (loadBalancerInfo, error) { + log.Writef(EventConsumer, "[%s] Listing ownership for %s/%s/%s", lb.details.ClientID, lb.details.FullyQualifiedNamespace, lb.details.EventHubName, lb.details.ConsumerGroup) + ownerships, err := lb.checkpointStore.ListOwnership(ctx, lb.details.FullyQualifiedNamespace, lb.details.EventHubName, lb.details.ConsumerGroup, nil) if err != nil { @@ -132,6 +164,9 @@ func (lb *processorLoadBalancer) getAvailablePartitions(ctx context.Context, par groupedByOwner[o.OwnerID] = append(groupedByOwner[o.OwnerID], o) } + numExpired := len(unownedOrExpired) + log.Writef(EventConsumer, "Expired: %d", numExpired) + // add in all the unowned partitions for _, partID := range partitionIDs { if alreadyAdded[partID] { @@ -149,6 +184,8 @@ func (lb *processorLoadBalancer) getAvailablePartitions(ctx context.Context, par }) } + log.Writef(EventConsumer, "Unowned: %d", len(unownedOrExpired)-numExpired) + maxAllowed := len(partitionIDs) / len(groupedByOwner) hasRemainder := len(partitionIDs)%len(groupedByOwner) > 0 @@ -188,6 +225,8 @@ func (lb *processorLoadBalancer) greedyLoadBalancer(ctx context.Context, lbinfo ours = append(ours, randomOwnerships...) if len(ours) < lbinfo.maxAllowed { + log.Writef(EventConsumer, "Not enough expired or unowned partitions, will need to steal from other processors") + // if that's not enough then we'll randomly steal from any owners that had partitions // above the maximum. randomOwnerships := getRandomOwnerships(lb.rnd, lbinfo.aboveMax, lbinfo.maxAllowed-len(ours)) @@ -197,6 +236,7 @@ func (lb *processorLoadBalancer) greedyLoadBalancer(ctx context.Context, lbinfo for i := 0; i < len(ours); i++ { ours[i] = lb.resetOwnership(ours[i]) } + return ours } @@ -225,7 +265,6 @@ func (lb *processorLoadBalancer) balancedLoadBalancer(ctx context.Context, lbinf } func (lb *processorLoadBalancer) resetOwnership(o Ownership) Ownership { - o.ETag = nil o.OwnerID = lb.details.ClientID return o } diff --git a/sdk/messaging/azeventhubs/processor_partition_client.go b/sdk/messaging/azeventhubs/processor_partition_client.go index da0f4eb402b8..cc52c533da5a 100644 --- a/sdk/messaging/azeventhubs/processor_partition_client.go +++ b/sdk/messaging/azeventhubs/processor_partition_client.go @@ -33,16 +33,19 @@ func (c *ProcessorPartitionClient) ReceiveEvents(ctx context.Context, count int, return c.innerClient.ReceiveEvents(ctx, count, options) } -// UpdateCheckpoint updates the checkpoint store. This ensure that if the Processor is restarted it will -// start from after this point. -func (p *ProcessorPartitionClient) UpdateCheckpoint(ctx context.Context, latestEvent *ReceivedEventData) error { - return p.checkpointStore.UpdateCheckpoint(ctx, Checkpoint{ +// UpdateCheckpoint updates the checkpoint in the CheckpointStore. New Processors will resume after +// this checkpoint for this partition. +func (p *ProcessorPartitionClient) UpdateCheckpoint(ctx context.Context, latestEvent *ReceivedEventData, options *UpdateCheckpointOptions) error { + seq := latestEvent.SequenceNumber + offset := latestEvent.Offset + + return p.checkpointStore.SetCheckpoint(ctx, Checkpoint{ ConsumerGroup: p.consumerClientDetails.ConsumerGroup, EventHubName: p.consumerClientDetails.EventHubName, FullyQualifiedNamespace: p.consumerClientDetails.FullyQualifiedNamespace, PartitionID: p.partitionID, - SequenceNumber: &latestEvent.SequenceNumber, - Offset: latestEvent.Offset, + SequenceNumber: &seq, + Offset: &offset, }, nil) } @@ -63,3 +66,8 @@ func (c *ProcessorPartitionClient) Close(ctx context.Context) error { return nil } + +// UpdateCheckpointOptions contains optional parameters for the [ProcessorPartitionClient.UpdateCheckpoint] function. +type UpdateCheckpointOptions struct { + // For future expansion +} diff --git a/sdk/messaging/azeventhubs/processor_test.go b/sdk/messaging/azeventhubs/processor_test.go index 136c3391066a..e08771110439 100644 --- a/sdk/messaging/azeventhubs/processor_test.go +++ b/sdk/messaging/azeventhubs/processor_test.go @@ -95,9 +95,7 @@ func TestProcessor_Contention(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) - processor, err := azeventhubs.NewProcessor(consumerClient, checkpointStore, &azeventhubs.ProcessorOptions{ - UpdateInterval: 10 * time.Second, - }) + processor, err := azeventhubs.NewProcessor(consumerClient, checkpointStore, nil) require.NoError(t, err) processors = append(processors, testData{ @@ -142,8 +140,8 @@ func TestProcessor_Contention(t *testing.T) { nextCtx, cancelNext := context.WithCancel(context.Background()) defer cancelNext() - // arbitrary, but basically if we go 20 seconds without a new partition acquisition we're probably balanced. - const idleInterval = 20 * time.Second + // arbitrary interval, we just want to give enough time that things seem balanced. + const idleInterval = 10 * time.Second active := time.AfterFunc(idleInterval, cancelNext) for { @@ -160,7 +158,7 @@ func TestProcessor_Contention(t *testing.T) { active.Reset(time.Minute) } - t.Logf("%s hasn't received a new partition in %sseconds", procStuff.name, idleInterval/time.Second) + t.Logf("%s hasn't received a new partition in %s", procStuff.name, idleInterval) }(client) } @@ -403,7 +401,7 @@ func processEventsForTest(t *testing.T, producerClient *azeventhubs.ProducerClie t.Logf("Updating checkpoint for partition %s", partitionClient.PartitionID()) - if err := partitionClient.UpdateCheckpoint(context.TODO(), events[len(events)-1]); err != nil { + if err := partitionClient.UpdateCheckpoint(context.TODO(), events[len(events)-1], nil); err != nil { return err } diff --git a/sdk/messaging/azeventhubs/processor_unit_test.go b/sdk/messaging/azeventhubs/processor_unit_test.go index c21b31e8c77e..950ec342d18e 100644 --- a/sdk/messaging/azeventhubs/processor_unit_test.go +++ b/sdk/messaging/azeventhubs/processor_unit_test.go @@ -224,7 +224,7 @@ func TestUnit_Processor_Run_singleConsumerPerPartition(t *testing.T) { func TestUnit_Processor_Run_startPosition(t *testing.T) { cps := newCheckpointStoreForTest() - err := cps.UpdateCheckpoint(context.Background(), Checkpoint{ + err := cps.SetCheckpoint(context.Background(), Checkpoint{ ConsumerGroup: "consumer-group", EventHubName: "event-hub", FullyQualifiedNamespace: "fqdn", @@ -236,7 +236,7 @@ func TestUnit_Processor_Run_startPosition(t *testing.T) { fakeConsumerClient := simpleFakeConsumerClient() fakeConsumerClient.newPartitionClientFn = func(partitionID string, options *PartitionClientOptions) (*PartitionClient, error) { - offsetExpr, err := getOffsetExpression(options.StartPosition) + offsetExpr, err := getStartExpression(options.StartPosition) require.NoError(t, err) return newFakePartitionClient(partitionID, offsetExpr), nil @@ -266,7 +266,7 @@ func TestUnit_Processor_Run_startPosition(t *testing.T) { err = partClient.UpdateCheckpoint(context.Background(), &ReceivedEventData{ SequenceNumber: 405, - }) + }, nil) require.NoError(t, err) checkpoints, err = cps.ListCheckpoints(context.Background(), processor.consumerClientDetails.FullyQualifiedNamespace, diff --git a/sdk/messaging/azeventhubs/producer_client.go b/sdk/messaging/azeventhubs/producer_client.go index 4d85956ff2ac..f887e265838b 100644 --- a/sdk/messaging/azeventhubs/producer_client.go +++ b/sdk/messaging/azeventhubs/producer_client.go @@ -17,7 +17,7 @@ import ( "github.com/Azure/azure-sdk-for-go/sdk/messaging/azeventhubs/internal" "github.com/Azure/azure-sdk-for-go/sdk/messaging/azeventhubs/internal/amqpwrap" "github.com/Azure/azure-sdk-for-go/sdk/messaging/azeventhubs/internal/exported" - "github.com/Azure/azure-sdk-for-go/sdk/messaging/azeventhubs/internal/go-amqp" + "github.com/Azure/go-amqp" ) // WebSocketConnParams are passed to your web socket creation function (ClientOptions.NewWebSocketConn) diff --git a/sdk/messaging/azservicebus/CHANGELOG.md b/sdk/messaging/azservicebus/CHANGELOG.md index 85df8928245c..d7af17b754fe 100644 --- a/sdk/messaging/azservicebus/CHANGELOG.md +++ b/sdk/messaging/azservicebus/CHANGELOG.md @@ -1,6 +1,6 @@ # Release History -## 1.3.0 (2023-04-11) +## 1.3.0 (2023-05-09) ### Features Added @@ -11,6 +11,8 @@ - Authentication errors could cause unnecessary retries, making calls taking longer to fail. (PR#20447) - Recovery now includes internal timeouts and also handles restarting a connection if AMQP primitives aren't closed cleanly. - Potential leaks for $cbs and $management when there was a partial failure. (PR#20564) +- Sending a message to an entity that is full will no longer retry. (PR#20722) +- Sending a message that is larger than what the link supports now returns ErrMessageTooLarge. (PR#20721) - Latest go-amqp changes have been merged in with fixes for robustness. ## 1.2.1 (2023-03-07) @@ -38,7 +40,7 @@ ### Bugs Fixed -- Removing changes for client-side idle timer and closing without timeout. Combined these are +- Removing changes for client-side idle timer and closing without timeout. Combined these are causing issues with links not properly recovering or closing. Investigating an alternative for a future release. @@ -46,7 +48,7 @@ ### Features Added -- Added a client-side idle timer which will reset Receiver links, transparently, if the link is idle for +- Added a client-side idle timer which will reset Receiver links, transparently, if the link is idle for 5 minutes. ### Bugs Fixed @@ -57,8 +59,8 @@ ### Bugs Fixed -- AcceptNextSessionForQueue and AcceptNextSessionForSubscription now return an azservicebus.Error with - Code set to CodeTimeout when they fail due to no sessions being available. Examples for this have +- AcceptNextSessionForQueue and AcceptNextSessionForSubscription now return an azservicebus.Error with + Code set to CodeTimeout when they fail due to no sessions being available. Examples for this have been added for `AcceptNextSessionForQueue`. PR#19113. - Retries now respect cancellation when they're in the "delay before next try" phase. @@ -66,19 +68,19 @@ ### Features Added -- Full access to send and receive all AMQP message properties. (#18413) +- Full access to send and receive all AMQP message properties. (#18413) - Send AMQP messages using the new `AMQPAnnotatedMessage` type and `Sender.SendAMQPAnnotatedMessage()`. - AMQP messages can be added to MessageBatch's as well using `MessageBatch.AddAMQPAnnotatedMessage()`. - AMQP messages can be scheduled using `Sender.ScheduleAMQPAnnotatedMessages`. - - Access the full set of AMQP message properties when receiving using the `ReceivedMessage.RawAMQPMessage` property. + - Access the full set of AMQP message properties when receiving using the `ReceivedMessage.RawAMQPMessage` property. ### Bugs Fixed -- Changed receive messages algorithm to avoid messages being excessively locked in Service Bus without +- Changed receive messages algorithm to avoid messages being excessively locked in Service Bus without being transferred to the client. (PR#18657) - Updating go-amqp, which fixes several bugs related to incorrect message locking (PR#18599) - - Requesting large quantities of messages in a single ReceiveMessages() call could result in messages - not being delivered, but still incrementing their delivery count and requiring the message lock + - Requesting large quantities of messages in a single ReceiveMessages() call could result in messages + not being delivered, but still incrementing their delivery count and requiring the message lock timeout to expire. - Link detach could result in messages being ignored, requiring the message lock timeout to expire. - Subscription rules weren't deserializing properly when created from the portal (PR#18813) @@ -87,11 +89,11 @@ ### Features Added -- Full access to send and receive all AMQP message properties. (#18413) +- Full access to send and receive all AMQP message properties. (#18413) - Send AMQP messages using the new `AMQPAnnotatedMessage` type and `Sender.SendAMQPAnnotatedMessage()`. - AMQP messages can be added to MessageBatch's as well using `MessageBatch.AddAMQPAnnotatedMessage()`. - AMQP messages can be scheduled using `Sender.ScheduleAMQPAnnotatedMessages`. - - Access the full set of AMQP message properties when receiving using the `ReceivedMessage.RawAMQPMessage` property. + - Access the full set of AMQP message properties when receiving using the `ReceivedMessage.RawAMQPMessage` property. ### Bugs Fixed @@ -107,7 +109,7 @@ ### Bugs Fixed - Handle a missing CountDetails node in the returned responses for GetRuntimeProperties which could cause a panic. (#18213) -- Adding the `associated-link-name` property to management operations (RenewLock, settlement and others), which +- Adding the `associated-link-name` property to management operations (RenewLock, settlement and others), which can help extend link lifetime (#18291) - Namespace closing didn't reset the internal client, which could lead to connection recovery thrashing. (#18323) @@ -122,16 +124,16 @@ ### Features Added - Exported log.Event constants for azservicebus. This will make them easier to - discover and they are also documented. NOTE: The log messages themselves + discover and they are also documented. NOTE: The log messages themselves are not guaranteed to be stable. (#17596) -- `admin.Client` can now manage authorization rules and subscription filters and +- `admin.Client` can now manage authorization rules and subscription filters and actions. (#17616) - Exported an official `*azservicebus.Error` type that gets returned if the failure is actionable. This can indicate if the connection was lost and could not be recovered with the configured retries or if a message lock was lost, which would cause - message settlement to fail. + message settlement to fail. - See the `ExampleReceiver_ReceiveMessages` in example_receiver_test.go for an example + See the `ExampleReceiver_ReceiveMessages` in example_receiver_test.go for an example on how to use it. (#17786) ### Breaking Changes @@ -142,7 +144,7 @@ ### Bugs Fixed -- Fixing issue where the AcceptNextSessionForQueue and AcceptNextSessionForSubscription +- Fixing issue where the AcceptNextSessionForQueue and AcceptNextSessionForSubscription couldn't be cancelled, forcing the user to wait for the service to timeout. (#17598) - Fixing bug where there was a chance that internally cached messages would not be returned when the receiver was draining. (#17893) @@ -158,7 +160,7 @@ - Fixed bug where message batch size calculation was inaccurate, resulting in batches that were too large to be sent. (#17318) - Fixing an issue with an entity not being found leading to a longer timeout than needed. (#17279) - Fixed the RPCLink so it does better handling of connection/link failures. (#17389) -- Fixed issue where a message lock expiring would cause unnecessary retries. These retries could cause message settlement calls (ex: Receiver.CompleteMessage) +- Fixed issue where a message lock expiring would cause unnecessary retries. These retries could cause message settlement calls (ex: Receiver.CompleteMessage) to appear to hang. (#17382) - Fixed issue where a cancellation on ReceiveMessages() would work, but wouldn't return the proper cancellation error. (#17422) @@ -168,54 +170,60 @@ - Multiple functions have had `options` parameters added. - `SessionReceiver.RenewMessageLock` has been removed - it isn't used for sessions. SessionReceivers should use `SessionReceiver.RenewSessionLock`. - The `admin.Client` type has been changed to conform with the latest Azure Go SDK guidelines. As part of this: + - Embedded `*Result` structs in `admin.Client`'s APIs have been removed. Inner *Properties values have been hoisted up to the `*Response` instead. - - `.Response` fields have been removed for successful results. These will be added back using a different pattern in the next release. - - Fields that were of type `time.Duration` have been changed to `*string`, where the value of the string is an ISO8601 timestamp. - Affected fields from Queues, Topics and Subscriptions: AutoDeleteOnIdle, DefaultMessageTimeToLive, DuplicateDetectionHistoryTimeWindow, LockDuration. + - `.Response` fields have been removed for successful results. These will be added back using a different pattern in the next release. + - Fields that were of type `time.Duration` have been changed to `*string`, where the value of the string is an ISO8601 timestamp. + Affected fields from Queues, Topics and Subscriptions: AutoDeleteOnIdle, DefaultMessageTimeToLive, DuplicateDetectionHistoryTimeWindow, LockDuration. - Properties that were passed as a parameter to CreateQueue, CreateTopic or CreateSubscription are now in the `options` parameter (as they were optional): Previously: + ```go // older code - adminClient.CreateQueue(context.Background(), queueName, &queueProperties, nil) + adminClient.CreateQueue(context.Background(), queueName, &queueProperties, nil) ``` And now: + ```go // new code adminClient.CreateQueue(context.Background(), queueName, &admin.CreateQueueOptions{ Properties: queueProperties, }) - ``` + ``` + - Pagers have been changed to use the new generics-based `runtime.Pager`: - + Previously: + ```go // older code for queuePager.NextPage(context.TODO()) { - for _, queue := range queuePager.PageResponse().Items { - fmt.Printf("Queue name: %s, max size in MB: %d\n", queue.QueueName, *queue.MaxSizeInMegabytes) - } - } - + for _, queue := range queuePager.PageResponse().Items { + fmt.Printf("Queue name: %s, max size in MB: %d\n", queue.QueueName, *queue.MaxSizeInMegabytes) + } + } + if err := queuePager.Err(); err != nil { panic(err) } ``` + And now: ```go // new code for queuePager.More() { - page, err := queuePager.NextPage(context.TODO()) + page, err := queuePager.NextPage(context.TODO()) - if err != nil { - panic(err) - } + if err != nil { + panic(err) + } - for _, queue := range page.Queues { - fmt.Printf("Queue name: %s, max size in MB: %d\n", queue.QueueName, *queue.MaxSizeInMegabytes) - } - } + for _, queue := range page.Queues { + fmt.Printf("Queue name: %s, max size in MB: %d\n", queue.QueueName, *queue.MaxSizeInMegabytes) + } + } ``` ## 0.3.6 (2022-03-08) @@ -248,7 +256,7 @@ ### Bugs Fixed -- Fix unaligned 64-bit atomic operation on mips. Thanks to @jackesdavid for contributing this fix. (#16847) +- Fix unaligned 64-bit atomic operation on mips. Thanks to @jackesdavid for contributing this fix. (#16847) - Multiple fixes to address connection/link recovery (#16831) - Fixing panic() when the links haven't been initialized (early cancellation) (#16941) - Handle 500 as a retryable code (no recovery needed) (#16925) @@ -259,7 +267,7 @@ - Support the pass-through of an Application ID when constructing an Azure Service Bus Client. PR#16558 (thanks halspang!) -### Bugs Fixed +### Bugs Fixed - Fixing connection/link recovery in Sender.SendMessages() and Sender.SendMessageBatch(). PR#16790 - Fixing bug in the management link which could cause it to panic during recovery. PR#16790 @@ -268,13 +276,13 @@ ### Features Added -- Enabling websocket support via `ClientOptions.NewWebSocketConn`. For an example, see the `ExampleNewClient_usingWebsockets` +- Enabling websocket support via `ClientOptions.NewWebSocketConn`. For an example, see the `ExampleNewClient_usingWebsockets` function in `example_client_test.go`. ### Breaking Changes -- Message properties that come from the standard AMQP message have been made into pointers, to allow them to be - properly omitted (or indicate that they've been omitted) when sending and receiving. +- Message properties that come from the standard AMQP message have been made into pointers, to allow them to be + properly omitted (or indicate that they've been omitted) when sending and receiving. ### Bugs Fixed @@ -283,13 +291,14 @@ - Attempting to settle messages received in ReceiveAndDelete mode would cause a panic. PR#16255 ### Other Changes + - Removed legacy dependencies, resulting in a much smaller package. ## 0.3.1 (2021-11-16) ### Bugs Fixed -- Updating go-amqp to v0.16.4 to fix a race condition found when running `go test -race`. Thanks to @peterzeller for reporting this issue. PR: #16168 +- Updating go-amqp to v0.16.4 to fix a race condition found when running `go test -race`. Thanks to @peterzeller for reporting this issue. PR: #16168 ## 0.3.0 (2021-11-12) @@ -303,27 +312,27 @@ - AdminClient has been moved into the `admin` subpackage. - ReceivedMessage.Body is now a function that returns a ([]byte, error), rather than being a field. - This protects against a potential data-loss scenario where a message is received with a payload + This protects against a potential data-loss scenario where a message is received with a payload encoded in the sequence or value sections of an AMQP message, which cannot be properly represented in the .Body. This will now return an error. -- Functions that have options or might have options in the future have an additional *options parameter. +- Functions that have options or might have options in the future have an additional \*options parameter. As usual, passing 'nil' ignores the options, and will cause the function to use defaults. -- MessageBatch.Add() has been renamed to MessageBatch.AddMessage(). AddMessage() now returns only an `error`, +- MessageBatch.Add() has been renamed to MessageBatch.AddMessage(). AddMessage() now returns only an `error`, with a sentinel error (ErrMessageTooLarge) signaling that the batch cannot fit a new message. - Sender.SendMessages() has been removed in favor of simplifications made in MessageBatch. ### Bugs Fixed -- ReceiveMessages has been tuned to match the .NET limits (which has worked well in practice). This partly addresses #15963, +- ReceiveMessages has been tuned to match the .NET limits (which has worked well in practice). This partly addresses #15963, as our default limit was far higher than needed. ## 0.2.0 (2021-11-02) ### Features Added -- Scheduling messages to be delivered at a later date, via the `Sender.ScheduleMessage(s)` function or +- Scheduling messages to be delivered at a later date, via the `Sender.ScheduleMessage(s)` function or setting `Message.ScheduledEnqueueTime`. -- Added in the `Sender.SendMessages([slice of sendable messages])` function, which batches messages +- Added in the `Sender.SendMessages([slice of sendable messages])` function, which batches messages automatically. Useful when you're sending multiple messages that you are already sure will be small enough to fit into a single batch. - Receiving from sessions using a SessionReceiver, created using Client.AcceptSessionFor(Queue|Subscription) @@ -338,4 +347,4 @@ ## 0.1.0 (2021-10-05) -- Initial preview for the new version of the Azure Service Bus Go SDK. +- Initial preview for the new version of the Azure Service Bus Go SDK. diff --git a/sdk/messaging/azservicebus/amqp_message.go b/sdk/messaging/azservicebus/amqp_message.go index c7484257994f..b96eb98d19c4 100644 --- a/sdk/messaging/azservicebus/amqp_message.go +++ b/sdk/messaging/azservicebus/amqp_message.go @@ -6,7 +6,7 @@ package azservicebus import ( "time" - "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus/internal/go-amqp" + "github.com/Azure/go-amqp" ) // AMQPAnnotatedMessage represents the AMQP message, as received from Service Bus. diff --git a/sdk/messaging/azservicebus/client_test.go b/sdk/messaging/azservicebus/client_test.go index fd7e7bf37732..e4eef534558a 100644 --- a/sdk/messaging/azservicebus/client_test.go +++ b/sdk/messaging/azservicebus/client_test.go @@ -442,14 +442,16 @@ func TestClientUnauthorizedCreds(t *testing.T) { }) t.Run("invalid identity creds", func(t *testing.T) { - tenantID := os.Getenv("AZURE_TENANT_ID") - clientID := os.Getenv("AZURE_CLIENT_ID") - endpoint := os.Getenv("SERVICEBUS_ENDPOINT") + identityVars := test.GetIdentityVars(t) - cliCred, err := azidentity.NewClientSecretCredential(tenantID, clientID, "bogus-client-secret", nil) + if identityVars == nil { + return + } + + cliCred, err := azidentity.NewClientSecretCredential(identityVars.TenantID, identityVars.ClientID, "bogus-client-secret", nil) require.NoError(t, err) - client, err := NewClient(endpoint, cliCred, nil) + client, err := NewClient(identityVars.Endpoint, cliCred, nil) require.NoError(t, err) defer test.RequireClose(t, client) diff --git a/sdk/messaging/azservicebus/go.mod b/sdk/messaging/azservicebus/go.mod index 3b70a5f5868e..1c391b1f80c9 100644 --- a/sdk/messaging/azservicebus/go.mod +++ b/sdk/messaging/azservicebus/go.mod @@ -8,6 +8,7 @@ require ( github.com/Azure/azure-sdk-for-go/sdk/azcore v1.4.0 github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.0.0 github.com/Azure/azure-sdk-for-go/sdk/internal v1.2.0 + github.com/Azure/go-amqp v1.0.0 ) require ( @@ -16,7 +17,7 @@ require ( // used in stress tests github.com/microsoft/ApplicationInsights-Go v0.4.4 - github.com/stretchr/testify v1.7.0 + github.com/stretchr/testify v1.7.1 // used in examples only nhooyr.io/websocket v1.8.7 @@ -30,7 +31,6 @@ require ( github.com/davecgh/go-spew v1.1.1 // indirect github.com/gofrs/uuid v3.3.0+incompatible // indirect github.com/golang-jwt/jwt v3.2.1+incompatible // indirect - github.com/google/go-cmp v0.5.1 // indirect github.com/google/uuid v1.1.1 // indirect github.com/klauspost/compress v1.10.3 // indirect github.com/kylelemons/godebug v1.1.0 // indirect diff --git a/sdk/messaging/azservicebus/go.sum b/sdk/messaging/azservicebus/go.sum index 69c9fadf8fe8..1cefd2440d19 100644 --- a/sdk/messaging/azservicebus/go.sum +++ b/sdk/messaging/azservicebus/go.sum @@ -6,12 +6,15 @@ github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.0.0 h1:Yoicul8bnVdQrhDMTHxdE github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.0.0/go.mod h1:+6sju8gk8FRmSajX3Oz4G5Gm7P+mbqE9FVaXXFYTkCM= github.com/Azure/azure-sdk-for-go/sdk/internal v1.2.0 h1:leh5DwKv6Ihwi+h60uHtn6UWAxBbZ0q8DwQVMzf61zw= github.com/Azure/azure-sdk-for-go/sdk/internal v1.2.0/go.mod h1:eWRD7oawr1Mu1sLCawqVc0CUiF43ia3qQMxLscsKQ9w= +github.com/Azure/go-amqp v1.0.0 h1:QfCugi1M+4F2JDTRgVnRw7PYXLXZ9hmqk3+9+oJh3OA= +github.com/Azure/go-amqp v1.0.0/go.mod h1:+bg0x3ce5+Q3ahCEXnCsGG3ETpDQe3MEVnOuT2ywPwc= github.com/AzureAD/microsoft-authentication-library-for-go v0.4.0 h1:WVsrXCnHlDDX8ls+tootqRE87/hL9S/g4ewig9RsD/c= github.com/AzureAD/microsoft-authentication-library-for-go v0.4.0/go.mod h1:Vt9sXTKwMyGcOxSmLDMnGPgqsUg7m8pe215qMLrDXw4= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/dnaeon/go-vcr v1.1.0 h1:ReYa/UBrRyQdant9B4fNHGoCNKw6qh6P0fsdGmZpR7c= +github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8vw= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= @@ -42,8 +45,7 @@ github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaW github.com/golang/protobuf v1.3.5 h1:F768QJ1E9tib+q5Sc8MkdJi1RxLTbRcTf8LJV56aRls= github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.1 h1:JFrFEBb2xKufg6XkJsJr+WbKb4FQlURi5RUcBveYu9k= -github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= @@ -84,8 +86,8 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= -github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/tedsuo/ifrit v0.0.0-20180802180643-bea94bb476cc/go.mod h1:eyZnKCc955uh98WQvzOm0dgAeLnf2O0Rz0LPoC5ze+0= github.com/ugorji/go v1.1.7 h1:/68gy2h+1mWMrwZFeD1kQialdSzAb432dtpeJ42ovdo= github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw= @@ -129,7 +131,6 @@ golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= diff --git a/sdk/messaging/azservicebus/internal/amqpLinks.go b/sdk/messaging/azservicebus/internal/amqpLinks.go index c187eacaf51b..a7d0590fc669 100644 --- a/sdk/messaging/azservicebus/internal/amqpLinks.go +++ b/sdk/messaging/azservicebus/internal/amqpLinks.go @@ -59,6 +59,13 @@ type AMQPLinks interface { // ClosedPermanently is true if AMQPLinks.Close(ctx, true) has been called. ClosedPermanently() bool + + // Writef logs a message, with a prefix that represents the AMQPLinks instance + // for better traceability. + Writef(evt azlog.Event, format string, args ...any) + + // Prefix is the current logging prefix, usable for logging and continuity. + Prefix() string } // AMQPLinksImpl manages the set of AMQP links (and detritus) typically needed to work @@ -107,7 +114,7 @@ type AMQPLinksImpl struct { ns NamespaceForAMQPLinks - name string + utils.Logger } // CreateLinkFunc creates the links, using the given session. Typically you'll only create either an @@ -132,6 +139,7 @@ func NewAMQPLinks(args NewAMQPLinksArgs) AMQPLinks { closedPermanently: false, getRecoveryKindFunc: args.GetRecoveryKindFunc, ns: args.NS, + Logger: utils.NewLogger(), } return l @@ -145,7 +153,7 @@ func (links *AMQPLinksImpl) ManagementPath() string { // recoverLink will recycle all associated links (mgmt, receiver, sender and session) // and recreate them using the link.linkCreator function. func (links *AMQPLinksImpl) recoverLink(ctx context.Context, theirLinkRevision LinkID) error { - log.Writef(exported.EventConn, "Recovering link only") + links.Writef(exported.EventConn, "Recovering link only") links.mu.RLock() closedPermanently := links.closedPermanently @@ -190,40 +198,44 @@ func (links *AMQPLinksImpl) RecoverIfNeeded(ctx context.Context, theirID LinkID, return nil } - log.Writef(exported.EventConn, "[%s] Recovering link for error %s", links.name, origErr.Error()) + links.Writef(exported.EventConn, "Recovering link for error %s", origErr.Error()) rk := links.getRecoveryKindFunc(origErr) if rk == RecoveryKindLink { + oldPrefix := links.Prefix() + if err := links.recoverLink(ctx, theirID); err != nil { - azlog.Writef(exported.EventConn, "[%s] Error when recovering link for recovery: %s", links.name, err) + links.Writef(exported.EventConn, "Error when recovering link for recovery: %s", err) return err } - log.Writef(exported.EventConn, "[%s] Recovered links", links.name) + links.Writef(exported.EventConn, "Recovered links (old: %s)", oldPrefix) return nil } else if rk == RecoveryKindConn { + oldPrefix := links.Prefix() + if err := links.recoverConnection(ctx, theirID); err != nil { - log.Writef(exported.EventConn, "[%s] failed to recreate connection: %s", links.name, err.Error()) + links.Writef(exported.EventConn, "failed to recreate connection: %s", err.Error()) return err } - log.Writef(exported.EventConn, "[%s] Recovered connection and links", links.name) + links.Writef(exported.EventConn, "Recovered connection and links (old: %s)", oldPrefix) return nil } - log.Writef(exported.EventConn, "[%s] Recovered, no action needed", links.name) + links.Writef(exported.EventConn, "Recovered, no action needed") return nil } func (links *AMQPLinksImpl) recoverConnection(ctx context.Context, theirID LinkID) error { - log.Writef(exported.EventConn, "Recovering connection (and links)") + links.Writef(exported.EventConn, "Recovering connection (and links)") links.mu.Lock() defer links.mu.Unlock() if theirID.Link == links.id.Link { - log.Writef(exported.EventConn, "closing old link: current:%v, old:%v", links.id, theirID) + links.Writef(exported.EventConn, "closing old link: current:%v, old:%v", links.id, theirID) // we're clearing out this link because the connection is about to get recreated. So we can // safely ignore any problems here, we're just trying to make sure the state is reset. @@ -233,7 +245,7 @@ func (links *AMQPLinksImpl) recoverConnection(ctx context.Context, theirID LinkI created, err := links.ns.Recover(ctx, uint64(theirID.Conn)) if err != nil { - log.Writef(exported.EventConn, "Recover connection failure: %s", err) + links.Writef(exported.EventConn, "Recover connection failure: %s", err) return err } @@ -243,7 +255,7 @@ func (links *AMQPLinksImpl) recoverConnection(ctx context.Context, theirID LinkI // (if it wasn't the same then we've already recovered and created a new link, // so no recovery would be needed) if created || theirID.Link == links.id.Link { - log.Writef(exported.EventConn, "recreating link: c: %v, current:%v, old:%v", created, links.id, theirID) + links.Writef(exported.EventConn, "recreating link: c: %v, current:%v, old:%v", created, links.id, theirID) // best effort close, the connection these were built on is gone. _ = links.closeWithoutLocking(ctx, false) @@ -303,21 +315,21 @@ func (l *AMQPLinksImpl) Get(ctx context.Context) (*LinksWithID, error) { }, nil } -func (l *AMQPLinksImpl) Retry(ctx context.Context, eventName log.Event, operation string, fn RetryWithLinksFn, o exported.RetryOptions) error { +func (links *AMQPLinksImpl) Retry(ctx context.Context, eventName log.Event, operation string, fn RetryWithLinksFn, o exported.RetryOptions) error { var lastID LinkID didQuickRetry := false isFatalErrorFunc := func(err error) bool { - return l.getRecoveryKindFunc(err) == RecoveryKindFatal + return links.getRecoveryKindFunc(err) == RecoveryKindFatal } - return utils.Retry(ctx, eventName, operation, func(ctx context.Context, args *utils.RetryFnArgs) error { - if err := l.RecoverIfNeeded(ctx, lastID, args.LastErr); err != nil { + return utils.Retry(ctx, eventName, links.Prefix()+"("+operation+")", func(ctx context.Context, args *utils.RetryFnArgs) error { + if err := links.RecoverIfNeeded(ctx, lastID, args.LastErr); err != nil { return err } - linksWithVersion, err := l.Get(ctx) + linksWithVersion, err := links.Get(ctx) if err != nil { return err @@ -345,7 +357,7 @@ func (l *AMQPLinksImpl) Retry(ctx context.Context, eventName log.Event, operatio // Whereas normally you'd do (for non-detach errors): // 0th attempt // (actual retries) - log.Writef(exported.EventConn, "(%s) Link was previously detached. Attempting quick reconnect to recover from error: %s", operation, err.Error()) + links.Writef(exported.EventConn, "(%s) Link was previously detached. Attempting quick reconnect to recover from error: %s", operation, err.Error()) didQuickRetry = true args.ResetAttempts() } @@ -387,29 +399,29 @@ func (l *AMQPLinksImpl) Close(ctx context.Context, permanent bool) error { // eats the cost of recovery, instead of doing it immediately. This is useful // if you're trying to exit out of a function quickly but still need to react // to a returned error. -func (l *AMQPLinksImpl) CloseIfNeeded(ctx context.Context, err error) RecoveryKind { - l.mu.Lock() - defer l.mu.Unlock() +func (links *AMQPLinksImpl) CloseIfNeeded(ctx context.Context, err error) RecoveryKind { + links.mu.Lock() + defer links.mu.Unlock() if IsCancelError(err) { - log.Writef(exported.EventConn, "[%s] No close needed for cancellation", l.name) + links.Writef(exported.EventConn, "No close needed for cancellation") return RecoveryKindNone } - rk := l.getRecoveryKindFunc(err) + rk := links.getRecoveryKindFunc(err) switch rk { case RecoveryKindLink: - log.Writef(exported.EventConn, "[%s] Closing links for error %s", l.name, err.Error()) - _ = l.closeWithoutLocking(ctx, false) + links.Writef(exported.EventConn, "Closing links for error %s", err.Error()) + _ = links.closeWithoutLocking(ctx, false) return rk case RecoveryKindFatal: - log.Writef(exported.EventConn, "[%s] Fatal error cleanup", l.name) + links.Writef(exported.EventConn, "Fatal error cleanup") fallthrough case RecoveryKindConn: - log.Writef(exported.EventConn, "[%s] Closing connection AND links for error %s", l.name, err.Error()) - _ = l.closeWithoutLocking(ctx, false) - _ = l.ns.Close(false) + links.Writef(exported.EventConn, "Closing connection AND links for error %s", err.Error()) + _ = links.closeWithoutLocking(ctx, false) + _ = links.ns.Close(false) return rk case RecoveryKindNone: return rk @@ -419,46 +431,46 @@ func (l *AMQPLinksImpl) CloseIfNeeded(ctx context.Context, err error) RecoveryKi } // initWithoutLocking will create a new link, unconditionally. -func (l *AMQPLinksImpl) initWithoutLocking(ctx context.Context) error { - tmpCancelAuthRefreshLink, _, err := l.ns.NegotiateClaim(ctx, l.entityPath) +func (links *AMQPLinksImpl) initWithoutLocking(ctx context.Context) error { + tmpCancelAuthRefreshLink, _, err := links.ns.NegotiateClaim(ctx, links.entityPath) if err != nil { - if err := l.closeWithoutLocking(ctx, false); err != nil { - log.Writef(exported.EventConn, "Failure during link cleanup after negotiateClaim: %s", err.Error()) + if err := links.closeWithoutLocking(ctx, false); err != nil { + links.Writef(exported.EventConn, "Failure during link cleanup after negotiateClaim: %s", err.Error()) } return err } - l.cancelAuthRefreshLink = tmpCancelAuthRefreshLink + links.cancelAuthRefreshLink = tmpCancelAuthRefreshLink - tmpCancelAuthRefreshMgmtLink, _, err := l.ns.NegotiateClaim(ctx, l.managementPath) + tmpCancelAuthRefreshMgmtLink, _, err := links.ns.NegotiateClaim(ctx, links.managementPath) if err != nil { - if err := l.closeWithoutLocking(ctx, false); err != nil { - log.Writef(exported.EventConn, "Failure during link cleanup after negotiate claim for mgmt link: %s", err.Error()) + if err := links.closeWithoutLocking(ctx, false); err != nil { + links.Writef(exported.EventConn, "Failure during link cleanup after negotiate claim for mgmt link: %s", err.Error()) } return err } - l.cancelAuthRefreshMgmtLink = tmpCancelAuthRefreshMgmtLink + links.cancelAuthRefreshMgmtLink = tmpCancelAuthRefreshMgmtLink - tmpSession, cr, err := l.ns.NewAMQPSession(ctx) + tmpSession, cr, err := links.ns.NewAMQPSession(ctx) if err != nil { - if err := l.closeWithoutLocking(ctx, false); err != nil { - log.Writef(exported.EventConn, "Failure during link cleanup after creating AMQP session: %s", err.Error()) + if err := links.closeWithoutLocking(ctx, false); err != nil { + links.Writef(exported.EventConn, "Failure during link cleanup after creating AMQP session: %s", err.Error()) } return err } - l.session = tmpSession - l.id.Conn = cr + links.session = tmpSession + links.id.Conn = cr - tmpSender, tmpReceiver, err := l.createLink(ctx, l.session) + tmpSender, tmpReceiver, err := links.createLink(ctx, links.session) if err != nil { - if err := l.closeWithoutLocking(ctx, false); err != nil { - log.Writef(exported.EventConn, "Failure during link cleanup after creating link: %s", err.Error()) + if err := links.closeWithoutLocking(ctx, false); err != nil { + links.Writef(exported.EventConn, "Failure during link cleanup after creating link: %s", err.Error()) } return err } @@ -467,28 +479,29 @@ func (l *AMQPLinksImpl) initWithoutLocking(ctx context.Context) error { panic("Both tmpReceiver and tmpSender are nil") } - l.Sender, l.Receiver = tmpSender, tmpReceiver + links.Sender, links.Receiver = tmpSender, tmpReceiver - tmpRPCLink, err := l.ns.NewRPCLink(ctx, l.ManagementPath()) + tmpRPCLink, err := links.ns.NewRPCLink(ctx, links.ManagementPath()) if err != nil { - if err := l.closeWithoutLocking(ctx, false); err != nil { - log.Writef("Failure during link cleanup after creating mgmt client: %s", err.Error()) + if err := links.closeWithoutLocking(ctx, false); err != nil { + links.Writef(exported.EventConn, "Failure during link cleanup after creating mgmt client: %s", err.Error()) } return err } - l.RPCLink = tmpRPCLink - l.id.Link++ + links.RPCLink = tmpRPCLink + links.id.Link++ - if l.Sender != nil { - linkName := l.Sender.LinkName() - l.name = fmt.Sprintf("c:%d, l:%d, s:name:%s", l.id.Conn, l.id.Link, linkName) - } else if l.Receiver != nil { - l.name = fmt.Sprintf("c:%d, l:%d, r:name:%s", l.id.Conn, l.id.Link, l.Receiver.LinkName()) + if links.Sender != nil { + linkName := links.Sender.LinkName() + links.SetPrefix("c:%d, l:%d, s:name:%0.6s", links.id.Conn, links.id.Link, linkName) + } else if links.Receiver != nil { + linkName := links.Receiver.LinkName() + links.SetPrefix("c:%d, l:%d, r:name:%0.6s", links.id.Conn, links.id.Link, linkName) } - log.Writef(exported.EventConn, "[%s] Links created", l.name) + links.Writef(exported.EventConn, "Links created") return nil } @@ -502,39 +515,39 @@ func (l *AMQPLinksImpl) initWithoutLocking(ctx context.Context) error { // Regardless of cancellation or Close() call failures, all local state will be cleaned up. // // NOTE: No locking is done in this function, call `Close` if you require locking. -func (l *AMQPLinksImpl) closeWithoutLocking(ctx context.Context, permanent bool) error { - if l.closedPermanently { +func (links *AMQPLinksImpl) closeWithoutLocking(ctx context.Context, permanent bool) error { + if links.closedPermanently { return nil } - log.Writef(exported.EventConn, "[%s] Links closing (permanent: %v)", l.name, permanent) + links.Writef(exported.EventConn, "Links closing (permanent: %v)", permanent) defer func() { if permanent { - l.closedPermanently = true + links.closedPermanently = true } }() var messages []string - if l.cancelAuthRefreshLink != nil { - l.cancelAuthRefreshLink() - l.cancelAuthRefreshLink = nil + if links.cancelAuthRefreshLink != nil { + links.cancelAuthRefreshLink() + links.cancelAuthRefreshLink = nil } - if l.cancelAuthRefreshMgmtLink != nil { - l.cancelAuthRefreshMgmtLink() - l.cancelAuthRefreshMgmtLink = nil + if links.cancelAuthRefreshMgmtLink != nil { + links.cancelAuthRefreshMgmtLink() + links.cancelAuthRefreshMgmtLink = nil } closeables := []struct { name string instance amqpwrap.Closeable }{ - {"Sender", l.Sender}, - {"Receiver", l.Receiver}, - {"Session", l.session}, - {"RPC", l.RPCLink}, + {"Sender", links.Sender}, + {"Receiver", links.Receiver}, + {"Session", links.session}, + {"RPC", links.RPCLink}, } wasCancelled := false @@ -546,6 +559,8 @@ func (l *AMQPLinksImpl) closeWithoutLocking(ctx context.Context, permanent bool) continue } + links.Writef(exported.EventConn, "Closing %s", c.name) + if err := c.instance.Close(ctx); err != nil { if IsCancelError(err) { wasCancelled = true @@ -555,7 +570,7 @@ func (l *AMQPLinksImpl) closeWithoutLocking(ctx context.Context, permanent bool) } } - l.Sender, l.Receiver, l.session, l.RPCLink = nil, nil, nil, nil + links.Sender, links.Receiver, links.session, links.RPCLink = nil, nil, nil, nil if wasCancelled { return ctx.Err() diff --git a/sdk/messaging/azservicebus/internal/amqpLinks_test.go b/sdk/messaging/azservicebus/internal/amqpLinks_test.go index 4b063bc1a3d6..fe1558fb20e1 100644 --- a/sdk/messaging/azservicebus/internal/amqpLinks_test.go +++ b/sdk/messaging/azservicebus/internal/amqpLinks_test.go @@ -15,9 +15,9 @@ import ( "github.com/Azure/azure-sdk-for-go/sdk/internal/log" "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus/internal/amqpwrap" "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus/internal/exported" - "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus/internal/go-amqp" "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus/internal/test" "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus/internal/utils" + "github.com/Azure/go-amqp" "github.com/stretchr/testify/require" ) diff --git a/sdk/messaging/azservicebus/internal/amqp_test_utils.go b/sdk/messaging/azservicebus/internal/amqp_test_utils.go index 5b4680769ae2..20dbf52cb7a7 100644 --- a/sdk/messaging/azservicebus/internal/amqp_test_utils.go +++ b/sdk/messaging/azservicebus/internal/amqp_test_utils.go @@ -8,10 +8,11 @@ import ( "fmt" "github.com/Azure/azure-sdk-for-go/sdk/internal/log" + azlog "github.com/Azure/azure-sdk-for-go/sdk/internal/log" "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus/internal/amqpwrap" "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus/internal/exported" - "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus/internal/go-amqp" "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus/internal/utils" + "github.com/Azure/go-amqp" ) type FakeNS struct { @@ -207,6 +208,14 @@ func (l *FakeAMQPLinks) Retry(ctx context.Context, eventName log.Event, operatio return fn(ctx, lwr, &utils.RetryFnArgs{}) } +func (l *FakeAMQPLinks) Writef(evt azlog.Event, format string, args ...any) { + log.Writef(evt, "[prefix] "+format, args...) +} + +func (l *FakeAMQPLinks) Prefix() string { + return "prefix" +} + func (l *FakeAMQPLinks) Close(ctx context.Context, permanently bool) error { if permanently { l.permanently = true diff --git a/sdk/messaging/azservicebus/internal/amqplinks_unit_test.go b/sdk/messaging/azservicebus/internal/amqplinks_unit_test.go index 5fdd1f3b894a..dcc7907cd33c 100644 --- a/sdk/messaging/azservicebus/internal/amqplinks_unit_test.go +++ b/sdk/messaging/azservicebus/internal/amqplinks_unit_test.go @@ -13,10 +13,10 @@ import ( "github.com/Azure/azure-sdk-for-go/sdk/internal/log" "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus/internal/amqpwrap" "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus/internal/exported" - "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus/internal/go-amqp" "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus/internal/mock/emulation" "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus/internal/test" "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus/internal/utils" + "github.com/Azure/go-amqp" "github.com/golang/mock/gomock" "github.com/stretchr/testify/require" ) @@ -88,7 +88,7 @@ func TestAMQPLinksRetriesUnit(t *testing.T) { logMessages := endLogging() if testData.ExpectReset { - require.Contains(t, logMessages, fmt.Sprintf("[azsb.Conn] (OverallOperation) Link was previously detached. Attempting quick reconnect to recover from error: %s", err.Error())) + require.Contains(t, logMessages, fmt.Sprintf("[azsb.Conn] [c:100, l:1, s:name:sender] (OverallOperation) Link was previously detached. Attempting quick reconnect to recover from error: %s", err.Error())) } else { for _, msg := range logMessages { require.NotContains(t, msg, "Link was previously detached") @@ -126,11 +126,11 @@ func TestAMQPLinks_Logging(t *testing.T) { actualLogs := endCapture() expectedLogs := []string{ - "[azsb.Conn] [] Recovering link for error amqp: link closed", + "[azsb.Conn] Recovering link for error amqp: link closed", "[azsb.Conn] Recovering link only", - "[azsb.Conn] [] Links closing (permanent: false)", - "[azsb.Conn] [c:100, l:1, r:name:fakelink] Links created", - "[azsb.Conn] [c:100, l:1, r:name:fakelink] Recovered links"} + "[azsb.Conn] Links closing (permanent: false)", + "[azsb.Conn] [c:100, l:1, r:name:fakeli] Links created", + "[azsb.Conn] [c:100, l:1, r:name:fakeli] Recovered links (old: )"} require.Equal(t, expectedLogs, actualLogs) }) @@ -161,14 +161,14 @@ func TestAMQPLinks_Logging(t *testing.T) { actualLogs := endCapture() expectedLogs := []string{ - "[azsb.Conn] [] Recovering link for error amqp: connection closed", + "[azsb.Conn] Recovering link for error amqp: connection closed", "[azsb.Conn] Recovering connection (and links)", "[azsb.Conn] closing old link: current:{0 0}, old:{0 0}", - "[azsb.Conn] [] Links closing (permanent: false)", + "[azsb.Conn] Links closing (permanent: false)", "[azsb.Conn] recreating link: c: true, current:{0 0}, old:{0 0}", - "[azsb.Conn] [] Links closing (permanent: false)", - "[azsb.Conn] [c:101, l:1, r:name:fakelink] Links created", - "[azsb.Conn] [c:101, l:1, r:name:fakelink] Recovered connection and links"} + "[azsb.Conn] Links closing (permanent: false)", + "[azsb.Conn] [c:101, l:1, r:name:fakeli] Links created", + "[azsb.Conn] [c:101, l:1, r:name:fakeli] Recovered connection and links (old: )"} require.Equal(t, expectedLogs, actualLogs) }) diff --git a/sdk/messaging/azservicebus/internal/amqpwrap/amqpwrap.go b/sdk/messaging/azservicebus/internal/amqpwrap/amqpwrap.go index 6e62d0b383d6..154e6ecb1d09 100644 --- a/sdk/messaging/azservicebus/internal/amqpwrap/amqpwrap.go +++ b/sdk/messaging/azservicebus/internal/amqpwrap/amqpwrap.go @@ -10,7 +10,7 @@ import ( "errors" "time" - "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus/internal/go-amqp" + "github.com/Azure/go-amqp" ) // AMQPReceiver is implemented by *amqp.Receiver diff --git a/sdk/messaging/azservicebus/internal/amqpwrap/mock_amqp_test.go b/sdk/messaging/azservicebus/internal/amqpwrap/mock_amqp_test.go index 0fa5e88b86ac..5970412670e6 100644 --- a/sdk/messaging/azservicebus/internal/amqpwrap/mock_amqp_test.go +++ b/sdk/messaging/azservicebus/internal/amqpwrap/mock_amqp_test.go @@ -12,7 +12,7 @@ import ( context "context" reflect "reflect" - go_amqp "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus/internal/go-amqp" + go_amqp "github.com/Azure/go-amqp" gomock "github.com/golang/mock/gomock" ) diff --git a/sdk/messaging/azservicebus/internal/amqpwrap/rpc.go b/sdk/messaging/azservicebus/internal/amqpwrap/rpc.go index 2bb4e75d890e..4804f1176939 100644 --- a/sdk/messaging/azservicebus/internal/amqpwrap/rpc.go +++ b/sdk/messaging/azservicebus/internal/amqpwrap/rpc.go @@ -6,7 +6,7 @@ package amqpwrap import ( "context" - "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus/internal/go-amqp" + "github.com/Azure/go-amqp" ) // RPCResponse is the simplified response structure from an RPC like call diff --git a/sdk/messaging/azservicebus/internal/cbs.go b/sdk/messaging/azservicebus/internal/cbs.go index fd484d93561c..5a43d5e1f7c8 100644 --- a/sdk/messaging/azservicebus/internal/cbs.go +++ b/sdk/messaging/azservicebus/internal/cbs.go @@ -11,7 +11,7 @@ import ( "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus/internal/amqpwrap" "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus/internal/auth" "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus/internal/exported" - "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus/internal/go-amqp" + "github.com/Azure/go-amqp" ) const ( diff --git a/sdk/messaging/azservicebus/internal/errors.go b/sdk/messaging/azservicebus/internal/errors.go index 81d8ea07086b..cdeb63d97581 100644 --- a/sdk/messaging/azservicebus/internal/errors.go +++ b/sdk/messaging/azservicebus/internal/errors.go @@ -15,7 +15,7 @@ import ( "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus/internal/amqpwrap" "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus/internal/exported" - "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus/internal/go-amqp" + "github.com/Azure/go-amqp" ) type errNonRetriable struct { @@ -160,6 +160,9 @@ var amqpConditionsToRecoveryKind = map[amqp.ErrCond]RecoveryKind{ amqp.ErrCondInternalError: RecoveryKindConn, // "amqp:internal-error" // No recovery possible - this operation is non retriable. + + // ErrCondResourceLimitExceeded comes back if the entity is actually full. + amqp.ErrCondResourceLimitExceeded: RecoveryKindFatal, // "amqp:resource-limit-exceeded" amqp.ErrCondMessageSizeExceeded: RecoveryKindFatal, // "amqp:link:message-size-exceeded" amqp.ErrCondUnauthorizedAccess: RecoveryKindFatal, // creds are bad amqp.ErrCondNotFound: RecoveryKindFatal, // "amqp:not-found" diff --git a/sdk/messaging/azservicebus/internal/errors_test.go b/sdk/messaging/azservicebus/internal/errors_test.go index c3fcdf2ad0c7..1343417dcfbc 100644 --- a/sdk/messaging/azservicebus/internal/errors_test.go +++ b/sdk/messaging/azservicebus/internal/errors_test.go @@ -15,7 +15,7 @@ import ( "github.com/Azure/azure-sdk-for-go/sdk/azidentity" "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus/internal/amqpwrap" "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus/internal/exported" - "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus/internal/go-amqp" + "github.com/Azure/go-amqp" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -227,6 +227,7 @@ func Test_ServiceBusError_LinkRecoveryNeeded(t *testing.T) { func Test_ServiceBusError_Fatal(t *testing.T) { var fatalConditions = []amqp.ErrCond{ amqp.ErrCondMessageSizeExceeded, + amqp.ErrCondResourceLimitExceeded, amqp.ErrCondUnauthorizedAccess, amqp.ErrCondNotFound, amqp.ErrCondNotAllowed, diff --git a/sdk/messaging/azservicebus/internal/exported/error_test.go b/sdk/messaging/azservicebus/internal/exported/error_test.go index 4fe69bb82344..a64d85d8fb22 100644 --- a/sdk/messaging/azservicebus/internal/exported/error_test.go +++ b/sdk/messaging/azservicebus/internal/exported/error_test.go @@ -6,7 +6,7 @@ package exported import ( "testing" - "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus/internal/go-amqp" + "github.com/Azure/go-amqp" "github.com/stretchr/testify/require" ) diff --git a/sdk/messaging/azservicebus/internal/go-amqp/LICENSE b/sdk/messaging/azservicebus/internal/go-amqp/LICENSE deleted file mode 100644 index 387b3e7e0f3b..000000000000 --- a/sdk/messaging/azservicebus/internal/go-amqp/LICENSE +++ /dev/null @@ -1,22 +0,0 @@ - MIT License - - Copyright (C) 2017 Kale Blankenship - Portions Copyright (C) Microsoft Corporation - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE diff --git a/sdk/messaging/azservicebus/internal/go-amqp/conn.go b/sdk/messaging/azservicebus/internal/go-amqp/conn.go deleted file mode 100644 index f6e4b808f922..000000000000 --- a/sdk/messaging/azservicebus/internal/go-amqp/conn.go +++ /dev/null @@ -1,1135 +0,0 @@ -// Copyright (C) 2017 Kale Blankenship -// Portions Copyright (c) Microsoft Corporation - -package amqp - -import ( - "bytes" - "context" - "crypto/tls" - "errors" - "fmt" - "math" - "net" - "net/url" - "sync" - "time" - - "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus/internal/go-amqp/internal/bitmap" - "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus/internal/go-amqp/internal/buffer" - "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus/internal/go-amqp/internal/debug" - "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus/internal/go-amqp/internal/encoding" - "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus/internal/go-amqp/internal/frames" - "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus/internal/go-amqp/internal/shared" -) - -// Default connection options -const ( - defaultIdleTimeout = 1 * time.Minute - defaultMaxFrameSize = 65536 - defaultMaxSessions = 65536 - defaultWriteTimeout = 30 * time.Second -) - -// ConnOptions contains the optional settings for configuring an AMQP connection. -type ConnOptions struct { - // ContainerID sets the container-id to use when opening the connection. - // - // A container ID will be randomly generated if this option is not used. - ContainerID string - - // HostName sets the hostname sent in the AMQP - // Open frame and TLS ServerName (if not otherwise set). - HostName string - - // IdleTimeout specifies the maximum period between - // receiving frames from the peer. - // - // Specify a value less than zero to disable idle timeout. - // - // Default: 1 minute (60000000000). - IdleTimeout time.Duration - - // MaxFrameSize sets the maximum frame size that - // the connection will accept. - // - // Must be 512 or greater. - // - // Default: 512. - MaxFrameSize uint32 - - // MaxSessions sets the maximum number of channels. - // The value must be greater than zero. - // - // Default: 65535. - MaxSessions uint16 - - // Properties sets an entry in the connection properties map sent to the server. - Properties map[string]any - - // SASLType contains the specified SASL authentication mechanism. - SASLType SASLType - - // TLSConfig sets the tls.Config to be used during - // TLS negotiation. - // - // This option is for advanced usage, in most scenarios - // providing a URL scheme of "amqps://" is sufficient. - TLSConfig *tls.Config - - // WriteTimeout controls the write deadline when writing AMQP frames to the - // underlying net.Conn and no caller provided context.Context is available or - // the context contains no deadline (e.g. context.Background()). - // The timeout is set per write. - // - // Setting to a value less than zero means no timeout is set, so writes - // defer to the underlying behavior of net.Conn with no write deadline. - // - // Default: 30s - WriteTimeout time.Duration - - // test hook - dialer dialer -} - -// Dial connects to an AMQP server. -// -// If the addr includes a scheme, it must be "amqp", "amqps", or "amqp+ssl". -// If no port is provided, 5672 will be used for "amqp" and 5671 for "amqps" or "amqp+ssl". -// -// If username and password information is not empty it's used as SASL PLAIN -// credentials, equal to passing ConnSASLPlain option. -// -// opts: pass nil to accept the default values. -func Dial(ctx context.Context, addr string, opts *ConnOptions) (*Conn, error) { - c, err := dialConn(ctx, addr, opts) - if err != nil { - return nil, err - } - err = c.start(ctx) - if err != nil { - return nil, err - } - return c, nil -} - -// NewConn establishes a new AMQP client connection over conn. -// opts: pass nil to accept the default values. -func NewConn(ctx context.Context, conn net.Conn, opts *ConnOptions) (*Conn, error) { - c, err := newConn(conn, opts) - if err != nil { - return nil, err - } - err = c.start(ctx) - if err != nil { - return nil, err - } - return c, nil -} - -// Conn is an AMQP connection. -type Conn struct { - net net.Conn // underlying connection - dialer dialer // used for testing purposes, it allows faking dialing TCP/TLS endpoints - writeTimeout time.Duration // controls write deadline in absense of a context - - // TLS - tlsNegotiation bool // negotiate TLS - tlsComplete bool // TLS negotiation complete - tlsConfig *tls.Config // TLS config, default used if nil (ServerName set to Client.hostname) - - // SASL - saslHandlers map[encoding.Symbol]stateFunc // map of supported handlers keyed by SASL mechanism, SASL not negotiated if nil - saslComplete bool // SASL negotiation complete; internal *except* for SASL auth methods - - // local settings - maxFrameSize uint32 // max frame size to accept - channelMax uint16 // maximum number of channels to allow - hostname string // hostname of remote server (set explicitly or parsed from URL) - idleTimeout time.Duration // maximum period between receiving frames - properties map[encoding.Symbol]any // additional properties sent upon connection open - containerID string // set explicitly or randomly generated - - // peer settings - peerIdleTimeout time.Duration // maximum period between sending frames - peerMaxFrameSize uint32 // maximum frame size peer will accept - - // conn state - done chan struct{} // indicates the connection has terminated - doneErr error // contains the error state returned from Close(); DO NOT TOUCH outside of conn.go until done has been closed! - - // connReader and connWriter management - rxtxExit chan struct{} // signals connReader and connWriter to exit - closeOnce sync.Once // ensures that close() is only called once - - // session tracking - channels *bitmap.Bitmap - sessionsByChannel map[uint16]*Session - sessionsByChannelMu sync.RWMutex - - abandonedSessionsMu sync.Mutex - abandonedSessions []*Session - - // connReader - rxBuf buffer.Buffer // incoming bytes buffer - rxDone chan struct{} // closed when connReader exits - rxErr error // contains last error reading from c.net; DO NOT TOUCH outside of connReader until rxDone has been closed! - - // connWriter - txFrame chan frameEnvelope // AMQP frames to be sent by connWriter - txBuf buffer.Buffer // buffer for marshaling frames before transmitting - txDone chan struct{} // closed when connWriter exits - txErr error // contains last error writing to c.net; DO NOT TOUCH outside of connWriter until txDone has been closed! -} - -// used to abstract the underlying dialer for testing purposes -type dialer interface { - NetDialerDial(ctx context.Context, c *Conn, host, port string) error - TLSDialWithDialer(ctx context.Context, c *Conn, host, port string) error -} - -// implements the dialer interface -type defaultDialer struct{} - -func (defaultDialer) NetDialerDial(ctx context.Context, c *Conn, host, port string) (err error) { - dialer := &net.Dialer{} - c.net, err = dialer.DialContext(ctx, "tcp", net.JoinHostPort(host, port)) - return -} - -func (defaultDialer) TLSDialWithDialer(ctx context.Context, c *Conn, host, port string) (err error) { - dialer := &tls.Dialer{Config: c.tlsConfig} - c.net, err = dialer.DialContext(ctx, "tcp", net.JoinHostPort(host, port)) - return -} - -func dialConn(ctx context.Context, addr string, opts *ConnOptions) (*Conn, error) { - u, err := url.Parse(addr) - if err != nil { - return nil, err - } - host, port := u.Hostname(), u.Port() - if port == "" { - port = "5672" - if u.Scheme == "amqps" || u.Scheme == "amqp+ssl" { - port = "5671" - } - } - - var cp ConnOptions - if opts != nil { - cp = *opts - } - - // prepend SASL credentials when the user/pass segment is not empty - if u.User != nil { - pass, _ := u.User.Password() - cp.SASLType = SASLTypePlain(u.User.Username(), pass) - } - - if cp.HostName == "" { - cp.HostName = host - } - - c, err := newConn(nil, &cp) - if err != nil { - return nil, err - } - - switch u.Scheme { - case "amqp", "": - err = c.dialer.NetDialerDial(ctx, c, host, port) - case "amqps", "amqp+ssl": - c.initTLSConfig() - c.tlsNegotiation = false - err = c.dialer.TLSDialWithDialer(ctx, c, host, port) - default: - err = fmt.Errorf("unsupported scheme %q", u.Scheme) - } - - if err != nil { - return nil, err - } - return c, nil -} - -func newConn(netConn net.Conn, opts *ConnOptions) (*Conn, error) { - c := &Conn{ - dialer: defaultDialer{}, - net: netConn, - maxFrameSize: defaultMaxFrameSize, - peerMaxFrameSize: defaultMaxFrameSize, - channelMax: defaultMaxSessions - 1, // -1 because channel-max starts at zero - idleTimeout: defaultIdleTimeout, - containerID: shared.RandString(40), - done: make(chan struct{}), - rxtxExit: make(chan struct{}), - rxDone: make(chan struct{}), - txFrame: make(chan frameEnvelope), - txDone: make(chan struct{}), - sessionsByChannel: map[uint16]*Session{}, - writeTimeout: defaultWriteTimeout, - } - - // apply options - if opts == nil { - opts = &ConnOptions{} - } - - if opts.WriteTimeout > 0 { - c.writeTimeout = opts.WriteTimeout - } else if opts.WriteTimeout < 0 { - c.writeTimeout = 0 - } - if opts.ContainerID != "" { - c.containerID = opts.ContainerID - } - if opts.HostName != "" { - c.hostname = opts.HostName - } - if opts.IdleTimeout > 0 { - c.idleTimeout = opts.IdleTimeout - } else if opts.IdleTimeout < 0 { - c.idleTimeout = 0 - } - if opts.MaxFrameSize > 0 && opts.MaxFrameSize < 512 { - return nil, fmt.Errorf("invalid MaxFrameSize value %d", opts.MaxFrameSize) - } else if opts.MaxFrameSize > 512 { - c.maxFrameSize = opts.MaxFrameSize - } - if opts.MaxSessions > 0 { - c.channelMax = opts.MaxSessions - } - if opts.SASLType != nil { - if err := opts.SASLType(c); err != nil { - return nil, err - } - } - if opts.Properties != nil { - c.properties = make(map[encoding.Symbol]any) - for key, val := range opts.Properties { - c.properties[encoding.Symbol(key)] = val - } - } - if opts.TLSConfig != nil { - c.tlsConfig = opts.TLSConfig.Clone() - } - if opts.dialer != nil { - c.dialer = opts.dialer - } - return c, nil -} - -func (c *Conn) initTLSConfig() { - // create a new config if not already set - if c.tlsConfig == nil { - c.tlsConfig = new(tls.Config) - } - - // TLS config must have ServerName or InsecureSkipVerify set - if c.tlsConfig.ServerName == "" && !c.tlsConfig.InsecureSkipVerify { - c.tlsConfig.ServerName = c.hostname - } -} - -// start establishes the connection and begins multiplexing network IO. -// It is an error to call Start() on a connection that's been closed. -func (c *Conn) start(ctx context.Context) (err error) { - // if the context has a deadline or is cancellable, start the interruptor goroutine. - // this will close the underlying net.Conn in response to the context. - - if ctx.Done() != nil { - done := make(chan struct{}) - interruptRes := make(chan error, 1) - - defer func() { - close(done) - if ctxErr := <-interruptRes; ctxErr != nil { - // return context error to caller - err = ctxErr - } - }() - - go func() { - select { - case <-ctx.Done(): - c.closeDuringStart() - interruptRes <- ctx.Err() - case <-done: - interruptRes <- nil - } - }() - } - - if err = c.startImpl(ctx); err != nil { - return err - } - - // we can't create the channel bitmap until the connection has been established. - // this is because our peer can tell us the max channels they support. - c.channels = bitmap.New(uint32(c.channelMax)) - - go c.connWriter() - go c.connReader() - - return -} - -func (c *Conn) startImpl(ctx context.Context) error { - // set connection establishment deadline as required - if deadline, ok := ctx.Deadline(); ok && !deadline.IsZero() { - _ = c.net.SetDeadline(deadline) - - // remove connection establishment deadline - defer func() { - _ = c.net.SetDeadline(time.Time{}) - }() - } - - // run connection establishment state machine - for state := c.negotiateProto; state != nil; { - var err error - state, err = state(ctx) - // check if err occurred - if err != nil { - c.closeDuringStart() - return err - } - } - - return nil -} - -// Close closes the connection. -func (c *Conn) Close() error { - c.close() - - // wait until the reader/writer goroutines have exited before proceeding. - // this is to prevent a race between calling Close() and a reader/writer - // goroutine calling close() due to a terminal error. - <-c.txDone - <-c.rxDone - - var connErr *ConnError - if errors.As(c.doneErr, &connErr) && connErr.RemoteErr == nil && connErr.inner == nil { - // an empty ConnectionError means the connection was closed by the caller - return nil - } - - // there was an error during shut-down or connReader/connWriter - // experienced a terminal error - return c.doneErr -} - -// close is called once, either from Close() or when connReader/connWriter exits -func (c *Conn) close() { - c.closeOnce.Do(func() { - defer close(c.done) - - close(c.rxtxExit) - - // wait for writing to stop, allows it to send the final close frame - <-c.txDone - - closeErr := c.net.Close() - - // check rxDone after closing net, otherwise may block - // for up to c.idleTimeout - <-c.rxDone - - if errors.Is(c.rxErr, net.ErrClosed) { - // this is the expected error when the connection is closed, swallow it - c.rxErr = nil - } - - if c.txErr == nil && c.rxErr == nil && closeErr == nil { - // if there are no errors, it means user initiated close() and we shut down cleanly - c.doneErr = &ConnError{} - } else if amqpErr, ok := c.rxErr.(*Error); ok { - // we experienced a peer-initiated close that contained an Error. return it - c.doneErr = &ConnError{RemoteErr: amqpErr} - } else if c.txErr != nil { - // c.txErr is already wrapped in a ConnError - c.doneErr = c.txErr - } else if c.rxErr != nil { - c.doneErr = &ConnError{inner: c.rxErr} - } else { - c.doneErr = &ConnError{inner: closeErr} - } - }) -} - -// closeDuringStart is a special close to be used only during startup (i.e. c.start() and any of its children) -func (c *Conn) closeDuringStart() { - c.closeOnce.Do(func() { - c.net.Close() - }) -} - -// NewSession starts a new session on the connection. -// - ctx controls waiting for the peer to acknowledge the session -// - opts contains optional values, pass nil to accept the defaults -// -// If the context's deadline expires or is cancelled before the operation -// completes, an error is returned. If the Session was successfully -// created, it will be cleaned up in future calls to NewSession. -func (c *Conn) NewSession(ctx context.Context, opts *SessionOptions) (*Session, error) { - // clean up any abandoned sessions first - if err := c.freeAbandonedSessions(ctx); err != nil { - return nil, err - } - - session, err := c.newSession(opts) - if err != nil { - return nil, err - } - - if err := session.begin(ctx); err != nil { - c.abandonSession(session) - return nil, err - } - - return session, nil -} - -func (c *Conn) freeAbandonedSessions(ctx context.Context) error { - c.abandonedSessionsMu.Lock() - defer c.abandonedSessionsMu.Unlock() - - debug.Log(3, "TX (Conn %p): cleaning up %d abandoned sessions", c, len(c.abandonedSessions)) - - for _, s := range c.abandonedSessions { - fr := frames.PerformEnd{} - if err := s.txFrameAndWait(ctx, &fr); err != nil { - return err - } - } - - c.abandonedSessions = nil - return nil -} - -func (c *Conn) newSession(opts *SessionOptions) (*Session, error) { - c.sessionsByChannelMu.Lock() - defer c.sessionsByChannelMu.Unlock() - - // create the next session to allocate - // note that channel always start at 0 - channel, ok := c.channels.Next() - if !ok { - if err := c.Close(); err != nil { - return nil, err - } - return nil, &ConnError{inner: fmt.Errorf("reached connection channel max (%d)", c.channelMax)} - } - session := newSession(c, uint16(channel), opts) - c.sessionsByChannel[session.channel] = session - - return session, nil -} - -func (c *Conn) deleteSession(s *Session) { - c.sessionsByChannelMu.Lock() - defer c.sessionsByChannelMu.Unlock() - - delete(c.sessionsByChannel, s.channel) - c.channels.Remove(uint32(s.channel)) -} - -func (c *Conn) abandonSession(s *Session) { - c.abandonedSessionsMu.Lock() - defer c.abandonedSessionsMu.Unlock() - c.abandonedSessions = append(c.abandonedSessions, s) -} - -// connReader reads from the net.Conn, decodes frames, and either handles -// them here as appropriate or sends them to the session.rx channel. -func (c *Conn) connReader() { - defer func() { - close(c.rxDone) - c.close() - }() - - var sessionsByRemoteChannel = make(map[uint16]*Session) - var err error - for { - if err != nil { - debug.Log(1, "RX (connReader %p): terminal error: %v", c, err) - c.rxErr = err - return - } - - var fr frames.Frame - fr, err = c.readFrame() - if err != nil { - continue - } - - debug.Log(1, "RX (connReader %p): %s", c, fr) - - var ( - session *Session - ok bool - ) - - switch body := fr.Body.(type) { - // Server initiated close. - case *frames.PerformClose: - // connWriter will send the close performative ack on its way out. - // it's a SHOULD though, not a MUST. - if body.Error == nil { - return - } - err = body.Error - continue - - // RemoteChannel should be used when frame is Begin - case *frames.PerformBegin: - if body.RemoteChannel == nil { - // since we only support remotely-initiated sessions, this is an error - // TODO: it would be ideal to not have this kill the connection - err = fmt.Errorf("%T: nil RemoteChannel", fr.Body) - continue - } - c.sessionsByChannelMu.RLock() - session, ok = c.sessionsByChannel[*body.RemoteChannel] - c.sessionsByChannelMu.RUnlock() - if !ok { - // this can happen if NewSession() exits due to the context expiring/cancelled - // before the begin ack is received. - err = fmt.Errorf("unexpected remote channel number %d", *body.RemoteChannel) - continue - } - - session.remoteChannel = fr.Channel - sessionsByRemoteChannel[fr.Channel] = session - - case *frames.PerformEnd: - session, ok = sessionsByRemoteChannel[fr.Channel] - if !ok { - err = fmt.Errorf("%T: didn't find channel %d in sessionsByRemoteChannel (PerformEnd)", fr.Body, fr.Channel) - continue - } - // we MUST remove the remote channel from our map as soon as we receive - // the ack (i.e. before passing it on to the session mux) on the session - // ending since the numbers are recycled. - delete(sessionsByRemoteChannel, fr.Channel) - c.deleteSession(session) - - default: - // pass on performative to the correct session - session, ok = sessionsByRemoteChannel[fr.Channel] - if !ok { - err = fmt.Errorf("%T: didn't find channel %d in sessionsByRemoteChannel", fr.Body, fr.Channel) - continue - } - } - - q := session.rxQ.Acquire() - q.Enqueue(fr.Body) - session.rxQ.Release(q) - debug.Log(2, "RX (connReader %p): mux frame to Session (%p): %s", c, session, fr) - } -} - -// readFrame reads a complete frame from c.net. -// it assumes that any read deadline has already been applied. -// used externally by SASL only. -func (c *Conn) readFrame() (frames.Frame, error) { - switch { - // Cheaply reuse free buffer space when fully read. - case c.rxBuf.Len() == 0: - c.rxBuf.Reset() - - // Prevent excessive/unbounded growth by shifting data to beginning of buffer. - case int64(c.rxBuf.Size()) > int64(c.maxFrameSize): - c.rxBuf.Reclaim() - } - - var ( - currentHeader frames.Header // keep track of the current header, for frames split across multiple TCP packets - frameInProgress bool // true if in the middle of receiving data for currentHeader - ) - - for { - // need to read more if buf doesn't contain the complete frame - // or there's not enough in buf to parse the header - if frameInProgress || c.rxBuf.Len() < frames.HeaderSize { - // we MUST reset the idle timeout before each read from net.Conn - if c.idleTimeout > 0 { - _ = c.net.SetReadDeadline(time.Now().Add(c.idleTimeout)) - } - err := c.rxBuf.ReadFromOnce(c.net) - if err != nil { - return frames.Frame{}, err - } - } - - // read more if buf doesn't contain enough to parse the header - if c.rxBuf.Len() < frames.HeaderSize { - continue - } - - // parse the header if a frame isn't in progress - if !frameInProgress { - var err error - currentHeader, err = frames.ParseHeader(&c.rxBuf) - if err != nil { - return frames.Frame{}, err - } - frameInProgress = true - } - - // check size is reasonable - if currentHeader.Size > math.MaxInt32 { // make max size configurable - return frames.Frame{}, errors.New("payload too large") - } - - bodySize := int64(currentHeader.Size - frames.HeaderSize) - - // the full frame hasn't been received, keep reading - if int64(c.rxBuf.Len()) < bodySize { - continue - } - frameInProgress = false - - // check if body is empty (keepalive) - if bodySize == 0 { - debug.Log(3, "RX (connReader %p): received keep-alive frame", c) - continue - } - - // parse the frame - b, ok := c.rxBuf.Next(bodySize) - if !ok { - return frames.Frame{}, fmt.Errorf("buffer EOF; requested bytes: %d, actual size: %d", bodySize, c.rxBuf.Len()) - } - - parsedBody, err := frames.ParseBody(buffer.New(b)) - if err != nil { - return frames.Frame{}, err - } - - return frames.Frame{Channel: currentHeader.Channel, Body: parsedBody}, nil - } -} - -// frameEnvelope is used when sending a frame to connWriter to be written to net.Conn -type frameEnvelope struct { - Ctx context.Context - Frame frames.Frame - - // optional channel that is closed on successful write to net.Conn or contains the write error - // NOTE: use a buffered channel of size 1 when populating - Sent chan error -} - -func (c *Conn) connWriter() { - defer func() { - close(c.txDone) - c.close() - }() - - var ( - // keepalives are sent at a rate of 1/2 idle timeout - keepaliveInterval = c.peerIdleTimeout / 2 - // 0 disables keepalives - keepalivesEnabled = keepaliveInterval > 0 - // set if enable, nil if not; nil channels block forever - keepalive <-chan time.Time - ) - - if keepalivesEnabled { - ticker := time.NewTicker(keepaliveInterval) - defer ticker.Stop() - keepalive = ticker.C - } - - var err error - for { - if err != nil { - debug.Log(1, "TX (connWriter %p): terminal error: %v", c, err) - c.txErr = err - return - } - - select { - // frame write request - case env := <-c.txFrame: - timeout, ctxErr := c.getWriteTimeout(env.Ctx) - if ctxErr != nil { - debug.Log(1, "TX (connWriter %p) deadline exceeded: %s", c, env.Frame) - if env.Sent != nil { - env.Sent <- ctxErr - } - continue - } - - debug.Log(1, "TX (connWriter %p) timeout %s: %s", c, timeout, env.Frame) - err = c.writeFrame(timeout, env.Frame) - if env.Sent != nil { - if err == nil { - close(env.Sent) - } else { - env.Sent <- err - } - } - - // keepalive timer - case <-keepalive: - debug.Log(3, "TX (connWriter %p): sending keep-alive frame", c) - _ = c.net.SetWriteDeadline(time.Now().Add(c.writeTimeout)) - if _, err = c.net.Write(keepaliveFrame); err != nil { - err = &ConnError{inner: err} - } - // It would be slightly more efficient in terms of network - // resources to reset the timer each time a frame is sent. - // However, keepalives are small (8 bytes) and the interval - // is usually on the order of minutes. It does not seem - // worth it to add extra operations in the write path to - // avoid. (To properly reset a timer it needs to be stopped, - // possibly drained, then reset.) - - // connection complete - case <-c.rxtxExit: - // send close performative. note that the spec says we - // SHOULD wait for the ack but we don't HAVE to, in order - // to be resilient to bad actors etc. so we just send - // the close performative and exit. - fr := frames.Frame{ - Type: frames.TypeAMQP, - Body: &frames.PerformClose{}, - } - debug.Log(1, "TX (connWriter %p): %s", c, fr) - c.txErr = c.writeFrame(c.writeTimeout, fr) - return - } - } -} - -// writeFrame writes a frame to the network. -// used externally by SASL only. -// - timeout - the write deadline to set. zero means no deadline -// -// errors are wrapped in a ConnError as they can be returned to outside callers. -func (c *Conn) writeFrame(timeout time.Duration, fr frames.Frame) error { - // writeFrame into txBuf - c.txBuf.Reset() - err := frames.Write(&c.txBuf, fr) - if err != nil { - return &ConnError{inner: err} - } - - // validate the frame isn't exceeding peer's max frame size - requiredFrameSize := c.txBuf.Len() - if uint64(requiredFrameSize) > uint64(c.peerMaxFrameSize) { - return &ConnError{inner: fmt.Errorf("%T frame size %d larger than peer's max frame size %d", fr, requiredFrameSize, c.peerMaxFrameSize)} - } - - if timeout == 0 { - _ = c.net.SetWriteDeadline(time.Time{}) - } else if timeout > 0 { - _ = c.net.SetWriteDeadline(time.Now().Add(timeout)) - } - - // write to network - n, err := c.net.Write(c.txBuf.Bytes()) - if l := c.txBuf.Len(); n > 0 && n < l && err != nil { - debug.Log(1, "TX (writeFrame %p): wrote %d bytes less than len %d: %v", c, n, l, err) - } - if err != nil { - err = &ConnError{inner: err} - } - return err -} - -// writeProtoHeader writes an AMQP protocol header to the -// network -func (c *Conn) writeProtoHeader(pID protoID) error { - _, err := c.net.Write([]byte{'A', 'M', 'Q', 'P', byte(pID), 1, 0, 0}) - return err -} - -// keepaliveFrame is an AMQP frame with no body, used for keepalives -var keepaliveFrame = []byte{0x00, 0x00, 0x00, 0x08, 0x02, 0x00, 0x00, 0x00} - -// SendFrame is used by sessions and links to send frames across the network. -// - ctx is used to provide the write deadline -// - fr is the frame to write to net.Conn -// - sent is the optional channel that will contain the error if the write fails -func (c *Conn) sendFrame(ctx context.Context, fr frames.Frame, sent chan error) { - select { - case c.txFrame <- frameEnvelope{Ctx: ctx, Frame: fr, Sent: sent}: - debug.Log(2, "TX (Conn %p): mux frame to connWriter: %s", c, fr) - case <-c.done: - if sent != nil { - sent <- c.doneErr - } - } -} - -// stateFunc is a state in a state machine. -// -// The state is advanced by returning the next state. -// The state machine concludes when nil is returned. -type stateFunc func(context.Context) (stateFunc, error) - -// negotiateProto determines which proto to negotiate next. -// used externally by SASL only. -func (c *Conn) negotiateProto(ctx context.Context) (stateFunc, error) { - // in the order each must be negotiated - switch { - case c.tlsNegotiation && !c.tlsComplete: - return c.exchangeProtoHeader(protoTLS) - case c.saslHandlers != nil && !c.saslComplete: - return c.exchangeProtoHeader(protoSASL) - default: - return c.exchangeProtoHeader(protoAMQP) - } -} - -type protoID uint8 - -// protocol IDs received in protoHeaders -const ( - protoAMQP protoID = 0x0 - protoTLS protoID = 0x2 - protoSASL protoID = 0x3 -) - -// exchangeProtoHeader performs the round trip exchange of protocol -// headers, validation, and returns the protoID specific next state. -func (c *Conn) exchangeProtoHeader(pID protoID) (stateFunc, error) { - // write the proto header - if err := c.writeProtoHeader(pID); err != nil { - return nil, err - } - - // read response header - p, err := c.readProtoHeader() - if err != nil { - return nil, err - } - - if pID != p.ProtoID { - return nil, fmt.Errorf("unexpected protocol header %#00x, expected %#00x", p.ProtoID, pID) - } - - // go to the proto specific state - switch pID { - case protoAMQP: - return c.openAMQP, nil - case protoTLS: - return c.startTLS, nil - case protoSASL: - return c.negotiateSASL, nil - default: - return nil, fmt.Errorf("unknown protocol ID %#02x", p.ProtoID) - } -} - -// readProtoHeader reads a protocol header packet from c.rxProto. -func (c *Conn) readProtoHeader() (protoHeader, error) { - const protoHeaderSize = 8 - - // only read from the network once our buffer has been exhausted. - // TODO: this preserves existing behavior as some tests rely on this - // implementation detail (it lets you replay a stream of bytes). we - // might want to consider removing this and fixing the tests as the - // protocol doesn't actually work this way. - if c.rxBuf.Len() == 0 { - for { - err := c.rxBuf.ReadFromOnce(c.net) - if err != nil { - return protoHeader{}, err - } - - // read more if buf doesn't contain enough to parse the header - if c.rxBuf.Len() >= protoHeaderSize { - break - } - } - } - - buf, ok := c.rxBuf.Next(protoHeaderSize) - if !ok { - return protoHeader{}, errors.New("invalid protoHeader") - } - // bounds check hint to compiler; see golang.org/issue/14808 - _ = buf[protoHeaderSize-1] - - if !bytes.Equal(buf[:4], []byte{'A', 'M', 'Q', 'P'}) { - return protoHeader{}, fmt.Errorf("unexpected protocol %q", buf[:4]) - } - - p := protoHeader{ - ProtoID: protoID(buf[4]), - Major: buf[5], - Minor: buf[6], - Revision: buf[7], - } - - if p.Major != 1 || p.Minor != 0 || p.Revision != 0 { - return protoHeader{}, fmt.Errorf("unexpected protocol version %d.%d.%d", p.Major, p.Minor, p.Revision) - } - - return p, nil -} - -// startTLS wraps the conn with TLS and returns to Client.negotiateProto -func (c *Conn) startTLS(ctx context.Context) (stateFunc, error) { - c.initTLSConfig() - - _ = c.net.SetReadDeadline(time.Time{}) // clear timeout - - // wrap existing net.Conn and perform TLS handshake - tlsConn := tls.Client(c.net, c.tlsConfig) - if err := tlsConn.HandshakeContext(ctx); err != nil { - return nil, err - } - - // swap net.Conn - c.net = tlsConn - c.tlsComplete = true - - // go to next protocol - return c.negotiateProto, nil -} - -// openAMQP round trips the AMQP open performative -func (c *Conn) openAMQP(ctx context.Context) (stateFunc, error) { - // send open frame - open := &frames.PerformOpen{ - ContainerID: c.containerID, - Hostname: c.hostname, - MaxFrameSize: c.maxFrameSize, - ChannelMax: c.channelMax, - IdleTimeout: c.idleTimeout / 2, // per spec, advertise half our idle timeout - Properties: c.properties, - } - fr := frames.Frame{ - Type: frames.TypeAMQP, - Body: open, - Channel: 0, - } - debug.Log(1, "TX (openAMQP %p): %s", c, fr) - timeout, err := c.getWriteTimeout(ctx) - if err != nil { - return nil, err - } - if err = c.writeFrame(timeout, fr); err != nil { - return nil, err - } - - // get the response - fr, err = c.readSingleFrame() - if err != nil { - return nil, err - } - debug.Log(1, "RX (openAMQP %p): %s", c, fr) - o, ok := fr.Body.(*frames.PerformOpen) - if !ok { - return nil, fmt.Errorf("openAMQP: unexpected frame type %T", fr.Body) - } - - // update peer settings - if o.MaxFrameSize > 0 { - c.peerMaxFrameSize = o.MaxFrameSize - } - if o.IdleTimeout > 0 { - // TODO: reject very small idle timeouts - c.peerIdleTimeout = o.IdleTimeout - } - if o.ChannelMax < c.channelMax { - c.channelMax = o.ChannelMax - } - - // connection established, exit state machine - return nil, nil -} - -// negotiateSASL returns the SASL handler for the first matched -// mechanism specified by the server -func (c *Conn) negotiateSASL(context.Context) (stateFunc, error) { - // read mechanisms frame - fr, err := c.readSingleFrame() - if err != nil { - return nil, err - } - debug.Log(1, "RX (negotiateSASL %p): %s", c, fr) - sm, ok := fr.Body.(*frames.SASLMechanisms) - if !ok { - return nil, fmt.Errorf("negotiateSASL: unexpected frame type %T", fr.Body) - } - - // return first match in c.saslHandlers based on order received - for _, mech := range sm.Mechanisms { - if state, ok := c.saslHandlers[mech]; ok { - return state, nil - } - } - - // no match - return nil, fmt.Errorf("no supported auth mechanism (%v)", sm.Mechanisms) // TODO: send "auth not supported" frame? -} - -// saslOutcome processes the SASL outcome frame and return Client.negotiateProto -// on success. -// -// SASL handlers return this stateFunc when the mechanism specific negotiation -// has completed. -// used externally by SASL only. -func (c *Conn) saslOutcome(context.Context) (stateFunc, error) { - // read outcome frame - fr, err := c.readSingleFrame() - if err != nil { - return nil, err - } - debug.Log(1, "RX (saslOutcome %p): %s", c, fr) - so, ok := fr.Body.(*frames.SASLOutcome) - if !ok { - return nil, fmt.Errorf("saslOutcome: unexpected frame type %T", fr.Body) - } - - // check if auth succeeded - if so.Code != encoding.CodeSASLOK { - return nil, fmt.Errorf("SASL PLAIN auth failed with code %#00x: %s", so.Code, so.AdditionalData) // implement Stringer for so.Code - } - - // return to c.negotiateProto - c.saslComplete = true - return c.negotiateProto, nil -} - -// readSingleFrame is used during connection establishment to read a single frame. -// -// After setup, conn.connReader handles incoming frames. -func (c *Conn) readSingleFrame() (frames.Frame, error) { - fr, err := c.readFrame() - if err != nil { - return frames.Frame{}, err - } - - return fr, nil -} - -// getWriteTimeout returns the timeout as calculated from the context's deadline -// or the default write timeout if the context has no deadline. -// if the context has timed out or was cancelled, an error is returned. -func (c *Conn) getWriteTimeout(ctx context.Context) (time.Duration, error) { - if deadline, ok := ctx.Deadline(); ok { - until := time.Until(deadline) - if until <= 0 { - return 0, context.DeadlineExceeded - } - return until, nil - } - return c.writeTimeout, nil -} - -type protoHeader struct { - ProtoID protoID - Major uint8 - Minor uint8 - Revision uint8 -} diff --git a/sdk/messaging/azservicebus/internal/go-amqp/const.go b/sdk/messaging/azservicebus/internal/go-amqp/const.go deleted file mode 100644 index 70a2aeff6b61..000000000000 --- a/sdk/messaging/azservicebus/internal/go-amqp/const.go +++ /dev/null @@ -1,96 +0,0 @@ -// Copyright (C) 2017 Kale Blankenship -// Portions Copyright (c) Microsoft Corporation - -package amqp - -import "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus/internal/go-amqp/internal/encoding" - -// Sender Settlement Modes -const ( - // Sender will send all deliveries initially unsettled to the receiver. - SenderSettleModeUnsettled SenderSettleMode = encoding.SenderSettleModeUnsettled - - // Sender will send all deliveries settled to the receiver. - SenderSettleModeSettled SenderSettleMode = encoding.SenderSettleModeSettled - - // Sender MAY send a mixture of settled and unsettled deliveries to the receiver. - SenderSettleModeMixed SenderSettleMode = encoding.SenderSettleModeMixed -) - -// SenderSettleMode specifies how the sender will settle messages. -type SenderSettleMode = encoding.SenderSettleMode - -func senderSettleModeValue(m *SenderSettleMode) SenderSettleMode { - if m == nil { - return SenderSettleModeMixed - } - return *m -} - -// Receiver Settlement Modes -const ( - // Receiver is the first to consider the message as settled. - // Once the corresponding disposition frame is sent, the message - // is considered to be settled. - ReceiverSettleModeFirst ReceiverSettleMode = encoding.ReceiverSettleModeFirst - - // Receiver is the second to consider the message as settled. - // Once the corresponding disposition frame is sent, the settlement - // is considered in-flight and the message will not be considered as - // settled until the sender replies acknowledging the settlement. - ReceiverSettleModeSecond ReceiverSettleMode = encoding.ReceiverSettleModeSecond -) - -// ReceiverSettleMode specifies how the receiver will settle messages. -type ReceiverSettleMode = encoding.ReceiverSettleMode - -func receiverSettleModeValue(m *ReceiverSettleMode) ReceiverSettleMode { - if m == nil { - return ReceiverSettleModeFirst - } - return *m -} - -// Durability Policies -const ( - // No terminus state is retained durably. - DurabilityNone Durability = encoding.DurabilityNone - - // Only the existence and configuration of the terminus is - // retained durably. - DurabilityConfiguration Durability = encoding.DurabilityConfiguration - - // In addition to the existence and configuration of the - // terminus, the unsettled state for durable messages is - // retained durably. - DurabilityUnsettledState Durability = encoding.DurabilityUnsettledState -) - -// Durability specifies the durability of a link. -type Durability = encoding.Durability - -// Expiry Policies -const ( - // The expiry timer starts when terminus is detached. - ExpiryPolicyLinkDetach ExpiryPolicy = encoding.ExpiryLinkDetach - - // The expiry timer starts when the most recently - // associated session is ended. - ExpiryPolicySessionEnd ExpiryPolicy = encoding.ExpirySessionEnd - - // The expiry timer starts when most recently associated - // connection is closed. - ExpiryPolicyConnectionClose ExpiryPolicy = encoding.ExpiryConnectionClose - - // The terminus never expires. - ExpiryPolicyNever ExpiryPolicy = encoding.ExpiryNever -) - -// ExpiryPolicy specifies when the expiry timer of a terminus -// starts counting down from the timeout value. -// -// If the link is subsequently re-attached before the terminus is expired, -// then the count down is aborted. If the conditions for the -// terminus-expiry-policy are subsequently re-met, the expiry timer restarts -// from its originally configured timeout value. -type ExpiryPolicy = encoding.ExpiryPolicy diff --git a/sdk/messaging/azservicebus/internal/go-amqp/creditor.go b/sdk/messaging/azservicebus/internal/go-amqp/creditor.go deleted file mode 100644 index 184702bca7d2..000000000000 --- a/sdk/messaging/azservicebus/internal/go-amqp/creditor.go +++ /dev/null @@ -1,119 +0,0 @@ -// Copyright (c) Microsoft Corporation - -package amqp - -import ( - "context" - "errors" - "sync" -) - -type creditor struct { - mu sync.Mutex - - // future values for the next flow frame. - pendingDrain bool - creditsToAdd uint32 - - // drained is set when a drain is active and we're waiting - // for the corresponding flow from the remote. - drained chan struct{} -} - -var ( - errLinkDraining = errors.New("link is currently draining, no credits can be added") - errAlreadyDraining = errors.New("drain already in process") -) - -// EndDrain ends the current drain, unblocking any active Drain calls. -func (mc *creditor) EndDrain() { - mc.mu.Lock() - defer mc.mu.Unlock() - - if mc.drained != nil { - close(mc.drained) - mc.drained = nil - } -} - -// FlowBits gets gets the proper values for the next flow frame -// and resets the internal state. -// Returns: -// -// (drain: true, credits: 0) if a flow is needed (drain) -// (drain: false, credits > 0) if a flow is needed (issue credit) -// (drain: false, credits == 0) if no flow needed. -func (mc *creditor) FlowBits(currentCredits uint32) (bool, uint32) { - mc.mu.Lock() - defer mc.mu.Unlock() - - drain := mc.pendingDrain - var credits uint32 - - if mc.pendingDrain { - // only send one drain request - mc.pendingDrain = false - } - - // either: - // drain is true (ie, we're going to send a drain frame, and the credits for it should be 0) - // mc.creditsToAdd == 0 (no flow frame needed, no new credits are being issued) - if drain || mc.creditsToAdd == 0 { - credits = 0 - } else { - credits = mc.creditsToAdd + currentCredits - } - - mc.creditsToAdd = 0 - - return drain, credits -} - -// Drain initiates a drain and blocks until EndDrain is called. -// If the context's deadline expires or is cancelled before the operation -// completes, the drain might not have happened. -func (mc *creditor) Drain(ctx context.Context, r *Receiver) error { - mc.mu.Lock() - - if mc.drained != nil { - mc.mu.Unlock() - return errAlreadyDraining - } - - mc.drained = make(chan struct{}) - // use a local copy to avoid racing with EndDrain() - drained := mc.drained - mc.pendingDrain = true - - mc.mu.Unlock() - - // cause mux() to check our flow conditions. - select { - case r.receiverReady <- struct{}{}: - default: - } - - // send drain, wait for responding flow frame - select { - case <-drained: - return nil - case <-r.l.done: - return r.l.doneErr - case <-ctx.Done(): - return ctx.Err() - } -} - -// IssueCredit queues up additional credits to be requested at the next -// call of FlowBits() -func (mc *creditor) IssueCredit(credits uint32) error { - mc.mu.Lock() - defer mc.mu.Unlock() - - if mc.drained != nil { - return errLinkDraining - } - - mc.creditsToAdd += credits - return nil -} diff --git a/sdk/messaging/azservicebus/internal/go-amqp/errors.go b/sdk/messaging/azservicebus/internal/go-amqp/errors.go deleted file mode 100644 index 126fc330ab05..000000000000 --- a/sdk/messaging/azservicebus/internal/go-amqp/errors.go +++ /dev/null @@ -1,107 +0,0 @@ -// Copyright (C) 2017 Kale Blankenship -// Portions Copyright (c) Microsoft Corporation - -package amqp - -import ( - "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus/internal/go-amqp/internal/encoding" -) - -// ErrCond is an AMQP defined error condition. -// See http://docs.oasis-open.org/amqp/core/v1.0/os/amqp-core-transport-v1.0-os.html#type-amqp-error for info on their meaning. -type ErrCond = encoding.ErrCond - -// Error Conditions -const ( - // AMQP Errors - ErrCondDecodeError ErrCond = "amqp:decode-error" - ErrCondFrameSizeTooSmall ErrCond = "amqp:frame-size-too-small" - ErrCondIllegalState ErrCond = "amqp:illegal-state" - ErrCondInternalError ErrCond = "amqp:internal-error" - ErrCondInvalidField ErrCond = "amqp:invalid-field" - ErrCondNotAllowed ErrCond = "amqp:not-allowed" - ErrCondNotFound ErrCond = "amqp:not-found" - ErrCondNotImplemented ErrCond = "amqp:not-implemented" - ErrCondPreconditionFailed ErrCond = "amqp:precondition-failed" - ErrCondResourceDeleted ErrCond = "amqp:resource-deleted" - ErrCondResourceLimitExceeded ErrCond = "amqp:resource-limit-exceeded" - ErrCondResourceLocked ErrCond = "amqp:resource-locked" - ErrCondUnauthorizedAccess ErrCond = "amqp:unauthorized-access" - - // Connection Errors - ErrCondConnectionForced ErrCond = "amqp:connection:forced" - ErrCondConnectionRedirect ErrCond = "amqp:connection:redirect" - ErrCondFramingError ErrCond = "amqp:connection:framing-error" - - // Session Errors - ErrCondErrantLink ErrCond = "amqp:session:errant-link" - ErrCondHandleInUse ErrCond = "amqp:session:handle-in-use" - ErrCondUnattachedHandle ErrCond = "amqp:session:unattached-handle" - ErrCondWindowViolation ErrCond = "amqp:session:window-violation" - - // Link Errors - ErrCondDetachForced ErrCond = "amqp:link:detach-forced" - ErrCondLinkRedirect ErrCond = "amqp:link:redirect" - ErrCondMessageSizeExceeded ErrCond = "amqp:link:message-size-exceeded" - ErrCondStolen ErrCond = "amqp:link:stolen" - ErrCondTransferLimitExceeded ErrCond = "amqp:link:transfer-limit-exceeded" -) - -// Error is an AMQP error. -type Error = encoding.Error - -// LinkError is returned by methods on Sender/Receiver when the link has closed. -type LinkError struct { - // RemoteErr contains any error information provided by the peer if the peer detached the link. - RemoteErr *Error - - inner error -} - -// Error implements the error interface for LinkError. -func (e *LinkError) Error() string { - if e.RemoteErr == nil && e.inner == nil { - return "amqp: link closed" - } else if e.RemoteErr != nil { - return e.RemoteErr.Error() - } - return e.inner.Error() -} - -// ConnError is returned by methods on Conn and propagated to Session and Senders/Receivers -// when the connection has been closed. -type ConnError struct { - // RemoteErr contains any error information provided by the peer if the peer closed the AMQP connection. - RemoteErr *Error - - inner error -} - -// Error implements the error interface for ConnectionError. -func (e *ConnError) Error() string { - if e.RemoteErr == nil && e.inner == nil { - return "amqp: connection closed" - } else if e.RemoteErr != nil { - return e.RemoteErr.Error() - } - return e.inner.Error() -} - -// SessionError is returned by methods on Session and propagated to Senders/Receivers -// when the session has been closed. -type SessionError struct { - // RemoteErr contains any error information provided by the peer if the peer closed the session. - RemoteErr *Error - - inner error -} - -// Error implements the error interface for SessionError. -func (e *SessionError) Error() string { - if e.RemoteErr == nil && e.inner == nil { - return "amqp: session closed" - } else if e.RemoteErr != nil { - return e.RemoteErr.Error() - } - return e.inner.Error() -} diff --git a/sdk/messaging/azservicebus/internal/go-amqp/internal/bitmap/bitmap.go b/sdk/messaging/azservicebus/internal/go-amqp/internal/bitmap/bitmap.go deleted file mode 100644 index d4d682e9199e..000000000000 --- a/sdk/messaging/azservicebus/internal/go-amqp/internal/bitmap/bitmap.go +++ /dev/null @@ -1,99 +0,0 @@ -// Copyright (C) 2017 Kale Blankenship -// Portions Copyright (c) Microsoft Corporation - -package bitmap - -import ( - "math/bits" -) - -// bitmap is a lazily initialized bitmap -type Bitmap struct { - max uint32 - bits []uint64 -} - -func New(max uint32) *Bitmap { - return &Bitmap{max: max} -} - -// add sets n in the bitmap. -// -// bits will be expanded as needed. -// -// If n is greater than max, the call has no effect. -func (b *Bitmap) Add(n uint32) { - if n > b.max { - return - } - - var ( - idx = n / 64 - offset = n % 64 - ) - - if l := len(b.bits); int(idx) >= l { - b.bits = append(b.bits, make([]uint64, int(idx)-l+1)...) - } - - b.bits[idx] |= 1 << offset -} - -// remove clears n from the bitmap. -// -// If n is not set or greater than max the call has not effect. -func (b *Bitmap) Remove(n uint32) { - var ( - idx = n / 64 - offset = n % 64 - ) - - if int(idx) >= len(b.bits) { - return - } - - b.bits[idx] &= ^uint64(1 << offset) -} - -// next sets and returns the lowest unset bit in the bitmap. -// -// bits will be expanded if necessary. -// -// If there are no unset bits below max, the second return -// value will be false. -func (b *Bitmap) Next() (uint32, bool) { - // find the first unset bit - for i, v := range b.bits { - // skip if all bits are set - if v == ^uint64(0) { - continue - } - - var ( - offset = bits.TrailingZeros64(^v) // invert and count zeroes - next = uint32(i*64 + offset) - ) - - // check if in bounds - if next > b.max { - return next, false - } - - // set bit - b.bits[i] |= 1 << uint32(offset) - return next, true - } - - // no unset bits in the current slice, - // check if the full range has been allocated - if uint64(len(b.bits)*64) > uint64(b.max) { - return 0, false - } - - // full range not allocated, append entry with first - // bit set - b.bits = append(b.bits, 1) - - // return the value of the first bit - return uint32(len(b.bits)-1) * 64, true -} diff --git a/sdk/messaging/azservicebus/internal/go-amqp/internal/buffer/buffer.go b/sdk/messaging/azservicebus/internal/go-amqp/internal/buffer/buffer.go deleted file mode 100644 index b82e5fab76a6..000000000000 --- a/sdk/messaging/azservicebus/internal/go-amqp/internal/buffer/buffer.go +++ /dev/null @@ -1,180 +0,0 @@ -// Copyright (C) 2017 Kale Blankenship -// Portions Copyright (c) Microsoft Corporation - -package buffer - -import ( - "encoding/binary" - "io" -) - -// buffer is similar to bytes.Buffer but specialized for this package -type Buffer struct { - b []byte - i int -} - -func New(b []byte) *Buffer { - return &Buffer{b: b} -} - -func (b *Buffer) Next(n int64) ([]byte, bool) { - if b.readCheck(n) { - buf := b.b[b.i:len(b.b)] - b.i = len(b.b) - return buf, false - } - - buf := b.b[b.i : b.i+int(n)] - b.i += int(n) - return buf, true -} - -func (b *Buffer) Skip(n int) { - b.i += n -} - -func (b *Buffer) Reset() { - b.b = b.b[:0] - b.i = 0 -} - -// reclaim shifts used buffer space to the beginning of the -// underlying slice. -func (b *Buffer) Reclaim() { - l := b.Len() - copy(b.b[:l], b.b[b.i:]) - b.b = b.b[:l] - b.i = 0 -} - -func (b *Buffer) readCheck(n int64) bool { - return int64(b.i)+n > int64(len(b.b)) -} - -func (b *Buffer) ReadByte() (byte, error) { - if b.readCheck(1) { - return 0, io.EOF - } - - byte_ := b.b[b.i] - b.i++ - return byte_, nil -} - -func (b *Buffer) PeekByte() (byte, error) { - if b.readCheck(1) { - return 0, io.EOF - } - - return b.b[b.i], nil -} - -func (b *Buffer) ReadUint16() (uint16, error) { - if b.readCheck(2) { - return 0, io.EOF - } - - n := binary.BigEndian.Uint16(b.b[b.i:]) - b.i += 2 - return n, nil -} - -func (b *Buffer) ReadUint32() (uint32, error) { - if b.readCheck(4) { - return 0, io.EOF - } - - n := binary.BigEndian.Uint32(b.b[b.i:]) - b.i += 4 - return n, nil -} - -func (b *Buffer) ReadUint64() (uint64, error) { - if b.readCheck(8) { - return 0, io.EOF - } - - n := binary.BigEndian.Uint64(b.b[b.i : b.i+8]) - b.i += 8 - return n, nil -} - -func (b *Buffer) ReadFromOnce(r io.Reader) error { - const minRead = 512 - - l := len(b.b) - if cap(b.b)-l < minRead { - total := l * 2 - if total == 0 { - total = minRead - } - new := make([]byte, l, total) - copy(new, b.b) - b.b = new - } - - n, err := r.Read(b.b[l:cap(b.b)]) - b.b = b.b[:l+n] - return err -} - -func (b *Buffer) Append(p []byte) { - b.b = append(b.b, p...) -} - -func (b *Buffer) AppendByte(bb byte) { - b.b = append(b.b, bb) -} - -func (b *Buffer) AppendString(s string) { - b.b = append(b.b, s...) -} - -func (b *Buffer) Len() int { - return len(b.b) - b.i -} - -func (b *Buffer) Size() int { - return b.i -} - -func (b *Buffer) Bytes() []byte { - return b.b[b.i:] -} - -func (b *Buffer) Detach() []byte { - temp := b.b - b.b = nil - b.i = 0 - return temp -} - -func (b *Buffer) AppendUint16(n uint16) { - b.b = append(b.b, - byte(n>>8), - byte(n), - ) -} - -func (b *Buffer) AppendUint32(n uint32) { - b.b = append(b.b, - byte(n>>24), - byte(n>>16), - byte(n>>8), - byte(n), - ) -} - -func (b *Buffer) AppendUint64(n uint64) { - b.b = append(b.b, - byte(n>>56), - byte(n>>48), - byte(n>>40), - byte(n>>32), - byte(n>>24), - byte(n>>16), - byte(n>>8), - byte(n), - ) -} diff --git a/sdk/messaging/azservicebus/internal/go-amqp/internal/debug/debug.go b/sdk/messaging/azservicebus/internal/go-amqp/internal/debug/debug.go deleted file mode 100644 index 3e6821e1f723..000000000000 --- a/sdk/messaging/azservicebus/internal/go-amqp/internal/debug/debug.go +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (C) 2017 Kale Blankenship -// Portions Copyright (c) Microsoft Corporation - -//go:build !debug -// +build !debug - -package debug - -// dummy functions used when debugging is not enabled - -// Log writes the formatted string to stderr. -// Level indicates the verbosity of the messages to log. -// The greater the value, the more verbose messages will be logged. -func Log(_ int, _ string, _ ...any) {} - -// Assert panics if the specified condition is false. -func Assert(bool) {} - -// Assert panics with the provided message if the specified condition is false. -func Assertf(bool, string, ...any) {} diff --git a/sdk/messaging/azservicebus/internal/go-amqp/internal/debug/debug_debug.go b/sdk/messaging/azservicebus/internal/go-amqp/internal/debug/debug_debug.go deleted file mode 100644 index 96d53768a5c9..000000000000 --- a/sdk/messaging/azservicebus/internal/go-amqp/internal/debug/debug_debug.go +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright (C) 2017 Kale Blankenship -// Portions Copyright (c) Microsoft Corporation - -//go:build debug -// +build debug - -package debug - -import ( - "fmt" - "log" - "os" - "strconv" -) - -var ( - debugLevel = 1 - logger = log.New(os.Stderr, "", log.Lmicroseconds) -) - -func init() { - level, err := strconv.Atoi(os.Getenv("DEBUG_LEVEL")) - if err != nil { - return - } - - debugLevel = level -} - -// Log writes the formatted string to stderr. -// Level indicates the verbosity of the messages to log. -// The greater the value, the more verbose messages will be logged. -func Log(level int, format string, v ...any) { - if level <= debugLevel { - logger.Printf(format, v...) - } -} - -// Assert panics if the specified condition is false. -func Assert(condition bool) { - if !condition { - panic("assertion failed!") - } -} - -// Assert panics with the provided message if the specified condition is false. -func Assertf(condition bool, msg string, v ...any) { - if !condition { - panic(fmt.Sprintf(msg, v...)) - } -} diff --git a/sdk/messaging/azservicebus/internal/go-amqp/internal/encoding/decode.go b/sdk/messaging/azservicebus/internal/go-amqp/internal/encoding/decode.go deleted file mode 100644 index ad360628547a..000000000000 --- a/sdk/messaging/azservicebus/internal/go-amqp/internal/encoding/decode.go +++ /dev/null @@ -1,1150 +0,0 @@ -// Copyright (C) 2017 Kale Blankenship -// Portions Copyright (c) Microsoft Corporation - -package encoding - -import ( - "encoding/binary" - "errors" - "fmt" - "math" - "reflect" - "time" - - "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus/internal/go-amqp/internal/buffer" -) - -// unmarshaler is fulfilled by types that can unmarshal -// themselves from AMQP data. -type unmarshaler interface { - Unmarshal(r *buffer.Buffer) error -} - -// unmarshal decodes AMQP encoded data into i. -// -// The decoding method is based on the type of i. -// -// If i implements unmarshaler, i.Unmarshal() will be called. -// -// Pointers to primitive types will be decoded via the appropriate read[Type] function. -// -// If i is a pointer to a pointer (**Type), it will be dereferenced and a new instance -// of (*Type) is allocated via reflection. -// -// Common map types (map[string]string, map[Symbol]any, and -// map[any]any), will be decoded via conversion to the mapStringAny, -// mapSymbolAny, and mapAnyAny types. -func Unmarshal(r *buffer.Buffer, i any) error { - if tryReadNull(r) { - return nil - } - - switch t := i.(type) { - case *int: - val, err := readInt(r) - if err != nil { - return err - } - *t = val - case *int8: - val, err := readSbyte(r) - if err != nil { - return err - } - *t = val - case *int16: - val, err := readShort(r) - if err != nil { - return err - } - *t = val - case *int32: - val, err := readInt32(r) - if err != nil { - return err - } - *t = val - case *int64: - val, err := readLong(r) - if err != nil { - return err - } - *t = val - case *uint64: - val, err := readUlong(r) - if err != nil { - return err - } - *t = val - case *uint32: - val, err := readUint32(r) - if err != nil { - return err - } - *t = val - case **uint32: // fastpath for uint32 pointer fields - val, err := readUint32(r) - if err != nil { - return err - } - *t = &val - case *uint16: - val, err := readUshort(r) - if err != nil { - return err - } - *t = val - case *uint8: - val, err := ReadUbyte(r) - if err != nil { - return err - } - *t = val - case *float32: - val, err := readFloat(r) - if err != nil { - return err - } - *t = val - case *float64: - val, err := readDouble(r) - if err != nil { - return err - } - *t = val - case *string: - val, err := ReadString(r) - if err != nil { - return err - } - *t = val - case *Symbol: - s, err := ReadString(r) - if err != nil { - return err - } - *t = Symbol(s) - case *[]byte: - val, err := readBinary(r) - if err != nil { - return err - } - *t = val - case *bool: - b, err := readBool(r) - if err != nil { - return err - } - *t = b - case *time.Time: - ts, err := readTimestamp(r) - if err != nil { - return err - } - *t = ts - case *[]int8: - return (*arrayInt8)(t).Unmarshal(r) - case *[]uint16: - return (*arrayUint16)(t).Unmarshal(r) - case *[]int16: - return (*arrayInt16)(t).Unmarshal(r) - case *[]uint32: - return (*arrayUint32)(t).Unmarshal(r) - case *[]int32: - return (*arrayInt32)(t).Unmarshal(r) - case *[]uint64: - return (*arrayUint64)(t).Unmarshal(r) - case *[]int64: - return (*arrayInt64)(t).Unmarshal(r) - case *[]float32: - return (*arrayFloat)(t).Unmarshal(r) - case *[]float64: - return (*arrayDouble)(t).Unmarshal(r) - case *[]bool: - return (*arrayBool)(t).Unmarshal(r) - case *[]string: - return (*arrayString)(t).Unmarshal(r) - case *[]Symbol: - return (*arraySymbol)(t).Unmarshal(r) - case *[][]byte: - return (*arrayBinary)(t).Unmarshal(r) - case *[]time.Time: - return (*arrayTimestamp)(t).Unmarshal(r) - case *[]UUID: - return (*arrayUUID)(t).Unmarshal(r) - case *[]any: - return (*list)(t).Unmarshal(r) - case *map[any]any: - return (*mapAnyAny)(t).Unmarshal(r) - case *map[string]any: - return (*mapStringAny)(t).Unmarshal(r) - case *map[Symbol]any: - return (*mapSymbolAny)(t).Unmarshal(r) - case *DeliveryState: - type_, _, err := PeekMessageType(r.Bytes()) - if err != nil { - return err - } - - switch AMQPType(type_) { - case TypeCodeStateAccepted: - *t = new(StateAccepted) - case TypeCodeStateModified: - *t = new(StateModified) - case TypeCodeStateReceived: - *t = new(StateReceived) - case TypeCodeStateRejected: - *t = new(StateRejected) - case TypeCodeStateReleased: - *t = new(StateReleased) - default: - return fmt.Errorf("unexpected type %d for deliveryState", type_) - } - return Unmarshal(r, *t) - - case *any: - v, err := ReadAny(r) - if err != nil { - return err - } - *t = v - - case unmarshaler: - return t.Unmarshal(r) - default: - // handle **T - v := reflect.Indirect(reflect.ValueOf(i)) - - // can't unmarshal into a non-pointer - if v.Kind() != reflect.Ptr { - return fmt.Errorf("unable to unmarshal %T", i) - } - - // if nil pointer, allocate a new value to - // unmarshal into - if v.IsNil() { - v.Set(reflect.New(v.Type().Elem())) - } - - return Unmarshal(r, v.Interface()) - } - return nil -} - -// unmarshalComposite is a helper for use in a composite's unmarshal() function. -// -// The composite from r will be unmarshaled into zero or more fields. An error -// will be returned if typ does not match the decoded type. -func UnmarshalComposite(r *buffer.Buffer, type_ AMQPType, fields ...UnmarshalField) error { - cType, numFields, err := readCompositeHeader(r) - if err != nil { - return err - } - - // check type matches expectation - if cType != type_ { - return fmt.Errorf("invalid header %#0x for %#0x", cType, type_) - } - - // Validate the field count is less than or equal to the number of fields - // provided. Fields may be omitted by the sender if they are not set. - if numFields > int64(len(fields)) { - return fmt.Errorf("invalid field count %d for %#0x", numFields, type_) - } - - for i, field := range fields[:numFields] { - // If the field is null and handleNull is set, call it. - if tryReadNull(r) { - if field.HandleNull != nil { - err = field.HandleNull() - if err != nil { - return err - } - } - continue - } - - // Unmarshal each of the received fields. - err = Unmarshal(r, field.Field) - if err != nil { - return fmt.Errorf("unmarshaling field %d: %v", i, err) - } - } - - // check and call handleNull for the remaining fields - for _, field := range fields[numFields:] { - if field.HandleNull != nil { - err = field.HandleNull() - if err != nil { - return err - } - } - } - - return nil -} - -// unmarshalField is a struct that contains a field to be unmarshaled into. -// -// An optional nullHandler can be set. If the composite field being unmarshaled -// is null and handleNull is not nil, nullHandler will be called. -type UnmarshalField struct { - Field any - HandleNull NullHandler -} - -// nullHandler is a function to be called when a composite's field -// is null. -type NullHandler func() error - -func readType(r *buffer.Buffer) (AMQPType, error) { - n, err := r.ReadByte() - return AMQPType(n), err -} - -func peekType(r *buffer.Buffer) (AMQPType, error) { - n, err := r.PeekByte() - return AMQPType(n), err -} - -// readCompositeHeader reads and consumes the composite header from r. -func readCompositeHeader(r *buffer.Buffer) (_ AMQPType, fields int64, _ error) { - type_, err := readType(r) - if err != nil { - return 0, 0, err - } - - // compsites always start with 0x0 - if type_ != 0 { - return 0, 0, fmt.Errorf("invalid composite header %#02x", type_) - } - - // next, the composite type is encoded as an AMQP uint8 - v, err := readUlong(r) - if err != nil { - return 0, 0, err - } - - // fields are represented as a list - fields, err = readListHeader(r) - - return AMQPType(v), fields, err -} - -func readListHeader(r *buffer.Buffer) (length int64, _ error) { - type_, err := readType(r) - if err != nil { - return 0, err - } - - listLength := r.Len() - - switch type_ { - case TypeCodeList0: - return 0, nil - case TypeCodeList8: - buf, ok := r.Next(2) - if !ok { - return 0, errors.New("invalid length") - } - _ = buf[1] - - size := int(buf[0]) - if size > listLength-1 { - return 0, errors.New("invalid length") - } - length = int64(buf[1]) - case TypeCodeList32: - buf, ok := r.Next(8) - if !ok { - return 0, errors.New("invalid length") - } - _ = buf[7] - - size := int(binary.BigEndian.Uint32(buf[:4])) - if size > listLength-4 { - return 0, errors.New("invalid length") - } - length = int64(binary.BigEndian.Uint32(buf[4:8])) - default: - return 0, fmt.Errorf("type code %#02x is not a recognized list type", type_) - } - - return length, nil -} - -func readArrayHeader(r *buffer.Buffer) (length int64, _ error) { - type_, err := readType(r) - if err != nil { - return 0, err - } - - arrayLength := r.Len() - - switch type_ { - case TypeCodeArray8: - buf, ok := r.Next(2) - if !ok { - return 0, errors.New("invalid length") - } - _ = buf[1] - - size := int(buf[0]) - if size > arrayLength-1 { - return 0, errors.New("invalid length") - } - length = int64(buf[1]) - case TypeCodeArray32: - buf, ok := r.Next(8) - if !ok { - return 0, errors.New("invalid length") - } - _ = buf[7] - - size := binary.BigEndian.Uint32(buf[:4]) - if int(size) > arrayLength-4 { - return 0, fmt.Errorf("invalid length for type %02x", type_) - } - length = int64(binary.BigEndian.Uint32(buf[4:8])) - default: - return 0, fmt.Errorf("type code %#02x is not a recognized array type", type_) - } - return length, nil -} - -func ReadString(r *buffer.Buffer) (string, error) { - type_, err := readType(r) - if err != nil { - return "", err - } - - var length int64 - switch type_ { - case TypeCodeStr8, TypeCodeSym8: - n, err := r.ReadByte() - if err != nil { - return "", err - } - length = int64(n) - case TypeCodeStr32, TypeCodeSym32: - buf, ok := r.Next(4) - if !ok { - return "", fmt.Errorf("invalid length for type %#02x", type_) - } - length = int64(binary.BigEndian.Uint32(buf)) - default: - return "", fmt.Errorf("type code %#02x is not a recognized string type", type_) - } - - buf, ok := r.Next(length) - if !ok { - return "", errors.New("invalid length") - } - return string(buf), nil -} - -func readBinary(r *buffer.Buffer) ([]byte, error) { - type_, err := readType(r) - if err != nil { - return nil, err - } - - var length int64 - switch type_ { - case TypeCodeVbin8: - n, err := r.ReadByte() - if err != nil { - return nil, err - } - length = int64(n) - case TypeCodeVbin32: - buf, ok := r.Next(4) - if !ok { - return nil, fmt.Errorf("invalid length for type %#02x", type_) - } - length = int64(binary.BigEndian.Uint32(buf)) - default: - return nil, fmt.Errorf("type code %#02x is not a recognized binary type", type_) - } - - if length == 0 { - // An empty value and a nil value are distinct, - // ensure that the returned value is not nil in this case. - return make([]byte, 0), nil - } - - buf, ok := r.Next(length) - if !ok { - return nil, errors.New("invalid length") - } - return append([]byte(nil), buf...), nil -} - -func ReadAny(r *buffer.Buffer) (any, error) { - if tryReadNull(r) { - return nil, nil - } - - type_, err := peekType(r) - if err != nil { - return nil, errors.New("invalid length") - } - - switch type_ { - // composite - case 0x0: - return readComposite(r) - - // bool - case TypeCodeBool, TypeCodeBoolTrue, TypeCodeBoolFalse: - return readBool(r) - - // uint - case TypeCodeUbyte: - return ReadUbyte(r) - case TypeCodeUshort: - return readUshort(r) - case TypeCodeUint, - TypeCodeSmallUint, - TypeCodeUint0: - return readUint32(r) - case TypeCodeUlong, - TypeCodeSmallUlong, - TypeCodeUlong0: - return readUlong(r) - - // int - case TypeCodeByte: - return readSbyte(r) - case TypeCodeShort: - return readShort(r) - case TypeCodeInt, - TypeCodeSmallint: - return readInt32(r) - case TypeCodeLong, - TypeCodeSmalllong: - return readLong(r) - - // floating point - case TypeCodeFloat: - return readFloat(r) - case TypeCodeDouble: - return readDouble(r) - - // binary - case TypeCodeVbin8, TypeCodeVbin32: - return readBinary(r) - - // strings - case TypeCodeStr8, TypeCodeStr32: - return ReadString(r) - case TypeCodeSym8, TypeCodeSym32: - // symbols currently decoded as string to avoid - // exposing symbol type in message, this may need - // to change if users need to distinguish strings - // from symbols - return ReadString(r) - - // timestamp - case TypeCodeTimestamp: - return readTimestamp(r) - - // UUID - case TypeCodeUUID: - return readUUID(r) - - // arrays - case TypeCodeArray8, TypeCodeArray32: - return readAnyArray(r) - - // lists - case TypeCodeList0, TypeCodeList8, TypeCodeList32: - return readAnyList(r) - - // maps - case TypeCodeMap8: - return readAnyMap(r) - case TypeCodeMap32: - return readAnyMap(r) - - // TODO: implement - case TypeCodeDecimal32: - return nil, errors.New("decimal32 not implemented") - case TypeCodeDecimal64: - return nil, errors.New("decimal64 not implemented") - case TypeCodeDecimal128: - return nil, errors.New("decimal128 not implemented") - case TypeCodeChar: - return nil, errors.New("char not implemented") - default: - return nil, fmt.Errorf("unknown type %#02x", type_) - } -} - -func readAnyMap(r *buffer.Buffer) (any, error) { - var m map[any]any - err := (*mapAnyAny)(&m).Unmarshal(r) - if err != nil { - return nil, err - } - - if len(m) == 0 { - return m, nil - } - - stringKeys := true -Loop: - for key := range m { - switch key.(type) { - case string: - case Symbol: - default: - stringKeys = false - break Loop - } - } - - if stringKeys { - mm := make(map[string]any, len(m)) - for key, value := range m { - switch key := key.(type) { - case string: - mm[key] = value - case Symbol: - mm[string(key)] = value - } - } - return mm, nil - } - - return m, nil -} - -func readAnyList(r *buffer.Buffer) (any, error) { - var a []any - err := (*list)(&a).Unmarshal(r) - return a, err -} - -func readAnyArray(r *buffer.Buffer) (any, error) { - // get the array type - buf := r.Bytes() - if len(buf) < 1 { - return nil, errors.New("invalid length") - } - - var typeIdx int - switch AMQPType(buf[0]) { - case TypeCodeArray8: - typeIdx = 3 - case TypeCodeArray32: - typeIdx = 9 - default: - return nil, fmt.Errorf("invalid array type %02x", buf[0]) - } - if len(buf) < typeIdx+1 { - return nil, errors.New("invalid length") - } - - switch AMQPType(buf[typeIdx]) { - case TypeCodeByte: - var a []int8 - err := (*arrayInt8)(&a).Unmarshal(r) - return a, err - case TypeCodeUbyte: - var a ArrayUByte - err := a.Unmarshal(r) - return a, err - case TypeCodeUshort: - var a []uint16 - err := (*arrayUint16)(&a).Unmarshal(r) - return a, err - case TypeCodeShort: - var a []int16 - err := (*arrayInt16)(&a).Unmarshal(r) - return a, err - case TypeCodeUint0, TypeCodeSmallUint, TypeCodeUint: - var a []uint32 - err := (*arrayUint32)(&a).Unmarshal(r) - return a, err - case TypeCodeSmallint, TypeCodeInt: - var a []int32 - err := (*arrayInt32)(&a).Unmarshal(r) - return a, err - case TypeCodeUlong0, TypeCodeSmallUlong, TypeCodeUlong: - var a []uint64 - err := (*arrayUint64)(&a).Unmarshal(r) - return a, err - case TypeCodeSmalllong, TypeCodeLong: - var a []int64 - err := (*arrayInt64)(&a).Unmarshal(r) - return a, err - case TypeCodeFloat: - var a []float32 - err := (*arrayFloat)(&a).Unmarshal(r) - return a, err - case TypeCodeDouble: - var a []float64 - err := (*arrayDouble)(&a).Unmarshal(r) - return a, err - case TypeCodeBool, TypeCodeBoolTrue, TypeCodeBoolFalse: - var a []bool - err := (*arrayBool)(&a).Unmarshal(r) - return a, err - case TypeCodeStr8, TypeCodeStr32: - var a []string - err := (*arrayString)(&a).Unmarshal(r) - return a, err - case TypeCodeSym8, TypeCodeSym32: - var a []Symbol - err := (*arraySymbol)(&a).Unmarshal(r) - return a, err - case TypeCodeVbin8, TypeCodeVbin32: - var a [][]byte - err := (*arrayBinary)(&a).Unmarshal(r) - return a, err - case TypeCodeTimestamp: - var a []time.Time - err := (*arrayTimestamp)(&a).Unmarshal(r) - return a, err - case TypeCodeUUID: - var a []UUID - err := (*arrayUUID)(&a).Unmarshal(r) - return a, err - default: - return nil, fmt.Errorf("array decoding not implemented for %#02x", buf[typeIdx]) - } -} - -func readComposite(r *buffer.Buffer) (any, error) { - buf := r.Bytes() - - if len(buf) < 2 { - return nil, errors.New("invalid length for composite") - } - - // compsites start with 0x0 - if AMQPType(buf[0]) != 0x0 { - return nil, fmt.Errorf("invalid composite header %#02x", buf[0]) - } - - var compositeType uint64 - switch AMQPType(buf[1]) { - case TypeCodeSmallUlong: - if len(buf) < 3 { - return nil, errors.New("invalid length for smallulong") - } - compositeType = uint64(buf[2]) - case TypeCodeUlong: - if len(buf) < 10 { - return nil, errors.New("invalid length for ulong") - } - compositeType = binary.BigEndian.Uint64(buf[2:]) - } - - if compositeType > math.MaxUint8 { - // try as described type - var dt DescribedType - err := dt.Unmarshal(r) - return dt, err - } - - switch AMQPType(compositeType) { - // Error - case TypeCodeError: - t := new(Error) - err := t.Unmarshal(r) - return t, err - - // Lifetime Policies - case TypeCodeDeleteOnClose: - t := DeleteOnClose - err := t.Unmarshal(r) - return t, err - case TypeCodeDeleteOnNoMessages: - t := DeleteOnNoMessages - err := t.Unmarshal(r) - return t, err - case TypeCodeDeleteOnNoLinks: - t := DeleteOnNoLinks - err := t.Unmarshal(r) - return t, err - case TypeCodeDeleteOnNoLinksOrMessages: - t := DeleteOnNoLinksOrMessages - err := t.Unmarshal(r) - return t, err - - // Delivery States - case TypeCodeStateAccepted: - t := new(StateAccepted) - err := t.Unmarshal(r) - return t, err - case TypeCodeStateModified: - t := new(StateModified) - err := t.Unmarshal(r) - return t, err - case TypeCodeStateReceived: - t := new(StateReceived) - err := t.Unmarshal(r) - return t, err - case TypeCodeStateRejected: - t := new(StateRejected) - err := t.Unmarshal(r) - return t, err - case TypeCodeStateReleased: - t := new(StateReleased) - err := t.Unmarshal(r) - return t, err - - case TypeCodeOpen, - TypeCodeBegin, - TypeCodeAttach, - TypeCodeFlow, - TypeCodeTransfer, - TypeCodeDisposition, - TypeCodeDetach, - TypeCodeEnd, - TypeCodeClose, - TypeCodeSource, - TypeCodeTarget, - TypeCodeMessageHeader, - TypeCodeDeliveryAnnotations, - TypeCodeMessageAnnotations, - TypeCodeMessageProperties, - TypeCodeApplicationProperties, - TypeCodeApplicationData, - TypeCodeAMQPSequence, - TypeCodeAMQPValue, - TypeCodeFooter, - TypeCodeSASLMechanism, - TypeCodeSASLInit, - TypeCodeSASLChallenge, - TypeCodeSASLResponse, - TypeCodeSASLOutcome: - return nil, fmt.Errorf("readComposite unmarshal not implemented for %#02x", compositeType) - - default: - // try as described type - var dt DescribedType - err := dt.Unmarshal(r) - return dt, err - } -} - -func readTimestamp(r *buffer.Buffer) (time.Time, error) { - type_, err := readType(r) - if err != nil { - return time.Time{}, err - } - - if type_ != TypeCodeTimestamp { - return time.Time{}, fmt.Errorf("invalid type for timestamp %02x", type_) - } - - n, err := r.ReadUint64() - ms := int64(n) - return time.Unix(ms/1000, (ms%1000)*1000000).UTC(), err -} - -func readInt(r *buffer.Buffer) (int, error) { - type_, err := peekType(r) - if err != nil { - return 0, err - } - - switch type_ { - // Unsigned - case TypeCodeUbyte: - n, err := ReadUbyte(r) - return int(n), err - case TypeCodeUshort: - n, err := readUshort(r) - return int(n), err - case TypeCodeUint0, TypeCodeSmallUint, TypeCodeUint: - n, err := readUint32(r) - return int(n), err - case TypeCodeUlong0, TypeCodeSmallUlong, TypeCodeUlong: - n, err := readUlong(r) - return int(n), err - - // Signed - case TypeCodeByte: - n, err := readSbyte(r) - return int(n), err - case TypeCodeShort: - n, err := readShort(r) - return int(n), err - case TypeCodeSmallint, TypeCodeInt: - n, err := readInt32(r) - return int(n), err - case TypeCodeSmalllong, TypeCodeLong: - n, err := readLong(r) - return int(n), err - default: - return 0, fmt.Errorf("type code %#02x is not a recognized number type", type_) - } -} - -func readLong(r *buffer.Buffer) (int64, error) { - type_, err := readType(r) - if err != nil { - return 0, err - } - - switch type_ { - case TypeCodeSmalllong: - n, err := r.ReadByte() - return int64(int8(n)), err - case TypeCodeLong: - n, err := r.ReadUint64() - return int64(n), err - default: - return 0, fmt.Errorf("invalid type for uint32 %02x", type_) - } -} - -func readInt32(r *buffer.Buffer) (int32, error) { - type_, err := readType(r) - if err != nil { - return 0, err - } - - switch type_ { - case TypeCodeSmallint: - n, err := r.ReadByte() - return int32(int8(n)), err - case TypeCodeInt: - n, err := r.ReadUint32() - return int32(n), err - default: - return 0, fmt.Errorf("invalid type for int32 %02x", type_) - } -} - -func readShort(r *buffer.Buffer) (int16, error) { - type_, err := readType(r) - if err != nil { - return 0, err - } - - if type_ != TypeCodeShort { - return 0, fmt.Errorf("invalid type for short %02x", type_) - } - - n, err := r.ReadUint16() - return int16(n), err -} - -func readSbyte(r *buffer.Buffer) (int8, error) { - type_, err := readType(r) - if err != nil { - return 0, err - } - - if type_ != TypeCodeByte { - return 0, fmt.Errorf("invalid type for int8 %02x", type_) - } - - n, err := r.ReadByte() - return int8(n), err -} - -func ReadUbyte(r *buffer.Buffer) (uint8, error) { - type_, err := readType(r) - if err != nil { - return 0, err - } - - if type_ != TypeCodeUbyte { - return 0, fmt.Errorf("invalid type for ubyte %02x", type_) - } - - return r.ReadByte() -} - -func readUshort(r *buffer.Buffer) (uint16, error) { - type_, err := readType(r) - if err != nil { - return 0, err - } - - if type_ != TypeCodeUshort { - return 0, fmt.Errorf("invalid type for ushort %02x", type_) - } - - return r.ReadUint16() -} - -func readUint32(r *buffer.Buffer) (uint32, error) { - type_, err := readType(r) - if err != nil { - return 0, err - } - - switch type_ { - case TypeCodeUint0: - return 0, nil - case TypeCodeSmallUint: - n, err := r.ReadByte() - return uint32(n), err - case TypeCodeUint: - return r.ReadUint32() - default: - return 0, fmt.Errorf("invalid type for uint32 %02x", type_) - } -} - -func readUlong(r *buffer.Buffer) (uint64, error) { - type_, err := readType(r) - if err != nil { - return 0, err - } - - switch type_ { - case TypeCodeUlong0: - return 0, nil - case TypeCodeSmallUlong: - n, err := r.ReadByte() - return uint64(n), err - case TypeCodeUlong: - return r.ReadUint64() - default: - return 0, fmt.Errorf("invalid type for uint32 %02x", type_) - } -} - -func readFloat(r *buffer.Buffer) (float32, error) { - type_, err := readType(r) - if err != nil { - return 0, err - } - - if type_ != TypeCodeFloat { - return 0, fmt.Errorf("invalid type for float32 %02x", type_) - } - - bits, err := r.ReadUint32() - return math.Float32frombits(bits), err -} - -func readDouble(r *buffer.Buffer) (float64, error) { - type_, err := readType(r) - if err != nil { - return 0, err - } - - if type_ != TypeCodeDouble { - return 0, fmt.Errorf("invalid type for float64 %02x", type_) - } - - bits, err := r.ReadUint64() - return math.Float64frombits(bits), err -} - -func readBool(r *buffer.Buffer) (bool, error) { - type_, err := readType(r) - if err != nil { - return false, err - } - - switch type_ { - case TypeCodeBool: - b, err := r.ReadByte() - return b != 0, err - case TypeCodeBoolTrue: - return true, nil - case TypeCodeBoolFalse: - return false, nil - default: - return false, fmt.Errorf("type code %#02x is not a recognized bool type", type_) - } -} - -func readUint(r *buffer.Buffer) (value uint64, _ error) { - type_, err := readType(r) - if err != nil { - return 0, err - } - - switch type_ { - case TypeCodeUint0, TypeCodeUlong0: - return 0, nil - case TypeCodeUbyte, TypeCodeSmallUint, TypeCodeSmallUlong: - n, err := r.ReadByte() - return uint64(n), err - case TypeCodeUshort: - n, err := r.ReadUint16() - return uint64(n), err - case TypeCodeUint: - n, err := r.ReadUint32() - return uint64(n), err - case TypeCodeUlong: - return r.ReadUint64() - default: - return 0, fmt.Errorf("type code %#02x is not a recognized number type", type_) - } -} - -func readUUID(r *buffer.Buffer) (UUID, error) { - var uuid UUID - - type_, err := readType(r) - if err != nil { - return uuid, err - } - - if type_ != TypeCodeUUID { - return uuid, fmt.Errorf("type code %#00x is not a UUID", type_) - } - - buf, ok := r.Next(16) - if !ok { - return uuid, errors.New("invalid length") - } - copy(uuid[:], buf) - - return uuid, nil -} - -func readMapHeader(r *buffer.Buffer) (count uint32, _ error) { - type_, err := readType(r) - if err != nil { - return 0, err - } - - length := r.Len() - - switch type_ { - case TypeCodeMap8: - buf, ok := r.Next(2) - if !ok { - return 0, errors.New("invalid length") - } - _ = buf[1] - - size := int(buf[0]) - if size > length-1 { - return 0, errors.New("invalid length") - } - count = uint32(buf[1]) - case TypeCodeMap32: - buf, ok := r.Next(8) - if !ok { - return 0, errors.New("invalid length") - } - _ = buf[7] - - size := int(binary.BigEndian.Uint32(buf[:4])) - if size > length-4 { - return 0, errors.New("invalid length") - } - count = binary.BigEndian.Uint32(buf[4:8]) - default: - return 0, fmt.Errorf("invalid map type %#02x", type_) - } - - if int(count) > r.Len() { - return 0, errors.New("invalid length") - } - return count, nil -} diff --git a/sdk/messaging/azservicebus/internal/go-amqp/internal/encoding/encode.go b/sdk/messaging/azservicebus/internal/go-amqp/internal/encoding/encode.go deleted file mode 100644 index 767318c02edc..000000000000 --- a/sdk/messaging/azservicebus/internal/go-amqp/internal/encoding/encode.go +++ /dev/null @@ -1,573 +0,0 @@ -// Copyright (C) 2017 Kale Blankenship -// Portions Copyright (c) Microsoft Corporation - -package encoding - -import ( - "encoding/binary" - "errors" - "fmt" - "math" - "time" - "unicode/utf8" - - "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus/internal/go-amqp/internal/buffer" -) - -type marshaler interface { - Marshal(*buffer.Buffer) error -} - -func Marshal(wr *buffer.Buffer, i any) error { - switch t := i.(type) { - case nil: - wr.AppendByte(byte(TypeCodeNull)) - case bool: - if t { - wr.AppendByte(byte(TypeCodeBoolTrue)) - } else { - wr.AppendByte(byte(TypeCodeBoolFalse)) - } - case *bool: - if *t { - wr.AppendByte(byte(TypeCodeBoolTrue)) - } else { - wr.AppendByte(byte(TypeCodeBoolFalse)) - } - case uint: - writeUint64(wr, uint64(t)) - case *uint: - writeUint64(wr, uint64(*t)) - case uint64: - writeUint64(wr, t) - case *uint64: - writeUint64(wr, *t) - case uint32: - writeUint32(wr, t) - case *uint32: - writeUint32(wr, *t) - case uint16: - wr.AppendByte(byte(TypeCodeUshort)) - wr.AppendUint16(t) - case *uint16: - wr.AppendByte(byte(TypeCodeUshort)) - wr.AppendUint16(*t) - case uint8: - wr.Append([]byte{ - byte(TypeCodeUbyte), - t, - }) - case *uint8: - wr.Append([]byte{ - byte(TypeCodeUbyte), - *t, - }) - case int: - writeInt64(wr, int64(t)) - case *int: - writeInt64(wr, int64(*t)) - case int8: - wr.Append([]byte{ - byte(TypeCodeByte), - uint8(t), - }) - case *int8: - wr.Append([]byte{ - byte(TypeCodeByte), - uint8(*t), - }) - case int16: - wr.AppendByte(byte(TypeCodeShort)) - wr.AppendUint16(uint16(t)) - case *int16: - wr.AppendByte(byte(TypeCodeShort)) - wr.AppendUint16(uint16(*t)) - case int32: - writeInt32(wr, t) - case *int32: - writeInt32(wr, *t) - case int64: - writeInt64(wr, t) - case *int64: - writeInt64(wr, *t) - case float32: - writeFloat(wr, t) - case *float32: - writeFloat(wr, *t) - case float64: - writeDouble(wr, t) - case *float64: - writeDouble(wr, *t) - case string: - return writeString(wr, t) - case *string: - return writeString(wr, *t) - case []byte: - return WriteBinary(wr, t) - case *[]byte: - return WriteBinary(wr, *t) - case map[any]any: - return writeMap(wr, t) - case *map[any]any: - return writeMap(wr, *t) - case map[string]any: - return writeMap(wr, t) - case *map[string]any: - return writeMap(wr, *t) - case map[Symbol]any: - return writeMap(wr, t) - case *map[Symbol]any: - return writeMap(wr, *t) - case Unsettled: - return writeMap(wr, t) - case *Unsettled: - return writeMap(wr, *t) - case time.Time: - writeTimestamp(wr, t) - case *time.Time: - writeTimestamp(wr, *t) - case []int8: - return arrayInt8(t).Marshal(wr) - case *[]int8: - return arrayInt8(*t).Marshal(wr) - case []uint16: - return arrayUint16(t).Marshal(wr) - case *[]uint16: - return arrayUint16(*t).Marshal(wr) - case []int16: - return arrayInt16(t).Marshal(wr) - case *[]int16: - return arrayInt16(*t).Marshal(wr) - case []uint32: - return arrayUint32(t).Marshal(wr) - case *[]uint32: - return arrayUint32(*t).Marshal(wr) - case []int32: - return arrayInt32(t).Marshal(wr) - case *[]int32: - return arrayInt32(*t).Marshal(wr) - case []uint64: - return arrayUint64(t).Marshal(wr) - case *[]uint64: - return arrayUint64(*t).Marshal(wr) - case []int64: - return arrayInt64(t).Marshal(wr) - case *[]int64: - return arrayInt64(*t).Marshal(wr) - case []float32: - return arrayFloat(t).Marshal(wr) - case *[]float32: - return arrayFloat(*t).Marshal(wr) - case []float64: - return arrayDouble(t).Marshal(wr) - case *[]float64: - return arrayDouble(*t).Marshal(wr) - case []bool: - return arrayBool(t).Marshal(wr) - case *[]bool: - return arrayBool(*t).Marshal(wr) - case []string: - return arrayString(t).Marshal(wr) - case *[]string: - return arrayString(*t).Marshal(wr) - case []Symbol: - return arraySymbol(t).Marshal(wr) - case *[]Symbol: - return arraySymbol(*t).Marshal(wr) - case [][]byte: - return arrayBinary(t).Marshal(wr) - case *[][]byte: - return arrayBinary(*t).Marshal(wr) - case []time.Time: - return arrayTimestamp(t).Marshal(wr) - case *[]time.Time: - return arrayTimestamp(*t).Marshal(wr) - case []UUID: - return arrayUUID(t).Marshal(wr) - case *[]UUID: - return arrayUUID(*t).Marshal(wr) - case []any: - return list(t).Marshal(wr) - case *[]any: - return list(*t).Marshal(wr) - case marshaler: - return t.Marshal(wr) - default: - return fmt.Errorf("marshal not implemented for %T", i) - } - return nil -} - -func writeInt32(wr *buffer.Buffer, n int32) { - if n < 128 && n >= -128 { - wr.Append([]byte{ - byte(TypeCodeSmallint), - byte(n), - }) - return - } - - wr.AppendByte(byte(TypeCodeInt)) - wr.AppendUint32(uint32(n)) -} - -func writeInt64(wr *buffer.Buffer, n int64) { - if n < 128 && n >= -128 { - wr.Append([]byte{ - byte(TypeCodeSmalllong), - byte(n), - }) - return - } - - wr.AppendByte(byte(TypeCodeLong)) - wr.AppendUint64(uint64(n)) -} - -func writeUint32(wr *buffer.Buffer, n uint32) { - if n == 0 { - wr.AppendByte(byte(TypeCodeUint0)) - return - } - - if n < 256 { - wr.Append([]byte{ - byte(TypeCodeSmallUint), - byte(n), - }) - return - } - - wr.AppendByte(byte(TypeCodeUint)) - wr.AppendUint32(n) -} - -func writeUint64(wr *buffer.Buffer, n uint64) { - if n == 0 { - wr.AppendByte(byte(TypeCodeUlong0)) - return - } - - if n < 256 { - wr.Append([]byte{ - byte(TypeCodeSmallUlong), - byte(n), - }) - return - } - - wr.AppendByte(byte(TypeCodeUlong)) - wr.AppendUint64(n) -} - -func writeFloat(wr *buffer.Buffer, f float32) { - wr.AppendByte(byte(TypeCodeFloat)) - wr.AppendUint32(math.Float32bits(f)) -} - -func writeDouble(wr *buffer.Buffer, f float64) { - wr.AppendByte(byte(TypeCodeDouble)) - wr.AppendUint64(math.Float64bits(f)) -} - -func writeTimestamp(wr *buffer.Buffer, t time.Time) { - wr.AppendByte(byte(TypeCodeTimestamp)) - ms := t.UnixNano() / int64(time.Millisecond) - wr.AppendUint64(uint64(ms)) -} - -// marshalField is a field to be marshaled -type MarshalField struct { - Value any // value to be marshaled, use pointers to avoid interface conversion overhead - Omit bool // indicates that this field should be omitted (set to null) -} - -// marshalComposite is a helper for us in a composite's marshal() function. -// -// The returned bytes include the composite header and fields. Fields with -// omit set to true will be encoded as null or omitted altogether if there are -// no non-null fields after them. -func MarshalComposite(wr *buffer.Buffer, code AMQPType, fields []MarshalField) error { - // lastSetIdx is the last index to have a non-omitted field. - // start at -1 as it's possible to have no fields in a composite - lastSetIdx := -1 - - // marshal each field into it's index in rawFields, - // null fields are skipped, leaving the index nil. - for i, f := range fields { - if f.Omit { - continue - } - lastSetIdx = i - } - - // write header only - if lastSetIdx == -1 { - wr.Append([]byte{ - 0x0, - byte(TypeCodeSmallUlong), - byte(code), - byte(TypeCodeList0), - }) - return nil - } - - // write header - WriteDescriptor(wr, code) - - // write fields - wr.AppendByte(byte(TypeCodeList32)) - - // write temp size, replace later - sizeIdx := wr.Len() - wr.Append([]byte{0, 0, 0, 0}) - preFieldLen := wr.Len() - - // field count - wr.AppendUint32(uint32(lastSetIdx + 1)) - - // write null to each index up to lastSetIdx - for _, f := range fields[:lastSetIdx+1] { - if f.Omit { - wr.AppendByte(byte(TypeCodeNull)) - continue - } - err := Marshal(wr, f.Value) - if err != nil { - return err - } - } - - // fix size - size := uint32(wr.Len() - preFieldLen) - buf := wr.Bytes() - binary.BigEndian.PutUint32(buf[sizeIdx:], size) - - return nil -} - -func WriteDescriptor(wr *buffer.Buffer, code AMQPType) { - wr.Append([]byte{ - 0x0, - byte(TypeCodeSmallUlong), - byte(code), - }) -} - -func writeString(wr *buffer.Buffer, str string) error { - if !utf8.ValidString(str) { - return errors.New("not a valid UTF-8 string") - } - l := len(str) - - switch { - // Str8 - case l < 256: - wr.Append([]byte{ - byte(TypeCodeStr8), - byte(l), - }) - wr.AppendString(str) - return nil - - // Str32 - case uint(l) < math.MaxUint32: - wr.AppendByte(byte(TypeCodeStr32)) - wr.AppendUint32(uint32(l)) - wr.AppendString(str) - return nil - - default: - return errors.New("too long") - } -} - -func WriteBinary(wr *buffer.Buffer, bin []byte) error { - l := len(bin) - - switch { - // List8 - case l < 256: - wr.Append([]byte{ - byte(TypeCodeVbin8), - byte(l), - }) - wr.Append(bin) - return nil - - // List32 - case uint(l) < math.MaxUint32: - wr.AppendByte(byte(TypeCodeVbin32)) - wr.AppendUint32(uint32(l)) - wr.Append(bin) - return nil - - default: - return errors.New("too long") - } -} - -func writeMap(wr *buffer.Buffer, m any) error { - startIdx := wr.Len() - wr.Append([]byte{ - byte(TypeCodeMap32), // type - 0, 0, 0, 0, // size placeholder - 0, 0, 0, 0, // length placeholder - }) - - var pairs int - switch m := m.(type) { - case map[any]any: - pairs = len(m) * 2 - for key, val := range m { - err := Marshal(wr, key) - if err != nil { - return err - } - err = Marshal(wr, val) - if err != nil { - return err - } - } - case map[string]any: - pairs = len(m) * 2 - for key, val := range m { - err := writeString(wr, key) - if err != nil { - return err - } - err = Marshal(wr, val) - if err != nil { - return err - } - } - case map[Symbol]any: - pairs = len(m) * 2 - for key, val := range m { - err := key.Marshal(wr) - if err != nil { - return err - } - err = Marshal(wr, val) - if err != nil { - return err - } - } - case Unsettled: - pairs = len(m) * 2 - for key, val := range m { - err := writeString(wr, key) - if err != nil { - return err - } - err = Marshal(wr, val) - if err != nil { - return err - } - } - case Filter: - pairs = len(m) * 2 - for key, val := range m { - err := key.Marshal(wr) - if err != nil { - return err - } - err = val.Marshal(wr) - if err != nil { - return err - } - } - case Annotations: - pairs = len(m) * 2 - for key, val := range m { - switch key := key.(type) { - case string: - err := Symbol(key).Marshal(wr) - if err != nil { - return err - } - case Symbol: - err := key.Marshal(wr) - if err != nil { - return err - } - case int64: - writeInt64(wr, key) - case int: - writeInt64(wr, int64(key)) - default: - return fmt.Errorf("unsupported Annotations key type %T", key) - } - - err := Marshal(wr, val) - if err != nil { - return err - } - } - default: - return fmt.Errorf("unsupported map type %T", m) - } - - if uint(pairs) > math.MaxUint32-4 { - return errors.New("map contains too many elements") - } - - // overwrite placeholder size and length - bytes := wr.Bytes()[startIdx+1 : startIdx+9] - _ = bytes[7] // bounds check hint - - length := wr.Len() - startIdx - 1 - 4 // -1 for type, -4 for length - binary.BigEndian.PutUint32(bytes[:4], uint32(length)) - binary.BigEndian.PutUint32(bytes[4:8], uint32(pairs)) - - return nil -} - -// type length sizes -const ( - array8TLSize = 2 - array32TLSize = 5 -) - -func writeArrayHeader(wr *buffer.Buffer, length, typeSize int, type_ AMQPType) { - size := length * typeSize - - // array type - if size+array8TLSize <= math.MaxUint8 { - wr.Append([]byte{ - byte(TypeCodeArray8), // type - byte(size + array8TLSize), // size - byte(length), // length - byte(type_), // element type - }) - } else { - wr.AppendByte(byte(TypeCodeArray32)) //type - wr.AppendUint32(uint32(size + array32TLSize)) // size - wr.AppendUint32(uint32(length)) // length - wr.AppendByte(byte(type_)) // element type - } -} - -func writeVariableArrayHeader(wr *buffer.Buffer, length, elementsSizeTotal int, type_ AMQPType) { - // 0xA_ == 1, 0xB_ == 4 - // http://docs.oasis-open.org/amqp/core/v1.0/os/amqp-core-types-v1.0-os.html#doc-idp82960 - elementTypeSize := 1 - if type_&0xf0 == 0xb0 { - elementTypeSize = 4 - } - - size := elementsSizeTotal + (length * elementTypeSize) // size excluding array length - if size+array8TLSize <= math.MaxUint8 { - wr.Append([]byte{ - byte(TypeCodeArray8), // type - byte(size + array8TLSize), // size - byte(length), // length - byte(type_), // element type - }) - } else { - wr.AppendByte(byte(TypeCodeArray32)) // type - wr.AppendUint32(uint32(size + array32TLSize)) // size - wr.AppendUint32(uint32(length)) // length - wr.AppendByte(byte(type_)) // element type - } -} diff --git a/sdk/messaging/azservicebus/internal/go-amqp/internal/encoding/types.go b/sdk/messaging/azservicebus/internal/go-amqp/internal/encoding/types.go deleted file mode 100644 index 1941f3f35ee3..000000000000 --- a/sdk/messaging/azservicebus/internal/go-amqp/internal/encoding/types.go +++ /dev/null @@ -1,2155 +0,0 @@ -// Copyright (C) 2017 Kale Blankenship -// Portions Copyright (c) Microsoft Corporation - -package encoding - -import ( - "encoding/binary" - "encoding/hex" - "errors" - "fmt" - "math" - "reflect" - "time" - "unicode/utf8" - - "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus/internal/go-amqp/internal/buffer" -) - -type AMQPType uint8 - -// Type codes -const ( - TypeCodeNull AMQPType = 0x40 - - // Bool - TypeCodeBool AMQPType = 0x56 // boolean with the octet 0x00 being false and octet 0x01 being true - TypeCodeBoolTrue AMQPType = 0x41 - TypeCodeBoolFalse AMQPType = 0x42 - - // Unsigned - TypeCodeUbyte AMQPType = 0x50 // 8-bit unsigned integer (1) - TypeCodeUshort AMQPType = 0x60 // 16-bit unsigned integer in network byte order (2) - TypeCodeUint AMQPType = 0x70 // 32-bit unsigned integer in network byte order (4) - TypeCodeSmallUint AMQPType = 0x52 // unsigned integer value in the range 0 to 255 inclusive (1) - TypeCodeUint0 AMQPType = 0x43 // the uint value 0 (0) - TypeCodeUlong AMQPType = 0x80 // 64-bit unsigned integer in network byte order (8) - TypeCodeSmallUlong AMQPType = 0x53 // unsigned long value in the range 0 to 255 inclusive (1) - TypeCodeUlong0 AMQPType = 0x44 // the ulong value 0 (0) - - // Signed - TypeCodeByte AMQPType = 0x51 // 8-bit two's-complement integer (1) - TypeCodeShort AMQPType = 0x61 // 16-bit two's-complement integer in network byte order (2) - TypeCodeInt AMQPType = 0x71 // 32-bit two's-complement integer in network byte order (4) - TypeCodeSmallint AMQPType = 0x54 // 8-bit two's-complement integer (1) - TypeCodeLong AMQPType = 0x81 // 64-bit two's-complement integer in network byte order (8) - TypeCodeSmalllong AMQPType = 0x55 // 8-bit two's-complement integer - - // Decimal - TypeCodeFloat AMQPType = 0x72 // IEEE 754-2008 binary32 (4) - TypeCodeDouble AMQPType = 0x82 // IEEE 754-2008 binary64 (8) - TypeCodeDecimal32 AMQPType = 0x74 // IEEE 754-2008 decimal32 using the Binary Integer Decimal encoding (4) - TypeCodeDecimal64 AMQPType = 0x84 // IEEE 754-2008 decimal64 using the Binary Integer Decimal encoding (8) - TypeCodeDecimal128 AMQPType = 0x94 // IEEE 754-2008 decimal128 using the Binary Integer Decimal encoding (16) - - // Other - TypeCodeChar AMQPType = 0x73 // a UTF-32BE encoded Unicode character (4) - TypeCodeTimestamp AMQPType = 0x83 // 64-bit two's-complement integer representing milliseconds since the unix epoch - TypeCodeUUID AMQPType = 0x98 // UUID as defined in section 4.1.2 of RFC-4122 - - // Variable Length - TypeCodeVbin8 AMQPType = 0xa0 // up to 2^8 - 1 octets of binary data (1 + variable) - TypeCodeVbin32 AMQPType = 0xb0 // up to 2^32 - 1 octets of binary data (4 + variable) - TypeCodeStr8 AMQPType = 0xa1 // up to 2^8 - 1 octets worth of UTF-8 Unicode (with no byte order mark) (1 + variable) - TypeCodeStr32 AMQPType = 0xb1 // up to 2^32 - 1 octets worth of UTF-8 Unicode (with no byte order mark) (4 +variable) - TypeCodeSym8 AMQPType = 0xa3 // up to 2^8 - 1 seven bit ASCII characters representing a symbolic value (1 + variable) - TypeCodeSym32 AMQPType = 0xb3 // up to 2^32 - 1 seven bit ASCII characters representing a symbolic value (4 + variable) - - // Compound - TypeCodeList0 AMQPType = 0x45 // the empty list (i.e. the list with no elements) (0) - TypeCodeList8 AMQPType = 0xc0 // up to 2^8 - 1 list elements with total size less than 2^8 octets (1 + compound) - TypeCodeList32 AMQPType = 0xd0 // up to 2^32 - 1 list elements with total size less than 2^32 octets (4 + compound) - TypeCodeMap8 AMQPType = 0xc1 // up to 2^8 - 1 octets of encoded map data (1 + compound) - TypeCodeMap32 AMQPType = 0xd1 // up to 2^32 - 1 octets of encoded map data (4 + compound) - TypeCodeArray8 AMQPType = 0xe0 // up to 2^8 - 1 array elements with total size less than 2^8 octets (1 + array) - TypeCodeArray32 AMQPType = 0xf0 // up to 2^32 - 1 array elements with total size less than 2^32 octets (4 + array) - - // Composites - TypeCodeOpen AMQPType = 0x10 - TypeCodeBegin AMQPType = 0x11 - TypeCodeAttach AMQPType = 0x12 - TypeCodeFlow AMQPType = 0x13 - TypeCodeTransfer AMQPType = 0x14 - TypeCodeDisposition AMQPType = 0x15 - TypeCodeDetach AMQPType = 0x16 - TypeCodeEnd AMQPType = 0x17 - TypeCodeClose AMQPType = 0x18 - - TypeCodeSource AMQPType = 0x28 - TypeCodeTarget AMQPType = 0x29 - TypeCodeError AMQPType = 0x1d - - TypeCodeMessageHeader AMQPType = 0x70 - TypeCodeDeliveryAnnotations AMQPType = 0x71 - TypeCodeMessageAnnotations AMQPType = 0x72 - TypeCodeMessageProperties AMQPType = 0x73 - TypeCodeApplicationProperties AMQPType = 0x74 - TypeCodeApplicationData AMQPType = 0x75 - TypeCodeAMQPSequence AMQPType = 0x76 - TypeCodeAMQPValue AMQPType = 0x77 - TypeCodeFooter AMQPType = 0x78 - - TypeCodeStateReceived AMQPType = 0x23 - TypeCodeStateAccepted AMQPType = 0x24 - TypeCodeStateRejected AMQPType = 0x25 - TypeCodeStateReleased AMQPType = 0x26 - TypeCodeStateModified AMQPType = 0x27 - - TypeCodeSASLMechanism AMQPType = 0x40 - TypeCodeSASLInit AMQPType = 0x41 - TypeCodeSASLChallenge AMQPType = 0x42 - TypeCodeSASLResponse AMQPType = 0x43 - TypeCodeSASLOutcome AMQPType = 0x44 - - TypeCodeDeleteOnClose AMQPType = 0x2b - TypeCodeDeleteOnNoLinks AMQPType = 0x2c - TypeCodeDeleteOnNoMessages AMQPType = 0x2d - TypeCodeDeleteOnNoLinksOrMessages AMQPType = 0x2e -) - -// Durability Policies -const ( - // No terminus state is retained durably. - DurabilityNone Durability = 0 - - // Only the existence and configuration of the terminus is - // retained durably. - DurabilityConfiguration Durability = 1 - - // In addition to the existence and configuration of the - // terminus, the unsettled state for durable messages is - // retained durably. - DurabilityUnsettledState Durability = 2 -) - -// Durability specifies the durability of a link. -type Durability uint32 - -func (d *Durability) String() string { - if d == nil { - return "" - } - - switch *d { - case DurabilityNone: - return "none" - case DurabilityConfiguration: - return "configuration" - case DurabilityUnsettledState: - return "unsettled-state" - default: - return fmt.Sprintf("unknown durability %d", *d) - } -} - -func (d Durability) Marshal(wr *buffer.Buffer) error { - return Marshal(wr, uint32(d)) -} - -func (d *Durability) Unmarshal(r *buffer.Buffer) error { - return Unmarshal(r, (*uint32)(d)) -} - -// Expiry Policies -const ( - // The expiry timer starts when terminus is detached. - ExpiryLinkDetach ExpiryPolicy = "link-detach" - - // The expiry timer starts when the most recently - // associated session is ended. - ExpirySessionEnd ExpiryPolicy = "session-end" - - // The expiry timer starts when most recently associated - // connection is closed. - ExpiryConnectionClose ExpiryPolicy = "connection-close" - - // The terminus never expires. - ExpiryNever ExpiryPolicy = "never" -) - -// ExpiryPolicy specifies when the expiry timer of a terminus -// starts counting down from the timeout value. -// -// If the link is subsequently re-attached before the terminus is expired, -// then the count down is aborted. If the conditions for the -// terminus-expiry-policy are subsequently re-met, the expiry timer restarts -// from its originally configured timeout value. -type ExpiryPolicy Symbol - -func ValidateExpiryPolicy(e ExpiryPolicy) error { - switch e { - case ExpiryLinkDetach, - ExpirySessionEnd, - ExpiryConnectionClose, - ExpiryNever: - return nil - default: - return fmt.Errorf("unknown expiry-policy %q", e) - } -} - -func (e ExpiryPolicy) Marshal(wr *buffer.Buffer) error { - return Symbol(e).Marshal(wr) -} - -func (e *ExpiryPolicy) Unmarshal(r *buffer.Buffer) error { - err := Unmarshal(r, (*Symbol)(e)) - if err != nil { - return err - } - return ValidateExpiryPolicy(*e) -} - -func (e *ExpiryPolicy) String() string { - if e == nil { - return "" - } - return string(*e) -} - -// Sender Settlement Modes -const ( - // Sender will send all deliveries initially unsettled to the receiver. - SenderSettleModeUnsettled SenderSettleMode = 0 - - // Sender will send all deliveries settled to the receiver. - SenderSettleModeSettled SenderSettleMode = 1 - - // Sender MAY send a mixture of settled and unsettled deliveries to the receiver. - SenderSettleModeMixed SenderSettleMode = 2 -) - -// SenderSettleMode specifies how the sender will settle messages. -type SenderSettleMode uint8 - -func (m SenderSettleMode) Ptr() *SenderSettleMode { - return &m -} - -func (m *SenderSettleMode) String() string { - if m == nil { - return "" - } - - switch *m { - case SenderSettleModeUnsettled: - return "unsettled" - - case SenderSettleModeSettled: - return "settled" - - case SenderSettleModeMixed: - return "mixed" - - default: - return fmt.Sprintf("unknown sender mode %d", uint8(*m)) - } -} - -func (m SenderSettleMode) Marshal(wr *buffer.Buffer) error { - return Marshal(wr, uint8(m)) -} - -func (m *SenderSettleMode) Unmarshal(r *buffer.Buffer) error { - n, err := ReadUbyte(r) - *m = SenderSettleMode(n) - return err -} - -// Receiver Settlement Modes -const ( - // Receiver will spontaneously settle all incoming transfers. - ReceiverSettleModeFirst ReceiverSettleMode = 0 - - // Receiver will only settle after sending the disposition to the - // sender and receiving a disposition indicating settlement of - // the delivery from the sender. - ReceiverSettleModeSecond ReceiverSettleMode = 1 -) - -// ReceiverSettleMode specifies how the receiver will settle messages. -type ReceiverSettleMode uint8 - -func (m ReceiverSettleMode) Ptr() *ReceiverSettleMode { - return &m -} - -func (m *ReceiverSettleMode) String() string { - if m == nil { - return "" - } - - switch *m { - case ReceiverSettleModeFirst: - return "first" - - case ReceiverSettleModeSecond: - return "second" - - default: - return fmt.Sprintf("unknown receiver mode %d", uint8(*m)) - } -} - -func (m ReceiverSettleMode) Marshal(wr *buffer.Buffer) error { - return Marshal(wr, uint8(m)) -} - -func (m *ReceiverSettleMode) Unmarshal(r *buffer.Buffer) error { - n, err := ReadUbyte(r) - *m = ReceiverSettleMode(n) - return err -} - -type Role bool - -const ( - RoleSender Role = false - RoleReceiver Role = true -) - -func (rl Role) String() string { - if rl { - return "Receiver" - } - return "Sender" -} - -func (rl *Role) Unmarshal(r *buffer.Buffer) error { - b, err := readBool(r) - *rl = Role(b) - return err -} - -func (rl Role) Marshal(wr *buffer.Buffer) error { - return Marshal(wr, (bool)(rl)) -} - -type SASLCode uint8 - -// SASL Codes -const ( - CodeSASLOK SASLCode = iota // Connection authentication succeeded. - CodeSASLAuth // Connection authentication failed due to an unspecified problem with the supplied credentials. - CodeSASLSysPerm // Connection authentication failed due to a system error that is unlikely to be corrected without intervention. -) - -func (s SASLCode) Marshal(wr *buffer.Buffer) error { - return Marshal(wr, uint8(s)) -} - -func (s *SASLCode) Unmarshal(r *buffer.Buffer) error { - n, err := ReadUbyte(r) - *s = SASLCode(n) - return err -} - -// DeliveryState encapsulates the various concrete delivery states. -// http://docs.oasis-open.org/amqp/core/v1.0/os/amqp-core-messaging-v1.0-os.html#section-delivery-state -// TODO: http://docs.oasis-open.org/amqp/core/v1.0/os/amqp-core-transactions-v1.0-os.html#type-declared -type DeliveryState interface { - deliveryState() // marker method -} - -type Unsettled map[string]DeliveryState - -func (u Unsettled) Marshal(wr *buffer.Buffer) error { - return writeMap(wr, u) -} - -func (u *Unsettled) Unmarshal(r *buffer.Buffer) error { - count, err := readMapHeader(r) - if err != nil { - return err - } - - m := make(Unsettled, count/2) - for i := uint32(0); i < count; i += 2 { - key, err := ReadString(r) - if err != nil { - return err - } - var value DeliveryState - err = Unmarshal(r, &value) - if err != nil { - return err - } - m[key] = value - } - *u = m - return nil -} - -type Filter map[Symbol]*DescribedType - -func (f Filter) Marshal(wr *buffer.Buffer) error { - return writeMap(wr, f) -} - -func (f *Filter) Unmarshal(r *buffer.Buffer) error { - count, err := readMapHeader(r) - if err != nil { - return err - } - - m := make(Filter, count/2) - for i := uint32(0); i < count; i += 2 { - key, err := ReadString(r) - if err != nil { - return err - } - var value DescribedType - err = Unmarshal(r, &value) - if err != nil { - return err - } - m[Symbol(key)] = &value - } - *f = m - return nil -} - -// peekMessageType reads the message type without -// modifying any data. -func PeekMessageType(buf []byte) (uint8, uint8, error) { - if len(buf) < 3 { - return 0, 0, errors.New("invalid message") - } - - if buf[0] != 0 { - return 0, 0, fmt.Errorf("invalid composite header %02x", buf[0]) - } - - // copied from readUlong to avoid allocations - t := AMQPType(buf[1]) - if t == TypeCodeUlong0 { - return 0, 2, nil - } - - if t == TypeCodeSmallUlong { - if len(buf[2:]) == 0 { - return 0, 0, errors.New("invalid ulong") - } - return buf[2], 3, nil - } - - if t != TypeCodeUlong { - return 0, 0, fmt.Errorf("invalid type for uint32 %02x", t) - } - - if len(buf[2:]) < 8 { - return 0, 0, errors.New("invalid ulong") - } - v := binary.BigEndian.Uint64(buf[2:10]) - - return uint8(v), 10, nil -} - -func tryReadNull(r *buffer.Buffer) bool { - if r.Len() > 0 && AMQPType(r.Bytes()[0]) == TypeCodeNull { - r.Skip(1) - return true - } - return false -} - -// Annotations keys must be of type string, int, or int64. -// -// String keys are encoded as AMQP Symbols. -type Annotations map[any]any - -func (a Annotations) Marshal(wr *buffer.Buffer) error { - return writeMap(wr, a) -} - -func (a *Annotations) Unmarshal(r *buffer.Buffer) error { - count, err := readMapHeader(r) - if err != nil { - return err - } - - m := make(Annotations, count/2) - for i := uint32(0); i < count; i += 2 { - key, err := ReadAny(r) - if err != nil { - return err - } - value, err := ReadAny(r) - if err != nil { - return err - } - m[key] = value - } - *a = m - return nil -} - -// ErrCond is one of the error conditions defined in the AMQP spec. -type ErrCond string - -func (ec ErrCond) Marshal(wr *buffer.Buffer) error { - return (Symbol)(ec).Marshal(wr) -} - -func (ec *ErrCond) Unmarshal(r *buffer.Buffer) error { - s, err := ReadString(r) - *ec = ErrCond(s) - return err -} - -/* - - - - - - -*/ - -// Error is an AMQP error. -type Error struct { - // A symbolic value indicating the error condition. - Condition ErrCond - - // descriptive text about the error condition - // - // This text supplies any supplementary details not indicated by the condition field. - // This text can be logged as an aid to resolving issues. - Description string - - // map carrying information about the error condition - Info map[string]any -} - -func (e *Error) Marshal(wr *buffer.Buffer) error { - return MarshalComposite(wr, TypeCodeError, []MarshalField{ - {Value: &e.Condition, Omit: false}, - {Value: &e.Description, Omit: e.Description == ""}, - {Value: e.Info, Omit: len(e.Info) == 0}, - }) -} - -func (e *Error) Unmarshal(r *buffer.Buffer) error { - return UnmarshalComposite(r, TypeCodeError, []UnmarshalField{ - {Field: &e.Condition, HandleNull: func() error { return errors.New("Error.Condition is required") }}, - {Field: &e.Description}, - {Field: &e.Info}, - }...) -} - -func (e *Error) String() string { - if e == nil { - return "*Error(nil)" - } - return fmt.Sprintf("*Error{Condition: %s, Description: %s, Info: %v}", - e.Condition, - e.Description, - e.Info, - ) -} - -func (e *Error) Error() string { - return e.String() -} - -/* - - - - - -*/ - -type StateReceived struct { - // When sent by the sender this indicates the first section of the message - // (with section-number 0 being the first section) for which data can be resent. - // Data from sections prior to the given section cannot be retransmitted for - // this delivery. - // - // When sent by the receiver this indicates the first section of the message - // for which all data might not yet have been received. - SectionNumber uint32 - - // When sent by the sender this indicates the first byte of the encoded section - // data of the section given by section-number for which data can be resent - // (with section-offset 0 being the first byte). Bytes from the same section - // prior to the given offset section cannot be retransmitted for this delivery. - // - // When sent by the receiver this indicates the first byte of the given section - // which has not yet been received. Note that if a receiver has received all of - // section number X (which contains N bytes of data), but none of section number - // X + 1, then it can indicate this by sending either Received(section-number=X, - // section-offset=N) or Received(section-number=X+1, section-offset=0). The state - // Received(section-number=0, section-offset=0) indicates that no message data - // at all has been transferred. - SectionOffset uint64 -} - -func (sr *StateReceived) deliveryState() {} - -func (sr *StateReceived) Marshal(wr *buffer.Buffer) error { - return MarshalComposite(wr, TypeCodeStateReceived, []MarshalField{ - {Value: &sr.SectionNumber, Omit: false}, - {Value: &sr.SectionOffset, Omit: false}, - }) -} - -func (sr *StateReceived) Unmarshal(r *buffer.Buffer) error { - return UnmarshalComposite(r, TypeCodeStateReceived, []UnmarshalField{ - {Field: &sr.SectionNumber, HandleNull: func() error { return errors.New("StateReceiver.SectionNumber is required") }}, - {Field: &sr.SectionOffset, HandleNull: func() error { return errors.New("StateReceiver.SectionOffset is required") }}, - }...) -} - -/* - - - -*/ - -type StateAccepted struct{} - -func (sr *StateAccepted) deliveryState() {} - -func (sa *StateAccepted) Marshal(wr *buffer.Buffer) error { - return MarshalComposite(wr, TypeCodeStateAccepted, nil) -} - -func (sa *StateAccepted) Unmarshal(r *buffer.Buffer) error { - return UnmarshalComposite(r, TypeCodeStateAccepted) -} - -func (sa *StateAccepted) String() string { - return "Accepted" -} - -/* - - - - -*/ - -type StateRejected struct { - Error *Error -} - -func (sr *StateRejected) deliveryState() {} - -func (sr *StateRejected) Marshal(wr *buffer.Buffer) error { - return MarshalComposite(wr, TypeCodeStateRejected, []MarshalField{ - {Value: sr.Error, Omit: sr.Error == nil}, - }) -} - -func (sr *StateRejected) Unmarshal(r *buffer.Buffer) error { - return UnmarshalComposite(r, TypeCodeStateRejected, - UnmarshalField{Field: &sr.Error}, - ) -} - -func (sr *StateRejected) String() string { - return fmt.Sprintf("Rejected{Error: %v}", sr.Error) -} - -/* - - - -*/ - -type StateReleased struct{} - -func (sr *StateReleased) deliveryState() {} - -func (sr *StateReleased) Marshal(wr *buffer.Buffer) error { - return MarshalComposite(wr, TypeCodeStateReleased, nil) -} - -func (sr *StateReleased) Unmarshal(r *buffer.Buffer) error { - return UnmarshalComposite(r, TypeCodeStateReleased) -} - -func (sr *StateReleased) String() string { - return "Released" -} - -/* - - - - - - -*/ - -type StateModified struct { - // count the transfer as an unsuccessful delivery attempt - // - // If the delivery-failed flag is set, any messages modified - // MUST have their delivery-count incremented. - DeliveryFailed bool - - // prevent redelivery - // - // If the undeliverable-here is set, then any messages released MUST NOT - // be redelivered to the modifying link endpoint. - UndeliverableHere bool - - // message attributes - // Map containing attributes to combine with the existing message-annotations - // held in the message's header section. Where the existing message-annotations - // of the message contain an entry with the same key as an entry in this field, - // the value in this field associated with that key replaces the one in the - // existing headers; where the existing message-annotations has no such value, - // the value in this map is added. - MessageAnnotations Annotations -} - -func (sr *StateModified) deliveryState() {} - -func (sm *StateModified) Marshal(wr *buffer.Buffer) error { - return MarshalComposite(wr, TypeCodeStateModified, []MarshalField{ - {Value: &sm.DeliveryFailed, Omit: !sm.DeliveryFailed}, - {Value: &sm.UndeliverableHere, Omit: !sm.UndeliverableHere}, - {Value: sm.MessageAnnotations, Omit: sm.MessageAnnotations == nil}, - }) -} - -func (sm *StateModified) Unmarshal(r *buffer.Buffer) error { - return UnmarshalComposite(r, TypeCodeStateModified, []UnmarshalField{ - {Field: &sm.DeliveryFailed}, - {Field: &sm.UndeliverableHere}, - {Field: &sm.MessageAnnotations}, - }...) -} - -func (sm *StateModified) String() string { - return fmt.Sprintf("Modified{DeliveryFailed: %t, UndeliverableHere: %t, MessageAnnotations: %v}", sm.DeliveryFailed, sm.UndeliverableHere, sm.MessageAnnotations) -} - -// symbol is an AMQP symbolic string. -type Symbol string - -func (s Symbol) Marshal(wr *buffer.Buffer) error { - l := len(s) - switch { - // Sym8 - case l < 256: - wr.Append([]byte{ - byte(TypeCodeSym8), - byte(l), - }) - wr.AppendString(string(s)) - - // Sym32 - case uint(l) < math.MaxUint32: - wr.AppendByte(uint8(TypeCodeSym32)) - wr.AppendUint32(uint32(l)) - wr.AppendString(string(s)) - default: - return errors.New("too long") - } - return nil -} - -type Milliseconds time.Duration - -func (m Milliseconds) Marshal(wr *buffer.Buffer) error { - writeUint32(wr, uint32(m/Milliseconds(time.Millisecond))) - return nil -} - -func (m *Milliseconds) Unmarshal(r *buffer.Buffer) error { - n, err := readUint(r) - *m = Milliseconds(time.Duration(n) * time.Millisecond) - return err -} - -// mapAnyAny is used to decode AMQP maps who's keys are undefined or -// inconsistently typed. -type mapAnyAny map[any]any - -func (m mapAnyAny) Marshal(wr *buffer.Buffer) error { - return writeMap(wr, map[any]any(m)) -} - -func (m *mapAnyAny) Unmarshal(r *buffer.Buffer) error { - count, err := readMapHeader(r) - if err != nil { - return err - } - - mm := make(mapAnyAny, count/2) - for i := uint32(0); i < count; i += 2 { - key, err := ReadAny(r) - if err != nil { - return err - } - value, err := ReadAny(r) - if err != nil { - return err - } - - // https://golang.org/ref/spec#Map_types: - // The comparison operators == and != must be fully defined - // for operands of the key type; thus the key type must not - // be a function, map, or slice. - switch reflect.ValueOf(key).Kind() { - case reflect.Slice, reflect.Func, reflect.Map: - return errors.New("invalid map key") - } - - mm[key] = value - } - *m = mm - return nil -} - -// mapStringAny is used to decode AMQP maps that have string keys -type mapStringAny map[string]any - -func (m mapStringAny) Marshal(wr *buffer.Buffer) error { - return writeMap(wr, map[string]any(m)) -} - -func (m *mapStringAny) Unmarshal(r *buffer.Buffer) error { - count, err := readMapHeader(r) - if err != nil { - return err - } - - mm := make(mapStringAny, count/2) - for i := uint32(0); i < count; i += 2 { - key, err := ReadString(r) - if err != nil { - return err - } - value, err := ReadAny(r) - if err != nil { - return err - } - mm[key] = value - } - *m = mm - - return nil -} - -// mapStringAny is used to decode AMQP maps that have Symbol keys -type mapSymbolAny map[Symbol]any - -func (m mapSymbolAny) Marshal(wr *buffer.Buffer) error { - return writeMap(wr, map[Symbol]any(m)) -} - -func (m *mapSymbolAny) Unmarshal(r *buffer.Buffer) error { - count, err := readMapHeader(r) - if err != nil { - return err - } - - mm := make(mapSymbolAny, count/2) - for i := uint32(0); i < count; i += 2 { - key, err := ReadString(r) - if err != nil { - return err - } - value, err := ReadAny(r) - if err != nil { - return err - } - mm[Symbol(key)] = value - } - *m = mm - return nil -} - -// UUID is a 128 bit identifier as defined in RFC 4122. -type UUID [16]byte - -// String returns the hex encoded representation described in RFC 4122, Section 3. -func (u UUID) String() string { - var buf [36]byte - hex.Encode(buf[:8], u[:4]) - buf[8] = '-' - hex.Encode(buf[9:13], u[4:6]) - buf[13] = '-' - hex.Encode(buf[14:18], u[6:8]) - buf[18] = '-' - hex.Encode(buf[19:23], u[8:10]) - buf[23] = '-' - hex.Encode(buf[24:], u[10:]) - return string(buf[:]) -} - -func (u UUID) Marshal(wr *buffer.Buffer) error { - wr.AppendByte(byte(TypeCodeUUID)) - wr.Append(u[:]) - return nil -} - -func (u *UUID) Unmarshal(r *buffer.Buffer) error { - un, err := readUUID(r) - *u = un - return err -} - -type LifetimePolicy uint8 - -const ( - DeleteOnClose = LifetimePolicy(TypeCodeDeleteOnClose) - DeleteOnNoLinks = LifetimePolicy(TypeCodeDeleteOnNoLinks) - DeleteOnNoMessages = LifetimePolicy(TypeCodeDeleteOnNoMessages) - DeleteOnNoLinksOrMessages = LifetimePolicy(TypeCodeDeleteOnNoLinksOrMessages) -) - -func (p LifetimePolicy) Marshal(wr *buffer.Buffer) error { - wr.Append([]byte{ - 0x0, - byte(TypeCodeSmallUlong), - byte(p), - byte(TypeCodeList0), - }) - return nil -} - -func (p *LifetimePolicy) Unmarshal(r *buffer.Buffer) error { - typ, fields, err := readCompositeHeader(r) - if err != nil { - return err - } - if fields != 0 { - return fmt.Errorf("invalid size %d for lifetime-policy", fields) - } - *p = LifetimePolicy(typ) - return nil -} - -type DescribedType struct { - Descriptor any - Value any -} - -func (t DescribedType) Marshal(wr *buffer.Buffer) error { - wr.AppendByte(0x0) // descriptor constructor - err := Marshal(wr, t.Descriptor) - if err != nil { - return err - } - return Marshal(wr, t.Value) -} - -func (t *DescribedType) Unmarshal(r *buffer.Buffer) error { - b, err := r.ReadByte() - if err != nil { - return err - } - - if b != 0x0 { - return fmt.Errorf("invalid described type header %02x", b) - } - - err = Unmarshal(r, &t.Descriptor) - if err != nil { - return err - } - return Unmarshal(r, &t.Value) -} - -func (t DescribedType) String() string { - return fmt.Sprintf("DescribedType{descriptor: %v, value: %v}", - t.Descriptor, - t.Value, - ) -} - -// SLICES - -// ArrayUByte allows encoding []uint8/[]byte as an array -// rather than binary data. -type ArrayUByte []uint8 - -func (a ArrayUByte) Marshal(wr *buffer.Buffer) error { - const typeSize = 1 - - writeArrayHeader(wr, len(a), typeSize, TypeCodeUbyte) - wr.Append(a) - - return nil -} - -func (a *ArrayUByte) Unmarshal(r *buffer.Buffer) error { - length, err := readArrayHeader(r) - if err != nil { - return err - } - - type_, err := readType(r) - if err != nil { - return err - } - if type_ != TypeCodeUbyte { - return fmt.Errorf("invalid type for []uint16 %02x", type_) - } - - buf, ok := r.Next(length) - if !ok { - return fmt.Errorf("invalid length %d", length) - } - *a = append([]byte(nil), buf...) - - return nil -} - -type arrayInt8 []int8 - -func (a arrayInt8) Marshal(wr *buffer.Buffer) error { - const typeSize = 1 - - writeArrayHeader(wr, len(a), typeSize, TypeCodeByte) - - for _, value := range a { - wr.AppendByte(uint8(value)) - } - - return nil -} - -func (a *arrayInt8) Unmarshal(r *buffer.Buffer) error { - length, err := readArrayHeader(r) - if err != nil { - return err - } - - type_, err := readType(r) - if err != nil { - return err - } - if type_ != TypeCodeByte { - return fmt.Errorf("invalid type for []uint16 %02x", type_) - } - - buf, ok := r.Next(length) - if !ok { - return fmt.Errorf("invalid length %d", length) - } - - aa := (*a)[:0] - if int64(cap(aa)) < length { - aa = make([]int8, length) - } else { - aa = aa[:length] - } - - for i, value := range buf { - aa[i] = int8(value) - } - - *a = aa - return nil -} - -type arrayUint16 []uint16 - -func (a arrayUint16) Marshal(wr *buffer.Buffer) error { - const typeSize = 2 - - writeArrayHeader(wr, len(a), typeSize, TypeCodeUshort) - - for _, element := range a { - wr.AppendUint16(element) - } - - return nil -} - -func (a *arrayUint16) Unmarshal(r *buffer.Buffer) error { - length, err := readArrayHeader(r) - if err != nil { - return err - } - - type_, err := readType(r) - if err != nil { - return err - } - if type_ != TypeCodeUshort { - return fmt.Errorf("invalid type for []uint16 %02x", type_) - } - - const typeSize = 2 - buf, ok := r.Next(length * typeSize) - if !ok { - return fmt.Errorf("invalid length %d", length) - } - - aa := (*a)[:0] - if int64(cap(aa)) < length { - aa = make([]uint16, length) - } else { - aa = aa[:length] - } - - var bufIdx int - for i := range aa { - aa[i] = binary.BigEndian.Uint16(buf[bufIdx:]) - bufIdx += 2 - } - - *a = aa - return nil -} - -type arrayInt16 []int16 - -func (a arrayInt16) Marshal(wr *buffer.Buffer) error { - const typeSize = 2 - - writeArrayHeader(wr, len(a), typeSize, TypeCodeShort) - - for _, element := range a { - wr.AppendUint16(uint16(element)) - } - - return nil -} - -func (a *arrayInt16) Unmarshal(r *buffer.Buffer) error { - length, err := readArrayHeader(r) - if err != nil { - return err - } - - type_, err := readType(r) - if err != nil { - return err - } - if type_ != TypeCodeShort { - return fmt.Errorf("invalid type for []uint16 %02x", type_) - } - - const typeSize = 2 - buf, ok := r.Next(length * typeSize) - if !ok { - return fmt.Errorf("invalid length %d", length) - } - - aa := (*a)[:0] - if int64(cap(aa)) < length { - aa = make([]int16, length) - } else { - aa = aa[:length] - } - - var bufIdx int - for i := range aa { - aa[i] = int16(binary.BigEndian.Uint16(buf[bufIdx : bufIdx+2])) - bufIdx += 2 - } - - *a = aa - return nil -} - -type arrayUint32 []uint32 - -func (a arrayUint32) Marshal(wr *buffer.Buffer) error { - var ( - typeSize = 1 - TypeCode = TypeCodeSmallUint - ) - for _, n := range a { - if n > math.MaxUint8 { - typeSize = 4 - TypeCode = TypeCodeUint - break - } - } - - writeArrayHeader(wr, len(a), typeSize, TypeCode) - - if TypeCode == TypeCodeUint { - for _, element := range a { - wr.AppendUint32(element) - } - } else { - for _, element := range a { - wr.AppendByte(byte(element)) - } - } - - return nil -} - -func (a *arrayUint32) Unmarshal(r *buffer.Buffer) error { - length, err := readArrayHeader(r) - if err != nil { - return err - } - - aa := (*a)[:0] - - type_, err := readType(r) - if err != nil { - return err - } - switch type_ { - case TypeCodeUint0: - if int64(cap(aa)) < length { - aa = make([]uint32, length) - } else { - aa = aa[:length] - for i := range aa { - aa[i] = 0 - } - } - case TypeCodeSmallUint: - buf, ok := r.Next(length) - if !ok { - return errors.New("invalid length") - } - - if int64(cap(aa)) < length { - aa = make([]uint32, length) - } else { - aa = aa[:length] - } - - for i, n := range buf { - aa[i] = uint32(n) - } - case TypeCodeUint: - const typeSize = 4 - buf, ok := r.Next(length * typeSize) - if !ok { - return fmt.Errorf("invalid length %d", length) - } - - if int64(cap(aa)) < length { - aa = make([]uint32, length) - } else { - aa = aa[:length] - } - - var bufIdx int - for i := range aa { - aa[i] = binary.BigEndian.Uint32(buf[bufIdx : bufIdx+4]) - bufIdx += 4 - } - default: - return fmt.Errorf("invalid type for []uint32 %02x", type_) - } - - *a = aa - return nil -} - -type arrayInt32 []int32 - -func (a arrayInt32) Marshal(wr *buffer.Buffer) error { - var ( - typeSize = 1 - TypeCode = TypeCodeSmallint - ) - for _, n := range a { - if n > math.MaxInt8 { - typeSize = 4 - TypeCode = TypeCodeInt - break - } - } - - writeArrayHeader(wr, len(a), typeSize, TypeCode) - - if TypeCode == TypeCodeInt { - for _, element := range a { - wr.AppendUint32(uint32(element)) - } - } else { - for _, element := range a { - wr.AppendByte(byte(element)) - } - } - - return nil -} - -func (a *arrayInt32) Unmarshal(r *buffer.Buffer) error { - length, err := readArrayHeader(r) - if err != nil { - return err - } - - aa := (*a)[:0] - - type_, err := readType(r) - if err != nil { - return err - } - switch type_ { - case TypeCodeSmallint: - buf, ok := r.Next(length) - if !ok { - return errors.New("invalid length") - } - - if int64(cap(aa)) < length { - aa = make([]int32, length) - } else { - aa = aa[:length] - } - - for i, n := range buf { - aa[i] = int32(int8(n)) - } - case TypeCodeInt: - const typeSize = 4 - buf, ok := r.Next(length * typeSize) - if !ok { - return fmt.Errorf("invalid length %d", length) - } - - if int64(cap(aa)) < length { - aa = make([]int32, length) - } else { - aa = aa[:length] - } - - var bufIdx int - for i := range aa { - aa[i] = int32(binary.BigEndian.Uint32(buf[bufIdx:])) - bufIdx += 4 - } - default: - return fmt.Errorf("invalid type for []int32 %02x", type_) - } - - *a = aa - return nil -} - -type arrayUint64 []uint64 - -func (a arrayUint64) Marshal(wr *buffer.Buffer) error { - var ( - typeSize = 1 - TypeCode = TypeCodeSmallUlong - ) - for _, n := range a { - if n > math.MaxUint8 { - typeSize = 8 - TypeCode = TypeCodeUlong - break - } - } - - writeArrayHeader(wr, len(a), typeSize, TypeCode) - - if TypeCode == TypeCodeUlong { - for _, element := range a { - wr.AppendUint64(element) - } - } else { - for _, element := range a { - wr.AppendByte(byte(element)) - } - } - - return nil -} - -func (a *arrayUint64) Unmarshal(r *buffer.Buffer) error { - length, err := readArrayHeader(r) - if err != nil { - return err - } - - aa := (*a)[:0] - - type_, err := readType(r) - if err != nil { - return err - } - switch type_ { - case TypeCodeUlong0: - if int64(cap(aa)) < length { - aa = make([]uint64, length) - } else { - aa = aa[:length] - for i := range aa { - aa[i] = 0 - } - } - case TypeCodeSmallUlong: - buf, ok := r.Next(length) - if !ok { - return errors.New("invalid length") - } - - if int64(cap(aa)) < length { - aa = make([]uint64, length) - } else { - aa = aa[:length] - } - - for i, n := range buf { - aa[i] = uint64(n) - } - case TypeCodeUlong: - const typeSize = 8 - buf, ok := r.Next(length * typeSize) - if !ok { - return errors.New("invalid length") - } - - if int64(cap(aa)) < length { - aa = make([]uint64, length) - } else { - aa = aa[:length] - } - - var bufIdx int - for i := range aa { - aa[i] = binary.BigEndian.Uint64(buf[bufIdx : bufIdx+8]) - bufIdx += 8 - } - default: - return fmt.Errorf("invalid type for []uint64 %02x", type_) - } - - *a = aa - return nil -} - -type arrayInt64 []int64 - -func (a arrayInt64) Marshal(wr *buffer.Buffer) error { - var ( - typeSize = 1 - TypeCode = TypeCodeSmalllong - ) - for _, n := range a { - if n > math.MaxInt8 { - typeSize = 8 - TypeCode = TypeCodeLong - break - } - } - - writeArrayHeader(wr, len(a), typeSize, TypeCode) - - if TypeCode == TypeCodeLong { - for _, element := range a { - wr.AppendUint64(uint64(element)) - } - } else { - for _, element := range a { - wr.AppendByte(byte(element)) - } - } - - return nil -} - -func (a *arrayInt64) Unmarshal(r *buffer.Buffer) error { - length, err := readArrayHeader(r) - if err != nil { - return err - } - - aa := (*a)[:0] - - type_, err := readType(r) - if err != nil { - return err - } - switch type_ { - case TypeCodeSmalllong: - buf, ok := r.Next(length) - if !ok { - return errors.New("invalid length") - } - - if int64(cap(aa)) < length { - aa = make([]int64, length) - } else { - aa = aa[:length] - } - - for i, n := range buf { - aa[i] = int64(int8(n)) - } - case TypeCodeLong: - const typeSize = 8 - buf, ok := r.Next(length * typeSize) - if !ok { - return errors.New("invalid length") - } - - if int64(cap(aa)) < length { - aa = make([]int64, length) - } else { - aa = aa[:length] - } - - var bufIdx int - for i := range aa { - aa[i] = int64(binary.BigEndian.Uint64(buf[bufIdx:])) - bufIdx += 8 - } - default: - return fmt.Errorf("invalid type for []uint64 %02x", type_) - } - - *a = aa - return nil -} - -type arrayFloat []float32 - -func (a arrayFloat) Marshal(wr *buffer.Buffer) error { - const typeSize = 4 - - writeArrayHeader(wr, len(a), typeSize, TypeCodeFloat) - - for _, element := range a { - wr.AppendUint32(math.Float32bits(element)) - } - - return nil -} - -func (a *arrayFloat) Unmarshal(r *buffer.Buffer) error { - length, err := readArrayHeader(r) - if err != nil { - return err - } - - type_, err := readType(r) - if err != nil { - return err - } - if type_ != TypeCodeFloat { - return fmt.Errorf("invalid type for []float32 %02x", type_) - } - - const typeSize = 4 - buf, ok := r.Next(length * typeSize) - if !ok { - return fmt.Errorf("invalid length %d", length) - } - - aa := (*a)[:0] - if int64(cap(aa)) < length { - aa = make([]float32, length) - } else { - aa = aa[:length] - } - - var bufIdx int - for i := range aa { - bits := binary.BigEndian.Uint32(buf[bufIdx:]) - aa[i] = math.Float32frombits(bits) - bufIdx += typeSize - } - - *a = aa - return nil -} - -type arrayDouble []float64 - -func (a arrayDouble) Marshal(wr *buffer.Buffer) error { - const typeSize = 8 - - writeArrayHeader(wr, len(a), typeSize, TypeCodeDouble) - - for _, element := range a { - wr.AppendUint64(math.Float64bits(element)) - } - - return nil -} - -func (a *arrayDouble) Unmarshal(r *buffer.Buffer) error { - length, err := readArrayHeader(r) - if err != nil { - return err - } - - type_, err := readType(r) - if err != nil { - return err - } - if type_ != TypeCodeDouble { - return fmt.Errorf("invalid type for []float64 %02x", type_) - } - - const typeSize = 8 - buf, ok := r.Next(length * typeSize) - if !ok { - return fmt.Errorf("invalid length %d", length) - } - - aa := (*a)[:0] - if int64(cap(aa)) < length { - aa = make([]float64, length) - } else { - aa = aa[:length] - } - - var bufIdx int - for i := range aa { - bits := binary.BigEndian.Uint64(buf[bufIdx:]) - aa[i] = math.Float64frombits(bits) - bufIdx += typeSize - } - - *a = aa - return nil -} - -type arrayBool []bool - -func (a arrayBool) Marshal(wr *buffer.Buffer) error { - const typeSize = 1 - - writeArrayHeader(wr, len(a), typeSize, TypeCodeBool) - - for _, element := range a { - value := byte(0) - if element { - value = 1 - } - wr.AppendByte(value) - } - - return nil -} - -func (a *arrayBool) Unmarshal(r *buffer.Buffer) error { - length, err := readArrayHeader(r) - if err != nil { - return err - } - - aa := (*a)[:0] - if int64(cap(aa)) < length { - aa = make([]bool, length) - } else { - aa = aa[:length] - } - - type_, err := readType(r) - if err != nil { - return err - } - switch type_ { - case TypeCodeBool: - buf, ok := r.Next(length) - if !ok { - return errors.New("invalid length") - } - - for i, value := range buf { - if value == 0 { - aa[i] = false - } else { - aa[i] = true - } - } - - case TypeCodeBoolTrue: - for i := range aa { - aa[i] = true - } - case TypeCodeBoolFalse: - for i := range aa { - aa[i] = false - } - default: - return fmt.Errorf("invalid type for []bool %02x", type_) - } - - *a = aa - return nil -} - -type arrayString []string - -func (a arrayString) Marshal(wr *buffer.Buffer) error { - var ( - elementType = TypeCodeStr8 - elementsSizeTotal int - ) - for _, element := range a { - if !utf8.ValidString(element) { - return errors.New("not a valid UTF-8 string") - } - - elementsSizeTotal += len(element) - - if len(element) > math.MaxUint8 { - elementType = TypeCodeStr32 - } - } - - writeVariableArrayHeader(wr, len(a), elementsSizeTotal, elementType) - - if elementType == TypeCodeStr32 { - for _, element := range a { - wr.AppendUint32(uint32(len(element))) - wr.AppendString(element) - } - } else { - for _, element := range a { - wr.AppendByte(byte(len(element))) - wr.AppendString(element) - } - } - - return nil -} - -func (a *arrayString) Unmarshal(r *buffer.Buffer) error { - length, err := readArrayHeader(r) - if err != nil { - return err - } - - const typeSize = 2 // assume all strings are at least 2 bytes - if length*typeSize > int64(r.Len()) { - return fmt.Errorf("invalid length %d", length) - } - - aa := (*a)[:0] - if int64(cap(aa)) < length { - aa = make([]string, length) - } else { - aa = aa[:length] - } - - type_, err := readType(r) - if err != nil { - return err - } - switch type_ { - case TypeCodeStr8: - for i := range aa { - size, err := r.ReadByte() - if err != nil { - return err - } - - buf, ok := r.Next(int64(size)) - if !ok { - return errors.New("invalid length") - } - - aa[i] = string(buf) - } - case TypeCodeStr32: - for i := range aa { - buf, ok := r.Next(4) - if !ok { - return errors.New("invalid length") - } - size := int64(binary.BigEndian.Uint32(buf)) - - buf, ok = r.Next(size) - if !ok { - return errors.New("invalid length") - } - aa[i] = string(buf) - } - default: - return fmt.Errorf("invalid type for []string %02x", type_) - } - - *a = aa - return nil -} - -type arraySymbol []Symbol - -func (a arraySymbol) Marshal(wr *buffer.Buffer) error { - var ( - elementType = TypeCodeSym8 - elementsSizeTotal int - ) - for _, element := range a { - elementsSizeTotal += len(element) - - if len(element) > math.MaxUint8 { - elementType = TypeCodeSym32 - } - } - - writeVariableArrayHeader(wr, len(a), elementsSizeTotal, elementType) - - if elementType == TypeCodeSym32 { - for _, element := range a { - wr.AppendUint32(uint32(len(element))) - wr.AppendString(string(element)) - } - } else { - for _, element := range a { - wr.AppendByte(byte(len(element))) - wr.AppendString(string(element)) - } - } - - return nil -} - -func (a *arraySymbol) Unmarshal(r *buffer.Buffer) error { - length, err := readArrayHeader(r) - if err != nil { - return err - } - - const typeSize = 2 // assume all symbols are at least 2 bytes - if length*typeSize > int64(r.Len()) { - return fmt.Errorf("invalid length %d", length) - } - - aa := (*a)[:0] - if int64(cap(aa)) < length { - aa = make([]Symbol, length) - } else { - aa = aa[:length] - } - - type_, err := readType(r) - if err != nil { - return err - } - switch type_ { - case TypeCodeSym8: - for i := range aa { - size, err := r.ReadByte() - if err != nil { - return err - } - - buf, ok := r.Next(int64(size)) - if !ok { - return errors.New("invalid length") - } - aa[i] = Symbol(buf) - } - case TypeCodeSym32: - for i := range aa { - buf, ok := r.Next(4) - if !ok { - return errors.New("invalid length") - } - size := int64(binary.BigEndian.Uint32(buf)) - - buf, ok = r.Next(size) - if !ok { - return errors.New("invalid length") - } - aa[i] = Symbol(buf) - } - default: - return fmt.Errorf("invalid type for []Symbol %02x", type_) - } - - *a = aa - return nil -} - -type arrayBinary [][]byte - -func (a arrayBinary) Marshal(wr *buffer.Buffer) error { - var ( - elementType = TypeCodeVbin8 - elementsSizeTotal int - ) - for _, element := range a { - elementsSizeTotal += len(element) - - if len(element) > math.MaxUint8 { - elementType = TypeCodeVbin32 - } - } - - writeVariableArrayHeader(wr, len(a), elementsSizeTotal, elementType) - - if elementType == TypeCodeVbin32 { - for _, element := range a { - wr.AppendUint32(uint32(len(element))) - wr.Append(element) - } - } else { - for _, element := range a { - wr.AppendByte(byte(len(element))) - wr.Append(element) - } - } - - return nil -} - -func (a *arrayBinary) Unmarshal(r *buffer.Buffer) error { - length, err := readArrayHeader(r) - if err != nil { - return err - } - - const typeSize = 2 // assume all binary is at least 2 bytes - if length*typeSize > int64(r.Len()) { - return fmt.Errorf("invalid length %d", length) - } - - aa := (*a)[:0] - if int64(cap(aa)) < length { - aa = make([][]byte, length) - } else { - aa = aa[:length] - } - - type_, err := readType(r) - if err != nil { - return err - } - switch type_ { - case TypeCodeVbin8: - for i := range aa { - size, err := r.ReadByte() - if err != nil { - return err - } - - buf, ok := r.Next(int64(size)) - if !ok { - return fmt.Errorf("invalid length %d", length) - } - aa[i] = append([]byte(nil), buf...) - } - case TypeCodeVbin32: - for i := range aa { - buf, ok := r.Next(4) - if !ok { - return errors.New("invalid length") - } - size := binary.BigEndian.Uint32(buf) - - buf, ok = r.Next(int64(size)) - if !ok { - return errors.New("invalid length") - } - aa[i] = append([]byte(nil), buf...) - } - default: - return fmt.Errorf("invalid type for [][]byte %02x", type_) - } - - *a = aa - return nil -} - -type arrayTimestamp []time.Time - -func (a arrayTimestamp) Marshal(wr *buffer.Buffer) error { - const typeSize = 8 - - writeArrayHeader(wr, len(a), typeSize, TypeCodeTimestamp) - - for _, element := range a { - ms := element.UnixNano() / int64(time.Millisecond) - wr.AppendUint64(uint64(ms)) - } - - return nil -} - -func (a *arrayTimestamp) Unmarshal(r *buffer.Buffer) error { - length, err := readArrayHeader(r) - if err != nil { - return err - } - - type_, err := readType(r) - if err != nil { - return err - } - if type_ != TypeCodeTimestamp { - return fmt.Errorf("invalid type for []time.Time %02x", type_) - } - - const typeSize = 8 - buf, ok := r.Next(length * typeSize) - if !ok { - return fmt.Errorf("invalid length %d", length) - } - - aa := (*a)[:0] - if int64(cap(aa)) < length { - aa = make([]time.Time, length) - } else { - aa = aa[:length] - } - - var bufIdx int - for i := range aa { - ms := int64(binary.BigEndian.Uint64(buf[bufIdx:])) - bufIdx += typeSize - aa[i] = time.Unix(ms/1000, (ms%1000)*1000000).UTC() - } - - *a = aa - return nil -} - -type arrayUUID []UUID - -func (a arrayUUID) Marshal(wr *buffer.Buffer) error { - const typeSize = 16 - - writeArrayHeader(wr, len(a), typeSize, TypeCodeUUID) - - for _, element := range a { - wr.Append(element[:]) - } - - return nil -} - -func (a *arrayUUID) Unmarshal(r *buffer.Buffer) error { - length, err := readArrayHeader(r) - if err != nil { - return err - } - - type_, err := readType(r) - if err != nil { - return err - } - if type_ != TypeCodeUUID { - return fmt.Errorf("invalid type for []UUID %#02x", type_) - } - - const typeSize = 16 - buf, ok := r.Next(length * typeSize) - if !ok { - return fmt.Errorf("invalid length %d", length) - } - - aa := (*a)[:0] - if int64(cap(aa)) < length { - aa = make([]UUID, length) - } else { - aa = aa[:length] - } - - var bufIdx int - for i := range aa { - copy(aa[i][:], buf[bufIdx:bufIdx+16]) - bufIdx += 16 - } - - *a = aa - return nil -} - -// LIST - -type list []any - -func (l list) Marshal(wr *buffer.Buffer) error { - length := len(l) - - // type - if length == 0 { - wr.AppendByte(byte(TypeCodeList0)) - return nil - } - wr.AppendByte(byte(TypeCodeList32)) - - // size - sizeIdx := wr.Len() - wr.Append([]byte{0, 0, 0, 0}) - - // length - wr.AppendUint32(uint32(length)) - - for _, element := range l { - err := Marshal(wr, element) - if err != nil { - return err - } - } - - // overwrite size - binary.BigEndian.PutUint32(wr.Bytes()[sizeIdx:], uint32(wr.Len()-(sizeIdx+4))) - - return nil -} - -func (l *list) Unmarshal(r *buffer.Buffer) error { - length, err := readListHeader(r) - if err != nil { - return err - } - - // assume that all types are at least 1 byte - if length > int64(r.Len()) { - return fmt.Errorf("invalid length %d", length) - } - - ll := *l - if int64(cap(ll)) < length { - ll = make([]any, length) - } else { - ll = ll[:length] - } - - for i := range ll { - ll[i], err = ReadAny(r) - if err != nil { - return err - } - } - - *l = ll - return nil -} - -// multiSymbol can decode a single symbol or an array. -type MultiSymbol []Symbol - -func (ms MultiSymbol) Marshal(wr *buffer.Buffer) error { - return Marshal(wr, []Symbol(ms)) -} - -func (ms *MultiSymbol) Unmarshal(r *buffer.Buffer) error { - type_, err := peekType(r) - if err != nil { - return err - } - - if type_ == TypeCodeSym8 || type_ == TypeCodeSym32 { - s, err := ReadString(r) - if err != nil { - return err - } - - *ms = []Symbol{Symbol(s)} - return nil - } - - return Unmarshal(r, (*[]Symbol)(ms)) -} diff --git a/sdk/messaging/azservicebus/internal/go-amqp/internal/frames/frames.go b/sdk/messaging/azservicebus/internal/go-amqp/internal/frames/frames.go deleted file mode 100644 index 86a2bc04f72c..000000000000 --- a/sdk/messaging/azservicebus/internal/go-amqp/internal/frames/frames.go +++ /dev/null @@ -1,1543 +0,0 @@ -// Copyright (C) 2017 Kale Blankenship -// Portions Copyright (c) Microsoft Corporation - -package frames - -import ( - "errors" - "fmt" - "strconv" - "time" - - "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus/internal/go-amqp/internal/buffer" - "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus/internal/go-amqp/internal/encoding" -) - -// Type contains the values for a frame's type. -type Type uint8 - -const ( - TypeAMQP Type = 0x0 - TypeSASL Type = 0x1 -) - -// String implements the fmt.Stringer interface for type Type. -func (t Type) String() string { - if t == 0 { - return "AMQP" - } - return "SASL" -} - -/* - - - - - - - - - - - - - - - - -*/ -type Source struct { - // the address of the source - // - // The address of the source MUST NOT be set when sent on a attach frame sent by - // the receiving link endpoint where the dynamic flag is set to true (that is where - // the receiver is requesting the sender to create an addressable node). - // - // The address of the source MUST be set when sent on a attach frame sent by the - // sending link endpoint where the dynamic flag is set to true (that is where the - // sender has created an addressable node at the request of the receiver and is now - // communicating the address of that created node). The generated name of the address - // SHOULD include the link name and the container-id of the remote container to allow - // for ease of identification. - Address string - - // indicates the durability of the terminus - // - // Indicates what state of the terminus will be retained durably: the state of durable - // messages, only existence and configuration of the terminus, or no state at all. - // - // 0: none - // 1: configuration - // 2: unsettled-state - Durable encoding.Durability - - // the expiry policy of the source - // - // link-detach: The expiry timer starts when terminus is detached. - // session-end: The expiry timer starts when the most recently associated session is - // ended. - // connection-close: The expiry timer starts when most recently associated connection - // is closed. - // never: The terminus never expires. - ExpiryPolicy encoding.ExpiryPolicy - - // duration that an expiring source will be retained - // - // The source starts expiring as indicated by the expiry-policy. - Timeout uint32 // seconds - - // request dynamic creation of a remote node - // - // When set to true by the receiving link endpoint, this field constitutes a request - // for the sending peer to dynamically create a node at the source. In this case the - // address field MUST NOT be set. - // - // When set to true by the sending link endpoint this field indicates creation of a - // dynamically created node. In this case the address field will contain the address - // of the created node. The generated address SHOULD include the link name and other - // available information on the initiator of the request (such as the remote - // container-id) in some recognizable form for ease of traceability. - Dynamic bool - - // properties of the dynamically created node - // - // If the dynamic field is not set to true this field MUST be left unset. - // - // When set by the receiving link endpoint, this field contains the desired - // properties of the node the receiver wishes to be created. When set by the - // sending link endpoint this field contains the actual properties of the - // dynamically created node. See subsection 3.5.9 for standard node properties. - // http://www.amqp.org/specification/1.0/node-properties - // - // lifetime-policy: The lifetime of a dynamically generated node. - // Definitionally, the lifetime will never be less than the lifetime - // of the link which caused its creation, however it is possible to - // extend the lifetime of dynamically created node using a lifetime - // policy. The value of this entry MUST be of a type which provides - // the lifetime-policy archetype. The following standard - // lifetime-policies are defined below: delete-on-close, - // delete-on-no-links, delete-on-no-messages or - // delete-on-no-links-or-messages. - // supported-dist-modes: The distribution modes that the node supports. - // The value of this entry MUST be one or more symbols which are valid - // distribution-modes. That is, the value MUST be of the same type as - // would be valid in a field defined with the following attributes: - // type="symbol" multiple="true" requires="distribution-mode" - DynamicNodeProperties map[encoding.Symbol]any // TODO: implement custom type with validation - - // the distribution mode of the link - // - // This field MUST be set by the sending end of the link if the endpoint supports more - // than one distribution-mode. This field MAY be set by the receiving end of the link - // to indicate a preference when a node supports multiple distribution modes. - DistributionMode encoding.Symbol - - // a set of predicates to filter the messages admitted onto the link - // - // The receiving endpoint sets its desired filter, the sending endpoint sets the filter - // actually in place (including any filters defaulted at the node). The receiving - // endpoint MUST check that the filter in place meets its needs and take responsibility - // for detaching if it does not. - Filter encoding.Filter - - // default outcome for unsettled transfers - // - // Indicates the outcome to be used for transfers that have not reached a terminal - // state at the receiver when the transfer is settled, including when the source - // is destroyed. The value MUST be a valid outcome (e.g., released or rejected). - DefaultOutcome any - - // descriptors for the outcomes that can be chosen on this link - // - // The values in this field are the symbolic descriptors of the outcomes that can - // be chosen on this link. This field MAY be empty, indicating that the default-outcome - // will be assumed for all message transfers (if the default-outcome is not set, and no - // outcomes are provided, then the accepted outcome MUST be supported by the source). - // - // When present, the values MUST be a symbolic descriptor of a valid outcome, - // e.g., "amqp:accepted:list". - Outcomes encoding.MultiSymbol - - // the extension capabilities the sender supports/desires - // - // http://www.amqp.org/specification/1.0/source-capabilities - Capabilities encoding.MultiSymbol -} - -func (s *Source) Marshal(wr *buffer.Buffer) error { - return encoding.MarshalComposite(wr, encoding.TypeCodeSource, []encoding.MarshalField{ - {Value: &s.Address, Omit: s.Address == ""}, - {Value: &s.Durable, Omit: s.Durable == encoding.DurabilityNone}, - {Value: &s.ExpiryPolicy, Omit: s.ExpiryPolicy == "" || s.ExpiryPolicy == encoding.ExpirySessionEnd}, - {Value: &s.Timeout, Omit: s.Timeout == 0}, - {Value: &s.Dynamic, Omit: !s.Dynamic}, - {Value: s.DynamicNodeProperties, Omit: len(s.DynamicNodeProperties) == 0}, - {Value: &s.DistributionMode, Omit: s.DistributionMode == ""}, - {Value: s.Filter, Omit: len(s.Filter) == 0}, - {Value: &s.DefaultOutcome, Omit: s.DefaultOutcome == nil}, - {Value: &s.Outcomes, Omit: len(s.Outcomes) == 0}, - {Value: &s.Capabilities, Omit: len(s.Capabilities) == 0}, - }) -} - -func (s *Source) Unmarshal(r *buffer.Buffer) error { - return encoding.UnmarshalComposite(r, encoding.TypeCodeSource, []encoding.UnmarshalField{ - {Field: &s.Address}, - {Field: &s.Durable}, - {Field: &s.ExpiryPolicy, HandleNull: func() error { s.ExpiryPolicy = encoding.ExpirySessionEnd; return nil }}, - {Field: &s.Timeout}, - {Field: &s.Dynamic}, - {Field: &s.DynamicNodeProperties}, - {Field: &s.DistributionMode}, - {Field: &s.Filter}, - {Field: &s.DefaultOutcome}, - {Field: &s.Outcomes}, - {Field: &s.Capabilities}, - }...) -} - -func (s Source) String() string { - return fmt.Sprintf("source{Address: %s, Durable: %d, ExpiryPolicy: %s, Timeout: %d, "+ - "Dynamic: %t, DynamicNodeProperties: %v, DistributionMode: %s, Filter: %v, DefaultOutcome: %v "+ - "Outcomes: %v, Capabilities: %v}", - s.Address, - s.Durable, - s.ExpiryPolicy, - s.Timeout, - s.Dynamic, - s.DynamicNodeProperties, - s.DistributionMode, - s.Filter, - s.DefaultOutcome, - s.Outcomes, - s.Capabilities, - ) -} - -/* - - - - - - - - - - - - -*/ -type Target struct { - // the address of the target - // - // The address of the target MUST NOT be set when sent on a attach frame sent by - // the sending link endpoint where the dynamic flag is set to true (that is where - // the sender is requesting the receiver to create an addressable node). - // - // The address of the source MUST be set when sent on a attach frame sent by the - // receiving link endpoint where the dynamic flag is set to true (that is where - // the receiver has created an addressable node at the request of the sender and - // is now communicating the address of that created node). The generated name of - // the address SHOULD include the link name and the container-id of the remote - // container to allow for ease of identification. - Address string - - // indicates the durability of the terminus - // - // Indicates what state of the terminus will be retained durably: the state of durable - // messages, only existence and configuration of the terminus, or no state at all. - // - // 0: none - // 1: configuration - // 2: unsettled-state - Durable encoding.Durability - - // the expiry policy of the target - // - // link-detach: The expiry timer starts when terminus is detached. - // session-end: The expiry timer starts when the most recently associated session is - // ended. - // connection-close: The expiry timer starts when most recently associated connection - // is closed. - // never: The terminus never expires. - ExpiryPolicy encoding.ExpiryPolicy - - // duration that an expiring target will be retained - // - // The target starts expiring as indicated by the expiry-policy. - Timeout uint32 // seconds - - // request dynamic creation of a remote node - // - // When set to true by the sending link endpoint, this field constitutes a request - // for the receiving peer to dynamically create a node at the target. In this case - // the address field MUST NOT be set. - // - // When set to true by the receiving link endpoint this field indicates creation of - // a dynamically created node. In this case the address field will contain the - // address of the created node. The generated address SHOULD include the link name - // and other available information on the initiator of the request (such as the - // remote container-id) in some recognizable form for ease of traceability. - Dynamic bool - - // properties of the dynamically created node - // - // If the dynamic field is not set to true this field MUST be left unset. - // - // When set by the sending link endpoint, this field contains the desired - // properties of the node the sender wishes to be created. When set by the - // receiving link endpoint this field contains the actual properties of the - // dynamically created node. See subsection 3.5.9 for standard node properties. - // http://www.amqp.org/specification/1.0/node-properties - // - // lifetime-policy: The lifetime of a dynamically generated node. - // Definitionally, the lifetime will never be less than the lifetime - // of the link which caused its creation, however it is possible to - // extend the lifetime of dynamically created node using a lifetime - // policy. The value of this entry MUST be of a type which provides - // the lifetime-policy archetype. The following standard - // lifetime-policies are defined below: delete-on-close, - // delete-on-no-links, delete-on-no-messages or - // delete-on-no-links-or-messages. - // supported-dist-modes: The distribution modes that the node supports. - // The value of this entry MUST be one or more symbols which are valid - // distribution-modes. That is, the value MUST be of the same type as - // would be valid in a field defined with the following attributes: - // type="symbol" multiple="true" requires="distribution-mode" - DynamicNodeProperties map[encoding.Symbol]any // TODO: implement custom type with validation - - // the extension capabilities the sender supports/desires - // - // http://www.amqp.org/specification/1.0/target-capabilities - Capabilities encoding.MultiSymbol -} - -func (t *Target) Marshal(wr *buffer.Buffer) error { - return encoding.MarshalComposite(wr, encoding.TypeCodeTarget, []encoding.MarshalField{ - {Value: &t.Address, Omit: t.Address == ""}, - {Value: &t.Durable, Omit: t.Durable == encoding.DurabilityNone}, - {Value: &t.ExpiryPolicy, Omit: t.ExpiryPolicy == "" || t.ExpiryPolicy == encoding.ExpirySessionEnd}, - {Value: &t.Timeout, Omit: t.Timeout == 0}, - {Value: &t.Dynamic, Omit: !t.Dynamic}, - {Value: t.DynamicNodeProperties, Omit: len(t.DynamicNodeProperties) == 0}, - {Value: &t.Capabilities, Omit: len(t.Capabilities) == 0}, - }) -} - -func (t *Target) Unmarshal(r *buffer.Buffer) error { - return encoding.UnmarshalComposite(r, encoding.TypeCodeTarget, []encoding.UnmarshalField{ - {Field: &t.Address}, - {Field: &t.Durable}, - {Field: &t.ExpiryPolicy, HandleNull: func() error { t.ExpiryPolicy = encoding.ExpirySessionEnd; return nil }}, - {Field: &t.Timeout}, - {Field: &t.Dynamic}, - {Field: &t.DynamicNodeProperties}, - {Field: &t.Capabilities}, - }...) -} - -func (t Target) String() string { - return fmt.Sprintf("source{Address: %s, Durable: %d, ExpiryPolicy: %s, Timeout: %d, "+ - "Dynamic: %t, DynamicNodeProperties: %v, Capabilities: %v}", - t.Address, - t.Durable, - t.ExpiryPolicy, - t.Timeout, - t.Dynamic, - t.DynamicNodeProperties, - t.Capabilities, - ) -} - -// frame is the decoded representation of a frame -type Frame struct { - Type Type // AMQP/SASL - Channel uint16 // channel this frame is for - Body FrameBody // body of the frame -} - -// String implements the fmt.Stringer interface for type Frame. -func (f Frame) String() string { - return fmt.Sprintf("Frame{Type: %s, Channel: %d, Body: %s}", f.Type, f.Channel, f.Body) -} - -// frameBody adds some type safety to frame encoding -type FrameBody interface { - frameBody() -} - -/* - - - - - - - - - - - - - -*/ - -type PerformOpen struct { - ContainerID string // required - Hostname string - MaxFrameSize uint32 // default: 4294967295 - ChannelMax uint16 // default: 65535 - IdleTimeout time.Duration // from milliseconds - OutgoingLocales encoding.MultiSymbol - IncomingLocales encoding.MultiSymbol - OfferedCapabilities encoding.MultiSymbol - DesiredCapabilities encoding.MultiSymbol - Properties map[encoding.Symbol]any -} - -func (o *PerformOpen) frameBody() {} - -func (o *PerformOpen) Marshal(wr *buffer.Buffer) error { - return encoding.MarshalComposite(wr, encoding.TypeCodeOpen, []encoding.MarshalField{ - {Value: &o.ContainerID, Omit: false}, - {Value: &o.Hostname, Omit: o.Hostname == ""}, - {Value: &o.MaxFrameSize, Omit: o.MaxFrameSize == 4294967295}, - {Value: &o.ChannelMax, Omit: o.ChannelMax == 65535}, - {Value: (*encoding.Milliseconds)(&o.IdleTimeout), Omit: o.IdleTimeout == 0}, - {Value: &o.OutgoingLocales, Omit: len(o.OutgoingLocales) == 0}, - {Value: &o.IncomingLocales, Omit: len(o.IncomingLocales) == 0}, - {Value: &o.OfferedCapabilities, Omit: len(o.OfferedCapabilities) == 0}, - {Value: &o.DesiredCapabilities, Omit: len(o.DesiredCapabilities) == 0}, - {Value: o.Properties, Omit: len(o.Properties) == 0}, - }) -} - -func (o *PerformOpen) Unmarshal(r *buffer.Buffer) error { - return encoding.UnmarshalComposite(r, encoding.TypeCodeOpen, []encoding.UnmarshalField{ - {Field: &o.ContainerID, HandleNull: func() error { return errors.New("Open.ContainerID is required") }}, - {Field: &o.Hostname}, - {Field: &o.MaxFrameSize, HandleNull: func() error { o.MaxFrameSize = 4294967295; return nil }}, - {Field: &o.ChannelMax, HandleNull: func() error { o.ChannelMax = 65535; return nil }}, - {Field: (*encoding.Milliseconds)(&o.IdleTimeout)}, - {Field: &o.OutgoingLocales}, - {Field: &o.IncomingLocales}, - {Field: &o.OfferedCapabilities}, - {Field: &o.DesiredCapabilities}, - {Field: &o.Properties}, - }...) -} - -func (o *PerformOpen) String() string { - return fmt.Sprintf("Open{ContainerID : %s, Hostname: %s, MaxFrameSize: %d, "+ - "ChannelMax: %d, IdleTimeout: %v, "+ - "OutgoingLocales: %v, IncomingLocales: %v, "+ - "OfferedCapabilities: %v, DesiredCapabilities: %v, "+ - "Properties: %v}", - o.ContainerID, - o.Hostname, - o.MaxFrameSize, - o.ChannelMax, - o.IdleTimeout, - o.OutgoingLocales, - o.IncomingLocales, - o.OfferedCapabilities, - o.DesiredCapabilities, - o.Properties, - ) -} - -/* - - - - - - - - - - - - - -*/ -type PerformBegin struct { - // the remote channel for this session - // If a session is locally initiated, the remote-channel MUST NOT be set. - // When an endpoint responds to a remotely initiated session, the remote-channel - // MUST be set to the channel on which the remote session sent the begin. - RemoteChannel *uint16 - - // the transfer-id of the first transfer id the sender will send - NextOutgoingID uint32 // required, sequence number http://www.ietf.org/rfc/rfc1982.txt - - // the initial incoming-window of the sender - IncomingWindow uint32 // required - - // the initial outgoing-window of the sender - OutgoingWindow uint32 // required - - // the maximum handle value that can be used on the session - // The handle-max value is the highest handle value that can be - // used on the session. A peer MUST NOT attempt to attach a link - // using a handle value outside the range that its partner can handle. - // A peer that receives a handle outside the supported range MUST - // close the connection with the framing-error error-code. - HandleMax uint32 // default 4294967295 - - // the extension capabilities the sender supports - // http://www.amqp.org/specification/1.0/session-capabilities - OfferedCapabilities encoding.MultiSymbol - - // the extension capabilities the sender can use if the receiver supports them - // The sender MUST NOT attempt to use any capability other than those it - // has declared in desired-capabilities field. - DesiredCapabilities encoding.MultiSymbol - - // session properties - // http://www.amqp.org/specification/1.0/session-properties - Properties map[encoding.Symbol]any -} - -func (b *PerformBegin) frameBody() {} - -func (b *PerformBegin) String() string { - return fmt.Sprintf("Begin{RemoteChannel: %v, NextOutgoingID: %d, IncomingWindow: %d, "+ - "OutgoingWindow: %d, HandleMax: %d, OfferedCapabilities: %v, DesiredCapabilities: %v, "+ - "Properties: %v}", - formatUint16Ptr(b.RemoteChannel), - b.NextOutgoingID, - b.IncomingWindow, - b.OutgoingWindow, - b.HandleMax, - b.OfferedCapabilities, - b.DesiredCapabilities, - b.Properties, - ) -} - -func formatUint16Ptr(p *uint16) string { - if p == nil { - return "" - } - return strconv.FormatUint(uint64(*p), 10) -} - -func (b *PerformBegin) Marshal(wr *buffer.Buffer) error { - return encoding.MarshalComposite(wr, encoding.TypeCodeBegin, []encoding.MarshalField{ - {Value: b.RemoteChannel, Omit: b.RemoteChannel == nil}, - {Value: &b.NextOutgoingID, Omit: false}, - {Value: &b.IncomingWindow, Omit: false}, - {Value: &b.OutgoingWindow, Omit: false}, - {Value: &b.HandleMax, Omit: b.HandleMax == 4294967295}, - {Value: &b.OfferedCapabilities, Omit: len(b.OfferedCapabilities) == 0}, - {Value: &b.DesiredCapabilities, Omit: len(b.DesiredCapabilities) == 0}, - {Value: b.Properties, Omit: b.Properties == nil}, - }) -} - -func (b *PerformBegin) Unmarshal(r *buffer.Buffer) error { - return encoding.UnmarshalComposite(r, encoding.TypeCodeBegin, []encoding.UnmarshalField{ - {Field: &b.RemoteChannel}, - {Field: &b.NextOutgoingID, HandleNull: func() error { return errors.New("Begin.NextOutgoingID is required") }}, - {Field: &b.IncomingWindow, HandleNull: func() error { return errors.New("Begin.IncomingWindow is required") }}, - {Field: &b.OutgoingWindow, HandleNull: func() error { return errors.New("Begin.OutgoingWindow is required") }}, - {Field: &b.HandleMax, HandleNull: func() error { b.HandleMax = 4294967295; return nil }}, - {Field: &b.OfferedCapabilities}, - {Field: &b.DesiredCapabilities}, - {Field: &b.Properties}, - }...) -} - -/* - - - - - - - - - - - - - - - - - - - -*/ -type PerformAttach struct { - // the name of the link - // - // This name uniquely identifies the link from the container of the source - // to the container of the target node, e.g., if the container of the source - // node is A, and the container of the target node is B, the link MAY be - // globally identified by the (ordered) tuple (A,B,). - Name string // required - - // the handle for the link while attached - // - // The numeric handle assigned by the the peer as a shorthand to refer to the - // link in all performatives that reference the link until the it is detached. - // - // The handle MUST NOT be used for other open links. An attempt to attach using - // a handle which is already associated with a link MUST be responded to with - // an immediate close carrying a handle-in-use session-error. - // - // To make it easier to monitor AMQP link attach frames, it is RECOMMENDED that - // implementations always assign the lowest available handle to this field. - // - // The two endpoints MAY potentially use different handles to refer to the same link. - // Link handles MAY be reused once a link is closed for both send and receive. - Handle uint32 // required - - // role of the link endpoint - // - // The role being played by the peer, i.e., whether the peer is the sender or the - // receiver of messages on the link. - Role encoding.Role - - // settlement policy for the sender - // - // The delivery settlement policy for the sender. When set at the receiver this - // indicates the desired value for the settlement mode at the sender. When set - // at the sender this indicates the actual settlement mode in use. The sender - // SHOULD respect the receiver's desired settlement mode if the receiver initiates - // the attach exchange and the sender supports the desired mode. - // - // 0: unsettled - The sender will send all deliveries initially unsettled to the receiver. - // 1: settled - The sender will send all deliveries settled to the receiver. - // 2: mixed - The sender MAY send a mixture of settled and unsettled deliveries to the receiver. - SenderSettleMode *encoding.SenderSettleMode - - // the settlement policy of the receiver - // - // The delivery settlement policy for the receiver. When set at the sender this - // indicates the desired value for the settlement mode at the receiver. - // When set at the receiver this indicates the actual settlement mode in use. - // The receiver SHOULD respect the sender's desired settlement mode if the sender - // initiates the attach exchange and the receiver supports the desired mode. - // - // 0: first - The receiver will spontaneously settle all incoming transfers. - // 1: second - The receiver will only settle after sending the disposition to - // the sender and receiving a disposition indicating settlement of - // the delivery from the sender. - ReceiverSettleMode *encoding.ReceiverSettleMode - - // the source for messages - // - // If no source is specified on an outgoing link, then there is no source currently - // attached to the link. A link with no source will never produce outgoing messages. - Source *Source - - // the target for messages - // - // If no target is specified on an incoming link, then there is no target currently - // attached to the link. A link with no target will never permit incoming messages. - Target *Target - - // unsettled delivery state - // - // This is used to indicate any unsettled delivery states when a suspended link is - // resumed. The map is keyed by delivery-tag with values indicating the delivery state. - // The local and remote delivery states for a given delivery-tag MUST be compared to - // resolve any in-doubt deliveries. If necessary, deliveries MAY be resent, or resumed - // based on the outcome of this comparison. See subsection 2.6.13. - // - // If the local unsettled map is too large to be encoded within a frame of the agreed - // maximum frame size then the session MAY be ended with the frame-size-too-small error. - // The endpoint SHOULD make use of the ability to send an incomplete unsettled map - // (see below) to avoid sending an error. - // - // The unsettled map MUST NOT contain null valued keys. - // - // When reattaching (as opposed to resuming), the unsettled map MUST be null. - Unsettled encoding.Unsettled - - // If set to true this field indicates that the unsettled map provided is not complete. - // When the map is incomplete the recipient of the map cannot take the absence of a - // delivery tag from the map as evidence of settlement. On receipt of an incomplete - // unsettled map a sending endpoint MUST NOT send any new deliveries (i.e. deliveries - // where resume is not set to true) to its partner (and a receiving endpoint which sent - // an incomplete unsettled map MUST detach with an error on receiving a transfer which - // does not have the resume flag set to true). - // - // Note that if this flag is set to true then the endpoints MUST detach and reattach at - // least once in order to send new deliveries. This flag can be useful when there are - // too many entries in the unsettled map to fit within a single frame. An endpoint can - // attach, resume, settle, and detach until enough unsettled state has been cleared for - // an attach where this flag is set to false. - IncompleteUnsettled bool // default: false - - // the sender's initial value for delivery-count - // - // This MUST NOT be null if role is sender, and it is ignored if the role is receiver. - InitialDeliveryCount uint32 // sequence number - - // the maximum message size supported by the link endpoint - // - // This field indicates the maximum message size supported by the link endpoint. - // Any attempt to deliver a message larger than this results in a message-size-exceeded - // link-error. If this field is zero or unset, there is no maximum size imposed by the - // link endpoint. - MaxMessageSize uint64 - - // the extension capabilities the sender supports - // http://www.amqp.org/specification/1.0/link-capabilities - OfferedCapabilities encoding.MultiSymbol - - // the extension capabilities the sender can use if the receiver supports them - // - // The sender MUST NOT attempt to use any capability other than those it - // has declared in desired-capabilities field. - DesiredCapabilities encoding.MultiSymbol - - // link properties - // http://www.amqp.org/specification/1.0/link-properties - Properties map[encoding.Symbol]any -} - -func (a *PerformAttach) frameBody() {} - -func (a PerformAttach) String() string { - return fmt.Sprintf("Attach{Name: %s, Handle: %d, Role: %s, SenderSettleMode: %s, ReceiverSettleMode: %s, "+ - "Source: %v, Target: %v, Unsettled: %v, IncompleteUnsettled: %t, InitialDeliveryCount: %d, MaxMessageSize: %d, "+ - "OfferedCapabilities: %v, DesiredCapabilities: %v, Properties: %v}", - a.Name, - a.Handle, - a.Role, - a.SenderSettleMode, - a.ReceiverSettleMode, - a.Source, - a.Target, - a.Unsettled, - a.IncompleteUnsettled, - a.InitialDeliveryCount, - a.MaxMessageSize, - a.OfferedCapabilities, - a.DesiredCapabilities, - a.Properties, - ) -} - -func (a *PerformAttach) Marshal(wr *buffer.Buffer) error { - return encoding.MarshalComposite(wr, encoding.TypeCodeAttach, []encoding.MarshalField{ - {Value: &a.Name, Omit: false}, - {Value: &a.Handle, Omit: false}, - {Value: &a.Role, Omit: false}, - {Value: a.SenderSettleMode, Omit: a.SenderSettleMode == nil}, - {Value: a.ReceiverSettleMode, Omit: a.ReceiverSettleMode == nil}, - {Value: a.Source, Omit: a.Source == nil}, - {Value: a.Target, Omit: a.Target == nil}, - {Value: a.Unsettled, Omit: len(a.Unsettled) == 0}, - {Value: &a.IncompleteUnsettled, Omit: !a.IncompleteUnsettled}, - {Value: &a.InitialDeliveryCount, Omit: a.Role == encoding.RoleReceiver}, - {Value: &a.MaxMessageSize, Omit: a.MaxMessageSize == 0}, - {Value: &a.OfferedCapabilities, Omit: len(a.OfferedCapabilities) == 0}, - {Value: &a.DesiredCapabilities, Omit: len(a.DesiredCapabilities) == 0}, - {Value: a.Properties, Omit: len(a.Properties) == 0}, - }) -} - -func (a *PerformAttach) Unmarshal(r *buffer.Buffer) error { - return encoding.UnmarshalComposite(r, encoding.TypeCodeAttach, []encoding.UnmarshalField{ - {Field: &a.Name, HandleNull: func() error { return errors.New("Attach.Name is required") }}, - {Field: &a.Handle, HandleNull: func() error { return errors.New("Attach.Handle is required") }}, - {Field: &a.Role, HandleNull: func() error { return errors.New("Attach.Role is required") }}, - {Field: &a.SenderSettleMode}, - {Field: &a.ReceiverSettleMode}, - {Field: &a.Source}, - {Field: &a.Target}, - {Field: &a.Unsettled}, - {Field: &a.IncompleteUnsettled}, - {Field: &a.InitialDeliveryCount}, - {Field: &a.MaxMessageSize}, - {Field: &a.OfferedCapabilities}, - {Field: &a.DesiredCapabilities}, - {Field: &a.Properties}, - }...) -} - -/* - - - - - - - - - - - - - - - - -*/ -type PerformFlow struct { - // Identifies the expected transfer-id of the next incoming transfer frame. - // This value MUST be set if the peer has received the begin frame for the - // session, and MUST NOT be set if it has not. See subsection 2.5.6 for more details. - NextIncomingID *uint32 // sequence number - - // Defines the maximum number of incoming transfer frames that the endpoint - // can currently receive. See subsection 2.5.6 for more details. - IncomingWindow uint32 // required - - // The transfer-id that will be assigned to the next outgoing transfer frame. - // See subsection 2.5.6 for more details. - NextOutgoingID uint32 // sequence number - - // Defines the maximum number of outgoing transfer frames that the endpoint - // could potentially currently send, if it was not constrained by restrictions - // imposed by its peer's incoming-window. See subsection 2.5.6 for more details. - OutgoingWindow uint32 - - // If set, indicates that the flow frame carries flow state information for the local - // link endpoint associated with the given handle. If not set, the flow frame is - // carrying only information pertaining to the session endpoint. - // - // If set to a handle that is not currently associated with an attached link, - // the recipient MUST respond by ending the session with an unattached-handle - // session error. - Handle *uint32 - - // The delivery-count is initialized by the sender when a link endpoint is created, - // and is incremented whenever a message is sent. Only the sender MAY independently - // modify this field. The receiver's value is calculated based on the last known - // value from the sender and any subsequent messages received on the link. Note that, - // despite its name, the delivery-count is not a count but a sequence number - // initialized at an arbitrary point by the sender. - // - // When the handle field is not set, this field MUST NOT be set. - // - // When the handle identifies that the flow state is being sent from the sender link - // endpoint to receiver link endpoint this field MUST be set to the current - // delivery-count of the link endpoint. - // - // When the flow state is being sent from the receiver endpoint to the sender endpoint - // this field MUST be set to the last known value of the corresponding sending endpoint. - // In the event that the receiving link endpoint has not yet seen the initial attach - // frame from the sender this field MUST NOT be set. - DeliveryCount *uint32 // sequence number - - // the current maximum number of messages that can be received - // - // The current maximum number of messages that can be handled at the receiver endpoint - // of the link. Only the receiver endpoint can independently set this value. The sender - // endpoint sets this to the last known value seen from the receiver. - // See subsection 2.6.7 for more details. - // - // When the handle field is not set, this field MUST NOT be set. - LinkCredit *uint32 - - // the number of available messages - // - // The number of messages awaiting credit at the link sender endpoint. Only the sender - // can independently set this value. The receiver sets this to the last known value seen - // from the sender. See subsection 2.6.7 for more details. - // - // When the handle field is not set, this field MUST NOT be set. - Available *uint32 - - // indicates drain mode - // - // When flow state is sent from the sender to the receiver, this field contains the - // actual drain mode of the sender. When flow state is sent from the receiver to the - // sender, this field contains the desired drain mode of the receiver. - // See subsection 2.6.7 for more details. - // - // When the handle field is not set, this field MUST NOT be set. - Drain bool - - // request state from partner - // - // If set to true then the receiver SHOULD send its state at the earliest convenient - // opportunity. - // - // If set to true, and the handle field is not set, then the sender only requires - // session endpoint state to be echoed, however, the receiver MAY fulfil this requirement - // by sending a flow performative carrying link-specific state (since any such flow also - // carries session state). - // - // If a sender makes multiple requests for the same state before the receiver can reply, - // the receiver MAY send only one flow in return. - // - // Note that if a peer responds to echo requests with flows which themselves have the - // echo field set to true, an infinite loop could result if its partner adopts the same - // policy (therefore such a policy SHOULD be avoided). - Echo bool - - // link state properties - // http://www.amqp.org/specification/1.0/link-state-properties - Properties map[encoding.Symbol]any -} - -func (f *PerformFlow) frameBody() {} - -func (f *PerformFlow) String() string { - return fmt.Sprintf("Flow{NextIncomingID: %s, IncomingWindow: %d, NextOutgoingID: %d, OutgoingWindow: %d, "+ - "Handle: %s, DeliveryCount: %s, LinkCredit: %s, Available: %s, Drain: %t, Echo: %t, Properties: %+v}", - formatUint32Ptr(f.NextIncomingID), - f.IncomingWindow, - f.NextOutgoingID, - f.OutgoingWindow, - formatUint32Ptr(f.Handle), - formatUint32Ptr(f.DeliveryCount), - formatUint32Ptr(f.LinkCredit), - formatUint32Ptr(f.Available), - f.Drain, - f.Echo, - f.Properties, - ) -} - -func formatUint32Ptr(p *uint32) string { - if p == nil { - return "" - } - return strconv.FormatUint(uint64(*p), 10) -} - -func (f *PerformFlow) Marshal(wr *buffer.Buffer) error { - return encoding.MarshalComposite(wr, encoding.TypeCodeFlow, []encoding.MarshalField{ - {Value: f.NextIncomingID, Omit: f.NextIncomingID == nil}, - {Value: &f.IncomingWindow, Omit: false}, - {Value: &f.NextOutgoingID, Omit: false}, - {Value: &f.OutgoingWindow, Omit: false}, - {Value: f.Handle, Omit: f.Handle == nil}, - {Value: f.DeliveryCount, Omit: f.DeliveryCount == nil}, - {Value: f.LinkCredit, Omit: f.LinkCredit == nil}, - {Value: f.Available, Omit: f.Available == nil}, - {Value: &f.Drain, Omit: !f.Drain}, - {Value: &f.Echo, Omit: !f.Echo}, - {Value: f.Properties, Omit: len(f.Properties) == 0}, - }) -} - -func (f *PerformFlow) Unmarshal(r *buffer.Buffer) error { - return encoding.UnmarshalComposite(r, encoding.TypeCodeFlow, []encoding.UnmarshalField{ - {Field: &f.NextIncomingID}, - {Field: &f.IncomingWindow, HandleNull: func() error { return errors.New("Flow.IncomingWindow is required") }}, - {Field: &f.NextOutgoingID, HandleNull: func() error { return errors.New("Flow.NextOutgoingID is required") }}, - {Field: &f.OutgoingWindow, HandleNull: func() error { return errors.New("Flow.OutgoingWindow is required") }}, - {Field: &f.Handle}, - {Field: &f.DeliveryCount}, - {Field: &f.LinkCredit}, - {Field: &f.Available}, - {Field: &f.Drain}, - {Field: &f.Echo}, - {Field: &f.Properties}, - }...) -} - -/* - - - - - - - - - - - - - - - - -*/ -type PerformTransfer struct { - // Specifies the link on which the message is transferred. - Handle uint32 // required - - // The delivery-id MUST be supplied on the first transfer of a multi-transfer - // delivery. On continuation transfers the delivery-id MAY be omitted. It is - // an error if the delivery-id on a continuation transfer differs from the - // delivery-id on the first transfer of a delivery. - DeliveryID *uint32 // sequence number - - // Uniquely identifies the delivery attempt for a given message on this link. - // This field MUST be specified for the first transfer of a multi-transfer - // message and can only be omitted for continuation transfers. It is an error - // if the delivery-tag on a continuation transfer differs from the delivery-tag - // on the first transfer of a delivery. - DeliveryTag []byte // up to 32 bytes - - // This field MUST be specified for the first transfer of a multi-transfer message - // and can only be omitted for continuation transfers. It is an error if the - // message-format on a continuation transfer differs from the message-format on - // the first transfer of a delivery. - // - // The upper three octets of a message format code identify a particular message - // format. The lowest octet indicates the version of said message format. Any given - // version of a format is forwards compatible with all higher versions. - MessageFormat *uint32 - - // If not set on the first (or only) transfer for a (multi-transfer) delivery, - // then the settled flag MUST be interpreted as being false. For subsequent - // transfers in a multi-transfer delivery if the settled flag is left unset then - // it MUST be interpreted as true if and only if the value of the settled flag on - // any of the preceding transfers was true; if no preceding transfer was sent with - // settled being true then the value when unset MUST be taken as false. - // - // If the negotiated value for snd-settle-mode at attachment is settled, then this - // field MUST be true on at least one transfer frame for a delivery (i.e., the - // delivery MUST be settled at the sender at the point the delivery has been - // completely transferred). - // - // If the negotiated value for snd-settle-mode at attachment is unsettled, then this - // field MUST be false (or unset) on every transfer frame for a delivery (unless the - // delivery is aborted). - Settled bool - - // indicates that the message has more content - // - // Note that if both the more and aborted fields are set to true, the aborted flag - // takes precedence. That is, a receiver SHOULD ignore the value of the more field - // if the transfer is marked as aborted. A sender SHOULD NOT set the more flag to - // true if it also sets the aborted flag to true. - More bool - - // If first, this indicates that the receiver MUST settle the delivery once it has - // arrived without waiting for the sender to settle first. - // - // If second, this indicates that the receiver MUST NOT settle until sending its - // disposition to the sender and receiving a settled disposition from the sender. - // - // If not set, this value is defaulted to the value negotiated on link attach. - // - // If the negotiated link value is first, then it is illegal to set this field - // to second. - // - // If the message is being sent settled by the sender, the value of this field - // is ignored. - // - // The (implicit or explicit) value of this field does not form part of the - // transfer state, and is not retained if a link is suspended and subsequently resumed. - // - // 0: first - The receiver will spontaneously settle all incoming transfers. - // 1: second - The receiver will only settle after sending the disposition to - // the sender and receiving a disposition indicating settlement of - // the delivery from the sender. - ReceiverSettleMode *encoding.ReceiverSettleMode - - // the state of the delivery at the sender - // - // When set this informs the receiver of the state of the delivery at the sender. - // This is particularly useful when transfers of unsettled deliveries are resumed - // after resuming a link. Setting the state on the transfer can be thought of as - // being equivalent to sending a disposition immediately before the transfer - // performative, i.e., it is the state of the delivery (not the transfer) that - // existed at the point the frame was sent. - // - // Note that if the transfer performative (or an earlier disposition performative - // referring to the delivery) indicates that the delivery has attained a terminal - // state, then no future transfer or disposition sent by the sender can alter that - // terminal state. - State encoding.DeliveryState - - // indicates a resumed delivery - // - // If true, the resume flag indicates that the transfer is being used to reassociate - // an unsettled delivery from a dissociated link endpoint. See subsection 2.6.13 - // for more details. - // - // The receiver MUST ignore resumed deliveries that are not in its local unsettled map. - // The sender MUST NOT send resumed transfers for deliveries not in its local - // unsettled map. - // - // If a resumed delivery spans more than one transfer performative, then the resume - // flag MUST be set to true on the first transfer of the resumed delivery. For - // subsequent transfers for the same delivery the resume flag MAY be set to true, - // or MAY be omitted. - // - // In the case where the exchange of unsettled maps makes clear that all message - // data has been successfully transferred to the receiver, and that only the final - // state (and potentially settlement) at the sender needs to be conveyed, then a - // resumed delivery MAY carry no payload and instead act solely as a vehicle for - // carrying the terminal state of the delivery at the sender. - Resume bool - - // indicates that the message is aborted - // - // Aborted messages SHOULD be discarded by the recipient (any payload within the - // frame carrying the performative MUST be ignored). An aborted message is - // implicitly settled. - Aborted bool - - // batchable hint - // - // If true, then the issuer is hinting that there is no need for the peer to urgently - // communicate updated delivery state. This hint MAY be used to artificially increase - // the amount of batching an implementation uses when communicating delivery states, - // and thereby save bandwidth. - // - // If the message being delivered is too large to fit within a single frame, then the - // setting of batchable to true on any of the transfer performatives for the delivery - // is equivalent to setting batchable to true for all the transfer performatives for - // the delivery. - // - // The batchable value does not form part of the transfer state, and is not retained - // if a link is suspended and subsequently resumed. - Batchable bool - - Payload []byte - - // optional channel to indicate to sender that transfer has completed - // - // Settled=true: closed when the transferred on network. - // Settled=false: closed when the receiver has confirmed settlement. - Done chan encoding.DeliveryState -} - -func (t *PerformTransfer) frameBody() {} - -func (t PerformTransfer) String() string { - deliveryTag := "" - if t.DeliveryTag != nil { - deliveryTag = fmt.Sprintf("%X", t.DeliveryTag) - } - - return fmt.Sprintf("Transfer{Handle: %d, DeliveryID: %s, DeliveryTag: %s, MessageFormat: %s, "+ - "Settled: %t, More: %t, ReceiverSettleMode: %s, State: %v, Resume: %t, Aborted: %t, "+ - "Batchable: %t, Payload [size]: %d}", - t.Handle, - formatUint32Ptr(t.DeliveryID), - deliveryTag, - formatUint32Ptr(t.MessageFormat), - t.Settled, - t.More, - t.ReceiverSettleMode, - t.State, - t.Resume, - t.Aborted, - t.Batchable, - len(t.Payload), - ) -} - -func (t *PerformTransfer) Marshal(wr *buffer.Buffer) error { - err := encoding.MarshalComposite(wr, encoding.TypeCodeTransfer, []encoding.MarshalField{ - {Value: &t.Handle}, - {Value: t.DeliveryID, Omit: t.DeliveryID == nil}, - {Value: &t.DeliveryTag, Omit: len(t.DeliveryTag) == 0}, - {Value: t.MessageFormat, Omit: t.MessageFormat == nil}, - {Value: &t.Settled, Omit: !t.Settled}, - {Value: &t.More, Omit: !t.More}, - {Value: t.ReceiverSettleMode, Omit: t.ReceiverSettleMode == nil}, - {Value: t.State, Omit: t.State == nil}, - {Value: &t.Resume, Omit: !t.Resume}, - {Value: &t.Aborted, Omit: !t.Aborted}, - {Value: &t.Batchable, Omit: !t.Batchable}, - }) - if err != nil { - return err - } - - wr.Append(t.Payload) - return nil -} - -func (t *PerformTransfer) Unmarshal(r *buffer.Buffer) error { - err := encoding.UnmarshalComposite(r, encoding.TypeCodeTransfer, []encoding.UnmarshalField{ - {Field: &t.Handle, HandleNull: func() error { return errors.New("Transfer.Handle is required") }}, - {Field: &t.DeliveryID}, - {Field: &t.DeliveryTag}, - {Field: &t.MessageFormat}, - {Field: &t.Settled}, - {Field: &t.More}, - {Field: &t.ReceiverSettleMode}, - {Field: &t.State}, - {Field: &t.Resume}, - {Field: &t.Aborted}, - {Field: &t.Batchable}, - }...) - if err != nil { - return err - } - - t.Payload = append([]byte(nil), r.Bytes()...) - - return err -} - -/* - - - - - - - - - - - -*/ -type PerformDisposition struct { - // directionality of disposition - // - // The role identifies whether the disposition frame contains information about - // sending link endpoints or receiving link endpoints. - Role encoding.Role - - // lower bound of deliveries - // - // Identifies the lower bound of delivery-ids for the deliveries in this set. - First uint32 // required, sequence number - - // upper bound of deliveries - // - // Identifies the upper bound of delivery-ids for the deliveries in this set. - // If not set, this is taken to be the same as first. - Last *uint32 // sequence number - - // indicates deliveries are settled - // - // If true, indicates that the referenced deliveries are considered settled by - // the issuing endpoint. - Settled bool - - // indicates state of deliveries - // - // Communicates the state of all the deliveries referenced by this disposition. - State encoding.DeliveryState - - // batchable hint - // - // If true, then the issuer is hinting that there is no need for the peer to - // urgently communicate the impact of the updated delivery states. This hint - // MAY be used to artificially increase the amount of batching an implementation - // uses when communicating delivery states, and thereby save bandwidth. - Batchable bool -} - -func (d *PerformDisposition) frameBody() {} - -func (d PerformDisposition) String() string { - return fmt.Sprintf("Disposition{Role: %s, First: %d, Last: %s, Settled: %t, State: %v, Batchable: %t}", - d.Role, - d.First, - formatUint32Ptr(d.Last), - d.Settled, - d.State, - d.Batchable, - ) -} - -func (d *PerformDisposition) Marshal(wr *buffer.Buffer) error { - return encoding.MarshalComposite(wr, encoding.TypeCodeDisposition, []encoding.MarshalField{ - {Value: &d.Role, Omit: false}, - {Value: &d.First, Omit: false}, - {Value: d.Last, Omit: d.Last == nil}, - {Value: &d.Settled, Omit: !d.Settled}, - {Value: d.State, Omit: d.State == nil}, - {Value: &d.Batchable, Omit: !d.Batchable}, - }) -} - -func (d *PerformDisposition) Unmarshal(r *buffer.Buffer) error { - return encoding.UnmarshalComposite(r, encoding.TypeCodeDisposition, []encoding.UnmarshalField{ - {Field: &d.Role, HandleNull: func() error { return errors.New("Disposition.Role is required") }}, - {Field: &d.First, HandleNull: func() error { return errors.New("Disposition.Handle is required") }}, - {Field: &d.Last}, - {Field: &d.Settled}, - {Field: &d.State}, - {Field: &d.Batchable}, - }...) -} - -/* - - - - - - - - -*/ -type PerformDetach struct { - // the local handle of the link to be detached - Handle uint32 //required - - // if true then the sender has closed the link - Closed bool - - // error causing the detach - // - // If set, this field indicates that the link is being detached due to an error - // condition. The value of the field SHOULD contain details on the cause of the error. - Error *encoding.Error -} - -func (d *PerformDetach) frameBody() {} - -func (d PerformDetach) String() string { - return fmt.Sprintf("Detach{Handle: %d, Closed: %t, Error: %v}", - d.Handle, - d.Closed, - d.Error, - ) -} - -func (d *PerformDetach) Marshal(wr *buffer.Buffer) error { - return encoding.MarshalComposite(wr, encoding.TypeCodeDetach, []encoding.MarshalField{ - {Value: &d.Handle, Omit: false}, - {Value: &d.Closed, Omit: !d.Closed}, - {Value: d.Error, Omit: d.Error == nil}, - }) -} - -func (d *PerformDetach) Unmarshal(r *buffer.Buffer) error { - return encoding.UnmarshalComposite(r, encoding.TypeCodeDetach, []encoding.UnmarshalField{ - {Field: &d.Handle, HandleNull: func() error { return errors.New("Detach.Handle is required") }}, - {Field: &d.Closed}, - {Field: &d.Error}, - }...) -} - -/* - - - - - - -*/ -type PerformEnd struct { - // error causing the end - // - // If set, this field indicates that the session is being ended due to an error - // condition. The value of the field SHOULD contain details on the cause of the error. - Error *encoding.Error -} - -func (e *PerformEnd) frameBody() {} - -func (d PerformEnd) String() string { - return fmt.Sprintf("End{Error: %v}", d.Error) -} - -func (e *PerformEnd) Marshal(wr *buffer.Buffer) error { - return encoding.MarshalComposite(wr, encoding.TypeCodeEnd, []encoding.MarshalField{ - {Value: e.Error, Omit: e.Error == nil}, - }) -} - -func (e *PerformEnd) Unmarshal(r *buffer.Buffer) error { - return encoding.UnmarshalComposite(r, encoding.TypeCodeEnd, - encoding.UnmarshalField{Field: &e.Error}, - ) -} - -/* - - - - - - -*/ -type PerformClose struct { - // error causing the close - // - // If set, this field indicates that the session is being closed due to an error - // condition. The value of the field SHOULD contain details on the cause of the error. - Error *encoding.Error -} - -func (c *PerformClose) frameBody() {} - -func (c *PerformClose) Marshal(wr *buffer.Buffer) error { - return encoding.MarshalComposite(wr, encoding.TypeCodeClose, []encoding.MarshalField{ - {Value: c.Error, Omit: c.Error == nil}, - }) -} - -func (c *PerformClose) Unmarshal(r *buffer.Buffer) error { - return encoding.UnmarshalComposite(r, encoding.TypeCodeClose, - encoding.UnmarshalField{Field: &c.Error}, - ) -} - -func (c *PerformClose) String() string { - return fmt.Sprintf("Close{Error: %s}", c.Error) -} - -/* - - - - - - -*/ - -type SASLInit struct { - Mechanism encoding.Symbol - InitialResponse []byte - Hostname string -} - -func (si *SASLInit) frameBody() {} - -func (si *SASLInit) Marshal(wr *buffer.Buffer) error { - return encoding.MarshalComposite(wr, encoding.TypeCodeSASLInit, []encoding.MarshalField{ - {Value: &si.Mechanism, Omit: false}, - {Value: &si.InitialResponse, Omit: false}, - {Value: &si.Hostname, Omit: len(si.Hostname) == 0}, - }) -} - -func (si *SASLInit) Unmarshal(r *buffer.Buffer) error { - return encoding.UnmarshalComposite(r, encoding.TypeCodeSASLInit, []encoding.UnmarshalField{ - {Field: &si.Mechanism, HandleNull: func() error { return errors.New("saslInit.Mechanism is required") }}, - {Field: &si.InitialResponse}, - {Field: &si.Hostname}, - }...) -} - -func (si *SASLInit) String() string { - // Elide the InitialResponse as it may contain a plain text secret. - return fmt.Sprintf("SaslInit{Mechanism : %s, InitialResponse: ********, Hostname: %s}", - si.Mechanism, - si.Hostname, - ) -} - -/* - - - - -*/ - -type SASLMechanisms struct { - Mechanisms encoding.MultiSymbol -} - -func (sm *SASLMechanisms) frameBody() {} - -func (sm *SASLMechanisms) Marshal(wr *buffer.Buffer) error { - return encoding.MarshalComposite(wr, encoding.TypeCodeSASLMechanism, []encoding.MarshalField{ - {Value: &sm.Mechanisms, Omit: false}, - }) -} - -func (sm *SASLMechanisms) Unmarshal(r *buffer.Buffer) error { - return encoding.UnmarshalComposite(r, encoding.TypeCodeSASLMechanism, - encoding.UnmarshalField{Field: &sm.Mechanisms, HandleNull: func() error { return errors.New("saslMechanisms.Mechanisms is required") }}, - ) -} - -func (sm *SASLMechanisms) String() string { - return fmt.Sprintf("SaslMechanisms{Mechanisms : %v}", - sm.Mechanisms, - ) -} - -/* - - - - -*/ - -type SASLChallenge struct { - Challenge []byte -} - -func (sc *SASLChallenge) String() string { - return "Challenge{Challenge: ********}" -} - -func (sc *SASLChallenge) frameBody() {} - -func (sc *SASLChallenge) Marshal(wr *buffer.Buffer) error { - return encoding.MarshalComposite(wr, encoding.TypeCodeSASLChallenge, []encoding.MarshalField{ - {Value: &sc.Challenge, Omit: false}, - }) -} - -func (sc *SASLChallenge) Unmarshal(r *buffer.Buffer) error { - return encoding.UnmarshalComposite(r, encoding.TypeCodeSASLChallenge, []encoding.UnmarshalField{ - {Field: &sc.Challenge, HandleNull: func() error { return errors.New("saslChallenge.Challenge is required") }}, - }...) -} - -/* - - - - -*/ - -type SASLResponse struct { - Response []byte -} - -func (sr *SASLResponse) String() string { - return "Response{Response: ********}" -} - -func (sr *SASLResponse) frameBody() {} - -func (sr *SASLResponse) Marshal(wr *buffer.Buffer) error { - return encoding.MarshalComposite(wr, encoding.TypeCodeSASLResponse, []encoding.MarshalField{ - {Value: &sr.Response, Omit: false}, - }) -} - -func (sr *SASLResponse) Unmarshal(r *buffer.Buffer) error { - return encoding.UnmarshalComposite(r, encoding.TypeCodeSASLResponse, []encoding.UnmarshalField{ - {Field: &sr.Response, HandleNull: func() error { return errors.New("saslResponse.Response is required") }}, - }...) -} - -/* - - - - - -*/ - -type SASLOutcome struct { - Code encoding.SASLCode - AdditionalData []byte -} - -func (so *SASLOutcome) frameBody() {} - -func (so *SASLOutcome) Marshal(wr *buffer.Buffer) error { - return encoding.MarshalComposite(wr, encoding.TypeCodeSASLOutcome, []encoding.MarshalField{ - {Value: &so.Code, Omit: false}, - {Value: &so.AdditionalData, Omit: len(so.AdditionalData) == 0}, - }) -} - -func (so *SASLOutcome) Unmarshal(r *buffer.Buffer) error { - return encoding.UnmarshalComposite(r, encoding.TypeCodeSASLOutcome, []encoding.UnmarshalField{ - {Field: &so.Code, HandleNull: func() error { return errors.New("saslOutcome.AdditionalData is required") }}, - {Field: &so.AdditionalData}, - }...) -} - -func (so *SASLOutcome) String() string { - return fmt.Sprintf("SaslOutcome{Code : %v, AdditionalData: %v}", - so.Code, - so.AdditionalData, - ) -} diff --git a/sdk/messaging/azservicebus/internal/go-amqp/internal/frames/parsing.go b/sdk/messaging/azservicebus/internal/go-amqp/internal/frames/parsing.go deleted file mode 100644 index 2b0b34837774..000000000000 --- a/sdk/messaging/azservicebus/internal/go-amqp/internal/frames/parsing.go +++ /dev/null @@ -1,162 +0,0 @@ -// Copyright (C) 2017 Kale Blankenship -// Portions Copyright (c) Microsoft Corporation - -package frames - -import ( - "encoding/binary" - "errors" - "fmt" - "math" - - "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus/internal/go-amqp/internal/buffer" - "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus/internal/go-amqp/internal/encoding" -) - -const HeaderSize = 8 - -// Frame structure: -// -// header (8 bytes) -// 0-3: SIZE (total size, at least 8 bytes for header, uint32) -// 4: DOFF (data offset,at least 2, count of 4 bytes words, uint8) -// 5: TYPE (frame type) -// 0x0: AMQP -// 0x1: SASL -// 6-7: type dependent (channel for AMQP) -// extended header (opt) -// body (opt) - -// Header in a structure appropriate for use with binary.Read() -type Header struct { - // size: an unsigned 32-bit integer that MUST contain the total frame size of the frame header, - // extended header, and frame body. The frame is malformed if the size is less than the size of - // the frame header (8 bytes). - Size uint32 - // doff: gives the position of the body within the frame. The value of the data offset is an - // unsigned, 8-bit integer specifying a count of 4-byte words. Due to the mandatory 8-byte - // frame header, the frame is malformed if the value is less than 2. - DataOffset uint8 - FrameType uint8 - Channel uint16 -} - -// ParseHeader reads the header from r and returns the result. -// -// No validation is done. -func ParseHeader(r *buffer.Buffer) (Header, error) { - buf, ok := r.Next(8) - if !ok { - return Header{}, errors.New("invalid frameHeader") - } - _ = buf[7] - - fh := Header{ - Size: binary.BigEndian.Uint32(buf[0:4]), - DataOffset: buf[4], - FrameType: buf[5], - Channel: binary.BigEndian.Uint16(buf[6:8]), - } - - if fh.Size < HeaderSize { - return fh, fmt.Errorf("received frame header with invalid size %d", fh.Size) - } - - if fh.DataOffset < 2 { - return fh, fmt.Errorf("received frame header with invalid data offset %d", fh.DataOffset) - } - - return fh, nil -} - -// ParseBody reads and unmarshals an AMQP frame. -func ParseBody(r *buffer.Buffer) (FrameBody, error) { - payload := r.Bytes() - - if r.Len() < 3 || payload[0] != 0 || encoding.AMQPType(payload[1]) != encoding.TypeCodeSmallUlong { - return nil, errors.New("invalid frame body header") - } - - switch pType := encoding.AMQPType(payload[2]); pType { - case encoding.TypeCodeOpen: - t := new(PerformOpen) - err := t.Unmarshal(r) - return t, err - case encoding.TypeCodeBegin: - t := new(PerformBegin) - err := t.Unmarshal(r) - return t, err - case encoding.TypeCodeAttach: - t := new(PerformAttach) - err := t.Unmarshal(r) - return t, err - case encoding.TypeCodeFlow: - t := new(PerformFlow) - err := t.Unmarshal(r) - return t, err - case encoding.TypeCodeTransfer: - t := new(PerformTransfer) - err := t.Unmarshal(r) - return t, err - case encoding.TypeCodeDisposition: - t := new(PerformDisposition) - err := t.Unmarshal(r) - return t, err - case encoding.TypeCodeDetach: - t := new(PerformDetach) - err := t.Unmarshal(r) - return t, err - case encoding.TypeCodeEnd: - t := new(PerformEnd) - err := t.Unmarshal(r) - return t, err - case encoding.TypeCodeClose: - t := new(PerformClose) - err := t.Unmarshal(r) - return t, err - case encoding.TypeCodeSASLMechanism: - t := new(SASLMechanisms) - err := t.Unmarshal(r) - return t, err - case encoding.TypeCodeSASLChallenge: - t := new(SASLChallenge) - err := t.Unmarshal(r) - return t, err - case encoding.TypeCodeSASLOutcome: - t := new(SASLOutcome) - err := t.Unmarshal(r) - return t, err - default: - return nil, fmt.Errorf("unknown performative type %02x", pType) - } -} - -// Write encodes fr into buf. -// split out from conn.WriteFrame for testing purposes. -func Write(buf *buffer.Buffer, fr Frame) error { - // write header - buf.Append([]byte{ - 0, 0, 0, 0, // size, overwrite later - 2, // doff, see frameHeader.DataOffset comment - uint8(fr.Type), // frame type - }) - buf.AppendUint16(fr.Channel) // channel - - // write AMQP frame body - err := encoding.Marshal(buf, fr.Body) - if err != nil { - return err - } - - // validate size - if uint(buf.Len()) > math.MaxUint32 { - return errors.New("frame too large") - } - - // retrieve raw bytes - bufBytes := buf.Bytes() - - // write correct size - binary.BigEndian.PutUint32(bufBytes, uint32(len(bufBytes))) - return nil -} diff --git a/sdk/messaging/azservicebus/internal/go-amqp/internal/queue/queue.go b/sdk/messaging/azservicebus/internal/go-amqp/internal/queue/queue.go deleted file mode 100644 index 45d6f5af9daf..000000000000 --- a/sdk/messaging/azservicebus/internal/go-amqp/internal/queue/queue.go +++ /dev/null @@ -1,164 +0,0 @@ -// Copyright (c) Microsoft Corporation - -package queue - -import ( - "container/ring" -) - -// Holder provides synchronized access to a *Queue[T]. -type Holder[T any] struct { - // these channels work in tandem to provide exclusive access to the underlying *Queue[T]. - // each channel is created with a buffer size of one. - // empty behaves like a mutex when there's one or more messages in the queue. - // populated is like a semaphore when the queue is empty. - // the *Queue[T] is only ever in one channel. which channel depends on if it contains any items. - // the initial state is for empty to contain an empty queue. - empty chan *Queue[T] - populated chan *Queue[T] -} - -// NewHolder creates a new Holder[T] that contains the provided *Queue[T]. -func NewHolder[T any](q *Queue[T]) *Holder[T] { - h := &Holder[T]{ - empty: make(chan *Queue[T], 1), - populated: make(chan *Queue[T], 1), - } - h.Release(q) - return h -} - -// Acquire attempts to acquire the *Queue[T]. If the *Queue[T] has already been acquired the call blocks. -// When the *Queue[T] is no longer required, you MUST call Release() to relinquish acquisition. -func (h *Holder[T]) Acquire() *Queue[T] { - // the queue will be in only one of the channels, it doesn't matter which one - var q *Queue[T] - select { - case q = <-h.empty: - // empty queue - case q = <-h.populated: - // populated queue - } - return q -} - -// Wait returns a channel that's signaled when the *Queue[T] contains at least one item. -// When the *Queue[T] is no longer required, you MUST call Release() to relinquish acquisition. -func (h *Holder[T]) Wait() <-chan *Queue[T] { - return h.populated -} - -// Release returns the *Queue[T] back to the Holder[T]. -// Once the *Queue[T] has been released, it is no longer safe to call its methods. -func (h *Holder[T]) Release(q *Queue[T]) { - if q.Len() == 0 { - h.empty <- q - } else { - h.populated <- q - } -} - -// Len returns the length of the *Queue[T]. -func (h *Holder[T]) Len() int { - msgLen := 0 - select { - case q := <-h.empty: - h.empty <- q - case q := <-h.populated: - msgLen = q.Len() - h.populated <- q - } - return msgLen -} - -// Queue[T] is a segmented FIFO queue of Ts. -type Queue[T any] struct { - head *ring.Ring - tail *ring.Ring - size int -} - -// New creates a new instance of Queue[T]. -// - size is the size of each Queue segment -func New[T any](size int) *Queue[T] { - r := &ring.Ring{ - Value: &segment[T]{ - items: make([]*T, size), - }, - } - return &Queue[T]{ - head: r, - tail: r, - } -} - -// Enqueue adds the specified item to the end of the queue. -// If the current segment is full, a new segment is created. -func (q *Queue[T]) Enqueue(item T) { - for { - r := q.tail - seg := r.Value.(*segment[T]) - - if seg.tail < len(seg.items) { - seg.items[seg.tail] = &item - seg.tail++ - q.size++ - return - } - - // segment is full, can we advance? - if next := r.Next(); next != q.head { - q.tail = next - continue - } - - // no, add a new ring - r.Link(&ring.Ring{ - Value: &segment[T]{ - items: make([]*T, len(seg.items)), - }, - }) - - q.tail = r.Next() - } -} - -// Dequeue removes and returns the item from the front of the queue. -func (q *Queue[T]) Dequeue() *T { - r := q.head - seg := r.Value.(*segment[T]) - - if seg.tail == 0 { - // queue is empty - return nil - } - - // remove first item - item := seg.items[seg.head] - seg.items[seg.head] = nil - seg.head++ - q.size-- - - if seg.head == seg.tail { - // segment is now empty, reset indices - seg.head, seg.tail = 0, 0 - - // if we're not at the last ring, advance head to the next one - if q.head != q.tail { - q.head = r.Next() - } - } - - return item -} - -// Len returns the total count of enqueued items. -func (q *Queue[T]) Len() int { - return q.size -} - -type segment[T any] struct { - items []*T - head int - tail int -} diff --git a/sdk/messaging/azservicebus/internal/go-amqp/internal/shared/shared.go b/sdk/messaging/azservicebus/internal/go-amqp/internal/shared/shared.go deleted file mode 100644 index 867c1e932bf5..000000000000 --- a/sdk/messaging/azservicebus/internal/go-amqp/internal/shared/shared.go +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright (c) Microsoft Corporation - -package shared - -import ( - "encoding/base64" - "math/rand" - "sync" - "time" -) - -// lockedRand provides a rand source that is safe for concurrent use. -type lockedRand struct { - mu sync.Mutex - src *rand.Rand -} - -func (r *lockedRand) Read(p []byte) (int, error) { - r.mu.Lock() - defer r.mu.Unlock() - return r.src.Read(p) -} - -// package scoped rand source to avoid any issues with seeding -// of the global source. -var pkgRand = &lockedRand{ - src: rand.New(rand.NewSource(time.Now().UnixNano())), -} - -// RandString returns a base64 encoded string of n bytes. -func RandString(n int) string { - b := make([]byte, n) - // from math/rand, cannot fail - _, _ = pkgRand.Read(b) - return base64.RawURLEncoding.EncodeToString(b) -} diff --git a/sdk/messaging/azservicebus/internal/go-amqp/link.go b/sdk/messaging/azservicebus/internal/go-amqp/link.go deleted file mode 100644 index 1965b75049ed..000000000000 --- a/sdk/messaging/azservicebus/internal/go-amqp/link.go +++ /dev/null @@ -1,390 +0,0 @@ -// Copyright (C) 2017 Kale Blankenship -// Portions Copyright (c) Microsoft Corporation - -package amqp - -import ( - "context" - "errors" - "fmt" - "sync" - - "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus/internal/go-amqp/internal/debug" - "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus/internal/go-amqp/internal/encoding" - "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus/internal/go-amqp/internal/frames" - "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus/internal/go-amqp/internal/queue" - "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus/internal/go-amqp/internal/shared" -) - -// linkKey uniquely identifies a link on a connection by name and direction. -// -// A link can be identified uniquely by the ordered tuple -// -// (source-container-id, target-container-id, name) -// -// On a single connection the container ID pairs can be abbreviated -// to a boolean flag indicating the direction of the link. -type linkKey struct { - name string - role encoding.Role // Local role: sender/receiver -} - -// link contains the common state and methods for sending and receiving links -type link struct { - key linkKey // Name and direction - handle uint32 // our handle - remoteHandle uint32 // remote's handle - dynamicAddr bool // request a dynamic link address from the server - - // frames destined for this link are added to this queue by Session.muxFrameToLink - rxQ *queue.Holder[frames.FrameBody] - - // used for gracefully closing link - close chan struct{} // signals a link's mux to shut down; DO NOT use this to check if a link has terminated, use done instead - closeOnce *sync.Once // closeOnce protects close from being closed multiple times - - done chan struct{} // closed when the link has terminated (mux exited); DO NOT wait on this from within a link's mux() as it will never trigger! - doneErr error // contains the mux error state; ONLY written to by the mux and MUST only be read from after done is closed! - closeErr error // contains the error state returned from closeLink(); ONLY closeLink() reads/writes this! - - session *Session // parent session - source *frames.Source // used for Receiver links - target *frames.Target // used for Sender links - properties map[encoding.Symbol]any // additional properties sent upon link attach - - // "The delivery-count is initialized by the sender when a link endpoint is created, - // and is incremented whenever a message is sent. Only the sender MAY independently - // modify this field. The receiver's value is calculated based on the last known - // value from the sender and any subsequent messages received on the link. Note that, - // despite its name, the delivery-count is not a count but a sequence number - // initialized at an arbitrary point by the sender." - deliveryCount uint32 - - // The current maximum number of messages that can be handled at the receiver endpoint of the link. Only the receiver endpoint - // can independently set this value. The sender endpoint sets this to the last known value seen from the receiver. - linkCredit uint32 - - senderSettleMode *SenderSettleMode - receiverSettleMode *ReceiverSettleMode - maxMessageSize uint64 - - closeInProgress bool // indicates that the detach performative has been sent -} - -func newLink(s *Session, r encoding.Role) link { - l := link{ - key: linkKey{shared.RandString(40), r}, - session: s, - close: make(chan struct{}), - closeOnce: &sync.Once{}, - done: make(chan struct{}), - } - - // set the segment size relative to respective window - var segmentSize int - if r == encoding.RoleReceiver { - segmentSize = int(s.incomingWindow) - } else { - segmentSize = int(s.outgoingWindow) - } - - l.rxQ = queue.NewHolder(queue.New[frames.FrameBody](segmentSize)) - return l -} - -// waitForFrame waits for an incoming frame to be queued. -// it returns the next frame from the queue, or an error. -// the error is either from the context or session.doneErr. -// not meant for consumption outside of link.go. -func (l *link) waitForFrame(ctx context.Context) (frames.FrameBody, error) { - select { - case <-ctx.Done(): - return nil, ctx.Err() - case <-l.session.done: - // session has terminated, no need to deallocate in this case - return nil, l.session.doneErr - case q := <-l.rxQ.Wait(): - // frame received - fr := q.Dequeue() - l.rxQ.Release(q) - return *fr, nil - } -} - -// attach sends the Attach performative to establish the link with its parent session. -// this is automatically called by the new*Link constructors. -func (l *link) attach(ctx context.Context, beforeAttach func(*frames.PerformAttach), afterAttach func(*frames.PerformAttach)) error { - if err := l.session.freeAbandonedLinks(ctx); err != nil { - return err - } - - // once the abandoned links have been cleaned up we can create our link - if err := l.session.allocateHandle(ctx, l); err != nil { - return err - } - - attach := &frames.PerformAttach{ - Name: l.key.name, - Handle: l.handle, - ReceiverSettleMode: l.receiverSettleMode, - SenderSettleMode: l.senderSettleMode, - MaxMessageSize: l.maxMessageSize, - Source: l.source, - Target: l.target, - Properties: l.properties, - } - - // link-specific configuration of the attach frame - beforeAttach(attach) - - if err := l.txFrameAndWait(ctx, attach); err != nil { - return err - } - - // wait for response - fr, err := l.waitForFrame(ctx) - if err != nil { - l.session.abandonLink(l) - return err - } - - resp, ok := fr.(*frames.PerformAttach) - if !ok { - debug.Log(1, "RX (link %p): unexpected attach response frame %T", l, fr) - if err := l.session.conn.Close(); err != nil { - return err - } - return &ConnError{inner: fmt.Errorf("unexpected attach response: %#v", fr)} - } - - // If the remote encounters an error during the attach it returns an Attach - // with no Source or Target. The remote then sends a Detach with an error. - // - // Note that if the application chooses not to create a terminus, the session - // endpoint will still create a link endpoint and issue an attach indicating - // that the link endpoint has no associated local terminus. In this case, the - // session endpoint MUST immediately detach the newly created link endpoint. - // - // http://docs.oasis-open.org/amqp/core/v1.0/csprd01/amqp-core-transport-v1.0-csprd01.html#doc-idp386144 - if resp.Source == nil && resp.Target == nil { - // wait for detach - fr, err := l.waitForFrame(ctx) - if err != nil { - // we timed out waiting for the peer to close the link, this really isn't an abandoned link. - // however, we still need to send the detach performative to ack the peer. - l.session.abandonLink(l) - return err - } - - detach, ok := fr.(*frames.PerformDetach) - if !ok { - if err := l.session.conn.Close(); err != nil { - return err - } - return &ConnError{inner: fmt.Errorf("unexpected frame while waiting for detach: %#v", fr)} - } - - // send return detach - fr = &frames.PerformDetach{ - Handle: l.handle, - Closed: true, - } - if err := l.txFrameAndWait(ctx, fr); err != nil { - return err - } - - if detach.Error == nil { - return fmt.Errorf("received detach with no error specified") - } - return detach.Error - } - - if l.maxMessageSize == 0 || resp.MaxMessageSize < l.maxMessageSize { - l.maxMessageSize = resp.MaxMessageSize - } - - // link-specific configuration post attach - afterAttach(resp) - - if err := l.setSettleModes(resp); err != nil { - // close the link as there's a mismatch on requested/supported settlement modes - dr := &frames.PerformDetach{ - Handle: l.handle, - Closed: true, - } - if err := l.txFrameAndWait(ctx, dr); err != nil { - return err - } - return err - } - - return nil -} - -// setSettleModes sets the settlement modes based on the resp frames.PerformAttach. -// -// If a settlement mode has been explicitly set locally and it was not honored by the -// server an error is returned. -func (l *link) setSettleModes(resp *frames.PerformAttach) error { - var ( - localRecvSettle = receiverSettleModeValue(l.receiverSettleMode) - respRecvSettle = receiverSettleModeValue(resp.ReceiverSettleMode) - ) - if l.receiverSettleMode != nil && localRecvSettle != respRecvSettle { - return fmt.Errorf("amqp: receiver settlement mode %q requested, received %q from server", l.receiverSettleMode, &respRecvSettle) - } - l.receiverSettleMode = &respRecvSettle - - var ( - localSendSettle = senderSettleModeValue(l.senderSettleMode) - respSendSettle = senderSettleModeValue(resp.SenderSettleMode) - ) - if l.senderSettleMode != nil && localSendSettle != respSendSettle { - return fmt.Errorf("amqp: sender settlement mode %q requested, received %q from server", l.senderSettleMode, &respSendSettle) - } - l.senderSettleMode = &respSendSettle - - return nil -} - -// muxHandleFrame processes fr based on type. -func (l *link) muxHandleFrame(fr frames.FrameBody) error { - switch fr := fr.(type) { - case *frames.PerformDetach: - if !fr.Closed { - l.closeWithError(ErrCondNotImplemented, fmt.Sprintf("non-closing detach not supported: %+v", fr)) - return nil - } - - // there are two possibilities: - // - this is the ack to a client-side Close() - // - the peer is closing the link so we must ack - - if l.closeInProgress { - // if the client-side close was initiated due to an error (l.closeWithError) - // then l.doneErr will already be set. in this case, return that error instead - // of an empty LinkError which indicates a clean client-side close. - if l.doneErr != nil { - return l.doneErr - } - return &LinkError{} - } - - dr := &frames.PerformDetach{ - Handle: l.handle, - Closed: true, - } - l.txFrame(context.Background(), dr, nil) - return &LinkError{RemoteErr: fr.Error} - - default: - debug.Log(1, "RX (link %p): unexpected frame: %s", l, fr) - l.closeWithError(ErrCondInternalError, fmt.Sprintf("link received unexpected frame %T", fr)) - return nil - } -} - -// Close closes the Sender and AMQP link. -func (l *link) closeLink(ctx context.Context) error { - var ctxErr error - l.closeOnce.Do(func() { - close(l.close) - - // once the mux has received the ack'ing detach performative, the mux will - // exit which deletes the link and closes l.done. - select { - case <-l.done: - l.closeErr = l.doneErr - case <-ctx.Done(): - // notify the caller that the close timed out/was cancelled. - // the mux will remain running and once the ack is received it will terminate. - ctxErr = ctx.Err() - - // record that the close timed out/was cancelled. - // subsequent calls to closeLink() will return this - debug.Log(1, "TX (link %p) closing %s: %v", l, l.key.name, ctxErr) - l.closeErr = &LinkError{inner: ctxErr} - } - }) - - if ctxErr != nil { - return ctxErr - } - - var linkErr *LinkError - if errors.As(l.closeErr, &linkErr) && linkErr.RemoteErr == nil && linkErr.inner == nil { - // an empty LinkError means the link was cleanly closed by the caller - return nil - } - return l.closeErr -} - -// closeWithError initiates closing the link with the specified AMQP error. -// the mux must continue to run until the ack'ing detach is received. -// l.doneErr is populated with a &LinkError{} containing an inner error constructed from the specified values -// - cnd is the AMQP error condition -// - desc is the error description -func (l *link) closeWithError(cnd ErrCond, desc string) { - amqpErr := &Error{Condition: cnd, Description: desc} - if l.closeInProgress { - debug.Log(3, "TX (link %p) close error already pending, discarding %v", l, amqpErr) - return - } - - dr := &frames.PerformDetach{ - Handle: l.handle, - Closed: true, - Error: amqpErr, - } - l.closeInProgress = true - l.doneErr = &LinkError{inner: fmt.Errorf("%s: %s", cnd, desc)} - l.txFrame(context.Background(), dr, nil) -} - -// txFrame sends the specified frame via the link's session. -// you MUST call this instead of session.txFrame() to ensure -// that frames are not sent during session shutdown. -func (l *link) txFrame(ctx context.Context, fr frames.FrameBody, sent chan error) { - // NOTE: there is no need to select on l.done as this is either - // called from a link's mux or before the mux has even started. - select { - case <-l.session.done: - if sent != nil { - sent <- l.session.doneErr - } - case <-l.session.endSent: - // we swallow this to prevent the link's mux from terminating. - // l.session.done will soon close so this is temporary. - return - case l.session.tx <- frameBodyEnvelope{Ctx: ctx, FrameBody: fr, Sent: sent}: - debug.Log(2, "TX (link %p): mux frame to Session (%p): %s", l, l.session, fr) - } -} - -// txFrame sends the specified frame via the link's session. -// you MUST call this instead of session.txFrame() to ensure -// that frames are not sent during session shutdown. -func (l *link) txFrameAndWait(ctx context.Context, fr frames.FrameBody) error { - // NOTE: there is no need to select on l.done as this is either - // called from a link's mux or before the mux has even started. - sent := make(chan error, 1) - select { - case <-l.session.done: - return l.session.doneErr - case <-l.session.endSent: - // we swallow this to prevent the link's mux from terminating. - // l.session.done will soon close so this is temporary. - return nil - case l.session.tx <- frameBodyEnvelope{Ctx: ctx, FrameBody: fr, Sent: sent}: - debug.Log(2, "TX (link %p): mux frame to Session (%p): %s", l, l.session, fr) - } - - select { - case err := <-sent: - return err - case <-l.done: - return l.doneErr - case <-l.session.done: - return l.session.doneErr - } -} diff --git a/sdk/messaging/azservicebus/internal/go-amqp/link_options.go b/sdk/messaging/azservicebus/internal/go-amqp/link_options.go deleted file mode 100644 index 31daa94eb9f6..000000000000 --- a/sdk/messaging/azservicebus/internal/go-amqp/link_options.go +++ /dev/null @@ -1,241 +0,0 @@ -// Copyright (C) 2017 Kale Blankenship -// Portions Copyright (c) Microsoft Corporation - -package amqp - -import ( - "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus/internal/go-amqp/internal/encoding" -) - -type SenderOptions struct { - // Capabilities is the list of extension capabilities the sender supports. - Capabilities []string - - // Durability indicates what state of the sender will be retained durably. - // - // Default: DurabilityNone. - Durability Durability - - // DynamicAddress indicates a dynamic address is to be used. - // Any specified address will be ignored. - // - // Default: false. - DynamicAddress bool - - // ExpiryPolicy determines when the expiry timer of the sender starts counting - // down from the timeout value. If the link is subsequently re-attached before - // the timeout is reached, the count down is aborted. - // - // Default: ExpirySessionEnd. - ExpiryPolicy ExpiryPolicy - - // ExpiryTimeout is the duration in seconds that the sender will be retained. - // - // Default: 0. - ExpiryTimeout uint32 - - // Name sets the name of the link. - // - // Link names must be unique per-connection and direction. - // - // Default: randomly generated. - Name string - - // Properties sets an entry in the link properties map sent to the server. - Properties map[string]any - - // RequestedReceiverSettleMode sets the requested receiver settlement mode. - // - // If a settlement mode is explicitly set and the server does not - // honor it an error will be returned during link attachment. - // - // Default: Accept the settlement mode set by the server, commonly ModeFirst. - RequestedReceiverSettleMode *ReceiverSettleMode - - // SettlementMode sets the settlement mode in use by this sender. - // - // Default: ModeMixed. - SettlementMode *SenderSettleMode - - // SourceAddress specifies the source address for this sender. - SourceAddress string - - // TargetCapabilities is the list of extension capabilities the sender desires. - TargetCapabilities []string - - // TargetDurability indicates what state of the peer will be retained durably. - // - // Default: DurabilityNone. - TargetDurability Durability - - // TargetExpiryPolicy determines when the expiry timer of the peer starts counting - // down from the timeout value. If the link is subsequently re-attached before - // the timeout is reached, the count down is aborted. - // - // Default: ExpirySessionEnd. - TargetExpiryPolicy ExpiryPolicy - - // TargetExpiryTimeout is the duration in seconds that the peer will be retained. - // - // Default: 0. - TargetExpiryTimeout uint32 -} - -type ReceiverOptions struct { - // Capabilities is the list of extension capabilities the receiver supports. - Capabilities []string - - // Credit specifies the maximum number of unacknowledged messages - // the sender can transmit. Once this limit is reached, no more messages - // will arrive until messages are acknowledged and settled. - // - // As messages are settled, any available credit will automatically be issued. - // - // Setting this to -1 requires manual management of link credit. - // Credits can be added with IssueCredit(), and links can also be - // drained with DrainCredit(). - // This should only be enabled when complete control of the link's - // flow control is required. - // - // Default: 1. - Credit int32 - - // Durability indicates what state of the receiver will be retained durably. - // - // Default: DurabilityNone. - Durability Durability - - // DynamicAddress indicates a dynamic address is to be used. - // Any specified address will be ignored. - // - // Default: false. - DynamicAddress bool - - // ExpiryPolicy determines when the expiry timer of the sender starts counting - // down from the timeout value. If the link is subsequently re-attached before - // the timeout is reached, the count down is aborted. - // - // Default: ExpirySessionEnd. - ExpiryPolicy ExpiryPolicy - - // ExpiryTimeout is the duration in seconds that the sender will be retained. - // - // Default: 0. - ExpiryTimeout uint32 - - // Filters contains the desired filters for this receiver. - // If the peer cannot fulfill the filters the link will be detached. - Filters []LinkFilter - - // MaxMessageSize sets the maximum message size that can - // be received on the link. - // - // A size of zero indicates no limit. - // - // Default: 0. - MaxMessageSize uint64 - - // Name sets the name of the link. - // - // Link names must be unique per-connection and direction. - // - // Default: randomly generated. - Name string - - // Properties sets an entry in the link properties map sent to the server. - Properties map[string]any - - // RequestedSenderSettleMode sets the requested sender settlement mode. - // - // If a settlement mode is explicitly set and the server does not - // honor it an error will be returned during link attachment. - // - // Default: Accept the settlement mode set by the server, commonly ModeMixed. - RequestedSenderSettleMode *SenderSettleMode - - // SettlementMode sets the settlement mode in use by this receiver. - // - // Default: ModeFirst. - SettlementMode *ReceiverSettleMode - - // TargetAddress specifies the target address for this receiver. - TargetAddress string - - // SourceCapabilities is the list of extension capabilities the receiver desires. - SourceCapabilities []string - - // SourceDurability indicates what state of the peer will be retained durably. - // - // Default: DurabilityNone. - SourceDurability Durability - - // SourceExpiryPolicy determines when the expiry timer of the peer starts counting - // down from the timeout value. If the link is subsequently re-attached before - // the timeout is reached, the count down is aborted. - // - // Default: ExpirySessionEnd. - SourceExpiryPolicy ExpiryPolicy - - // SourceExpiryTimeout is the duration in seconds that the peer will be retained. - // - // Default: 0. - SourceExpiryTimeout uint32 -} - -// LinkFilter is an advanced API for setting non-standard source filters. -// Please file an issue or open a PR if a standard filter is missing from this -// library. -// -// The name is the key for the filter map. It will be encoded as an AMQP symbol type. -// -// The code is the descriptor of the described type value. The domain-id and descriptor-id -// should be concatenated together. If 0 is passed as the code, the name will be used as -// the descriptor. -// -// The value is the value of the descriped types. Acceptable types for value are specific -// to the filter. -// -// Example: -// -// The standard selector-filter is defined as: -// -// -// -// In this case the name is "apache.org:selector-filter:string" and the code is -// 0x0000468C00000004. -// -// LinkSourceFilter("apache.org:selector-filter:string", 0x0000468C00000004, exampleValue) -// -// References: -// -// http://docs.oasis-open.org/amqp/core/v1.0/os/amqp-core-messaging-v1.0-os.html#type-filter-set -// http://docs.oasis-open.org/amqp/core/v1.0/os/amqp-core-types-v1.0-os.html#section-descriptor-values -type LinkFilter func(encoding.Filter) - -// NewLinkFilter creates a new LinkFilter with the specified values. -// Any preexisting link filter with the same name will be updated with the new code and value. -func NewLinkFilter(name string, code uint64, value any) LinkFilter { - return func(f encoding.Filter) { - var descriptor any - if code != 0 { - descriptor = code - } else { - descriptor = encoding.Symbol(name) - } - f[encoding.Symbol(name)] = &encoding.DescribedType{ - Descriptor: descriptor, - Value: value, - } - } -} - -// NewSelectorFilter creates a new selector filter (apache.org:selector-filter:string) with the specified filter value. -// Any preexisting selector filter will be updated with the new filter value. -func NewSelectorFilter(filter string) LinkFilter { - return NewLinkFilter(selectorFilter, selectorFilterCode, filter) -} - -const ( - selectorFilter = "apache.org:selector-filter:string" - selectorFilterCode = uint64(0x0000468C00000004) -) diff --git a/sdk/messaging/azservicebus/internal/go-amqp/message.go b/sdk/messaging/azservicebus/internal/go-amqp/message.go deleted file mode 100644 index 404a3cc186da..000000000000 --- a/sdk/messaging/azservicebus/internal/go-amqp/message.go +++ /dev/null @@ -1,492 +0,0 @@ -// Copyright (C) 2017 Kale Blankenship -// Portions Copyright (c) Microsoft Corporation - -package amqp - -import ( - "fmt" - "time" - - "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus/internal/go-amqp/internal/buffer" - "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus/internal/go-amqp/internal/encoding" -) - -// Message is an AMQP message. -type Message struct { - // Message format code. - // - // The upper three octets of a message format code identify a particular message - // format. The lowest octet indicates the version of said message format. Any - // given version of a format is forwards compatible with all higher versions. - Format uint32 - - // The DeliveryTag can be up to 32 octets of binary data. - // Note that when mode one is enabled there will be no delivery tag. - DeliveryTag []byte - - // The header section carries standard delivery details about the transfer - // of a message through the AMQP network. - Header *MessageHeader - // If the header section is omitted the receiver MUST assume the appropriate - // default values (or the meaning implied by no value being set) for the - // fields within the header unless other target or node specific defaults - // have otherwise been set. - - // The delivery-annotations section is used for delivery-specific non-standard - // properties at the head of the message. Delivery annotations convey information - // from the sending peer to the receiving peer. - DeliveryAnnotations Annotations - // If the recipient does not understand the annotation it cannot be acted upon - // and its effects (such as any implied propagation) cannot be acted upon. - // Annotations might be specific to one implementation, or common to multiple - // implementations. The capabilities negotiated on link attach and on the source - // and target SHOULD be used to establish which annotations a peer supports. A - // registry of defined annotations and their meanings is maintained [AMQPDELANN]. - // The symbolic key "rejected" is reserved for the use of communicating error - // information regarding rejected messages. Any values associated with the - // "rejected" key MUST be of type error. - // - // If the delivery-annotations section is omitted, it is equivalent to a - // delivery-annotations section containing an empty map of annotations. - - // The message-annotations section is used for properties of the message which - // are aimed at the infrastructure. - Annotations Annotations - // The message-annotations section is used for properties of the message which - // are aimed at the infrastructure and SHOULD be propagated across every - // delivery step. Message annotations convey information about the message. - // Intermediaries MUST propagate the annotations unless the annotations are - // explicitly augmented or modified (e.g., by the use of the modified outcome). - // - // The capabilities negotiated on link attach and on the source and target can - // be used to establish which annotations a peer understands; however, in a - // network of AMQP intermediaries it might not be possible to know if every - // intermediary will understand the annotation. Note that for some annotations - // it might not be necessary for the intermediary to understand their purpose, - // i.e., they could be used purely as an attribute which can be filtered on. - // - // A registry of defined annotations and their meanings is maintained [AMQPMESSANN]. - // - // If the message-annotations section is omitted, it is equivalent to a - // message-annotations section containing an empty map of annotations. - - // The properties section is used for a defined set of standard properties of - // the message. - Properties *MessageProperties - // The properties section is part of the bare message; therefore, - // if retransmitted by an intermediary, it MUST remain unaltered. - - // The application-properties section is a part of the bare message used for - // structured application data. Intermediaries can use the data within this - // structure for the purposes of filtering or routing. - ApplicationProperties map[string]any - // The keys of this map are restricted to be of type string (which excludes - // the possibility of a null key) and the values are restricted to be of - // simple types only, that is, excluding map, list, and array types. - - // Data payloads. - // A data section contains opaque binary data. - Data [][]byte - - // Value payload. - // An amqp-value section contains a single AMQP value. - Value any - - // Sequence will contain AMQP sequence sections from the body of the message. - // An amqp-sequence section contains an AMQP sequence. - Sequence [][]any - - // The footer section is used for details about the message or delivery which - // can only be calculated or evaluated once the whole bare message has been - // constructed or seen (for example message hashes, HMACs, signatures and - // encryption details). - Footer Annotations - - deliveryID uint32 // used when sending disposition - settled bool // whether transfer was settled by sender -} - -// NewMessage returns a *Message with data as the payload. -// -// This constructor is intended as a helper for basic Messages with a -// single data payload. It is valid to construct a Message directly for -// more complex usages. -func NewMessage(data []byte) *Message { - return &Message{ - Data: [][]byte{data}, - } -} - -// GetData returns the first []byte from the Data field -// or nil if Data is empty. -func (m *Message) GetData() []byte { - if len(m.Data) < 1 { - return nil - } - return m.Data[0] -} - -// MarshalBinary encodes the message into binary form. -func (m *Message) MarshalBinary() ([]byte, error) { - buf := &buffer.Buffer{} - err := m.Marshal(buf) - return buf.Detach(), err -} - -func (m *Message) Marshal(wr *buffer.Buffer) error { - if m.Header != nil { - err := m.Header.Marshal(wr) - if err != nil { - return err - } - } - - if m.DeliveryAnnotations != nil { - encoding.WriteDescriptor(wr, encoding.TypeCodeDeliveryAnnotations) - err := encoding.Marshal(wr, m.DeliveryAnnotations) - if err != nil { - return err - } - } - - if m.Annotations != nil { - encoding.WriteDescriptor(wr, encoding.TypeCodeMessageAnnotations) - err := encoding.Marshal(wr, m.Annotations) - if err != nil { - return err - } - } - - if m.Properties != nil { - err := encoding.Marshal(wr, m.Properties) - if err != nil { - return err - } - } - - if m.ApplicationProperties != nil { - encoding.WriteDescriptor(wr, encoding.TypeCodeApplicationProperties) - err := encoding.Marshal(wr, m.ApplicationProperties) - if err != nil { - return err - } - } - - for _, data := range m.Data { - encoding.WriteDescriptor(wr, encoding.TypeCodeApplicationData) - err := encoding.WriteBinary(wr, data) - if err != nil { - return err - } - } - - if m.Value != nil { - encoding.WriteDescriptor(wr, encoding.TypeCodeAMQPValue) - err := encoding.Marshal(wr, m.Value) - if err != nil { - return err - } - } - - if m.Sequence != nil { - // the body can basically be one of three different types (value, data or sequence). - // When it's sequence it's actually _several_ sequence sections, one for each sub-array. - for _, v := range m.Sequence { - encoding.WriteDescriptor(wr, encoding.TypeCodeAMQPSequence) - err := encoding.Marshal(wr, v) - if err != nil { - return err - } - } - } - - if m.Footer != nil { - encoding.WriteDescriptor(wr, encoding.TypeCodeFooter) - err := encoding.Marshal(wr, m.Footer) - if err != nil { - return err - } - } - - return nil -} - -// UnmarshalBinary decodes the message from binary form. -func (m *Message) UnmarshalBinary(data []byte) error { - buf := buffer.New(data) - return m.Unmarshal(buf) -} - -func (m *Message) Unmarshal(r *buffer.Buffer) error { - // loop, decoding sections until bytes have been consumed - for r.Len() > 0 { - // determine type - type_, headerLength, err := encoding.PeekMessageType(r.Bytes()) - if err != nil { - return err - } - - var ( - section any - // section header is read from r before - // unmarshaling section is set to true - discardHeader = true - ) - switch encoding.AMQPType(type_) { - - case encoding.TypeCodeMessageHeader: - discardHeader = false - section = &m.Header - - case encoding.TypeCodeDeliveryAnnotations: - section = &m.DeliveryAnnotations - - case encoding.TypeCodeMessageAnnotations: - section = &m.Annotations - - case encoding.TypeCodeMessageProperties: - discardHeader = false - section = &m.Properties - - case encoding.TypeCodeApplicationProperties: - section = &m.ApplicationProperties - - case encoding.TypeCodeApplicationData: - r.Skip(int(headerLength)) - - var data []byte - err = encoding.Unmarshal(r, &data) - if err != nil { - return err - } - - m.Data = append(m.Data, data) - continue - - case encoding.TypeCodeAMQPSequence: - r.Skip(int(headerLength)) - - var data []any - err = encoding.Unmarshal(r, &data) - if err != nil { - return err - } - - m.Sequence = append(m.Sequence, data) - continue - - case encoding.TypeCodeFooter: - section = &m.Footer - - case encoding.TypeCodeAMQPValue: - section = &m.Value - - default: - return fmt.Errorf("unknown message section %#02x", type_) - } - - if discardHeader { - r.Skip(int(headerLength)) - } - - err = encoding.Unmarshal(r, section) - if err != nil { - return err - } - } - return nil -} - -/* - - - - - - - - -*/ - -// MessageHeader carries standard delivery details about the transfer -// of a message. -type MessageHeader struct { - Durable bool - Priority uint8 - TTL time.Duration // from milliseconds - FirstAcquirer bool - DeliveryCount uint32 -} - -func (h *MessageHeader) Marshal(wr *buffer.Buffer) error { - return encoding.MarshalComposite(wr, encoding.TypeCodeMessageHeader, []encoding.MarshalField{ - {Value: &h.Durable, Omit: !h.Durable}, - {Value: &h.Priority, Omit: h.Priority == 4}, - {Value: (*encoding.Milliseconds)(&h.TTL), Omit: h.TTL == 0}, - {Value: &h.FirstAcquirer, Omit: !h.FirstAcquirer}, - {Value: &h.DeliveryCount, Omit: h.DeliveryCount == 0}, - }) -} - -func (h *MessageHeader) Unmarshal(r *buffer.Buffer) error { - return encoding.UnmarshalComposite(r, encoding.TypeCodeMessageHeader, []encoding.UnmarshalField{ - {Field: &h.Durable}, - {Field: &h.Priority, HandleNull: func() error { h.Priority = 4; return nil }}, - {Field: (*encoding.Milliseconds)(&h.TTL)}, - {Field: &h.FirstAcquirer}, - {Field: &h.DeliveryCount}, - }...) -} - -/* - - - - - - - - - - - - - - - - -*/ - -// MessageProperties is the defined set of properties for AMQP messages. -type MessageProperties struct { - // Message-id, if set, uniquely identifies a message within the message system. - // The message producer is usually responsible for setting the message-id in - // such a way that it is assured to be globally unique. A broker MAY discard a - // message as a duplicate if the value of the message-id matches that of a - // previously received message sent to the same node. - // - // The value is restricted to the following types - // - uint64, UUID, []byte, or string - MessageID any - - // The identity of the user responsible for producing the message. - // The client sets this value, and it MAY be authenticated by intermediaries. - UserID []byte - - // The to field identifies the node that is the intended destination of the message. - // On any given transfer this might not be the node at the receiving end of the link. - To *string - - // A common field for summary information about the message content and purpose. - Subject *string - - // The address of the node to send replies to. - ReplyTo *string - - // This is a client-specific id that can be used to mark or identify messages - // between clients. - // - // The value is restricted to the following types - // - uint64, UUID, []byte, or string - CorrelationID any - - // The RFC-2046 [RFC2046] MIME type for the message's application-data section - // (body). As per RFC-2046 [RFC2046] this can contain a charset parameter defining - // the character encoding used: e.g., 'text/plain; charset="utf-8"'. - // - // For clarity, as per section 7.2.1 of RFC-2616 [RFC2616], where the content type - // is unknown the content-type SHOULD NOT be set. This allows the recipient the - // opportunity to determine the actual type. Where the section is known to be truly - // opaque binary data, the content-type SHOULD be set to application/octet-stream. - // - // When using an application-data section with a section code other than data, - // content-type SHOULD NOT be set. - ContentType *string - - // The content-encoding property is used as a modifier to the content-type. - // When present, its value indicates what additional content encodings have been - // applied to the application-data, and thus what decoding mechanisms need to be - // applied in order to obtain the media-type referenced by the content-type header - // field. - // - // Content-encoding is primarily used to allow a document to be compressed without - // losing the identity of its underlying content type. - // - // Content-encodings are to be interpreted as per section 3.5 of RFC 2616 [RFC2616]. - // Valid content-encodings are registered at IANA [IANAHTTPPARAMS]. - // - // The content-encoding MUST NOT be set when the application-data section is other - // than data. The binary representation of all other application-data section types - // is defined completely in terms of the AMQP type system. - // - // Implementations MUST NOT use the identity encoding. Instead, implementations - // SHOULD NOT set this property. Implementations SHOULD NOT use the compress encoding, - // except as to remain compatible with messages originally sent with other protocols, - // e.g. HTTP or SMTP. - // - // Implementations SHOULD NOT specify multiple content-encoding values except as to - // be compatible with messages originally sent with other protocols, e.g. HTTP or SMTP. - ContentEncoding *string - - // An absolute time when this message is considered to be expired. - AbsoluteExpiryTime *time.Time - - // An absolute time when this message was created. - CreationTime *time.Time - - // Identifies the group the message belongs to. - GroupID *string - - // The relative position of this message within its group. - // - // The value is defined as a RFC-1982 sequence number - GroupSequence *uint32 - - // This is a client-specific id that is used so that client can send replies to this - // message to a specific group. - ReplyToGroupID *string -} - -func (p *MessageProperties) Marshal(wr *buffer.Buffer) error { - return encoding.MarshalComposite(wr, encoding.TypeCodeMessageProperties, []encoding.MarshalField{ - {Value: p.MessageID, Omit: p.MessageID == nil}, - {Value: &p.UserID, Omit: len(p.UserID) == 0}, - {Value: p.To, Omit: p.To == nil}, - {Value: p.Subject, Omit: p.Subject == nil}, - {Value: p.ReplyTo, Omit: p.ReplyTo == nil}, - {Value: p.CorrelationID, Omit: p.CorrelationID == nil}, - {Value: (*encoding.Symbol)(p.ContentType), Omit: p.ContentType == nil}, - {Value: (*encoding.Symbol)(p.ContentEncoding), Omit: p.ContentEncoding == nil}, - {Value: p.AbsoluteExpiryTime, Omit: p.AbsoluteExpiryTime == nil}, - {Value: p.CreationTime, Omit: p.CreationTime == nil}, - {Value: p.GroupID, Omit: p.GroupID == nil}, - {Value: p.GroupSequence, Omit: p.GroupSequence == nil}, - {Value: p.ReplyToGroupID, Omit: p.ReplyToGroupID == nil}, - }) -} - -func (p *MessageProperties) Unmarshal(r *buffer.Buffer) error { - return encoding.UnmarshalComposite(r, encoding.TypeCodeMessageProperties, []encoding.UnmarshalField{ - {Field: &p.MessageID}, - {Field: &p.UserID}, - {Field: &p.To}, - {Field: &p.Subject}, - {Field: &p.ReplyTo}, - {Field: &p.CorrelationID}, - {Field: &p.ContentType}, - {Field: &p.ContentEncoding}, - {Field: &p.AbsoluteExpiryTime}, - {Field: &p.CreationTime}, - {Field: &p.GroupID}, - {Field: &p.GroupSequence}, - {Field: &p.ReplyToGroupID}, - }...) -} - -// Annotations keys must be of type string, int, or int64. -// -// String keys are encoded as AMQP Symbols. -type Annotations = encoding.Annotations - -// UUID is a 128 bit identifier as defined in RFC 4122. -type UUID = encoding.UUID diff --git a/sdk/messaging/azservicebus/internal/go-amqp/receiver.go b/sdk/messaging/azservicebus/internal/go-amqp/receiver.go deleted file mode 100644 index 8bcd7b293ca4..000000000000 --- a/sdk/messaging/azservicebus/internal/go-amqp/receiver.go +++ /dev/null @@ -1,897 +0,0 @@ -// Copyright (C) 2017 Kale Blankenship -// Portions Copyright (c) Microsoft Corporation - -package amqp - -import ( - "bytes" - "context" - "errors" - "fmt" - "sync" - - "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus/internal/go-amqp/internal/buffer" - "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus/internal/go-amqp/internal/debug" - "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus/internal/go-amqp/internal/encoding" - "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus/internal/go-amqp/internal/frames" - "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus/internal/go-amqp/internal/queue" -) - -// Default link options -const ( - defaultLinkCredit = 1 -) - -// Receiver receives messages on a single AMQP link. -type Receiver struct { - l link - - // message receiving - receiverReady chan struct{} // receiver sends on this when mux is paused to indicate it can handle more messages - messagesQ *queue.Holder[Message] // used to send completed messages to receiver - txDisposition chan frameBodyEnvelope // used to funnel disposition frames through the mux - - unsettledMessages map[string]struct{} // used to keep track of messages being handled downstream - unsettledMessagesLock sync.RWMutex // lock to protect concurrent access to unsettledMessages - msgBuf buffer.Buffer // buffered bytes for current message - more bool // if true, buf contains a partial message - msg Message // current message being decoded - - settlementCount uint32 // the count of settled messages - settlementCountMu sync.Mutex // must be held when accessing settlementCount - - autoSendFlow bool // automatically send flow frames as credit becomes available - inFlight inFlight // used to track message disposition when rcv-settle-mode == second - creditor creditor // manages credits via calls to IssueCredit/DrainCredit -} - -// IssueCredit adds credits to be requested in the next flow request. -// Attempting to issue more credit than the receiver's max credit as -// specified in ReceiverOptions.MaxCredit will result in an error. -func (r *Receiver) IssueCredit(credit uint32) error { - if r.autoSendFlow { - return errors.New("issueCredit can only be used with receiver links using manual credit management") - } - - if err := r.creditor.IssueCredit(credit); err != nil { - return err - } - - // cause mux() to check our flow conditions. - select { - case r.receiverReady <- struct{}{}: - default: - } - - return nil -} - -// Prefetched returns the next message that is stored in the Receiver's -// prefetch cache. It does NOT wait for the remote sender to send messages -// and returns immediately if the prefetch cache is empty. To receive from the -// prefetch and wait for messages from the remote Sender use `Receive`. -// -// Once a message is received, and if the sender is configured in any mode other -// than SenderSettleModeSettled, you *must* take an action on the message by calling -// one of the following: AcceptMessage, RejectMessage, ReleaseMessage, ModifyMessage. -func (r *Receiver) Prefetched() *Message { - select { - case r.receiverReady <- struct{}{}: - default: - } - - // non-blocking receive to ensure buffered messages are - // delivered regardless of whether the link has been closed. - q := r.messagesQ.Acquire() - msg := q.Dequeue() - r.messagesQ.Release(q) - - if msg == nil { - return nil - } - - debug.Log(3, "RX (Receiver %p): prefetched delivery ID %d", r, msg.deliveryID) - - if msg.settled { - r.onSettlement(1) - } - - return msg -} - -// ReceiveOptions contains any optional values for the Receiver.Receive method. -type ReceiveOptions struct { - // for future expansion -} - -// Receive returns the next message from the sender. -// Blocks until a message is received, ctx completes, or an error occurs. -// -// Once a message is received, and if the sender is configured in any mode other -// than SenderSettleModeSettled, you *must* take an action on the message by calling -// one of the following: AcceptMessage, RejectMessage, ReleaseMessage, ModifyMessage. -func (r *Receiver) Receive(ctx context.Context, opts *ReceiveOptions) (*Message, error) { - if msg := r.Prefetched(); msg != nil { - return msg, nil - } - - // wait for the next message - select { - case q := <-r.messagesQ.Wait(): - msg := q.Dequeue() - debug.Assert(msg != nil) - debug.Log(3, "RX (Receiver %p): received delivery ID %d", r, msg.deliveryID) - r.messagesQ.Release(q) - if msg.settled { - r.onSettlement(1) - } - return msg, nil - case <-r.l.done: - // if the link receives messages and is then closed between the above call to r.Prefetched() - // and this select statement, the order of selecting r.messages and r.l.done is undefined. - // however, once r.l.done is closed the link cannot receive any more messages. so be sure to - // drain any that might have trickled in within this window. - if msg := r.Prefetched(); msg != nil { - return msg, nil - } - return nil, r.l.doneErr - case <-ctx.Done(): - return nil, ctx.Err() - } -} - -// Accept notifies the server that the message has been accepted and does not require redelivery. -// - ctx controls waiting for the peer to acknowledge the disposition -// - msg is the message to accept -// -// If the context's deadline expires or is cancelled before the operation -// completes, the message's disposition is in an unknown state. -func (r *Receiver) AcceptMessage(ctx context.Context, msg *Message) error { - return r.messageDisposition(ctx, msg, &encoding.StateAccepted{}) -} - -// Reject notifies the server that the message is invalid. -// - ctx controls waiting for the peer to acknowledge the disposition -// - msg is the message to reject -// - e is an optional rejection error -// -// If the context's deadline expires or is cancelled before the operation -// completes, the message's disposition is in an unknown state. -func (r *Receiver) RejectMessage(ctx context.Context, msg *Message, e *Error) error { - return r.messageDisposition(ctx, msg, &encoding.StateRejected{Error: e}) -} - -// Release releases the message back to the server. The message may be redelivered to this or another consumer. -// - ctx controls waiting for the peer to acknowledge the disposition -// - msg is the message to release -// -// If the context's deadline expires or is cancelled before the operation -// completes, the message's disposition is in an unknown state. -func (r *Receiver) ReleaseMessage(ctx context.Context, msg *Message) error { - return r.messageDisposition(ctx, msg, &encoding.StateReleased{}) -} - -// Modify notifies the server that the message was not acted upon and should be modifed. -// - ctx controls waiting for the peer to acknowledge the disposition -// - msg is the message to modify -// - options contains the optional settings to modify -// -// If the context's deadline expires or is cancelled before the operation -// completes, the message's disposition is in an unknown state. -func (r *Receiver) ModifyMessage(ctx context.Context, msg *Message, options *ModifyMessageOptions) error { - if options == nil { - options = &ModifyMessageOptions{} - } - return r.messageDisposition(ctx, - msg, &encoding.StateModified{ - DeliveryFailed: options.DeliveryFailed, - UndeliverableHere: options.UndeliverableHere, - MessageAnnotations: options.Annotations, - }) -} - -// ModifyMessageOptions contains the optional parameters to ModifyMessage. -type ModifyMessageOptions struct { - // DeliveryFailed indicates that the server must consider this an - // unsuccessful delivery attempt and increment the delivery count. - DeliveryFailed bool - - // UndeliverableHere indicates that the server must not redeliver - // the message to this link. - UndeliverableHere bool - - // Annotations is an optional annotation map to be merged - // with the existing message annotations, overwriting existing keys - // if necessary. - Annotations Annotations -} - -// Address returns the link's address. -func (r *Receiver) Address() string { - if r.l.source == nil { - return "" - } - return r.l.source.Address -} - -// LinkName returns associated link name or an empty string if link is not defined. -func (r *Receiver) LinkName() string { - return r.l.key.name -} - -// LinkSourceFilterValue retrieves the specified link source filter value or nil if it doesn't exist. -func (r *Receiver) LinkSourceFilterValue(name string) any { - if r.l.source == nil { - return nil - } - filter, ok := r.l.source.Filter[encoding.Symbol(name)] - if !ok { - return nil - } - return filter.Value -} - -// Close closes the Receiver and AMQP link. -// - ctx controls waiting for the peer to acknowledge the close -// -// If the context's deadline expires or is cancelled before the operation -// completes, an error is returned. However, the operation will continue to -// execute in the background. Subsequent calls will return a *LinkError -// that contains the context's error message. -func (r *Receiver) Close(ctx context.Context) error { - return r.l.closeLink(ctx) -} - -// sendDisposition sends a disposition frame to the peer -func (r *Receiver) sendDisposition(ctx context.Context, first uint32, last *uint32, state encoding.DeliveryState) error { - fr := &frames.PerformDisposition{ - Role: encoding.RoleReceiver, - First: first, - Last: last, - Settled: r.l.receiverSettleMode == nil || *r.l.receiverSettleMode == ReceiverSettleModeFirst, - State: state, - } - - sent := make(chan error, 1) - select { - case r.txDisposition <- frameBodyEnvelope{Ctx: ctx, FrameBody: fr, Sent: sent}: - debug.Log(2, "TX (Receiver %p): mux txDisposition %s", r, fr) - case <-r.l.done: - return r.l.doneErr - } - - select { - case err := <-sent: - return err - case <-r.l.done: - return r.l.doneErr - } -} - -func (r *Receiver) messageDisposition(ctx context.Context, msg *Message, state encoding.DeliveryState) error { - if msg.settled { - return nil - } - - // NOTE: we MUST add to the in-flight map before sending the disposition. if not, it's possible - // to receive the ack'ing disposition frame *before* the in-flight map has been updated which - // will cause the below <-wait to never trigger. - - var wait chan error - if r.l.receiverSettleMode != nil && *r.l.receiverSettleMode == ReceiverSettleModeSecond { - debug.Log(3, "TX (Receiver %p): delivery ID %d is in flight", r, msg.deliveryID) - wait = r.inFlight.add(msg) - } - - if err := r.sendDisposition(ctx, msg.deliveryID, nil, state); err != nil { - return err - } - - if wait == nil { - // mode first, there will be no settlement ack - r.deleteUnsettled(msg) - r.onSettlement(1) - return nil - } - - select { - case err := <-wait: - // err has three possibilities - // - nil, meaning the peer acknowledged the settlement - // - an *Error, meaning the peer rejected the message with a provided error - // - a non-AMQP error. this comes from calls to inFlight.clear() during mux unwind. - // only for the first two cases is the message considered settled - - if amqpErr := (&Error{}); err == nil || errors.As(err, &amqpErr) { - debug.Log(3, "RX (Receiver %p): delivery ID %d has been settled", r, msg.deliveryID) - // we've received confirmation of disposition - return err - } - - debug.Log(3, "RX (Receiver %p): error settling delivery ID %d: %v", r, msg.deliveryID, err) - return err - - case <-ctx.Done(): - // didn't receive the ack in the time allotted, leave message as unsettled - // TODO: if the ack arrives later, we need to remove the message from the unsettled map and reclaim the credit - return ctx.Err() - } -} - -// onSettlement is to be called after message settlement. -// - count is the number of messages that were settled -func (r *Receiver) onSettlement(count uint32) { - if !r.autoSendFlow { - return - } - - r.settlementCountMu.Lock() - r.settlementCount += count - r.settlementCountMu.Unlock() - - select { - case r.receiverReady <- struct{}{}: - // woke up - default: - // wake pending - } -} - -func (r *Receiver) addUnsettled(msg *Message) { - r.unsettledMessagesLock.Lock() - r.unsettledMessages[string(msg.DeliveryTag)] = struct{}{} - r.unsettledMessagesLock.Unlock() -} - -func (r *Receiver) deleteUnsettled(msg *Message) { - r.unsettledMessagesLock.Lock() - delete(r.unsettledMessages, string(msg.DeliveryTag)) - r.unsettledMessagesLock.Unlock() -} - -func (r *Receiver) countUnsettled() int { - r.unsettledMessagesLock.RLock() - count := len(r.unsettledMessages) - r.unsettledMessagesLock.RUnlock() - return count -} - -func newReceiver(source string, session *Session, opts *ReceiverOptions) (*Receiver, error) { - l := newLink(session, encoding.RoleReceiver) - l.source = &frames.Source{Address: source} - l.target = new(frames.Target) - l.linkCredit = defaultLinkCredit - r := &Receiver{ - l: l, - autoSendFlow: true, - receiverReady: make(chan struct{}, 1), - txDisposition: make(chan frameBodyEnvelope), - } - - r.messagesQ = queue.NewHolder(queue.New[Message](int(session.incomingWindow))) - - if opts == nil { - return r, nil - } - - for _, v := range opts.Capabilities { - r.l.target.Capabilities = append(r.l.target.Capabilities, encoding.Symbol(v)) - } - if opts.Credit > 0 { - r.l.linkCredit = uint32(opts.Credit) - } else if opts.Credit < 0 { - r.l.linkCredit = 0 - r.autoSendFlow = false - } - if opts.Durability > DurabilityUnsettledState { - return nil, fmt.Errorf("invalid Durability %d", opts.Durability) - } - r.l.target.Durable = opts.Durability - if opts.DynamicAddress { - r.l.source.Address = "" - r.l.dynamicAddr = opts.DynamicAddress - } - if opts.ExpiryPolicy != "" { - if err := encoding.ValidateExpiryPolicy(opts.ExpiryPolicy); err != nil { - return nil, err - } - r.l.target.ExpiryPolicy = opts.ExpiryPolicy - } - r.l.target.Timeout = opts.ExpiryTimeout - if opts.Filters != nil { - r.l.source.Filter = make(encoding.Filter) - for _, f := range opts.Filters { - f(r.l.source.Filter) - } - } - if opts.MaxMessageSize > 0 { - r.l.maxMessageSize = opts.MaxMessageSize - } - if opts.Name != "" { - r.l.key.name = opts.Name - } - if opts.Properties != nil { - r.l.properties = make(map[encoding.Symbol]any) - for k, v := range opts.Properties { - if k == "" { - return nil, errors.New("link property key must not be empty") - } - r.l.properties[encoding.Symbol(k)] = v - } - } - if opts.RequestedSenderSettleMode != nil { - if rsm := *opts.RequestedSenderSettleMode; rsm > SenderSettleModeMixed { - return nil, fmt.Errorf("invalid RequestedSenderSettleMode %d", rsm) - } - r.l.senderSettleMode = opts.RequestedSenderSettleMode - } - if opts.SettlementMode != nil { - if rsm := *opts.SettlementMode; rsm > ReceiverSettleModeSecond { - return nil, fmt.Errorf("invalid SettlementMode %d", rsm) - } - r.l.receiverSettleMode = opts.SettlementMode - } - r.l.target.Address = opts.TargetAddress - for _, v := range opts.SourceCapabilities { - r.l.source.Capabilities = append(r.l.source.Capabilities, encoding.Symbol(v)) - } - if opts.SourceDurability != DurabilityNone { - r.l.source.Durable = opts.SourceDurability - } - if opts.SourceExpiryPolicy != ExpiryPolicySessionEnd { - r.l.source.ExpiryPolicy = opts.SourceExpiryPolicy - } - if opts.SourceExpiryTimeout != 0 { - r.l.source.Timeout = opts.SourceExpiryTimeout - } - return r, nil -} - -// attach sends the Attach performative to establish the link with its parent session. -// this is automatically called by the new*Link constructors. -func (r *Receiver) attach(ctx context.Context) error { - if err := r.l.attach(ctx, func(pa *frames.PerformAttach) { - pa.Role = encoding.RoleReceiver - if pa.Source == nil { - pa.Source = new(frames.Source) - } - pa.Source.Dynamic = r.l.dynamicAddr - }, func(pa *frames.PerformAttach) { - if r.l.source == nil { - r.l.source = new(frames.Source) - } - // if dynamic address requested, copy assigned name to address - if r.l.dynamicAddr && pa.Source != nil { - r.l.source.Address = pa.Source.Address - } - // deliveryCount is a sequence number, must initialize to sender's initial sequence number - r.l.deliveryCount = pa.InitialDeliveryCount - r.unsettledMessages = map[string]struct{}{} - // copy the received filter values - if pa.Source != nil { - r.l.source.Filter = pa.Source.Filter - } - }); err != nil { - return err - } - - return nil -} - -func nop() {} - -type receiverTestHooks struct { - MuxStart func() - MuxSelect func() -} - -func (r *Receiver) mux(hooks receiverTestHooks) { - if hooks.MuxSelect == nil { - hooks.MuxSelect = nop - } - if hooks.MuxStart == nil { - hooks.MuxStart = nop - } - - defer func() { - // unblock any in flight message dispositions - r.inFlight.clear(r.l.doneErr) - - if !r.autoSendFlow { - // unblock any pending drain requests - r.creditor.EndDrain() - } - - close(r.l.done) - }() - - hooks.MuxStart() - - if r.autoSendFlow { - r.l.doneErr = r.muxFlow(r.l.linkCredit, false) - } - - for { - msgLen := r.messagesQ.Len() - - r.settlementCountMu.Lock() - // counter that accumulates the settled delivery count. - // once the threshold has been reached, the counter is - // reset and a flow frame is sent. - previousSettlementCount := r.settlementCount - if previousSettlementCount >= r.l.linkCredit { - r.settlementCount = 0 - } - r.settlementCountMu.Unlock() - - // once we have pending credit equal to or greater than our available credit, reclaim it. - // we do this instead of settlementCount > 0 to prevent flow frames from being too chatty. - // NOTE: we compare the settlementCount against the current link credit instead of some - // fixed threshold to ensure credit is reclaimed in cases where the number of unsettled - // messages remains high for whatever reason. - if r.autoSendFlow && previousSettlementCount > 0 && previousSettlementCount >= r.l.linkCredit { - debug.Log(1, "RX (Receiver %p) (auto): source: %q, inflight: %d, linkCredit: %d, deliveryCount: %d, messages: %d, unsettled: %d, settlementCount: %d, settleMode: %s", - r, r.l.source.Address, r.inFlight.len(), r.l.linkCredit, r.l.deliveryCount, msgLen, r.countUnsettled(), previousSettlementCount, r.l.receiverSettleMode.String()) - r.l.doneErr = r.creditor.IssueCredit(previousSettlementCount) - } else if r.l.linkCredit == 0 { - debug.Log(1, "RX (Receiver %p) (pause): source: %q, inflight: %d, linkCredit: %d, deliveryCount: %d, messages: %d, unsettled: %d, settlementCount: %d, settleMode: %s", - r, r.l.source.Address, r.inFlight.len(), r.l.linkCredit, r.l.deliveryCount, msgLen, r.countUnsettled(), previousSettlementCount, r.l.receiverSettleMode.String()) - } - - if r.l.doneErr != nil { - return - } - - drain, credits := r.creditor.FlowBits(r.l.linkCredit) - if drain || credits > 0 { - debug.Log(1, "RX (Receiver %p) (flow): source: %q, inflight: %d, curLinkCredit: %d, newLinkCredit: %d, drain: %v, deliveryCount: %d, messages: %d, unsettled: %d, settlementCount: %d, settleMode: %s", - r, r.l.source.Address, r.inFlight.len(), r.l.linkCredit, credits, drain, r.l.deliveryCount, msgLen, r.countUnsettled(), previousSettlementCount, r.l.receiverSettleMode.String()) - - // send a flow frame. - r.l.doneErr = r.muxFlow(credits, drain) - } - - if r.l.doneErr != nil { - return - } - - txDisposition := r.txDisposition - closed := r.l.close - if r.l.closeInProgress { - // swap out channel so it no longer triggers - closed = nil - - // disable sending of disposition frames once closing is in progress. - // this is to prevent races between mux shutdown and clearing of - // any in-flight dispositions. - txDisposition = nil - } - - hooks.MuxSelect() - - select { - case q := <-r.l.rxQ.Wait(): - // populated queue - fr := *q.Dequeue() - r.l.rxQ.Release(q) - - // if muxHandleFrame returns an error it means the mux must terminate. - // note that in the case of a client-side close due to an error, nil - // is returned in order to keep the mux running to ack the detach frame. - if err := r.muxHandleFrame(fr); err != nil { - r.l.doneErr = err - return - } - - case env := <-txDisposition: - r.l.txFrame(env.Ctx, env.FrameBody, env.Sent) - - case <-r.receiverReady: - continue - - case <-closed: - if r.l.closeInProgress { - // a client-side close due to protocol error is in progress - continue - } - - // receiver is being closed by the client - r.l.closeInProgress = true - fr := &frames.PerformDetach{ - Handle: r.l.handle, - Closed: true, - } - r.l.txFrame(context.Background(), fr, nil) - - case <-r.l.session.done: - r.l.doneErr = r.l.session.doneErr - return - } - } -} - -// muxFlow sends tr to the session mux. -// l.linkCredit will also be updated to `linkCredit` -func (r *Receiver) muxFlow(linkCredit uint32, drain bool) error { - var ( - deliveryCount = r.l.deliveryCount - ) - - fr := &frames.PerformFlow{ - Handle: &r.l.handle, - DeliveryCount: &deliveryCount, - LinkCredit: &linkCredit, // max number of messages, - Drain: drain, - } - - // Update credit. This must happen before entering loop below - // because incoming messages handled while waiting to transmit - // flow increment deliveryCount. This causes the credit to become - // out of sync with the server. - - if !drain { - // if we're draining we don't want to touch our internal credit - we're not changing it so any issued credits - // are still valid until drain completes, at which point they will be naturally zeroed. - r.l.linkCredit = linkCredit - } - - select { - case r.l.session.tx <- frameBodyEnvelope{Ctx: context.Background(), FrameBody: fr}: - debug.Log(2, "TX (Receiver %p): mux frame to Session (%p): %d, %s", r, r.l.session, r.l.session.channel, fr) - return nil - case <-r.l.close: - return nil - case <-r.l.session.done: - return r.l.session.doneErr - } -} - -// muxHandleFrame processes fr based on type. -func (r *Receiver) muxHandleFrame(fr frames.FrameBody) error { - debug.Log(2, "RX (Receiver %p): %s", r, fr) - switch fr := fr.(type) { - // message frame - case *frames.PerformTransfer: - r.muxReceive(*fr) - - // flow control frame - case *frames.PerformFlow: - if !fr.Echo { - // if the 'drain' flag has been set in the frame sent to the _receiver_ then - // we signal whomever is waiting (the service has seen and acknowledged our drain) - if fr.Drain && !r.autoSendFlow { - r.l.linkCredit = 0 // we have no active credits at this point. - r.creditor.EndDrain() - } - return nil - } - - var ( - // copy because sent by pointer below; prevent race - linkCredit = r.l.linkCredit - deliveryCount = r.l.deliveryCount - ) - - // send flow - resp := &frames.PerformFlow{ - Handle: &r.l.handle, - DeliveryCount: &deliveryCount, - LinkCredit: &linkCredit, // max number of messages - } - - select { - case r.l.session.tx <- frameBodyEnvelope{Ctx: context.Background(), FrameBody: resp}: - debug.Log(2, "TX (Receiver %p): mux frame to Session (%p): %d, %s", r, r.l.session, r.l.session.channel, resp) - case <-r.l.close: - return nil - case <-r.l.session.done: - return r.l.session.doneErr - } - - case *frames.PerformDisposition: - // Unblock receivers waiting for message disposition - // bubble disposition error up to the receiver - var dispositionError error - if state, ok := fr.State.(*encoding.StateRejected); ok { - // state.Error isn't required to be filled out. For instance if you dead letter a message - // you will get a rejected response that doesn't contain an error. - if state.Error != nil { - dispositionError = state.Error - } - } - // removal from the in-flight map will also remove the message from the unsettled map - count := r.inFlight.remove(fr.First, fr.Last, dispositionError, func(msg *Message) { - r.deleteUnsettled(msg) - msg.settled = true - }) - r.onSettlement(count) - - default: - return r.l.muxHandleFrame(fr) - } - - return nil -} - -func (r *Receiver) muxReceive(fr frames.PerformTransfer) { - if !r.more { - // this is the first transfer of a message, - // record the delivery ID, message format, - // and delivery Tag - if fr.DeliveryID != nil { - r.msg.deliveryID = *fr.DeliveryID - } - if fr.MessageFormat != nil { - r.msg.Format = *fr.MessageFormat - } - r.msg.DeliveryTag = fr.DeliveryTag - - // these fields are required on first transfer of a message - if fr.DeliveryID == nil { - r.l.closeWithError(ErrCondNotAllowed, "received message without a delivery-id") - return - } - if fr.MessageFormat == nil { - r.l.closeWithError(ErrCondNotAllowed, "received message without a message-format") - return - } - if fr.DeliveryTag == nil { - r.l.closeWithError(ErrCondNotAllowed, "received message without a delivery-tag") - return - } - } else { - // this is a continuation of a multipart message - // some fields may be omitted on continuation transfers, - // but if they are included they must be consistent - // with the first. - - if fr.DeliveryID != nil && *fr.DeliveryID != r.msg.deliveryID { - msg := fmt.Sprintf( - "received continuation transfer with inconsistent delivery-id: %d != %d", - *fr.DeliveryID, r.msg.deliveryID, - ) - r.l.closeWithError(ErrCondNotAllowed, msg) - return - } - if fr.MessageFormat != nil && *fr.MessageFormat != r.msg.Format { - msg := fmt.Sprintf( - "received continuation transfer with inconsistent message-format: %d != %d", - *fr.MessageFormat, r.msg.Format, - ) - r.l.closeWithError(ErrCondNotAllowed, msg) - return - } - if fr.DeliveryTag != nil && !bytes.Equal(fr.DeliveryTag, r.msg.DeliveryTag) { - msg := fmt.Sprintf( - "received continuation transfer with inconsistent delivery-tag: %q != %q", - fr.DeliveryTag, r.msg.DeliveryTag, - ) - r.l.closeWithError(ErrCondNotAllowed, msg) - return - } - } - - // discard message if it's been aborted - if fr.Aborted { - r.msgBuf.Reset() - r.msg = Message{} - r.more = false - return - } - - // ensure maxMessageSize will not be exceeded - if r.l.maxMessageSize != 0 && uint64(r.msgBuf.Len())+uint64(len(fr.Payload)) > r.l.maxMessageSize { - r.l.closeWithError(ErrCondMessageSizeExceeded, fmt.Sprintf("received message larger than max size of %d", r.l.maxMessageSize)) - return - } - - // add the payload the the buffer - r.msgBuf.Append(fr.Payload) - - // mark as settled if at least one frame is settled - r.msg.settled = r.msg.settled || fr.Settled - - // save in-progress status - r.more = fr.More - - if fr.More { - return - } - - // last frame in message - err := r.msg.Unmarshal(&r.msgBuf) - if err != nil { - r.l.closeWithError(ErrCondInternalError, err.Error()) - return - } - - // send to receiver - if !r.msg.settled { - r.addUnsettled(&r.msg) - debug.Log(3, "RX (Receiver %p): add unsettled delivery ID %d", r, r.msg.deliveryID) - } - - q := r.messagesQ.Acquire() - q.Enqueue(r.msg) - msgLen := q.Len() - r.messagesQ.Release(q) - - // reset progress - r.msgBuf.Reset() - r.msg = Message{} - - // decrement link-credit after entire message received - r.l.deliveryCount++ - r.l.linkCredit-- - debug.Log(3, "RX (Receiver %p) link %s - deliveryCount: %d, linkCredit: %d, len(messages): %d", r, r.l.key.name, r.l.deliveryCount, r.l.linkCredit, msgLen) -} - -// inFlight tracks in-flight message dispositions allowing receivers -// to block waiting for the server to respond when an appropriate -// settlement mode is configured. -type inFlight struct { - mu sync.RWMutex - m map[uint32]inFlightInfo -} - -type inFlightInfo struct { - wait chan error - msg *Message -} - -func (f *inFlight) add(msg *Message) chan error { - wait := make(chan error, 1) - - f.mu.Lock() - if f.m == nil { - f.m = make(map[uint32]inFlightInfo) - } - - f.m[msg.deliveryID] = inFlightInfo{wait: wait, msg: msg} - f.mu.Unlock() - - return wait -} - -func (f *inFlight) remove(first uint32, last *uint32, err error, handler func(*Message)) uint32 { - f.mu.Lock() - - if f.m == nil { - f.mu.Unlock() - return 0 - } - - ll := first - if last != nil { - ll = *last - } - - count := uint32(0) - for i := first; i <= ll; i++ { - info, ok := f.m[i] - if ok { - handler(info.msg) - info.wait <- err - delete(f.m, i) - count++ - } - } - - f.mu.Unlock() - return count -} - -func (f *inFlight) clear(err error) { - f.mu.Lock() - for id, info := range f.m { - info.wait <- err - delete(f.m, id) - } - f.mu.Unlock() -} - -func (f *inFlight) len() int { - f.mu.RLock() - defer f.mu.RUnlock() - return len(f.m) -} diff --git a/sdk/messaging/azservicebus/internal/go-amqp/sasl.go b/sdk/messaging/azservicebus/internal/go-amqp/sasl.go deleted file mode 100644 index c50ecdcbd83e..000000000000 --- a/sdk/messaging/azservicebus/internal/go-amqp/sasl.go +++ /dev/null @@ -1,262 +0,0 @@ -// Copyright (C) 2017 Kale Blankenship -// Portions Copyright (c) Microsoft Corporation - -package amqp - -import ( - "context" - "fmt" - - "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus/internal/go-amqp/internal/debug" - "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus/internal/go-amqp/internal/encoding" - "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus/internal/go-amqp/internal/frames" -) - -// SASL Mechanisms -const ( - saslMechanismPLAIN encoding.Symbol = "PLAIN" - saslMechanismANONYMOUS encoding.Symbol = "ANONYMOUS" - saslMechanismEXTERNAL encoding.Symbol = "EXTERNAL" - saslMechanismXOAUTH2 encoding.Symbol = "XOAUTH2" -) - -// SASLType represents a SASL configuration to use during authentication. -type SASLType func(c *Conn) error - -// ConnSASLPlain enables SASL PLAIN authentication for the connection. -// -// SASL PLAIN transmits credentials in plain text and should only be used -// on TLS/SSL enabled connection. -func SASLTypePlain(username, password string) SASLType { - // TODO: how widely used is hostname? should it be supported - return func(c *Conn) error { - // make handlers map if no other mechanism has - if c.saslHandlers == nil { - c.saslHandlers = make(map[encoding.Symbol]stateFunc) - } - - // add the handler the the map - c.saslHandlers[saslMechanismPLAIN] = func(ctx context.Context) (stateFunc, error) { - // send saslInit with PLAIN payload - init := &frames.SASLInit{ - Mechanism: "PLAIN", - InitialResponse: []byte("\x00" + username + "\x00" + password), - Hostname: "", - } - fr := frames.Frame{ - Type: frames.TypeSASL, - Body: init, - } - debug.Log(1, "TX (ConnSASLPlain %p): %s", c, fr) - timeout, err := c.getWriteTimeout(ctx) - if err != nil { - return nil, err - } - if err = c.writeFrame(timeout, fr); err != nil { - return nil, err - } - - // go to c.saslOutcome to handle the server response - return c.saslOutcome, nil - } - return nil - } -} - -// ConnSASLAnonymous enables SASL ANONYMOUS authentication for the connection. -func SASLTypeAnonymous() SASLType { - return func(c *Conn) error { - // make handlers map if no other mechanism has - if c.saslHandlers == nil { - c.saslHandlers = make(map[encoding.Symbol]stateFunc) - } - - // add the handler the the map - c.saslHandlers[saslMechanismANONYMOUS] = func(ctx context.Context) (stateFunc, error) { - init := &frames.SASLInit{ - Mechanism: saslMechanismANONYMOUS, - InitialResponse: []byte("anonymous"), - } - fr := frames.Frame{ - Type: frames.TypeSASL, - Body: init, - } - debug.Log(1, "TX (ConnSASLAnonymous %p): %s", c, fr) - timeout, err := c.getWriteTimeout(ctx) - if err != nil { - return nil, err - } - if err = c.writeFrame(timeout, fr); err != nil { - return nil, err - } - - // go to c.saslOutcome to handle the server response - return c.saslOutcome, nil - } - return nil - } -} - -// ConnSASLExternal enables SASL EXTERNAL authentication for the connection. -// The value for resp is dependent on the type of authentication (empty string is common for TLS). -// See https://datatracker.ietf.org/doc/html/rfc4422#appendix-A for additional info. -func SASLTypeExternal(resp string) SASLType { - return func(c *Conn) error { - // make handlers map if no other mechanism has - if c.saslHandlers == nil { - c.saslHandlers = make(map[encoding.Symbol]stateFunc) - } - - // add the handler the the map - c.saslHandlers[saslMechanismEXTERNAL] = func(ctx context.Context) (stateFunc, error) { - init := &frames.SASLInit{ - Mechanism: saslMechanismEXTERNAL, - InitialResponse: []byte(resp), - } - fr := frames.Frame{ - Type: frames.TypeSASL, - Body: init, - } - debug.Log(1, "TX (ConnSASLExternal %p): %s", c, fr) - timeout, err := c.getWriteTimeout(ctx) - if err != nil { - return nil, err - } - if err = c.writeFrame(timeout, fr); err != nil { - return nil, err - } - - // go to c.saslOutcome to handle the server response - return c.saslOutcome, nil - } - return nil - } -} - -// ConnSASLXOAUTH2 enables SASL XOAUTH2 authentication for the connection. -// -// The saslMaxFrameSizeOverride parameter allows the limit that governs the maximum frame size this client will allow -// itself to generate to be raised for the sasl-init frame only. Set this when the size of the size of the SASL XOAUTH2 -// initial client response (which contains the username and bearer token) would otherwise breach the 512 byte min-max-frame-size -// (http://docs.oasis-open.org/amqp/core/v1.0/os/amqp-core-transport-v1.0-os.html#definition-MIN-MAX-FRAME-SIZE). Pass -1 -// to keep the default. -// -// SASL XOAUTH2 transmits the bearer in plain text and should only be used -// on TLS/SSL enabled connection. -func SASLTypeXOAUTH2(username, bearer string, saslMaxFrameSizeOverride uint32) SASLType { - return func(c *Conn) error { - // make handlers map if no other mechanism has - if c.saslHandlers == nil { - c.saslHandlers = make(map[encoding.Symbol]stateFunc) - } - - response, err := saslXOAUTH2InitialResponse(username, bearer) - if err != nil { - return err - } - - handler := saslXOAUTH2Handler{ - conn: c, - maxFrameSizeOverride: saslMaxFrameSizeOverride, - response: response, - } - // add the handler the the map - c.saslHandlers[saslMechanismXOAUTH2] = handler.init - return nil - } -} - -type saslXOAUTH2Handler struct { - conn *Conn - maxFrameSizeOverride uint32 - response []byte - errorResponse []byte // https://developers.google.com/gmail/imap/xoauth2-protocol#error_response -} - -func (s saslXOAUTH2Handler) init(ctx context.Context) (stateFunc, error) { - originalPeerMaxFrameSize := s.conn.peerMaxFrameSize - if s.maxFrameSizeOverride > s.conn.peerMaxFrameSize { - s.conn.peerMaxFrameSize = s.maxFrameSizeOverride - } - timeout, err := s.conn.getWriteTimeout(ctx) - if err != nil { - return nil, err - } - err = s.conn.writeFrame(timeout, frames.Frame{ - Type: frames.TypeSASL, - Body: &frames.SASLInit{ - Mechanism: saslMechanismXOAUTH2, - InitialResponse: s.response, - }, - }) - s.conn.peerMaxFrameSize = originalPeerMaxFrameSize - if err != nil { - return nil, err - } - - return s.step, nil -} - -func (s saslXOAUTH2Handler) step(ctx context.Context) (stateFunc, error) { - // read challenge or outcome frame - fr, err := s.conn.readFrame() - if err != nil { - return nil, err - } - - switch v := fr.Body.(type) { - case *frames.SASLOutcome: - // check if auth succeeded - if v.Code != encoding.CodeSASLOK { - return nil, fmt.Errorf("SASL XOAUTH2 auth failed with code %#00x: %s : %s", - v.Code, v.AdditionalData, s.errorResponse) - } - - // return to c.negotiateProto - s.conn.saslComplete = true - return s.conn.negotiateProto, nil - case *frames.SASLChallenge: - if s.errorResponse == nil { - s.errorResponse = v.Challenge - - timeout, err := s.conn.getWriteTimeout(ctx) - if err != nil { - return nil, err - } - - // The SASL protocol requires clients to send an empty response to this challenge. - err = s.conn.writeFrame(timeout, frames.Frame{ - Type: frames.TypeSASL, - Body: &frames.SASLResponse{ - Response: []byte{}, - }, - }) - if err != nil { - return nil, err - } - return s.step, nil - } else { - return nil, fmt.Errorf("SASL XOAUTH2 unexpected additional error response received during "+ - "exchange. Initial error response: %s, additional response: %s", s.errorResponse, v.Challenge) - } - default: - return nil, fmt.Errorf("sasl: unexpected frame type %T", fr.Body) - } -} - -func saslXOAUTH2InitialResponse(username string, bearer string) ([]byte, error) { - if len(bearer) == 0 { - return []byte{}, fmt.Errorf("unacceptable bearer token") - } - for _, char := range bearer { - if char < '\x20' || char > '\x7E' { - return []byte{}, fmt.Errorf("unacceptable bearer token") - } - } - for _, char := range username { - if char == '\x01' { - return []byte{}, fmt.Errorf("unacceptable username") - } - } - return []byte("user=" + username + "\x01auth=Bearer " + bearer + "\x01\x01"), nil -} diff --git a/sdk/messaging/azservicebus/internal/go-amqp/sender.go b/sdk/messaging/azservicebus/internal/go-amqp/sender.go deleted file mode 100644 index dcfb4dc557be..000000000000 --- a/sdk/messaging/azservicebus/internal/go-amqp/sender.go +++ /dev/null @@ -1,476 +0,0 @@ -// Copyright (C) 2017 Kale Blankenship -// Portions Copyright (c) Microsoft Corporation - -package amqp - -import ( - "context" - "encoding/binary" - "errors" - "fmt" - "sync" - - "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus/internal/go-amqp/internal/buffer" - "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus/internal/go-amqp/internal/debug" - "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus/internal/go-amqp/internal/encoding" - "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus/internal/go-amqp/internal/frames" -) - -// Sender sends messages on a single AMQP link. -type Sender struct { - l link - transfers chan transferEnvelope // sender uses to send transfer frames - - mu sync.Mutex // protects buf and nextDeliveryTag - buf buffer.Buffer - nextDeliveryTag uint64 -} - -// LinkName() is the name of the link used for this Sender. -func (s *Sender) LinkName() string { - return s.l.key.name -} - -// MaxMessageSize is the maximum size of a single message. -func (s *Sender) MaxMessageSize() uint64 { - return s.l.maxMessageSize -} - -// SendOptions contains any optional values for the Sender.Send method. -type SendOptions struct { - // Indicates the message is to be sent as settled when settlement mode is SenderSettleModeMixed. - // If the settlement mode is SenderSettleModeUnsettled and Settled is true, an error is returned. - Settled bool -} - -// Send sends a Message. -// -// Blocks until the message is sent or an error occurs. If the peer is -// configured for receiver settlement mode second, the call also blocks -// until the peer confirms message settlement. -// -// - ctx controls waiting for the message to be sent and possibly confirmed -// - msg is the message to send -// - opts contains optional values, pass nil to accept the defaults -// -// If the context's deadline expires or is cancelled before the operation -// completes, the message is in an unknown state of transmission. -// -// Send is safe for concurrent use. Since only a single message can be -// sent on a link at a time, this is most useful when settlement confirmation -// has been requested (receiver settle mode is second). In this case, -// additional messages can be sent while the current goroutine is waiting -// for the confirmation. -func (s *Sender) Send(ctx context.Context, msg *Message, opts *SendOptions) error { - // check if the link is dead. while it's safe to call s.send - // in this case, this will avoid some allocations etc. - select { - case <-s.l.done: - return s.l.doneErr - default: - // link is still active - } - done, err := s.send(ctx, msg, opts) - if err != nil { - return err - } - - // wait for transfer to be confirmed - select { - case state := <-done: - if state, ok := state.(*encoding.StateRejected); ok { - if state.Error != nil { - return state.Error - } - return errors.New("the peer rejected the message without specifying an error") - } - return nil - case <-s.l.done: - return s.l.doneErr - case <-ctx.Done(): - // TODO: if the message is not settled and we never received a disposition, how can we consider the message as sent? - return ctx.Err() - } -} - -// send is separated from Send so that the mutex unlock can be deferred without -// locking the transfer confirmation that happens in Send. -func (s *Sender) send(ctx context.Context, msg *Message, opts *SendOptions) (chan encoding.DeliveryState, error) { - const ( - maxDeliveryTagLength = 32 - maxTransferFrameHeader = 66 // determined by calcMaxTransferFrameHeader - ) - if len(msg.DeliveryTag) > maxDeliveryTagLength { - return nil, fmt.Errorf("delivery tag is over the allowed %v bytes, len: %v", maxDeliveryTagLength, len(msg.DeliveryTag)) - } - - s.mu.Lock() - defer s.mu.Unlock() - - s.buf.Reset() - err := msg.Marshal(&s.buf) - if err != nil { - return nil, err - } - - if s.l.maxMessageSize != 0 && uint64(s.buf.Len()) > s.l.maxMessageSize { - return nil, fmt.Errorf("encoded message size exceeds max of %d", s.l.maxMessageSize) - } - - senderSettled := senderSettleModeValue(s.l.senderSettleMode) == SenderSettleModeSettled - if opts != nil { - if opts.Settled && senderSettleModeValue(s.l.senderSettleMode) == SenderSettleModeUnsettled { - return nil, errors.New("can't send message as settled when sender settlement mode is unsettled") - } else if opts.Settled { - senderSettled = true - } - } - - var ( - maxPayloadSize = int64(s.l.session.conn.peerMaxFrameSize) - maxTransferFrameHeader - ) - - deliveryTag := msg.DeliveryTag - if len(deliveryTag) == 0 { - // use uint64 encoded as []byte as deliveryTag - deliveryTag = make([]byte, 8) - binary.BigEndian.PutUint64(deliveryTag, s.nextDeliveryTag) - s.nextDeliveryTag++ - } - - fr := frames.PerformTransfer{ - Handle: s.l.handle, - DeliveryID: &needsDeliveryID, - DeliveryTag: deliveryTag, - MessageFormat: &msg.Format, - More: s.buf.Len() > 0, - } - - for fr.More { - buf, _ := s.buf.Next(maxPayloadSize) - fr.Payload = append([]byte(nil), buf...) - fr.More = s.buf.Len() > 0 - if !fr.More { - // SSM=settled: overrides RSM; no acks. - // SSM=unsettled: sender should wait for receiver to ack - // RSM=first: receiver considers it settled immediately, but must still send ack (SSM=unsettled only) - // RSM=second: receiver sends ack and waits for return ack from sender (SSM=unsettled only) - - // mark final transfer as settled when sender mode is settled - fr.Settled = senderSettled - - // set done on last frame - fr.Done = make(chan encoding.DeliveryState, 1) - } - - // NOTE: we MUST send a copy of fr here since we modify it post send - - sent := make(chan error, 1) - select { - case s.transfers <- transferEnvelope{Ctx: ctx, Frame: fr, Sent: sent}: - // frame was sent to our mux - case <-s.l.done: - return nil, s.l.doneErr - case <-ctx.Done(): - return nil, &Error{Condition: ErrCondTransferLimitExceeded, Description: fmt.Sprintf("credit limit exceeded for sending link %s", s.l.key.name)} - } - - select { - case err := <-sent: - if err != nil { - return nil, err - } - case <-s.l.done: - return nil, s.l.doneErr - } - - // clear values that are only required on first message - fr.DeliveryID = nil - fr.DeliveryTag = nil - fr.MessageFormat = nil - } - - return fr.Done, nil -} - -// Address returns the link's address. -func (s *Sender) Address() string { - if s.l.target == nil { - return "" - } - return s.l.target.Address -} - -// Close closes the Sender and AMQP link. -// - ctx controls waiting for the peer to acknowledge the close -// -// If the context's deadline expires or is cancelled before the operation -// completes, an error is returned. However, the operation will continue to -// execute in the background. Subsequent calls will return a *LinkError -// that contains the context's error message. -func (s *Sender) Close(ctx context.Context) error { - return s.l.closeLink(ctx) -} - -// newSendingLink creates a new sending link and attaches it to the session -func newSender(target string, session *Session, opts *SenderOptions) (*Sender, error) { - l := newLink(session, encoding.RoleSender) - l.target = &frames.Target{Address: target} - l.source = new(frames.Source) - s := &Sender{ - l: l, - } - - if opts == nil { - return s, nil - } - - for _, v := range opts.Capabilities { - s.l.source.Capabilities = append(s.l.source.Capabilities, encoding.Symbol(v)) - } - if opts.Durability > DurabilityUnsettledState { - return nil, fmt.Errorf("invalid Durability %d", opts.Durability) - } - s.l.source.Durable = opts.Durability - if opts.DynamicAddress { - s.l.target.Address = "" - s.l.dynamicAddr = opts.DynamicAddress - } - if opts.ExpiryPolicy != "" { - if err := encoding.ValidateExpiryPolicy(opts.ExpiryPolicy); err != nil { - return nil, err - } - s.l.source.ExpiryPolicy = opts.ExpiryPolicy - } - s.l.source.Timeout = opts.ExpiryTimeout - if opts.Name != "" { - s.l.key.name = opts.Name - } - if opts.Properties != nil { - s.l.properties = make(map[encoding.Symbol]any) - for k, v := range opts.Properties { - if k == "" { - return nil, errors.New("link property key must not be empty") - } - s.l.properties[encoding.Symbol(k)] = v - } - } - if opts.RequestedReceiverSettleMode != nil { - if rsm := *opts.RequestedReceiverSettleMode; rsm > ReceiverSettleModeSecond { - return nil, fmt.Errorf("invalid RequestedReceiverSettleMode %d", rsm) - } - s.l.receiverSettleMode = opts.RequestedReceiverSettleMode - } - if opts.SettlementMode != nil { - if ssm := *opts.SettlementMode; ssm > SenderSettleModeMixed { - return nil, fmt.Errorf("invalid SettlementMode %d", ssm) - } - s.l.senderSettleMode = opts.SettlementMode - } - s.l.source.Address = opts.SourceAddress - for _, v := range opts.TargetCapabilities { - s.l.target.Capabilities = append(s.l.target.Capabilities, encoding.Symbol(v)) - } - if opts.TargetDurability != DurabilityNone { - s.l.target.Durable = opts.TargetDurability - } - if opts.TargetExpiryPolicy != ExpiryPolicySessionEnd { - s.l.target.ExpiryPolicy = opts.TargetExpiryPolicy - } - if opts.TargetExpiryTimeout != 0 { - s.l.target.Timeout = opts.TargetExpiryTimeout - } - return s, nil -} - -func (s *Sender) attach(ctx context.Context) error { - if err := s.l.attach(ctx, func(pa *frames.PerformAttach) { - pa.Role = encoding.RoleSender - if pa.Target == nil { - pa.Target = new(frames.Target) - } - pa.Target.Dynamic = s.l.dynamicAddr - }, func(pa *frames.PerformAttach) { - if s.l.target == nil { - s.l.target = new(frames.Target) - } - - // if dynamic address requested, copy assigned name to address - if s.l.dynamicAddr && pa.Target != nil { - s.l.target.Address = pa.Target.Address - } - }); err != nil { - return err - } - - s.transfers = make(chan transferEnvelope) - - return nil -} - -type senderTestHooks struct { - MuxTransfer func() -} - -func (s *Sender) mux(hooks senderTestHooks) { - if hooks.MuxTransfer == nil { - hooks.MuxTransfer = nop - } - - defer func() { - close(s.l.done) - }() - -Loop: - for { - var outgoingTransfers chan transferEnvelope - if s.l.linkCredit > 0 { - debug.Log(1, "TX (Sender %p) (enable): target: %q, link credit: %d, deliveryCount: %d", s, s.l.target.Address, s.l.linkCredit, s.l.deliveryCount) - outgoingTransfers = s.transfers - } else { - debug.Log(1, "TX (Sender %p) (pause): target: %q, link credit: %d, deliveryCount: %d", s, s.l.target.Address, s.l.linkCredit, s.l.deliveryCount) - } - - closed := s.l.close - if s.l.closeInProgress { - // swap out channel so it no longer triggers - closed = nil - - // disable sending once closing is in progress. - // this prevents races with mux shutdown and - // the peer sending disposition frames. - outgoingTransfers = nil - } - - select { - // received frame - case q := <-s.l.rxQ.Wait(): - // populated queue - fr := *q.Dequeue() - s.l.rxQ.Release(q) - - // if muxHandleFrame returns an error it means the mux must terminate. - // note that in the case of a client-side close due to an error, nil - // is returned in order to keep the mux running to ack the detach frame. - if err := s.muxHandleFrame(fr); err != nil { - s.l.doneErr = err - return - } - - // send data - case env := <-outgoingTransfers: - hooks.MuxTransfer() - select { - case s.l.session.txTransfer <- env: - debug.Log(2, "TX (Sender %p): mux transfer to Session: %d, %s", s, s.l.session.channel, env.Frame) - // decrement link-credit after entire message transferred - if !env.Frame.More { - s.l.deliveryCount++ - s.l.linkCredit-- - // we are the sender and we keep track of the peer's link credit - debug.Log(3, "TX (Sender %p): link: %s, link credit: %d", s, s.l.key.name, s.l.linkCredit) - } - continue Loop - case <-s.l.close: - continue Loop - case <-s.l.session.done: - continue Loop - } - - case <-closed: - if s.l.closeInProgress { - // a client-side close due to protocol error is in progress - continue - } - - // sender is being closed by the client - s.l.closeInProgress = true - fr := &frames.PerformDetach{ - Handle: s.l.handle, - Closed: true, - } - s.l.txFrame(context.Background(), fr, nil) - - case <-s.l.session.done: - s.l.doneErr = s.l.session.doneErr - return - } - } -} - -// muxHandleFrame processes fr based on type. -// depending on the peer's RSM, it might return a disposition frame for sending -func (s *Sender) muxHandleFrame(fr frames.FrameBody) error { - debug.Log(2, "RX (Sender %p): %s", s, fr) - switch fr := fr.(type) { - // flow control frame - case *frames.PerformFlow: - // the sender's link-credit variable MUST be set according to this formula when flow information is given by the receiver: - // link-credit(snd) := delivery-count(rcv) + link-credit(rcv) - delivery-count(snd) - linkCredit := *fr.LinkCredit - s.l.deliveryCount - if fr.DeliveryCount != nil { - // DeliveryCount can be nil if the receiver hasn't processed - // the attach. That shouldn't be the case here, but it's - // what ActiveMQ does. - linkCredit += *fr.DeliveryCount - } - - s.l.linkCredit = linkCredit - - if !fr.Echo { - return nil - } - - var ( - // copy because sent by pointer below; prevent race - deliveryCount = s.l.deliveryCount - ) - - // send flow - resp := &frames.PerformFlow{ - Handle: &s.l.handle, - DeliveryCount: &deliveryCount, - LinkCredit: &linkCredit, // max number of messages - } - - select { - case s.l.session.tx <- frameBodyEnvelope{Ctx: context.Background(), FrameBody: resp}: - debug.Log(2, "TX (Sender %p): mux frame to Session (%p): %d, %s", s, s.l.session, s.l.session.channel, resp) - case <-s.l.close: - return nil - case <-s.l.session.done: - return s.l.session.doneErr - } - - case *frames.PerformDisposition: - if fr.Settled { - return nil - } - - // peer is in mode second, so we must send confirmation of disposition. - // NOTE: the ack must be sent through the session so it can close out - // the in-flight disposition. - dr := &frames.PerformDisposition{ - Role: encoding.RoleSender, - First: fr.First, - Last: fr.Last, - Settled: true, - } - - select { - case s.l.session.tx <- frameBodyEnvelope{Ctx: context.Background(), FrameBody: dr}: - debug.Log(2, "TX (Sender %p): mux frame to Session (%p): %d, %s", s, s.l.session, s.l.session.channel, dr) - case <-s.l.close: - return nil - case <-s.l.session.done: - return s.l.session.doneErr - } - - return nil - - default: - return s.l.muxHandleFrame(fr) - } - - return nil -} diff --git a/sdk/messaging/azservicebus/internal/go-amqp/session.go b/sdk/messaging/azservicebus/internal/go-amqp/session.go deleted file mode 100644 index d9087be92e80..000000000000 --- a/sdk/messaging/azservicebus/internal/go-amqp/session.go +++ /dev/null @@ -1,792 +0,0 @@ -// Copyright (C) 2017 Kale Blankenship -// Portions Copyright (c) Microsoft Corporation - -package amqp - -import ( - "context" - "errors" - "fmt" - "math" - "sync" - - "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus/internal/go-amqp/internal/bitmap" - "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus/internal/go-amqp/internal/debug" - "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus/internal/go-amqp/internal/encoding" - "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus/internal/go-amqp/internal/frames" - "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus/internal/go-amqp/internal/queue" -) - -// Default session options -const ( - defaultWindow = 5000 -) - -// SessionOptions contains the optional settings for configuring an AMQP session. -type SessionOptions struct { - // MaxLinks sets the maximum number of links (Senders/Receivers) - // allowed on the session. - // - // Minimum: 1. - // Default: 4294967295. - MaxLinks uint32 -} - -// Session is an AMQP session. -// -// A session multiplexes Receivers. -type Session struct { - channel uint16 // session's local channel - remoteChannel uint16 // session's remote channel, owned by conn.connReader - conn *Conn // underlying conn - tx chan frameBodyEnvelope // non-transfer frames to be sent; session must track disposition - txTransfer chan transferEnvelope // transfer frames to be sent; session must track disposition - - // frames destined for this session are added to this queue by conn.connReader - rxQ *queue.Holder[frames.FrameBody] - - // flow control - incomingWindow uint32 - outgoingWindow uint32 - needFlowCount uint32 - - handleMax uint32 - - // link management - linksMu sync.RWMutex // used to synchronize link handle allocation - linksByKey map[linkKey]*link // mapping of name+role link - handles *bitmap.Bitmap // allocated handles - - abandonedLinksMu sync.Mutex - abandonedLinks []*link - - // used for gracefully closing session - close chan struct{} // closed by calling Close(). it signals that the end performative should be sent - closeOnce sync.Once - - // part of internal public surface area - done chan struct{} // closed when the session has terminated (mux exited); DO NOT wait on this from within Session.mux() as it will never trigger! - endSent chan struct{} // closed when the end performative has been sent; once this is closed, links MUST NOT send any frames! - doneErr error // contains the mux error state; ONLY written to by the mux and MUST only be read from after done is closed! - closeErr error // contains the error state returned from Close(); ONLY Close() reads/writes this! -} - -func newSession(c *Conn, channel uint16, opts *SessionOptions) *Session { - s := &Session{ - conn: c, - channel: channel, - tx: make(chan frameBodyEnvelope), - txTransfer: make(chan transferEnvelope), - incomingWindow: defaultWindow, - outgoingWindow: defaultWindow, - handleMax: math.MaxUint32 - 1, - linksMu: sync.RWMutex{}, - linksByKey: make(map[linkKey]*link), - close: make(chan struct{}), - done: make(chan struct{}), - endSent: make(chan struct{}), - } - - if opts != nil { - if opts.MaxLinks != 0 { - // MaxLinks is the number of total links. - // handleMax is the max handle ID which starts - // at zero. so we decrement by one - s.handleMax = opts.MaxLinks - 1 - } - } - - // create handle map after options have been applied - s.handles = bitmap.New(s.handleMax) - - s.rxQ = queue.NewHolder(queue.New[frames.FrameBody](int(s.incomingWindow))) - - return s -} - -// waitForFrame waits for an incoming frame to be queued. -// it returns the next frame from the queue, or an error. -// the error is either from the context or conn.doneErr. -// not meant for consumption outside of session.go. -func (s *Session) waitForFrame(ctx context.Context) (frames.FrameBody, error) { - var q *queue.Queue[frames.FrameBody] - select { - case <-ctx.Done(): - return nil, ctx.Err() - case <-s.conn.done: - return nil, s.conn.doneErr - case q = <-s.rxQ.Wait(): - // populated queue - } - - fr := q.Dequeue() - s.rxQ.Release(q) - - return *fr, nil -} - -func (s *Session) begin(ctx context.Context) error { - // send Begin to server - begin := &frames.PerformBegin{ - NextOutgoingID: 0, - IncomingWindow: s.incomingWindow, - OutgoingWindow: s.outgoingWindow, - HandleMax: s.handleMax, - } - - if err := s.txFrameAndWait(ctx, begin); err != nil { - return err - } - - // wait for response - fr, err := s.waitForFrame(ctx) - if err != nil { - // if we exit before receiving the ack, our caller will clean up the channel. - // however, it does mean that the peer will now have assigned an outgoing - // channel ID that's not in use. - return err - } - - begin, ok := fr.(*frames.PerformBegin) - if !ok { - // this codepath is hard to hit (impossible?). if the response isn't a PerformBegin and we've not - // yet seen the remote channel number, the default clause in conn.connReader will protect us from that. - // if we have seen the remote channel number then it's likely the session.mux for that channel will - // either swallow the frame or blow up in some other way, both causing this call to hang. - // deallocate session on error. we can't call - // s.Close() as the session mux hasn't started yet. - debug.Log(1, "RX (Session %p): unexpected begin response frame %T", s, fr) - s.conn.deleteSession(s) - if err := s.conn.Close(); err != nil { - return err - } - return &ConnError{inner: fmt.Errorf("unexpected begin response: %#v", fr)} - } - - // start Session multiplexor - go s.mux(begin) - - return nil -} - -// Close closes the session. -// - ctx controls waiting for the peer to acknowledge the session is closed -// -// If the context's deadline expires or is cancelled before the operation -// completes, an error is returned. However, the operation will continue to -// execute in the background. Subsequent calls will return a *SessionError -// that contains the context's error message. -func (s *Session) Close(ctx context.Context) error { - var ctxErr error - s.closeOnce.Do(func() { - close(s.close) - - // once the mux has received the ack'ing end performative, the mux will - // exit which deletes the session and closes s.done. - select { - case <-s.done: - s.closeErr = s.doneErr - - case <-ctx.Done(): - // notify the caller that the close timed out/was cancelled. - // the mux will remain running and once the ack is received it will terminate. - ctxErr = ctx.Err() - - // record that the close timed out/was cancelled. - // subsequent calls to Close() will return this - debug.Log(1, "TX (Session %p) channel %d: %v", s, s.channel, ctxErr) - s.closeErr = &SessionError{inner: ctxErr} - } - }) - - if ctxErr != nil { - return ctxErr - } - - var sessionErr *SessionError - if errors.As(s.closeErr, &sessionErr) && sessionErr.RemoteErr == nil && sessionErr.inner == nil { - // an empty SessionError means the session was cleanly closed by the caller - return nil - } - return s.closeErr -} - -// txFrame sends a frame to the connWriter. -// - ctx is used to provide the write deadline -// - fr is the frame to write to net.Conn -// - sent is the optional channel that will contain the error if the write fails -func (s *Session) txFrame(ctx context.Context, fr frames.FrameBody, sent chan error) { - debug.Log(2, "TX (Session %p) mux frame to Conn (%p): %s", s, s.conn, fr) - s.conn.sendFrame(ctx, frames.Frame{ - Type: frames.TypeAMQP, - Channel: s.channel, - Body: fr, - }, sent) -} - -// txFrameAndWait sends a frame to the connWriter and waits for the write to complete -// - ctx is used to provide the write deadline -// - fr is the frame to write to net.Conn -func (s *Session) txFrameAndWait(ctx context.Context, fr frames.FrameBody) error { - sent := make(chan error, 1) - s.txFrame(ctx, fr, sent) - - select { - case err := <-sent: - return err - case <-s.conn.done: - return s.conn.doneErr - case <-s.done: - return s.doneErr - } -} - -// NewReceiver opens a new receiver link on the session. -// - ctx controls waiting for the peer to create a sending terminus -// - source is the name of the peer's sending terminus -// - opts contains optional values, pass nil to accept the defaults -// -// If the context's deadline expires or is cancelled before the operation -// completes, an error is returned. If the Receiver was successfully -// created, it will be cleaned up in future calls to NewReceiver. -func (s *Session) NewReceiver(ctx context.Context, source string, opts *ReceiverOptions) (*Receiver, error) { - r, err := newReceiver(source, s, opts) - if err != nil { - return nil, err - } - if err = r.attach(ctx); err != nil { - return nil, err - } - - go r.mux(receiverTestHooks{}) - - return r, nil -} - -// NewSender opens a new sender link on the session. -// - ctx controls waiting for the peer to create a receiver terminus -// - target is the name of the peer's receiver terminus -// - opts contains optional values, pass nil to accept the defaults -// -// If the context's deadline expires or is cancelled before the operation -// completes, an error is returned. If the Sender was successfully -// created, it will be cleaned up in future calls to NewSender. -func (s *Session) NewSender(ctx context.Context, target string, opts *SenderOptions) (*Sender, error) { - l, err := newSender(target, s, opts) - if err != nil { - return nil, err - } - if err = l.attach(ctx); err != nil { - return nil, err - } - - go l.mux(senderTestHooks{}) - - return l, nil -} - -func (s *Session) mux(remoteBegin *frames.PerformBegin) { - defer func() { - if s.doneErr == nil { - s.doneErr = &SessionError{} - } else if connErr := (&ConnError{}); !errors.As(s.doneErr, &connErr) { - // only wrap non-ConnError error types - var amqpErr *Error - if errors.As(s.doneErr, &amqpErr) { - s.doneErr = &SessionError{RemoteErr: amqpErr} - } else { - s.doneErr = &SessionError{inner: s.doneErr} - } - } - // Signal goroutines waiting on the session. - close(s.done) - }() - - var ( - links = make(map[uint32]*link) // mapping of remote handles to links - handlesByDeliveryID = make(map[uint32]uint32) // mapping of deliveryIDs to handles - deliveryIDByHandle = make(map[uint32]uint32) // mapping of handles to latest deliveryID - handlesByRemoteDeliveryID = make(map[uint32]uint32) // mapping of remote deliveryID to handles - - settlementByDeliveryID = make(map[uint32]chan encoding.DeliveryState) - - nextDeliveryID uint32 // tracks the next delivery ID for outgoing transfers - - // flow control values - nextOutgoingID uint32 - nextIncomingID = remoteBegin.NextOutgoingID - remoteIncomingWindow = remoteBegin.IncomingWindow - remoteOutgoingWindow = remoteBegin.OutgoingWindow - - closeInProgress bool // indicates the end performative has been sent - ) - - closeWithError := func(e1 *Error, e2 error) { - if closeInProgress { - debug.Log(3, "TX (Session %p): close already pending, discarding %v", s, e1) - return - } - - closeInProgress = true - s.doneErr = e2 - s.txFrame(context.Background(), &frames.PerformEnd{Error: e1}, nil) - close(s.endSent) - } - - for { - txTransfer := s.txTransfer - // disable txTransfer if flow control windows have been exceeded - if remoteIncomingWindow == 0 || s.outgoingWindow == 0 { - debug.Log(1, "TX (Session %p): disabling txTransfer - window exceeded. remoteIncomingWindow: %d outgoingWindow: %d", - s, remoteIncomingWindow, s.outgoingWindow) - txTransfer = nil - } - - tx := s.tx - closed := s.close - if closeInProgress { - // swap out channel so it no longer triggers - closed = nil - - // once the end performative is sent, we're not allowed to send any frames - tx = nil - txTransfer = nil - } - - // notes on client-side closing session - // when session is closed, we must keep the mux running until the ack'ing end performative - // has been received. during this window, the session is allowed to receive frames but cannot - // send them. - // client-side close happens either by user calling Session.Close() or due to mux initiated - // close due to a violation of some invariant (see sending &Error{} to s.close). in the case - // that both code paths have been triggered, we must be careful to preserve the error that - // triggered the mux initiated close so it can be surfaced to the caller. - - select { - // conn has completed, exit - case <-s.conn.done: - s.doneErr = s.conn.doneErr - return - - case <-closed: - if closeInProgress { - // a client-side close due to protocol error is in progress - continue - } - // session is being closed by the client - closeInProgress = true - s.txFrame(context.Background(), &frames.PerformEnd{}, nil) - close(s.endSent) - - // incoming frame - case q := <-s.rxQ.Wait(): - fr := *q.Dequeue() - s.rxQ.Release(q) - debug.Log(2, "RX (Session %p): %s", s, fr) - - switch body := fr.(type) { - // Disposition frames can reference transfers from more than one - // link. Send this frame to all of them. - case *frames.PerformDisposition: - start := body.First - end := start - if body.Last != nil { - end = *body.Last - } - for deliveryID := start; deliveryID <= end; deliveryID++ { - handles := handlesByDeliveryID - if body.Role == encoding.RoleSender { - handles = handlesByRemoteDeliveryID - } - - handle, ok := handles[deliveryID] - if !ok { - debug.Log(2, "RX (Session %p): role %s: didn't find deliveryID %d in handles map", s, body.Role, deliveryID) - continue - } - delete(handles, deliveryID) - - if body.Settled && body.Role == encoding.RoleReceiver { - // check if settlement confirmation was requested, if so - // confirm by closing channel - if done, ok := settlementByDeliveryID[deliveryID]; ok { - delete(settlementByDeliveryID, deliveryID) - select { - case done <- body.State: - default: - } - close(done) - } - } - - link, ok := links[handle] - if !ok { - closeWithError(&Error{ - Condition: ErrCondUnattachedHandle, - Description: "received disposition frame referencing a handle that's not in use", - }, fmt.Errorf("received disposition frame with unknown link handle %d", handle)) - continue - } - - s.muxFrameToLink(link, fr) - } - continue - case *frames.PerformFlow: - if body.NextIncomingID == nil { - // This is a protocol error: - // "[...] MUST be set if the peer has received - // the begin frame for the session" - closeWithError(&Error{ - Condition: ErrCondNotAllowed, - Description: "next-incoming-id not set after session established", - }, errors.New("protocol error: received flow without next-incoming-id after session established")) - continue - } - - // "When the endpoint receives a flow frame from its peer, - // it MUST update the next-incoming-id directly from the - // next-outgoing-id of the frame, and it MUST update the - // remote-outgoing-window directly from the outgoing-window - // of the frame." - nextIncomingID = body.NextOutgoingID - remoteOutgoingWindow = body.OutgoingWindow - - // "The remote-incoming-window is computed as follows: - // - // next-incoming-id(flow) + incoming-window(flow) - next-outgoing-id(endpoint) - // - // If the next-incoming-id field of the flow frame is not set, then remote-incoming-window is computed as follows: - // - // initial-outgoing-id(endpoint) + incoming-window(flow) - next-outgoing-id(endpoint)" - remoteIncomingWindow = body.IncomingWindow - nextOutgoingID - remoteIncomingWindow += *body.NextIncomingID - debug.Log(3, "RX (Session %p): flow - remoteOutgoingWindow: %d remoteIncomingWindow: %d nextOutgoingID: %d", s, remoteOutgoingWindow, remoteIncomingWindow, nextOutgoingID) - - // Send to link if handle is set - if body.Handle != nil { - link, ok := links[*body.Handle] - if !ok { - closeWithError(&Error{ - Condition: ErrCondUnattachedHandle, - Description: "received flow frame referencing a handle that's not in use", - }, fmt.Errorf("received flow frame with unknown link handle %d", body.Handle)) - continue - } - - s.muxFrameToLink(link, fr) - continue - } - - if body.Echo && !closeInProgress { - niID := nextIncomingID - resp := &frames.PerformFlow{ - NextIncomingID: &niID, - IncomingWindow: s.incomingWindow, - NextOutgoingID: nextOutgoingID, - OutgoingWindow: s.outgoingWindow, - } - s.txFrame(context.Background(), resp, nil) - } - - case *frames.PerformAttach: - // On Attach response link should be looked up by name, then added - // to the links map with the remote's handle contained in this - // attach frame. - // - // Note body.Role is the remote peer's role, we reverse for the local key. - s.linksMu.RLock() - link, linkOk := s.linksByKey[linkKey{name: body.Name, role: !body.Role}] - s.linksMu.RUnlock() - if !linkOk { - closeWithError(&Error{ - Condition: ErrCondNotAllowed, - Description: "received mismatched attach frame", - }, fmt.Errorf("protocol error: received mismatched attach frame %+v", body)) - continue - } - - link.remoteHandle = body.Handle - links[link.remoteHandle] = link - - s.muxFrameToLink(link, fr) - - case *frames.PerformTransfer: - s.needFlowCount++ - // "Upon receiving a transfer, the receiving endpoint will - // increment the next-incoming-id to match the implicit - // transfer-id of the incoming transfer plus one, as well - // as decrementing the remote-outgoing-window, and MAY - // (depending on policy) decrement its incoming-window." - nextIncomingID++ - // don't loop to intmax - if remoteOutgoingWindow > 0 { - remoteOutgoingWindow-- - } - link, ok := links[body.Handle] - if !ok { - closeWithError(&Error{ - Condition: ErrCondUnattachedHandle, - Description: "received transfer frame referencing a handle that's not in use", - }, fmt.Errorf("received transfer frame with unknown link handle %d", body.Handle)) - continue - } - - s.muxFrameToLink(link, fr) - - // if this message is received unsettled and link rcv-settle-mode == second, add to handlesByRemoteDeliveryID - if !body.Settled && body.DeliveryID != nil && link.receiverSettleMode != nil && *link.receiverSettleMode == ReceiverSettleModeSecond { - debug.Log(1, "RX (Session %p): adding handle to handlesByRemoteDeliveryID. delivery ID: %d", s, *body.DeliveryID) - handlesByRemoteDeliveryID[*body.DeliveryID] = body.Handle - } - - // Update peer's outgoing window if half has been consumed. - if s.needFlowCount >= s.incomingWindow/2 && !closeInProgress { - debug.Log(3, "RX (Session %p): channel %d: flow - s.needFlowCount(%d) >= s.incomingWindow(%d)/2\n", s, s.channel, s.needFlowCount, s.incomingWindow) - s.needFlowCount = 0 - nID := nextIncomingID - flow := &frames.PerformFlow{ - NextIncomingID: &nID, - IncomingWindow: s.incomingWindow, - NextOutgoingID: nextOutgoingID, - OutgoingWindow: s.outgoingWindow, - } - s.txFrame(context.Background(), flow, nil) - } - - case *frames.PerformDetach: - link, ok := links[body.Handle] - if !ok { - closeWithError(&Error{ - Condition: ErrCondUnattachedHandle, - Description: "received detach frame referencing a handle that's not in use", - }, fmt.Errorf("received detach frame with unknown link handle %d", body.Handle)) - continue - } - s.muxFrameToLink(link, fr) - - // we received a detach frame and sent it to the link. - // this was either the response to a client-side initiated - // detach or our peer detached us. either way, now that - // the link has processed the frame it's detached so we - // are safe to clean up its state. - delete(links, link.remoteHandle) - delete(deliveryIDByHandle, link.handle) - s.deallocateHandle(link) - - case *frames.PerformEnd: - // there are two possibilities: - // - this is the ack to a client-side Close() - // - the peer is ending the session so we must ack - - if closeInProgress { - return - } - - // peer detached us with an error, save it and send the ack - if body.Error != nil { - s.doneErr = body.Error - } - - fr := frames.PerformEnd{} - s.txFrame(context.Background(), &fr, nil) - - // per spec, when end is received, we're no longer allowed to receive frames - return - - default: - debug.Log(1, "RX (Session %p): unexpected frame: %s\n", s, body) - closeWithError(&Error{ - Condition: ErrCondInternalError, - Description: "session received unexpected frame", - }, fmt.Errorf("internal error: unexpected frame %T", body)) - } - - case env := <-txTransfer: - fr := &env.Frame - // record current delivery ID - var deliveryID uint32 - if fr.DeliveryID == &needsDeliveryID { - deliveryID = nextDeliveryID - fr.DeliveryID = &deliveryID - nextDeliveryID++ - deliveryIDByHandle[fr.Handle] = deliveryID - - // add to handleByDeliveryID if not sender-settled - if !fr.Settled { - handlesByDeliveryID[deliveryID] = fr.Handle - } - } else { - // if fr.DeliveryID is nil it must have been added - // to deliveryIDByHandle already - deliveryID = deliveryIDByHandle[fr.Handle] - } - - // log after the delivery ID has been assigned - debug.Log(2, "TX (Session %p): %d, %s", s, s.channel, fr) - - // frame has been sender-settled, remove from map - if fr.Settled { - delete(handlesByDeliveryID, deliveryID) - } - - s.txFrame(env.Ctx, fr, env.Sent) - if sendErr := <-env.Sent; sendErr != nil { - s.doneErr = sendErr - - // put the error back as our sender will read from this channel - env.Sent <- sendErr - return - } - - // if not settled, add done chan to map - if !fr.Settled && fr.Done != nil { - settlementByDeliveryID[deliveryID] = fr.Done - } else if fr.Done != nil { - // sender-settled, close done now that the transfer has been sent - close(fr.Done) - } - - // "Upon sending a transfer, the sending endpoint will increment - // its next-outgoing-id, decrement its remote-incoming-window, - // and MAY (depending on policy) decrement its outgoing-window." - nextOutgoingID++ - // don't decrement if we're at 0 or we could loop to int max - if remoteIncomingWindow != 0 { - remoteIncomingWindow-- - } - - case env := <-tx: - fr := env.FrameBody - debug.Log(2, "TX (Session %p): %d, %s", s, s.channel, fr) - switch fr := env.FrameBody.(type) { - case *frames.PerformDisposition: - if fr.Settled && fr.Role == encoding.RoleSender { - // sender with a peer that's in mode second; sending confirmation of disposition. - // disposition frames can reference a range of delivery IDs, although it's highly - // likely in this case there will only be one. - start := fr.First - end := start - if fr.Last != nil { - end = *fr.Last - } - for deliveryID := start; deliveryID <= end; deliveryID++ { - // send delivery state to the channel and close it to signal - // that the delivery has completed. - if done, ok := settlementByDeliveryID[deliveryID]; ok { - delete(settlementByDeliveryID, deliveryID) - select { - case done <- fr.State: - default: - } - close(done) - } - } - } - s.txFrame(env.Ctx, fr, env.Sent) - case *frames.PerformFlow: - niID := nextIncomingID - fr.NextIncomingID = &niID - fr.IncomingWindow = s.incomingWindow - fr.NextOutgoingID = nextOutgoingID - fr.OutgoingWindow = s.outgoingWindow - s.txFrame(context.Background(), fr, env.Sent) - case *frames.PerformTransfer: - panic("transfer frames must use txTransfer") - default: - s.txFrame(context.Background(), fr, env.Sent) - } - } - } -} - -func (s *Session) allocateHandle(ctx context.Context, l *link) error { - s.linksMu.Lock() - defer s.linksMu.Unlock() - - // Check if link name already exists, if so then an error should be returned - existing := s.linksByKey[l.key] - if existing != nil { - return fmt.Errorf("link with name '%v' already exists", l.key.name) - } - - next, ok := s.handles.Next() - if !ok { - if err := s.Close(ctx); err != nil { - return err - } - // handle numbers are zero-based, report the actual count - return &SessionError{inner: fmt.Errorf("reached session handle max (%d)", s.handleMax+1)} - } - - l.handle = next // allocate handle to the link - s.linksByKey[l.key] = l // add to mapping - - return nil -} - -func (s *Session) deallocateHandle(l *link) { - s.linksMu.Lock() - defer s.linksMu.Unlock() - - delete(s.linksByKey, l.key) - s.handles.Remove(l.handle) -} - -func (s *Session) abandonLink(l *link) { - s.abandonedLinksMu.Lock() - defer s.abandonedLinksMu.Unlock() - s.abandonedLinks = append(s.abandonedLinks, l) -} - -func (s *Session) freeAbandonedLinks(ctx context.Context) error { - s.abandonedLinksMu.Lock() - defer s.abandonedLinksMu.Unlock() - - debug.Log(3, "TX (Session %p): cleaning up %d abandoned links", s, len(s.abandonedLinks)) - - for _, l := range s.abandonedLinks { - dr := &frames.PerformDetach{ - Handle: l.handle, - Closed: true, - } - if err := s.txFrameAndWait(ctx, dr); err != nil { - return err - } - } - - s.abandonedLinks = nil - return nil -} - -func (s *Session) muxFrameToLink(l *link, fr frames.FrameBody) { - q := l.rxQ.Acquire() - q.Enqueue(fr) - l.rxQ.Release(q) - debug.Log(2, "RX (Session %p): mux frame to link (%p): %s, %s", s, l, l.key.name, fr) -} - -// transferEnvelope is used by senders to send transfer frames -type transferEnvelope struct { - Ctx context.Context - Frame frames.PerformTransfer - - // Sent is *never* nil as we use this for confirmation of sending - // NOTE: use a buffered channel of size 1 when populating - Sent chan error -} - -// frameBodyEnvelope is used by senders and receivers to send frames. -type frameBodyEnvelope struct { - Ctx context.Context - FrameBody frames.FrameBody - - // Sent *can* be nil depending on what frame is being sent. - // e.g. sending a disposition frame frame a receiver's settlement - // APIs will have a non-nil channel vs sending a flow frame - // NOTE: use a buffered channel of size 1 when populating - Sent chan error -} - -// the address of this var is a sentinel value indicating -// that a transfer frame is in need of a delivery ID -var needsDeliveryID uint32 diff --git a/sdk/messaging/azservicebus/internal/mgmt.go b/sdk/messaging/azservicebus/internal/mgmt.go index 74f42d117b0e..cf57ba06e004 100644 --- a/sdk/messaging/azservicebus/internal/mgmt.go +++ b/sdk/messaging/azservicebus/internal/mgmt.go @@ -12,7 +12,7 @@ import ( "github.com/Azure/azure-sdk-for-go/sdk/internal/uuid" "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus/internal/amqpwrap" "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus/internal/exported" - "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus/internal/go-amqp" + "github.com/Azure/go-amqp" ) type Disposition struct { diff --git a/sdk/messaging/azservicebus/internal/mock/emulation/events.go b/sdk/messaging/azservicebus/internal/mock/emulation/events.go index e2e19e32e628..d34791841e05 100644 --- a/sdk/messaging/azservicebus/internal/mock/emulation/events.go +++ b/sdk/messaging/azservicebus/internal/mock/emulation/events.go @@ -7,7 +7,7 @@ import ( "fmt" "sync" - "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus/internal/go-amqp" + "github.com/Azure/go-amqp" ) type EventType string diff --git a/sdk/messaging/azservicebus/internal/mock/emulation/mock_data.go b/sdk/messaging/azservicebus/internal/mock/emulation/mock_data.go index cb2fd0ded2d7..6e49410a9191 100644 --- a/sdk/messaging/azservicebus/internal/mock/emulation/mock_data.go +++ b/sdk/messaging/azservicebus/internal/mock/emulation/mock_data.go @@ -17,9 +17,9 @@ import ( "github.com/Azure/azure-sdk-for-go/sdk/internal/log" "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus/internal/amqpwrap" "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus/internal/auth" - "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus/internal/go-amqp" "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus/internal/mock" "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus/internal/sbauth" + "github.com/Azure/go-amqp" "github.com/golang/mock/gomock" ) diff --git a/sdk/messaging/azservicebus/internal/mock/emulation/mock_data_receiver.go b/sdk/messaging/azservicebus/internal/mock/emulation/mock_data_receiver.go index 73dc7c15720c..bcef3023fcc3 100644 --- a/sdk/messaging/azservicebus/internal/mock/emulation/mock_data_receiver.go +++ b/sdk/messaging/azservicebus/internal/mock/emulation/mock_data_receiver.go @@ -10,8 +10,8 @@ import ( "sync/atomic" "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus/internal/amqpwrap" - "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus/internal/go-amqp" "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus/internal/mock" + "github.com/Azure/go-amqp" "github.com/golang/mock/gomock" ) diff --git a/sdk/messaging/azservicebus/internal/mock/emulation/mock_data_sender.go b/sdk/messaging/azservicebus/internal/mock/emulation/mock_data_sender.go index aa02398a85c4..7ee49c436bc3 100644 --- a/sdk/messaging/azservicebus/internal/mock/emulation/mock_data_sender.go +++ b/sdk/messaging/azservicebus/internal/mock/emulation/mock_data_sender.go @@ -9,8 +9,8 @@ import ( "sync/atomic" "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus/internal/amqpwrap" - "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus/internal/go-amqp" "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus/internal/mock" + "github.com/Azure/go-amqp" "github.com/golang/mock/gomock" ) diff --git a/sdk/messaging/azservicebus/internal/mock/emulation/mock_data_session.go b/sdk/messaging/azservicebus/internal/mock/emulation/mock_data_session.go index 5bc7529d25da..0b3f34e8deef 100644 --- a/sdk/messaging/azservicebus/internal/mock/emulation/mock_data_session.go +++ b/sdk/messaging/azservicebus/internal/mock/emulation/mock_data_session.go @@ -7,8 +7,8 @@ import ( "context" "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus/internal/amqpwrap" - "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus/internal/go-amqp" "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus/internal/mock" + "github.com/Azure/go-amqp" "github.com/golang/mock/gomock" ) diff --git a/sdk/messaging/azservicebus/internal/mock/emulation/mock_data_test.go b/sdk/messaging/azservicebus/internal/mock/emulation/mock_data_test.go index 8d6ea6c2e2a1..7cca0c64d372 100644 --- a/sdk/messaging/azservicebus/internal/mock/emulation/mock_data_test.go +++ b/sdk/messaging/azservicebus/internal/mock/emulation/mock_data_test.go @@ -8,8 +8,8 @@ import ( "testing" "time" - "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus/internal/go-amqp" "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus/internal/mock/emulation" + "github.com/Azure/go-amqp" "github.com/stretchr/testify/require" ) diff --git a/sdk/messaging/azservicebus/internal/mock/emulation/queue.go b/sdk/messaging/azservicebus/internal/mock/emulation/queue.go index faf80a446e82..f336d67c6cc0 100644 --- a/sdk/messaging/azservicebus/internal/mock/emulation/queue.go +++ b/sdk/messaging/azservicebus/internal/mock/emulation/queue.go @@ -9,8 +9,8 @@ import ( "sync" azlog "github.com/Azure/azure-sdk-for-go/sdk/internal/log" - "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus/internal/go-amqp" "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus/internal/test" + "github.com/Azure/go-amqp" ) type Operation struct { diff --git a/sdk/messaging/azservicebus/internal/mock/emulation/queue_test.go b/sdk/messaging/azservicebus/internal/mock/emulation/queue_test.go index 0a9b822ef539..636d71e93010 100644 --- a/sdk/messaging/azservicebus/internal/mock/emulation/queue_test.go +++ b/sdk/messaging/azservicebus/internal/mock/emulation/queue_test.go @@ -8,8 +8,8 @@ import ( "testing" "time" - "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus/internal/go-amqp" "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus/internal/mock/emulation" + "github.com/Azure/go-amqp" "github.com/stretchr/testify/require" ) diff --git a/sdk/messaging/azservicebus/internal/mock/mock_amqp.go b/sdk/messaging/azservicebus/internal/mock/mock_amqp.go index 5ee2c0e5ea6a..9bd0b22f579d 100644 --- a/sdk/messaging/azservicebus/internal/mock/mock_amqp.go +++ b/sdk/messaging/azservicebus/internal/mock/mock_amqp.go @@ -13,7 +13,7 @@ import ( reflect "reflect" amqpwrap "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus/internal/amqpwrap" - amqp "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus/internal/go-amqp" + amqp "github.com/Azure/go-amqp" gomock "github.com/golang/mock/gomock" ) diff --git a/sdk/messaging/azservicebus/internal/mock/mock_helpers.go b/sdk/messaging/azservicebus/internal/mock/mock_helpers.go index 1695aaf5c3d6..fa4480069435 100644 --- a/sdk/messaging/azservicebus/internal/mock/mock_helpers.go +++ b/sdk/messaging/azservicebus/internal/mock/mock_helpers.go @@ -8,7 +8,7 @@ import ( "fmt" "time" - "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus/internal/go-amqp" + "github.com/Azure/go-amqp" gomock "github.com/golang/mock/gomock" ) diff --git a/sdk/messaging/azservicebus/internal/mock/mock_rpc.go b/sdk/messaging/azservicebus/internal/mock/mock_rpc.go index 94fb00fcf2cb..193c3653f18d 100644 --- a/sdk/messaging/azservicebus/internal/mock/mock_rpc.go +++ b/sdk/messaging/azservicebus/internal/mock/mock_rpc.go @@ -13,7 +13,7 @@ import ( reflect "reflect" amqpwrap "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus/internal/amqpwrap" - amqp "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus/internal/go-amqp" + amqp "github.com/Azure/go-amqp" gomock "github.com/golang/mock/gomock" ) diff --git a/sdk/messaging/azservicebus/internal/namespace.go b/sdk/messaging/azservicebus/internal/namespace.go index 8d40a7ab6f36..c56a1e083067 100644 --- a/sdk/messaging/azservicebus/internal/namespace.go +++ b/sdk/messaging/azservicebus/internal/namespace.go @@ -20,9 +20,9 @@ import ( "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus/internal/auth" "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus/internal/conn" "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus/internal/exported" - "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus/internal/go-amqp" "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus/internal/sbauth" "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus/internal/utils" + "github.com/Azure/go-amqp" ) var rootUserAgent = telemetry.Format("azservicebus", Version) diff --git a/sdk/messaging/azservicebus/internal/namespace_test.go b/sdk/messaging/azservicebus/internal/namespace_test.go index 910eb1eeedd2..82d7ef9aed27 100644 --- a/sdk/messaging/azservicebus/internal/namespace_test.go +++ b/sdk/messaging/azservicebus/internal/namespace_test.go @@ -15,9 +15,9 @@ import ( "github.com/Azure/azure-sdk-for-go/sdk/internal/telemetry" "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus/internal/amqpwrap" "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus/internal/auth" - "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus/internal/go-amqp" "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus/internal/sbauth" "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus/internal/test" + "github.com/Azure/go-amqp" "github.com/stretchr/testify/require" ) diff --git a/sdk/messaging/azservicebus/internal/rpc.go b/sdk/messaging/azservicebus/internal/rpc.go index a69c37c4a248..a23fede1964a 100644 --- a/sdk/messaging/azservicebus/internal/rpc.go +++ b/sdk/messaging/azservicebus/internal/rpc.go @@ -14,7 +14,7 @@ import ( azlog "github.com/Azure/azure-sdk-for-go/sdk/internal/log" "github.com/Azure/azure-sdk-for-go/sdk/internal/uuid" "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus/internal/amqpwrap" - "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus/internal/go-amqp" + "github.com/Azure/go-amqp" ) const ( @@ -148,13 +148,10 @@ func NewRPCLink(ctx context.Context, args RPCLinkArgs) (amqpwrap.RPCLink, error) return link, nil } -const responseRouterShutdownMessage = "Response router has shut down" - // responseRouter is responsible for taking any messages received on the 'response' // link and forwarding it to the proper channel. The channel is being select'd by the // original `RPC` call. func (l *rpcLink) responseRouter() { - defer azlog.Writef(l.logEvent, responseRouterShutdownMessage) defer close(l.responseRouterClosed) for { diff --git a/sdk/messaging/azservicebus/internal/rpc_test.go b/sdk/messaging/azservicebus/internal/rpc_test.go index 4bf5a2865278..704e4137b1f7 100644 --- a/sdk/messaging/azservicebus/internal/rpc_test.go +++ b/sdk/messaging/azservicebus/internal/rpc_test.go @@ -8,12 +8,11 @@ import ( "errors" "net" "testing" - "time" "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus/internal/amqpwrap" - "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus/internal/go-amqp" "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus/internal/mock" "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus/internal/test" + "github.com/Azure/go-amqp" "github.com/golang/mock/gomock" "github.com/stretchr/testify/require" ) @@ -36,10 +35,6 @@ func TestRPCLinkNonErrorRequiresRecovery(t *testing.T) { defer func() { require.NoError(t, link.Close(context.Background())) }() - messagesCh := make(chan string, 10000) - endCapture := test.CaptureLogsForTestWithChannel(messagesCh, false) - defer endCapture() - responses := []*rpcTestResp{ // this error requires recovery (in this case, connection but there's no // distinction between types in RPCLink) @@ -53,23 +48,11 @@ func TestRPCLinkNonErrorRequiresRecovery(t *testing.T) { }) require.Nil(t, resp) - // (give the response router a teeny bit to shut down) - time.Sleep(500 * time.Millisecond) + linkImpl := link.(*rpcLink) + <-linkImpl.responseRouterClosed var netOpError net.Error require.ErrorAs(t, err, &netOpError) - -LogLoop: - for { - select { - case msg := <-messagesCh: - if msg == "[rpctesting] "+responseRouterShutdownMessage { - break LogLoop - } - default: - require.Fail(t, "RPC router never shut down") - } - } } func TestRPCLinkNonErrorRequiresNoRecovery(t *testing.T) { diff --git a/sdk/messaging/azservicebus/internal/stress/.gitignore b/sdk/messaging/azservicebus/internal/stress/.gitignore index fcef718cad3c..099d255e217d 100644 --- a/sdk/messaging/azservicebus/internal/stress/.gitignore +++ b/sdk/messaging/azservicebus/internal/stress/.gitignore @@ -3,4 +3,4 @@ stress.exe logs generatedValues.yaml deploy-test-*.ps1 - +*.log diff --git a/sdk/messaging/azservicebus/internal/stress/.helmignore b/sdk/messaging/azservicebus/internal/stress/.helmignore index 43294410b6b0..d7c1ed9789e0 100644 --- a/sdk/messaging/azservicebus/internal/stress/.helmignore +++ b/sdk/messaging/azservicebus/internal/stress/.helmignore @@ -3,3 +3,4 @@ stress.exe .env Dockerfile *.go +*.log diff --git a/sdk/messaging/azservicebus/internal/stress/deploy.ps1 b/sdk/messaging/azservicebus/internal/stress/deploy.ps1 index 8369fb669503..c6191940ade6 100644 --- a/sdk/messaging/azservicebus/internal/stress/deploy.ps1 +++ b/sdk/messaging/azservicebus/internal/stress/deploy.ps1 @@ -1,2 +1,25 @@ Set-Location $PSScriptRoot + +function deployUsingLocalAddons() { + $azureSDKToolsRoot="" + $stressTestAddonsFolder = "$azureSDKToolsRoot/tools/stress-cluster/cluster/kubernetes/stress-test-addons" + $clusterResourceGroup = "" + $clusterSubscription = "" + $helmEnv = "pg2" + + if (-not (Get-ChildItem $stressTestAddonsFolder)) { + Write-Host "Can't find the the new stress test addons folder at $stressTestAddonsFolder" + return + } + + pwsh "$azureSDKToolsRoot/eng/common/scripts/stress-testing/deploy-stress-tests.ps1" ` + -LocalAddonsPath "$stressTestAddonsFolder" ` + -clusterGroup "$clusterResourceGroup" ` + -subscription "$clusterSubscription" ` + -Environment $helmEnv ` + -Login ` + -PushImages +} + +#deployUsingLocalAddons pwsh "../../../../../eng/common/scripts/stress-testing/deploy-stress-tests.ps1" -Login -PushImages @args diff --git a/sdk/messaging/azservicebus/internal/stress/scenarios-matrix.yaml b/sdk/messaging/azservicebus/internal/stress/scenarios-matrix.yaml index bfca4a7af5f7..4c095d870e01 100644 --- a/sdk/messaging/azservicebus/internal/stress/scenarios-matrix.yaml +++ b/sdk/messaging/azservicebus/internal/stress/scenarios-matrix.yaml @@ -12,46 +12,46 @@ matrix: scenarios: constantDetach: testTarget: constantDetach - memory: "1.5Gi" + memory: "0.5Gi" constantDetachmentSender: testTarget: constantDetachmentSender - memory: "1.5Gi" + memory: "0.5Gi" emptySessions: testTarget: emptySessions memory: "1.0Gi" finitePeeks: testTarget: finitePeeks - memory: "1.5Gi" + memory: "0.5Gi" finiteSendAndReceive: testTarget: finiteSendAndReceive - memory: "1.5Gi" + memory: "0.5Gi" finiteSessions: testTarget: finiteSessions memory: "4Gi" idleFastReconnect: testTarget: idleFastReconnect - memory: "1.5Gi" + memory: "0.5Gi" infiniteSendAndReceive: testTarget: infiniteSendAndReceive - memory: "1.5Gi" + memory: "0.5Gi" infiniteSendAndReceiveWithChaos: testTarget: infiniteSendAndReceive # this value is injected as a label value in templates/deploy-job.yaml # this'll activate our standard chaos policy, which is at the bottom of that file. chaos: "true" - memory: "1.5Gi" + memory: "0.5Gi" longRunningRenewLock: testTarget: longRunningRenewLock - memory: "1.5Gi" + memory: "0.5Gi" mostlyIdleReceiver: testTarget: mostlyIdleReceiver - memory: "1.5Gi" + memory: "0.5Gi" rapidOpenClose: testTarget: rapidOpenClose - memory: "1.5Gi" + memory: "0.5Gi" receiveCancellation: testTarget: receiveCancellation - memory: "1.5Gi" + memory: "0.5Gi" sendAndReceiveDrain: testTarget: sendAndReceiveDrain - memory: "1.5Gi" + memory: "0.5Gi" diff --git a/sdk/messaging/azservicebus/internal/stress/templates/stress-test-job.yaml b/sdk/messaging/azservicebus/internal/stress/templates/stress-test-job.yaml index a2d1c74d746d..5fb46c12b168 100644 --- a/sdk/messaging/azservicebus/internal/stress/templates/stress-test-job.yaml +++ b/sdk/messaging/azservicebus/internal/stress/templates/stress-test-job.yaml @@ -17,7 +17,7 @@ spec: - > set -ex; mkdir -p "$DEBUG_SHARE"; - /app/stress tests "{{ .Stress.testTarget }}" | tee "${DEBUG_SHARE}/{{ .Stress.Scenario }}.log"; + /app/stress tests "{{ .Stress.testTarget }}" 2>&1 | tee -a "${DEBUG_SHARE}/{{ .Stress.Scenario }}-`date +%s`.log"; # Pulls the image on pod start, always. We tend to push to the same image and tag over and over again # when iterating, so this is a must. imagePullPolicy: Always @@ -29,7 +29,7 @@ spec: resources: limits: memory: {{.Stress.memory }} - cpu: "1" + cpu: "0.5" {{- include "stress-test-addons.container-env" . | nindent 6 }} {{- end -}} diff --git a/sdk/messaging/azservicebus/internal/stress/tests/finite_peeks.go b/sdk/messaging/azservicebus/internal/stress/tests/finite_peeks.go index ca0dc64ae33c..ba8735bf536c 100644 --- a/sdk/messaging/azservicebus/internal/stress/tests/finite_peeks.go +++ b/sdk/messaging/azservicebus/internal/stress/tests/finite_peeks.go @@ -28,11 +28,13 @@ func FinitePeeks(remainingArgs []string) { sender, err := client.NewSender(queueName, nil) sc.PanicOnError("failed to create sender", err) + log.Printf("Sending a single message") err = sender.SendMessage(sc.Context, &azservicebus.Message{ Body: []byte("peekable message"), }, nil) sc.PanicOnError("failed to send message", err) + log.Printf("Closing sender") _ = sender.Close(sc.Context) receiver, err := client.NewReceiverForQueue(queueName, nil) @@ -51,9 +53,13 @@ func FinitePeeks(remainingArgs []string) { sc.PanicOnError("failed to abandon message", receiver.AbandonMessage(sc.Context, tmp[0], nil)) - for i := 0; i < 10000; i++ { - log.Printf("Sleeping for 1 second before iteration %d", i) - time.Sleep(time.Second) + const maxPeeks = 10000 + const peekSleep = 500 * time.Millisecond + + log.Printf("Now peeking %d times, every %dms", maxPeeks, peekSleep/time.Millisecond) + + for i := 1; i <= maxPeeks; i++ { + time.Sleep(peekSleep) seqNum := int64(0) @@ -65,4 +71,6 @@ func FinitePeeks(remainingArgs []string) { receiverStats.AddReceived(int32(1)) } + + log.Printf("Done, peeked %d times", maxPeeks) } diff --git a/sdk/messaging/azservicebus/internal/stress/tests/mostly_idle_receiver.go b/sdk/messaging/azservicebus/internal/stress/tests/mostly_idle_receiver.go index d707f1edd747..1d9b40c23c1d 100644 --- a/sdk/messaging/azservicebus/internal/stress/tests/mostly_idle_receiver.go +++ b/sdk/messaging/azservicebus/internal/stress/tests/mostly_idle_receiver.go @@ -83,7 +83,7 @@ func MostlyIdleReceiver(remainingArgs []string) { messages, err := receiver.ReceiveMessages(sc.Context, 1, nil) sc.PanicOnError(fmt.Sprintf("failed receiving messages for duration %s", duration), err) - log.Printf("Received messages %#v", messages) + log.Printf("Received %d messages", len(messages)) stats.AddReceived(int32(len(messages))) for _, msg := range messages { diff --git a/sdk/messaging/azservicebus/internal/test/test_helpers.go b/sdk/messaging/azservicebus/internal/test/test_helpers.go index 7a1fb62812cc..655c94bc4d64 100644 --- a/sdk/messaging/azservicebus/internal/test/test_helpers.go +++ b/sdk/messaging/azservicebus/internal/test/test_helpers.go @@ -18,7 +18,7 @@ import ( azlog "github.com/Azure/azure-sdk-for-go/sdk/internal/log" "github.com/Azure/azure-sdk-for-go/sdk/internal/uuid" "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus/internal/atom" - "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus/internal/go-amqp" + "github.com/Azure/go-amqp" "github.com/stretchr/testify/require" ) @@ -67,6 +67,31 @@ func GetConnectionStringListenOnly(t *testing.T) string { return getEnvOrSkipTest(t, "SERVICEBUS_CONNECTION_STRING_LISTEN_ONLY") } +func GetIdentityVars(t *testing.T) *struct { + TenantID string + ClientID string + Secret string + Endpoint string +} { + runningLiveTest := GetConnectionString(t) != "" + + if !runningLiveTest { + return nil + } + + return &struct { + TenantID string + ClientID string + Secret string + Endpoint string + }{ + TenantID: getEnvOrSkipTest(t, "AZURE_TENANT_ID"), + ClientID: getEnvOrSkipTest(t, "AZURE_CLIENT_ID"), + Endpoint: getEnvOrSkipTest(t, "SERVICEBUS_ENDPOINT"), + Secret: getEnvOrSkipTest(t, "AZURE_CLIENT_SECRET"), + } +} + func getEnvOrSkipTest(t *testing.T, name string) string { cs := os.Getenv(name) diff --git a/sdk/messaging/azservicebus/internal/utils/logger.go b/sdk/messaging/azservicebus/internal/utils/logger.go new file mode 100644 index 000000000000..7298427e0251 --- /dev/null +++ b/sdk/messaging/azservicebus/internal/utils/logger.go @@ -0,0 +1,37 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package utils + +import ( + "fmt" + "sync/atomic" + + azlog "github.com/Azure/azure-sdk-for-go/sdk/internal/log" +) + +type Logger struct { + prefix *atomic.Value +} + +func NewLogger() Logger { + value := &atomic.Value{} + value.Store("") + + return Logger{ + prefix: value, + } +} + +func (l *Logger) SetPrefix(format string, args ...any) { + l.prefix.Store(fmt.Sprintf("["+format+"] ", args...)) +} + +func (l *Logger) Prefix() string { + return l.prefix.Load().(string) +} + +func (l *Logger) Writef(evt azlog.Event, format string, args ...any) { + prefix := l.prefix.Load().(string) + azlog.Writef(evt, prefix+format, args...) +} diff --git a/sdk/messaging/azservicebus/internal/utils/retrier.go b/sdk/messaging/azservicebus/internal/utils/retrier.go index 53d03a68202e..5fe3434d7842 100644 --- a/sdk/messaging/azservicebus/internal/utils/retrier.go +++ b/sdk/messaging/azservicebus/internal/utils/retrier.go @@ -50,7 +50,7 @@ func Retry(ctx context.Context, eventName log.Event, operation string, fn func(c for i := int32(0); i <= ro.MaxRetries; i++ { if i > 0 { sleep := calcDelay(ro, i) - log.Writef(eventName, "(%s) Retry attempt %d sleeping for %s", operation, i, sleep) + log.Writef(eventName, "%s Retry attempt %d sleeping for %s", operation, i, sleep) select { case <-ctx.Done(): @@ -66,7 +66,7 @@ func Retry(ctx context.Context, eventName log.Event, operation string, fn func(c err = fn(ctx, &args) if args.resetAttempts { - log.Writef(eventName, "(%s) Resetting retry attempts", operation) + log.Writef(eventName, "%s Resetting retry attempts", operation) // it looks weird, but we're doing -1 here because the post-increment // will set it back to 0, which is what we want - go back to the 0th @@ -79,13 +79,13 @@ func Retry(ctx context.Context, eventName log.Event, operation string, fn func(c if err != nil { if isFatalFn(err) { if errors.Is(err, context.Canceled) || errors.Is(err, context.DeadlineExceeded) { - log.Writef(eventName, "(%s) Retry attempt %d was cancelled, stopping: %s", operation, i, err.Error()) + log.Writef(eventName, "%s Retry attempt %d was cancelled, stopping: %s", operation, i, err.Error()) } else { - log.Writef(eventName, "(%s) Retry attempt %d returned non-retryable error: %s", operation, i, err.Error()) + log.Writef(eventName, "%s Retry attempt %d returned non-retryable error: %s", operation, i, err.Error()) } return err } else { - log.Writef(eventName, "(%s) Retry attempt %d returned retryable error: %s", operation, i, err.Error()) + log.Writef(eventName, "%s Retry attempt %d returned retryable error: %s", operation, i, err.Error()) } continue diff --git a/sdk/messaging/azservicebus/internal/utils/retrier_test.go b/sdk/messaging/azservicebus/internal/utils/retrier_test.go index c316fcdf23a1..cc0551c61033 100644 --- a/sdk/messaging/azservicebus/internal/utils/retrier_test.go +++ b/sdk/messaging/azservicebus/internal/utils/retrier_test.go @@ -14,8 +14,8 @@ import ( azlog "github.com/Azure/azure-sdk-for-go/sdk/internal/log" "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus/internal/exported" - "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus/internal/go-amqp" "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus/internal/test" + "github.com/Azure/go-amqp" "github.com/stretchr/testify/require" ) @@ -294,7 +294,7 @@ func TestRetryLogging(t *testing.T) { t.Run("normal error", func(t *testing.T) { logsFn := test.CaptureLogsForTest(false) - err := Retry(context.Background(), testLogEvent, "my_operation", func(ctx context.Context, args *RetryFnArgs) error { + err := Retry(context.Background(), testLogEvent, "(my_operation)", func(ctx context.Context, args *RetryFnArgs) error { azlog.Writef("TestFunc", "Attempt %d, within test func, returning error hello", args.I) return errors.New("hello") }, func(err error) bool { @@ -325,7 +325,7 @@ func TestRetryLogging(t *testing.T) { t.Run("normal error2", func(t *testing.T) { test.EnableStdoutLogging(t) - err := Retry(context.Background(), testLogEvent, "my_operation", func(ctx context.Context, args *RetryFnArgs) error { + err := Retry(context.Background(), testLogEvent, "(my_operation)", func(ctx context.Context, args *RetryFnArgs) error { azlog.Writef("TestFunc", "Attempt %d, within test func, returning error hello", args.I) return errors.New("hello") }, func(err error) bool { @@ -339,7 +339,7 @@ func TestRetryLogging(t *testing.T) { t.Run("cancellation error", func(t *testing.T) { logsFn := test.CaptureLogsForTest(false) - err := Retry(context.Background(), testLogEvent, "test_operation", func(ctx context.Context, args *RetryFnArgs) error { + err := Retry(context.Background(), testLogEvent, "(test_operation)", func(ctx context.Context, args *RetryFnArgs) error { azlog.Writef("TestFunc", "Attempt %d, within test func", args.I) return context.Canceled @@ -359,7 +359,7 @@ func TestRetryLogging(t *testing.T) { t.Run("custom fatal error", func(t *testing.T) { logsFn := test.CaptureLogsForTest(false) - err := Retry(context.Background(), testLogEvent, "test_operation", func(ctx context.Context, args *RetryFnArgs) error { + err := Retry(context.Background(), testLogEvent, "(test_operation)", func(ctx context.Context, args *RetryFnArgs) error { azlog.Writef("TestFunc", "Attempt %d, within test func", args.I) return errors.New("custom fatal error") @@ -380,7 +380,7 @@ func TestRetryLogging(t *testing.T) { logsFn := test.CaptureLogsForTest(false) reset := false - err := Retry(context.Background(), testLogEvent, "test_operation", func(ctx context.Context, args *RetryFnArgs) error { + err := Retry(context.Background(), testLogEvent, "(test_operation)", func(ctx context.Context, args *RetryFnArgs) error { azlog.Writef("TestFunc", "Attempt %d, within test func", args.I) if !reset { diff --git a/sdk/messaging/azservicebus/message.go b/sdk/messaging/azservicebus/message.go index b3247fd5d355..40b690b0f548 100644 --- a/sdk/messaging/azservicebus/message.go +++ b/sdk/messaging/azservicebus/message.go @@ -9,7 +9,7 @@ import ( "github.com/Azure/azure-sdk-for-go/sdk/azcore/to" "github.com/Azure/azure-sdk-for-go/sdk/internal/log" - "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus/internal/go-amqp" + "github.com/Azure/go-amqp" ) // ReceivedMessage is a received message from a Client.NewReceiver(). diff --git a/sdk/messaging/azservicebus/messageSettler.go b/sdk/messaging/azservicebus/messageSettler.go index 0b787efadb67..915cc020d905 100644 --- a/sdk/messaging/azservicebus/messageSettler.go +++ b/sdk/messaging/azservicebus/messageSettler.go @@ -8,8 +8,8 @@ import ( "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus/internal" "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus/internal/amqpwrap" - "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus/internal/go-amqp" "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus/internal/utils" + "github.com/Azure/go-amqp" ) type settler interface { diff --git a/sdk/messaging/azservicebus/message_batch.go b/sdk/messaging/azservicebus/message_batch.go index fd33a0195ff5..8b1e10a8c5d8 100644 --- a/sdk/messaging/azservicebus/message_batch.go +++ b/sdk/messaging/azservicebus/message_batch.go @@ -8,11 +8,12 @@ import ( "sync" "github.com/Azure/azure-sdk-for-go/sdk/internal/uuid" - "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus/internal/go-amqp" + "github.com/Azure/go-amqp" ) // ErrMessageTooLarge is returned when a message cannot fit into a batch when using MessageBatch.Add() -var ErrMessageTooLarge = errors.New("the message could not be added because it is too large for the batch") +// or if the message is being sent on its own and is too large for the link. +var ErrMessageTooLarge = errors.New("the message is too large") type ( // MessageBatch represents a batch of messages to send to Service Bus in a single message diff --git a/sdk/messaging/azservicebus/message_batch_test.go b/sdk/messaging/azservicebus/message_batch_test.go index fee360a7bbd8..5ab3e9dbf35b 100644 --- a/sdk/messaging/azservicebus/message_batch_test.go +++ b/sdk/messaging/azservicebus/message_batch_test.go @@ -7,7 +7,7 @@ import ( "sync" "testing" - "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus/internal/go-amqp" + "github.com/Azure/go-amqp" "github.com/stretchr/testify/require" ) diff --git a/sdk/messaging/azservicebus/message_test.go b/sdk/messaging/azservicebus/message_test.go index 2db45826d68c..3704b7591f35 100644 --- a/sdk/messaging/azservicebus/message_test.go +++ b/sdk/messaging/azservicebus/message_test.go @@ -9,7 +9,7 @@ import ( "time" "github.com/Azure/azure-sdk-for-go/sdk/azcore/to" - "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus/internal/go-amqp" + "github.com/Azure/go-amqp" "github.com/stretchr/testify/require" ) diff --git a/sdk/messaging/azservicebus/receiver.go b/sdk/messaging/azservicebus/receiver.go index 59b5b48db698..3646a9c1c8e0 100644 --- a/sdk/messaging/azservicebus/receiver.go +++ b/sdk/messaging/azservicebus/receiver.go @@ -11,12 +11,11 @@ import ( "sync/atomic" "time" - "github.com/Azure/azure-sdk-for-go/sdk/internal/log" "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus/internal" "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus/internal/amqpwrap" "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus/internal/exported" - "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus/internal/go-amqp" "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus/internal/utils" + "github.com/Azure/go-amqp" ) // ReceiveMode represents the lock style to use for a receiver - either @@ -321,7 +320,7 @@ func (r *Receiver) RenewMessageLock(ctx context.Context, msg *ReceivedMessage, o func (r *Receiver) Close(ctx context.Context) error { cancelReleaser := r.cancelReleaser.Swap(emptyCancelFn).(func() string) releaserID := cancelReleaser() - log.Writef(EventReceiver, "Stopped message releaser with ID '%s'", releaserID) + r.amqpLinks.Writef(EventReceiver, "Stopped message releaser with ID '%s'", releaserID) r.cleanupOnClose() return r.amqpLinks.Close(ctx, true) @@ -388,21 +387,20 @@ func (r *Receiver) receiveMessagesImpl(ctx context.Context, maxMessages int, opt // might have exited before all credits were used up. currentReceiverCredits := int64(linksWithID.Receiver.Credits()) creditsToIssue := int64(maxMessages) - currentReceiverCredits - log.Writef(EventReceiver, "Asking for %d credits", maxMessages) if creditsToIssue > 0 { - log.Writef(EventReceiver, "Only need to issue %d additional credits", creditsToIssue) + r.amqpLinks.Writef(EventReceiver, "Issuing %d credits, have %d", creditsToIssue, currentReceiverCredits) if err := linksWithID.Receiver.IssueCredit(uint32(creditsToIssue)); err != nil { return nil, err } } else { - log.Writef(EventReceiver, "No additional credits needed, still have %d credits active", currentReceiverCredits) + r.amqpLinks.Writef(EventReceiver, "Have %d credits, no new credits needed", currentReceiverCredits) } result := r.fetchMessages(ctx, linksWithID.Receiver, maxMessages, r.defaultTimeAfterFirstMsg) - log.Writef(EventReceiver, "Received %d/%d messages", len(result.Messages), maxMessages) + r.amqpLinks.Writef(EventReceiver, "Received %d/%d messages", len(result.Messages), maxMessages) // this'll only close anything if the error indicates that the link/connection is bad. // it's safe to call with cancellation errors. @@ -417,7 +415,7 @@ func (r *Receiver) receiveMessagesImpl(ctx context.Context, maxMessages int, opt releaserFunc := r.newReleaserFunc(linksWithID.Receiver) go releaserFunc() } else { - log.Writef(EventReceiver, "Failure when receiving messages: %s", result.Error) + r.amqpLinks.Writef(EventReceiver, "Failure when receiving messages: %s", result.Error) } // If the user does get some messages we ignore 'error' and return only the messages. @@ -616,8 +614,6 @@ func (r *Receiver) newReleaserFunc(receiver amqpwrap.AMQPReceiver) func() { return func() { defer close(done) - log.Writef(EventReceiver, "[%s] Message releaser starting...", receiver.LinkName()) - for { // we might not have all the messages we need here. msg, err := receiver.Receive(ctx, nil) @@ -631,10 +627,12 @@ func (r *Receiver) newReleaserFunc(receiver amqpwrap.AMQPReceiver) func() { } if internal.IsCancelError(err) { - log.Writef(exported.EventReceiver, "[%s] Message releaser pausing. Released %d messages", receiver.LinkName(), released) + if released > 0 { + r.amqpLinks.Writef(exported.EventReceiver, "Message releaser pausing. Released %d messages", released) + } break } else if internal.GetRecoveryKind(err) != internal.RecoveryKindNone { - log.Writef(exported.EventReceiver, "[%s] Message releaser stopping because of link failure. Released %d messages. Will start again after next receive: %s", receiver.LinkName(), released, err) + r.amqpLinks.Writef(exported.EventReceiver, "Message releaser stopping because of link failure. Released %d messages. Will start again after next receive: %s", released, err) break } } diff --git a/sdk/messaging/azservicebus/receiver_helpers_test.go b/sdk/messaging/azservicebus/receiver_helpers_test.go index 1a56ae304e9e..bb2fb6698ea4 100644 --- a/sdk/messaging/azservicebus/receiver_helpers_test.go +++ b/sdk/messaging/azservicebus/receiver_helpers_test.go @@ -7,7 +7,7 @@ import ( "context" "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus/internal/amqpwrap" - "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus/internal/go-amqp" + "github.com/Azure/go-amqp" ) type StubAMQPReceiver struct { diff --git a/sdk/messaging/azservicebus/receiver_simulated_test.go b/sdk/messaging/azservicebus/receiver_simulated_test.go index f61cd95878b5..b2444e3cb22a 100644 --- a/sdk/messaging/azservicebus/receiver_simulated_test.go +++ b/sdk/messaging/azservicebus/receiver_simulated_test.go @@ -14,10 +14,10 @@ import ( "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus/internal" "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus/internal/amqpwrap" "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus/internal/exported" - "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus/internal/go-amqp" "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus/internal/mock" "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus/internal/mock/emulation" "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus/internal/test" + "github.com/Azure/go-amqp" "github.com/golang/mock/gomock" "github.com/stretchr/testify/require" ) @@ -632,7 +632,9 @@ func TestReceiver_CreditsDontExceedMax(t *testing.T) { messages, err = receiver.ReceiveMessages(baseReceiveCtx, 5000, nil) require.NoError(t, err) require.Equal(t, []string{"hello world"}, getSortedBodies(messages)) - require.Contains(t, logsFn(), "[azsb.Receiver] No additional credits needed, still have 5000 credits active") + logs := logsFn() + + require.Contains(t, logs, "[azsb.Receiver] [c:1, l:1, r:name:c:001|] Have 5000 credits, no new credits needed") ctx, cancel = context.WithTimeout(baseReceiveCtx, time.Second) defer cancel() @@ -644,7 +646,7 @@ func TestReceiver_CreditsDontExceedMax(t *testing.T) { messages, err = receiver.ReceiveMessages(ctx, 5000, nil) require.ErrorIs(t, err, context.DeadlineExceeded) require.Empty(t, messages) - require.Contains(t, logsFn(), "[azsb.Receiver] Only need to issue 1 additional credits") + require.Contains(t, logsFn(), "[azsb.Receiver] [c:1, l:1, r:name:c:001|] Issuing 1 credits, have 4999") require.Equal(t, 1, len(md.Events.GetOpenConns())) require.Equal(t, 3+3, len(md.Events.GetOpenLinks()), "Sender and Receiver each own 3 links apiece ($mgmt, actual link)") diff --git a/sdk/messaging/azservicebus/receiver_test.go b/sdk/messaging/azservicebus/receiver_test.go index 640a6abe651e..d1617f77526a 100644 --- a/sdk/messaging/azservicebus/receiver_test.go +++ b/sdk/messaging/azservicebus/receiver_test.go @@ -6,7 +6,7 @@ package azservicebus import ( "context" "fmt" - "os" + "regexp" "sort" "strings" "testing" @@ -15,9 +15,9 @@ import ( "github.com/Azure/azure-sdk-for-go/sdk/azcore/to" "github.com/Azure/azure-sdk-for-go/sdk/azidentity" "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus/admin" - "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus/internal/go-amqp" "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus/internal/sas" "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus/internal/test" + "github.com/Azure/go-amqp" "github.com/stretchr/testify/require" ) @@ -569,8 +569,11 @@ func TestReceiver_RenewMessageLock(t *testing.T) { logMessages := endCaptureFn() failedOnFirstTry := false + + re := regexp.MustCompile(`^\[azsb.Receiver\] \[c:1, l:1, r:name:[^\]]+\] \(renewMessageLock\) Retry attempt 0 returned non-retryable error`) + for _, msg := range logMessages { - if strings.HasPrefix(msg, "[azsb.Receiver] (renewMessageLock) Retry attempt 0 returned non-retryable error") { + if re.MatchString(msg) { failedOnFirstTry = true } } @@ -607,7 +610,7 @@ func TestReceiverAMQPDataTypes(t *testing.T) { // - TypeCodeDecimal64 // - TypeCodeDecimal128 // - TypeCodeChar (although note below that a 'character' does work, although it's not a TypecodeChar value) - // https://github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus/internal/go-amqp/blob/e0c6c63fb01e6642686ee4f8e7412da042bf35dd/internal/encoding/decode.go#L568 + // https://github.com/Azure/go-amqp/blob/e0c6c63fb01e6642686ee4f8e7412da042bf35dd/internal/encoding/decode.go#L568 "timestamp": expectedTime, "byte": byte(128), @@ -866,14 +869,15 @@ func TestReceiverUnauthorizedCreds(t *testing.T) { }) t.Run("invalid identity creds", func(t *testing.T) { - tenantID := os.Getenv("AZURE_TENANT_ID") - clientID := os.Getenv("AZURE_CLIENT_ID") - endpoint := os.Getenv("SERVICEBUS_ENDPOINT") + identityVars := test.GetIdentityVars(t) + if identityVars == nil { + return + } - cliCred, err := azidentity.NewClientSecretCredential(tenantID, clientID, "bogus-client-secret", nil) + cliCred, err := azidentity.NewClientSecretCredential(identityVars.TenantID, identityVars.ClientID, "bogus-client-secret", nil) require.NoError(t, err) - client, err := NewClient(endpoint, cliCred, nil) + client, err := NewClient(identityVars.Endpoint, cliCred, nil) require.NoError(t, err) defer test.RequireClose(t, client) diff --git a/sdk/messaging/azservicebus/receiver_unit_test.go b/sdk/messaging/azservicebus/receiver_unit_test.go index d06f86f5ddf4..0b131f4ee9ca 100644 --- a/sdk/messaging/azservicebus/receiver_unit_test.go +++ b/sdk/messaging/azservicebus/receiver_unit_test.go @@ -13,8 +13,8 @@ import ( "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus/internal" "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus/internal/amqpwrap" "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus/internal/exported" - "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus/internal/go-amqp" "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus/internal/test" + "github.com/Azure/go-amqp" "github.com/stretchr/testify/require" ) @@ -183,9 +183,11 @@ func TestReceiver_releaserFunc(t *testing.T) { <-receiverClosed t.Logf("Receiver has closed") + logs := logsFn() + require.Contains(t, - logsFn(), - fmt.Sprintf("[azsb.Receiver] [fakelink] Message releaser pausing. Released %d messages", successfulReleases), + logs, + fmt.Sprintf("[azsb.Receiver] [prefix] Message releaser pausing. Released %d messages", successfulReleases), ) } @@ -224,7 +226,7 @@ func TestReceiver_releaserFunc_errorOnFirstMessage(t *testing.T) { require.Contains(t, logsFn(), - fmt.Sprintf("[azsb.Receiver] [fakelink] Message releaser stopping because of link failure. Released 0 messages. Will start again after next receive: %s", &amqp.LinkError{})) + fmt.Sprintf("[azsb.Receiver] Message releaser stopping because of link failure. Released 0 messages. Will start again after next receive: %s", &amqp.LinkError{})) } func TestReceiver_releaserFunc_receiveAndDeleteIsNoop(t *testing.T) { diff --git a/sdk/messaging/azservicebus/sender.go b/sdk/messaging/azservicebus/sender.go index 1c549c8094df..7e4c31d90773 100644 --- a/sdk/messaging/azservicebus/sender.go +++ b/sdk/messaging/azservicebus/sender.go @@ -5,12 +5,13 @@ package azservicebus import ( "context" + "errors" "time" "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus/internal" "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus/internal/amqpwrap" - "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus/internal/go-amqp" "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus/internal/utils" + "github.com/Azure/go-amqp" ) type ( @@ -33,7 +34,7 @@ type MessageBatchOptions struct { // NewMessageBatch can be used to create a batch that contain multiple // messages. Sending a batch of messages is more efficient than sending the // messages one at a time. -// If the operation fails it can return an *azservicebus.Error type if the failure is actionable. +// If the operation fails it can return an [*azservicebus.Error] type if the failure is actionable. func (s *Sender) NewMessageBatch(ctx context.Context, options *MessageBatchOptions) (*MessageBatch, error) { var batch *MessageBatch @@ -61,7 +62,9 @@ type SendMessageOptions struct { } // SendMessage sends a Message to a queue or topic. -// If the operation fails it can return an *azservicebus.Error type if the failure is actionable. +// If the operation fails it can return: +// - [ErrMessageTooLarge] if the message is larger than the maximum allowed link size. +// - An [*azservicebus.Error] type if the failure is actionable. func (s *Sender) SendMessage(ctx context.Context, message *Message, options *SendMessageOptions) error { return s.sendMessage(ctx, message) } @@ -74,7 +77,9 @@ type SendAMQPAnnotatedMessageOptions struct { // SendAMQPAnnotatedMessage sends an AMQPMessage to a queue or topic. // Using an AMQPMessage allows for advanced use cases, like payload encoding, as well as better // interoperability with pure AMQP clients. -// If the operation fails it can return an *azservicebus.Error type if the failure is actionable. +// If the operation fails it can return: +// - [ErrMessageTooLarge] if the message is larger than the maximum allowed link size. +// - An [*azservicebus.Error] type if the failure is actionable. func (s *Sender) SendAMQPAnnotatedMessage(ctx context.Context, message *AMQPAnnotatedMessage, options *SendAMQPAnnotatedMessageOptions) error { return s.sendMessage(ctx, message) } @@ -171,6 +176,10 @@ func (s *Sender) sendMessage(ctx context.Context, message amqpCompatibleMessage) return lwid.Sender.Send(ctx, message.toAMQPMessage(), nil) }, RetryOptions(s.retryOptions)) + if amqpErr := (*amqp.Error)(nil); errors.As(err, &amqpErr) && amqpErr.Condition == amqp.ErrCondMessageSizeExceeded { + return ErrMessageTooLarge + } + return internal.TransformError(err) } diff --git a/sdk/messaging/azservicebus/sender_test.go b/sdk/messaging/azservicebus/sender_test.go index 0c0892a55b28..e3648f8f9148 100644 --- a/sdk/messaging/azservicebus/sender_test.go +++ b/sdk/messaging/azservicebus/sender_test.go @@ -734,3 +734,47 @@ func (rm receivedMessages) Less(i, j int) bool { func (rm receivedMessages) Swap(i, j int) { rm[i], rm[j] = rm[j], rm[i] } + +func Test_Sender_Send_MessageTooBig(t *testing.T) { + client, cleanup, queueName := setupLiveTest(t, &liveTestOptions{ + ClientOptions: &ClientOptions{ + RetryOptions: RetryOptions{ + // This is a purposefully ridiculous wait time but we'll never hit it + // because exceeding the max message size is NOT a retryable error. + RetryDelay: time.Hour, + }, + }, + QueueProperties: &admin.QueueProperties{ + EnablePartitioning: to.Ptr(true), + }}) + defer cleanup() + + sender, err := client.NewSender(queueName, nil) + require.NoError(t, err) + + hugePayload := []byte{} + + for i := 0; i < 1000*1000; i++ { + hugePayload = append(hugePayload, 100) + } + + ctx, cancel := context.WithTimeout(context.Background(), time.Minute) + defer cancel() + err = sender.SendMessage(ctx, &Message{ + MessageID: to.Ptr("message with a message ID"), + Body: hugePayload, + }, nil) + + require.ErrorIs(t, err, ErrMessageTooLarge) + + ctx, cancel = context.WithTimeout(context.Background(), time.Minute) + defer cancel() + + err = sender.SendAMQPAnnotatedMessage(ctx, &AMQPAnnotatedMessage{ + Body: AMQPAnnotatedMessageBody{ + Data: [][]byte{hugePayload}, + }, + }, nil) + + require.ErrorIs(t, err, ErrMessageTooLarge) +} diff --git a/sdk/messaging/azservicebus/sender_unit_test.go b/sdk/messaging/azservicebus/sender_unit_test.go index 5ab1781b9eba..b676ffc75150 100644 --- a/sdk/messaging/azservicebus/sender_unit_test.go +++ b/sdk/messaging/azservicebus/sender_unit_test.go @@ -8,8 +8,8 @@ import ( "testing" "time" - "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus/internal/go-amqp" "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus/internal/mock/emulation" + "github.com/Azure/go-amqp" "github.com/golang/mock/gomock" "github.com/stretchr/testify/require" ) diff --git a/sdk/messaging/azservicebus/session_receiver.go b/sdk/messaging/azservicebus/session_receiver.go index 07ee1ba90276..6b9a0f9af450 100644 --- a/sdk/messaging/azservicebus/session_receiver.go +++ b/sdk/messaging/azservicebus/session_receiver.go @@ -10,8 +10,8 @@ import ( "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus/internal" "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus/internal/amqpwrap" - "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus/internal/go-amqp" "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus/internal/utils" + "github.com/Azure/go-amqp" ) // SessionReceiver is a Receiver that handles sessions. diff --git a/sdk/messaging/azservicebus/session_receiver_test.go b/sdk/messaging/azservicebus/session_receiver_test.go index c58e4b6b3797..5a0c89ff877f 100644 --- a/sdk/messaging/azservicebus/session_receiver_test.go +++ b/sdk/messaging/azservicebus/session_receiver_test.go @@ -14,8 +14,8 @@ import ( "github.com/Azure/azure-sdk-for-go/sdk/azcore/to" "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus/admin" "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus/internal" - "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus/internal/go-amqp" "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus/internal/test" + "github.com/Azure/go-amqp" "github.com/stretchr/testify/require" ) diff --git a/sdk/monitor/azquery/CHANGELOG.md b/sdk/monitor/azquery/CHANGELOG.md index c0367796af1b..fb6606ebc3e5 100644 --- a/sdk/monitor/azquery/CHANGELOG.md +++ b/sdk/monitor/azquery/CHANGELOG.md @@ -1,6 +1,6 @@ # Release History -## 1.1.0-beta.2 (Unreleased) +## 1.1.1 (Unreleased) ### Features Added @@ -10,6 +10,11 @@ ### Other Changes +## 1.1.0 (2023-05-09) + +### Other Changes +* Updated doc comments + ## 1.1.0-beta.1 (2023-04-11) ### Features Added diff --git a/sdk/monitor/azquery/MIGRATION.md b/sdk/monitor/azquery/MIGRATION.md new file mode 100644 index 000000000000..caf6c162586b --- /dev/null +++ b/sdk/monitor/azquery/MIGRATION.md @@ -0,0 +1,177 @@ +# Guide to migrate from `operationalinsights` and monitor `insights` to `azquery` + +This guide is intended to assist in the migration to the `azquery` module. `azquery` allows users to retrieve log and metric data from Azure Monitor. + +## Package consolidation + + Azure Monitor allows users to retrieve telemetry data for their Azure resources. The main two data catagories for Azure Monitor are [metrics](https://learn.microsoft.com/azure/azure-monitor/essentials/data-platform-metrics) and [logs](https://learn.microsoft.com/azure/azure-monitor/logs/data-platform-logs). + + There have been a number of [terminology](https://learn.microsoft.com/azure/azure-monitor/terminology) changes for Azure Monitor over the years which resulted in the operations being spread over multiple packages. For Go, metrics methods were contained in `github.com/Azure/azure-sdk-for-go/services/preview/monitor/mgmt//insights` and logs methods resided in `github.com/Azure/azure-sdk-for-go/services/operationalinsights/v1/operationalinsights`. + +The new `azquery` module condenses metrics and logs functionality into one package for simpler access. The `azquery` module contains two clients: [LogsClient](https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/monitor/azquery#LogsClient) and [MetricsClient](https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/monitor/azquery#MetricsClient). + +Transitioning to a single package has resulted in a number of name changes, as detailed below. + +### Log name changes + +| `operationalinsights` | `azquery` | +| ----------- | ----------- | +| QueryClient.Execute | LogsClient.QueryWorkspace | +| MetadataClient.Get and MetadataClient.Post | N/A | + +The `azquery` module does not contain the `MetadataClient`. For that functionality, please use the old [`operationalinsights`](https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/services/operationalinsights/v1/operationalinsights) module or [file an issue in our github repo](https://github.com/Azure/azure-sdk-for-go/issues), so we can prioritize adding it to `azquery`. + +### Metrics name changes + +| `insights` | `azquery` | +| ----------- | ----------- | +| MetricsClient.List | MetricsClient.QueryResource | +| MetricDefinitionsClient.List | MetricsClient.NewListDefinitionsPager | +| MetricNamespacesClient.List | MetricsClient.NewListNamespacesPager | + +## Query Logs + +### `operationalinsights` +```go +import ( + "context" + + "github.com/Azure/azure-sdk-for-go/services/operationalinsights/v1/operationalinsights" + "github.com/Azure/go-autorest/autorest" +) + +// create the client +client := operationalinsights.NewQueryClient() +client.Authorizer = autorest.NewAPIKeyAuthorizerWithHeaders(map[string]interface{}{ + "x-api-key": "DEMO_KEY", +}) + +// execute the query +query := "" +timespan := "2023-12-25/2023-12-26" + +res, err := client.Execute(context.TODO(), "DEMO_WORKSPACE", operationalinsights.QueryBody{Query: &query, Timespan: ×pan}) +if err != nil { + //TODO: handle error +} +``` + +### `azquery` + +Compared to previous versions, querying logs with the new `azquery` module is clearer and simpler. There are a number of name changes for clarity, like how the old `Execute` method is now [`QueryWorkspace`](https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/monitor/azquery#LogsClient.QueryWorkspace). In addition, there is improved time support. Before if a user added a timespan over which to query the request, it had to be a string constructed in the ISO8601 interval format. Users frequently made mistakes when constructing this string. With the new `QueryWorkspace` method, the type of timespan has been changed from a string to a new type named [`TimeInterval`](https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/monitor/azquery#TimeInterval). `TimeInterval` has a contructor that allows users to take advantage of Go's time package, allowing easier creation. + +```go +import ( + "context" + "time" + + "github.com/Azure/azure-sdk-for-go/sdk/azcore/to" + "github.com/Azure/azure-sdk-for-go/sdk/azidentity" + "github.com/Azure/azure-sdk-for-go/sdk/monitor/azquery" +) + +// create the logs client +cred, err := azidentity.NewDefaultAzureCredential(nil) +if err != nil { + //TODO: handle error +} +client, err := azquery.NewLogsClient(cred, nil) +if err != nil { + //TODO: handle error +} + +// execute the logs query +res, err := client.QueryWorkspace(context.TODO(), workspaceID, + azquery.Body{ + Query: to.Ptr(""), + Timespan: to.Ptr(azquery.NewTimeInterval(time.Date(2022, 12, 25, 0, 0, 0, 0, time.UTC), time.Date(2022, 12, 25, 12, 0, 0, 0, time.UTC))), + }, + nil) +if err != nil { + //TODO: handle error +} +if res.Error != nil { + //TODO: handle partial error +} +``` + +## Query Metrics + +### `insights` + +```go +import ( + "context" + + "github.com/Azure/azure-sdk-for-go/services/preview/monitor/mgmt/2022-10-01-preview/insights" + "github.com/Azure/go-autorest/autorest/azure/auth" +) + +// create the client +client := insights.NewMetricsClient("") +authorizer, err := auth.NewAuthorizerFromCLI() +if err == nil { + client.Authorizer = authorizer +} + +// execute the query +timespan := "2023-12-25/2023-12-26" +interval := "PT1M" +metricnames := "" +aggregation := "Average" +top := 3 +orderby := "Average asc" +filter := "BlobType eq '*'" +resultType := insights.ResultTypeData +metricnamespace := "Microsoft.Storage/storageAccounts/blobServices" + +res, err := client.List(context.TODO(), resourceURI, timespan, &interval, metricnames, aggregation, &top, orderby, filter, resultType, metricnamespace) +if err != nil { + //TODO: handle error +} +``` + +### `azquery` + +The main difference between the old and new methods of querying metrics is in the naming. The new method has an updated convention for clarity. For example, the old name of the method was simply `List`. Now, it's `QueryResource`. There have also been a number of casing fixes and the query options have been moved into the options struct. + +```go +import ( + "context" + "time" + + "github.com/Azure/azure-sdk-for-go/sdk/azcore/to" + "github.com/Azure/azure-sdk-for-go/sdk/azidentity" + "github.com/Azure/azure-sdk-for-go/sdk/monitor/azquery" +) + +// create the metrics client +cred, err := azidentity.NewDefaultAzureCredential(nil) +if err != nil { + //TODO: handle error +} +client, err := azquery.NewMetricsClient(cred, nil) +if err != nil { + //TODO: handle error +} + +// execute the metrics query +res, err := metricsClient.QueryResource(context.TODO(), resourceURI, + &azquery.MetricsClientQueryResourceOptions{ + Timespan: to.Ptr(azquery.NewTimeInterval(time.Date(2022, 12, 25, 0, 0, 0, 0, time.UTC), time.Date(2022, 12, 25, 12, 0, 0, 0, time.UTC))), + Interval: to.Ptr("PT1M"), + MetricNames: nil, + Aggregation: to.SliceOfPtrs(azquery.AggregationTypeAverage, azquery.AggregationTypeCount), + Top: to.Ptr[int32](3), + OrderBy: to.Ptr("Average asc"), + Filter: to.Ptr("BlobType eq '*'"), + ResultType: nil, + MetricNamespace: to.Ptr("Microsoft.Storage/storageAccounts/blobServices"), + }) +if err != nil { + //TODO: handle error +} +``` + + + diff --git a/sdk/monitor/azquery/autorest.md b/sdk/monitor/azquery/autorest.md index 52b9cdea95f8..d2b07a06316f 100644 --- a/sdk/monitor/azquery/autorest.md +++ b/sdk/monitor/azquery/autorest.md @@ -9,7 +9,7 @@ clear-output-folder: false export-clients: true go: true input-file: - - https://github.com/Azure/azure-rest-api-specs/blob/605407bc0c1a133018285f550d01175469cb3c3a/specification/operationalinsights/data-plane/Microsoft.OperationalInsights/stable/2022-10-27/OperationalInsights.json + - https://github.com/Azure/azure-rest-api-specs/blob/72427ef3ff5875bd8409ef112ef5e6f3cf2b8795/specification/operationalinsights/data-plane/Microsoft.OperationalInsights/stable/2022-10-27/OperationalInsights.json - https://github.com/Azure/azure-rest-api-specs/blob/dba6ed1f03bda88ac6884c0a883246446cc72495/specification/monitor/resource-manager/Microsoft.Insights/stable/2018-01-01/metricDefinitions_API.json - https://github.com/Azure/azure-rest-api-specs/blob/dba6ed1f03bda88ac6884c0a883246446cc72495/specification/monitor/resource-manager/Microsoft.Insights/stable/2018-01-01/metrics_API.json - https://github.com/Azure/azure-rest-api-specs/blob/dba6ed1f03bda88ac6884c0a883246446cc72495/specification/monitor/resource-manager/Microsoft.Insights/preview/2017-12-01-preview/metricNamespaces_API.json @@ -152,48 +152,10 @@ directive: transform: $["name"] = "BatchQueryRequestMethod" # add descriptions for models and constants that don't have them - - from: swagger-document - where: $.definitions.batchQueryRequest.properties.path - transform: $["description"] = "The query path of a single request in a batch, defaults to /query" - - from: swagger-document - where: $.definitions.batchQueryRequest.properties.method - transform: $["description"] = "The method of a single request in a batch, defaults to POST" - - from: swagger-document - where: $.definitions.batchQueryResponse - transform: $["description"] = "Contains the batch query response and the headers, id, and status of the request" - from: constants.go where: $ transform: return $.replace(/type ResultType string/, "//ResultType - Reduces the set of data collected. The syntax allowed depends on the operation. See the operation's description for details.\ntype ResultType string"); - # update doc comments - - from: swagger-document - where: $.paths["/workspaces/{workspaceId}/query"].post - transform: $["description"] = "Executes an Analytics query for data." - - from: swagger-document - where: $.paths["/$batch"].post - transform: $["description"] = "Executes a batch of Analytics queries for data." - - from: swagger-document - where: $.definitions.queryResults.properties.tables - transform: $["description"] = "The results of the query in tabular format." - - from: swagger-document - where: $.definitions.batchQueryResults.properties.tables - transform: $["description"] = "The results of the query in tabular format." - - from: swagger-document - where: $.definitions.queryBody.properties.workspaces - transform: $["description"] = "A list of workspaces to query in addition to the primary workspace." - - from: swagger-document - where: $.definitions.batchQueryRequest.properties.headers - transform: $["description"] = "Optional. Headers of the request. Can use prefer header to set server timeout, query statistics and visualization information. For more information, see https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/monitor/azquery#readme-increase-wait-time-include-statistics-include-render-visualization" - - from: swagger-document - where: $.definitions.batchQueryRequest.properties.workspace - transform: $["description"] = "Primary Workspace ID of the query" - - from: swagger-document - where: $.definitions.batchQueryRequest.properties.id - transform: $["description"] = "Unique ID corresponding to each request in the batch" - - from: swagger-document - where: $.parameters.workspaceId - transform: $["description"] = "Primary Workspace ID of the query. This is Workspace ID from the Properties blade in the Azure portal" - # delete unused error models - from: models.go where: $ @@ -222,29 +184,7 @@ directive: # change Table.Rows from type [][]interface{} to type []Row - from: models.go where: $ - transform: return $.replace(/Rows \[\]\[\]any/, "Rows []Row"); - - # change render and statistics type to []byte - - from: models.go - where: $ - transform: return $.replace(/Statistics any/g, "Statistics []byte"); - - from: models.go - where: $ - transform: return $.replace(/Visualization any/g, "Visualization []byte"); - - from: models_serde.go - where: $ - transform: return - $.replace(/err(.*)r\.Statistics\)/, "r.Statistics = val") - - from: models_serde.go - where: $ - transform: return $.replace(/err(.*)r\.Visualization\)/, "r.Visualization = val"); - - from: models_serde.go - where: $ - transform: return - $.replace(/err(.*)b\.Statistics\)/, "b.Statistics = val") - - from: models_serde.go - where: $ - transform: return $.replace(/err(.*)b\.Visualization\)/, "b.Visualization = val"); + transform: return $.replace(/Rows \[\]\[\]byte/, "Rows []Row"); # change type of timespan from *string to *TimeInterval - from: models.go diff --git a/sdk/monitor/azquery/build.go b/sdk/monitor/azquery/build.go index d547e0d3ce3c..8634768d24b1 100644 --- a/sdk/monitor/azquery/build.go +++ b/sdk/monitor/azquery/build.go @@ -1,7 +1,7 @@ //go:build go1.18 // +build go1.18 -//go:generate autorest ./autorest.md +//go:generate autorest ./autorest.md --rawjson-as-bytes //go:generate gofmt -w . // Copyright (c) Microsoft Corporation. All rights reserved. diff --git a/sdk/monitor/azquery/logs_client.go b/sdk/monitor/azquery/logs_client.go index 9d22842a5111..d12a59eda261 100644 --- a/sdk/monitor/azquery/logs_client.go +++ b/sdk/monitor/azquery/logs_client.go @@ -27,7 +27,8 @@ type LogsClient struct { internal *azcore.Client } -// QueryBatch - Executes a batch of Analytics queries for data. +// QueryBatch - Executes a batch of Analytics queries for data. Here [https://learn.microsoft.com/azure/azure-monitor/logs/api/batch-queries] +// is an example for using POST with an Analytics query. // If the operation fails it returns an *azcore.ResponseError type. // // Generated from API version 2022-10-27 @@ -68,7 +69,7 @@ func (client *LogsClient) queryBatchHandleResponse(resp *http.Response) (LogsCli return result, nil } -// QueryResource - Executes an Analytics query for data in the context of a resource. Here [https://docs.microsoft.com/azure/azure-monitor/logs/api/azure-resource-queries] +// QueryResource - Executes an Analytics query for data in the context of a resource. Here [https://learn.microsoft.com/azure/azure-monitor/logs/api/azure-resource-queries] // is an example for using POST with an Analytics // query. // If the operation fails it returns an *azcore.ResponseError type. @@ -116,11 +117,12 @@ func (client *LogsClient) queryResourceHandleResponse(resp *http.Response) (Logs return result, nil } -// QueryWorkspace - Executes an Analytics query for data. +// QueryWorkspace - Executes an Analytics query for data. Here [https://learn.microsoft.com/azure/azure-monitor/logs/api/request-format] +// is an example for using POST with an Analytics query. // If the operation fails it returns an *azcore.ResponseError type. // // Generated from API version 2022-10-27 -// - workspaceID - Primary Workspace ID of the query. This is Workspace ID from the Properties blade in the Azure portal +// - workspaceID - Primary Workspace ID of the query. This is the Workspace ID from the Properties blade in the Azure portal. // - body - The Analytics query. Learn more about the Analytics query syntax [https://azure.microsoft.com/documentation/articles/app-insights-analytics-reference/] // - options - LogsClientQueryWorkspaceOptions contains the optional parameters for the LogsClient.QueryWorkspace method. func (client *LogsClient) QueryWorkspace(ctx context.Context, workspaceID string, body Body, options *LogsClientQueryWorkspaceOptions) (LogsClientQueryWorkspaceResponse, error) { diff --git a/sdk/monitor/azquery/models.go b/sdk/monitor/azquery/models.go index 6185b68ca31c..1fc49eeeb8f9 100644 --- a/sdk/monitor/azquery/models.go +++ b/sdk/monitor/azquery/models.go @@ -16,15 +16,13 @@ type BatchQueryRequest struct { // REQUIRED; The Analytics query. Learn more about the Analytics query syntax [https://azure.microsoft.com/documentation/articles/app-insights-analytics-reference/] Body *Body `json:"body,omitempty"` - // REQUIRED; Unique ID corresponding to each request in the batch + // REQUIRED; Unique ID corresponding to each request in the batch. CorrelationID *string `json:"id,omitempty"` - // REQUIRED; Primary Workspace ID of the query + // REQUIRED; Primary Workspace ID of the query. This is the Workspace ID from the Properties blade in the Azure portal. WorkspaceID *string `json:"workspace,omitempty"` - // Optional. Headers of the request. Can use prefer header to set server timeout, query statistics and visualization information. - // For more information, see - // https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/monitor/azquery#readme-increase-wait-time-include-statistics-include-render-visualization + // Headers of the request. Can use prefer header to set server timeout and to query statistics and visualization information. Headers map[string]*string `json:"headers,omitempty"` // The method of a single request in a batch, defaults to POST diff --git a/sdk/monitor/azquery/models_serde.go b/sdk/monitor/azquery/models_serde.go index 9667f3ecec6f..26af83bea4e6 100644 --- a/sdk/monitor/azquery/models_serde.go +++ b/sdk/monitor/azquery/models_serde.go @@ -113,9 +113,9 @@ func (b *BatchQueryResponse) UnmarshalJSON(data []byte) error { func (b BatchQueryResults) MarshalJSON() ([]byte, error) { objectMap := make(map[string]any) populate(objectMap, "error", b.Error) - populate(objectMap, "statistics", &b.Statistics) + populate(objectMap, "statistics", json.RawMessage(b.Statistics)) populate(objectMap, "tables", b.Tables) - populate(objectMap, "render", &b.Visualization) + populate(objectMap, "render", json.RawMessage(b.Visualization)) return json.Marshal(objectMap) } @@ -713,9 +713,9 @@ func (r *Response) UnmarshalJSON(data []byte) error { func (r Results) MarshalJSON() ([]byte, error) { objectMap := make(map[string]any) populate(objectMap, "error", r.Error) - populate(objectMap, "statistics", &r.Statistics) + populate(objectMap, "statistics", json.RawMessage(r.Statistics)) populate(objectMap, "tables", r.Tables) - populate(objectMap, "render", &r.Visualization) + populate(objectMap, "render", json.RawMessage(r.Visualization)) return json.Marshal(objectMap) } diff --git a/sdk/monitor/azquery/version.go b/sdk/monitor/azquery/version.go index 58d40bd4c5d0..3e826b868deb 100644 --- a/sdk/monitor/azquery/version.go +++ b/sdk/monitor/azquery/version.go @@ -8,5 +8,5 @@ package azquery const ( moduleName = "azquery" - version = "v1.1.0-beta.2" + version = "v1.1.1" ) diff --git a/sdk/resourcemanager/compute/armcompute/assets.json b/sdk/resourcemanager/compute/armcompute/assets.json index 740c95e53803..ac6ee8d491e5 100644 --- a/sdk/resourcemanager/compute/armcompute/assets.json +++ b/sdk/resourcemanager/compute/armcompute/assets.json @@ -2,5 +2,5 @@ "AssetsRepo": "Azure/azure-sdk-assets", "AssetsRepoPrefixPath": "go", "TagPrefix": "go/resourcemanager/compute/armcompute", - "Tag": "go/resourcemanager/compute/armcompute_7dca156240" + "Tag": "go/resourcemanager/compute/armcompute_d7f582b36e" } diff --git a/sdk/resourcemanager/compute/armcompute/availabilityset_live_test.go b/sdk/resourcemanager/compute/armcompute/availabilityset_live_test.go new file mode 100644 index 000000000000..938bb22c9b5a --- /dev/null +++ b/sdk/resourcemanager/compute/armcompute/availabilityset_live_test.go @@ -0,0 +1,117 @@ +//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. +// Code generated by Microsoft (R) AutoRest Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. + +package armcompute_test + +import ( + "context" + "fmt" + "testing" + + "github.com/Azure/azure-sdk-for-go/sdk/azcore" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/arm" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/to" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v4" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/internal/testutil" + "github.com/stretchr/testify/suite" +) + +type AvailabilitySetTestSuite struct { + suite.Suite + + ctx context.Context + cred azcore.TokenCredential + options *arm.ClientOptions + location string + resourceGroupName string + subscriptionId string + availabilitySetName string +} + +func (testsuite *AvailabilitySetTestSuite) SetupSuite() { + testutil.StartRecording(testsuite.T(), "sdk/resourcemanager/compute/armcompute/testdata") + + testsuite.ctx = context.Background() + testsuite.cred, testsuite.options = testutil.GetCredAndClientOptions(testsuite.T()) + testsuite.availabilitySetName = testutil.GenerateAlphaNumericID(testsuite.T(), "availabili", 6) + testsuite.location = testutil.GetEnv("LOCATION", "eastus") + testsuite.resourceGroupName = testutil.GetEnv("RESOURCE_GROUP_NAME", "scenarioTestTempGroup") + testsuite.subscriptionId = testutil.GetEnv("AZURE_SUBSCRIPTION_ID", "00000000-0000-0000-0000-000000000000") + resourceGroup, _, err := testutil.CreateResourceGroup(testsuite.ctx, testsuite.subscriptionId, testsuite.cred, testsuite.options, testsuite.location) + testsuite.Require().NoError(err) + testsuite.resourceGroupName = *resourceGroup.Name +} + +func (testsuite *AvailabilitySetTestSuite) TearDownSuite() { + _, err := testutil.DeleteResourceGroup(testsuite.ctx, testsuite.subscriptionId, testsuite.cred, testsuite.options, testsuite.resourceGroupName) + testsuite.Require().NoError(err) + testutil.StopRecording(testsuite.T()) +} + +func TestAvailabilitySetTestSuite(t *testing.T) { + suite.Run(t, new(AvailabilitySetTestSuite)) +} + +// Microsoft.Compute/availabilitySets +func (testsuite *AvailabilitySetTestSuite) TestAvailabilitySets() { + var err error + // From step AvailabilitySets_CreateOrUpdate + fmt.Println("Call operation: AvailabilitySets_CreateOrUpdate") + availabilitySetsClient, err := armcompute.NewAvailabilitySetsClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + _, err = availabilitySetsClient.CreateOrUpdate(testsuite.ctx, testsuite.resourceGroupName, testsuite.availabilitySetName, armcompute.AvailabilitySet{ + Location: to.Ptr(testsuite.location), + Properties: &armcompute.AvailabilitySetProperties{ + PlatformFaultDomainCount: to.Ptr[int32](2), + PlatformUpdateDomainCount: to.Ptr[int32](20), + }, + }, nil) + testsuite.Require().NoError(err) + + // From step AvailabilitySets_ListBySubscription + fmt.Println("Call operation: AvailabilitySets_ListBySubscription") + availabilitySetsClientNewListBySubscriptionPager := availabilitySetsClient.NewListBySubscriptionPager(&armcompute.AvailabilitySetsClientListBySubscriptionOptions{Expand: nil}) + for availabilitySetsClientNewListBySubscriptionPager.More() { + _, err := availabilitySetsClientNewListBySubscriptionPager.NextPage(testsuite.ctx) + testsuite.Require().NoError(err) + break + } + + // From step AvailabilitySets_List + fmt.Println("Call operation: AvailabilitySets_List") + availabilitySetsClientNewListPager := availabilitySetsClient.NewListPager(testsuite.resourceGroupName, nil) + for availabilitySetsClientNewListPager.More() { + _, err := availabilitySetsClientNewListPager.NextPage(testsuite.ctx) + testsuite.Require().NoError(err) + break + } + + // From step AvailabilitySets_Get + fmt.Println("Call operation: AvailabilitySets_Get") + _, err = availabilitySetsClient.Get(testsuite.ctx, testsuite.resourceGroupName, testsuite.availabilitySetName, nil) + testsuite.Require().NoError(err) + + // From step AvailabilitySets_ListAvailableSizes + fmt.Println("Call operation: AvailabilitySets_ListAvailableSizes") + availabilitySetsClientNewListAvailableSizesPager := availabilitySetsClient.NewListAvailableSizesPager(testsuite.resourceGroupName, testsuite.availabilitySetName, nil) + for availabilitySetsClientNewListAvailableSizesPager.More() { + _, err := availabilitySetsClientNewListAvailableSizesPager.NextPage(testsuite.ctx) + testsuite.Require().NoError(err) + break + } + + // From step AvailabilitySets_Update + fmt.Println("Call operation: AvailabilitySets_Update") + _, err = availabilitySetsClient.Update(testsuite.ctx, testsuite.resourceGroupName, testsuite.availabilitySetName, armcompute.AvailabilitySetUpdate{}, nil) + testsuite.Require().NoError(err) + + // From step AvailabilitySets_Delete + fmt.Println("Call operation: AvailabilitySets_Delete") + _, err = availabilitySetsClient.Delete(testsuite.ctx, testsuite.resourceGroupName, testsuite.availabilitySetName, nil) + testsuite.Require().NoError(err) +} diff --git a/sdk/resourcemanager/compute/armcompute/availabilitysets_client_live_test.go b/sdk/resourcemanager/compute/armcompute/availabilitysets_client_live_test.go deleted file mode 100644 index 014e6b7e340c..000000000000 --- a/sdk/resourcemanager/compute/armcompute/availabilitysets_client_live_test.go +++ /dev/null @@ -1,120 +0,0 @@ -//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 armcompute_test - -import ( - "context" - "fmt" - "testing" - - "github.com/Azure/azure-sdk-for-go/sdk/azcore" - "github.com/Azure/azure-sdk-for-go/sdk/azcore/arm" - "github.com/Azure/azure-sdk-for-go/sdk/azcore/to" - "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v4" - "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/internal/testutil" - "github.com/stretchr/testify/suite" -) - -type AvailabilitySetsClientTestSuite struct { - suite.Suite - - ctx context.Context - cred azcore.TokenCredential - options *arm.ClientOptions - location string - resourceGroupName string - subscriptionID string -} - -func (testsuite *AvailabilitySetsClientTestSuite) SetupSuite() { - testsuite.ctx = context.Background() - testsuite.cred, testsuite.options = testutil.GetCredAndClientOptions(testsuite.T()) - testsuite.location = testutil.GetEnv("LOCATION", "eastus") - testsuite.subscriptionID = testutil.GetEnv("AZURE_SUBSCRIPTION_ID", "00000000-0000-0000-0000-000000000000") - testutil.StartRecording(testsuite.T(), "sdk/resourcemanager/compute/armcompute/testdata") - resourceGroup, _, err := testutil.CreateResourceGroup(testsuite.ctx, testsuite.subscriptionID, testsuite.cred, testsuite.options, testsuite.location) - testsuite.Require().NoError(err) - testsuite.resourceGroupName = *resourceGroup.Name -} - -func (testsuite *AvailabilitySetsClientTestSuite) TearDownSuite() { - _, err := testutil.DeleteResourceGroup(testsuite.ctx, testsuite.subscriptionID, testsuite.cred, testsuite.options, testsuite.resourceGroupName) - testsuite.Require().NoError(err) - testutil.StopRecording(testsuite.T()) -} - -func TestAvailabilitySetsClient(t *testing.T) { - suite.Run(t, new(AvailabilitySetsClientTestSuite)) -} - -func (testsuite *AvailabilitySetsClientTestSuite) TestAvailabilitySetsCRUD() { - // create availability sets - fmt.Println("Call operation: AvailabilitySets_CreateOrUpdate") - client, err := armcompute.NewAvailabilitySetsClient(testsuite.subscriptionID, testsuite.cred, testsuite.options) - testsuite.Require().NoError(err) - name := "go-test-availability" - resp, err := client.CreateOrUpdate( - testsuite.ctx, - testsuite.resourceGroupName, - name, - armcompute.AvailabilitySet{ - Location: to.Ptr("westus"), - SKU: &armcompute.SKU{ - Name: to.Ptr(string(armcompute.AvailabilitySetSKUTypesAligned)), - }, - Properties: &armcompute.AvailabilitySetProperties{ - PlatformFaultDomainCount: to.Ptr[int32](1), - PlatformUpdateDomainCount: to.Ptr[int32](1), - }, - }, - nil, - ) - testsuite.Require().NoError(err) - testsuite.Require().Equal(*resp.Name, name) - - // get - fmt.Println("Call operation: AvailabilitySets_Get") - getResp, err := client.Get(testsuite.ctx, testsuite.resourceGroupName, name, nil) - testsuite.Require().NoError(err) - testsuite.Require().Equal(*getResp.Name, name) - - // list - fmt.Println("Call operation: AvailabilitySets_List") - listPager := client.NewListPager(testsuite.resourceGroupName, nil) - testsuite.Require().True(listPager.More()) - - // list available size - fmt.Println("Call operation: AvailabilitySets_ListAvailableSize") - listResp := client.NewListAvailableSizesPager(testsuite.resourceGroupName, name, nil) - testsuite.Require().True(listResp.More()) - - // list by subscription - fmt.Println("Call operation: AvailabilitySets_ListBySubscription") - listBySubscription := client.NewListBySubscriptionPager(nil) - testsuite.Require().True(listBySubscription.More()) - - // update - fmt.Println("Call operation: AvailabilitySets_Update") - updateResp, err := client.Update( - testsuite.ctx, - testsuite.resourceGroupName, - name, - armcompute.AvailabilitySetUpdate{ - Tags: map[string]*string{ - "tag": to.Ptr("value"), - }, - }, - nil, - ) - testsuite.Require().NoError(err) - testsuite.Require().Equal(name, *updateResp.Name) - - // delete - fmt.Println("Call operation: AvailabilitySets_Delete") - _, err = client.Delete(testsuite.ctx, testsuite.resourceGroupName, name, nil) - testsuite.Require().NoError(err) -} diff --git a/sdk/resourcemanager/compute/armcompute/capacityreservation_live_test.go b/sdk/resourcemanager/compute/armcompute/capacityreservation_live_test.go new file mode 100644 index 000000000000..768fca18eae0 --- /dev/null +++ b/sdk/resourcemanager/compute/armcompute/capacityreservation_live_test.go @@ -0,0 +1,122 @@ +//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. +// Code generated by Microsoft (R) AutoRest Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. + +package armcompute_test + +import ( + "context" + "fmt" + "testing" + + "github.com/Azure/azure-sdk-for-go/sdk/azcore" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/arm" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/to" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v4" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/internal/testutil" + "github.com/stretchr/testify/suite" +) + +type CapacityReservationTestSuite struct { + suite.Suite + + ctx context.Context + cred azcore.TokenCredential + options *arm.ClientOptions + capacityReservationGroupName string + location string + resourceGroupName string + subscriptionId string +} + +func (testsuite *CapacityReservationTestSuite) SetupSuite() { + testutil.StartRecording(testsuite.T(), "sdk/resourcemanager/compute/armcompute/testdata") + + testsuite.ctx = context.Background() + testsuite.cred, testsuite.options = testutil.GetCredAndClientOptions(testsuite.T()) + testsuite.capacityReservationGroupName = testutil.GenerateAlphaNumericID(testsuite.T(), "capacityre", 6) + testsuite.location = testutil.GetEnv("LOCATION", "eastus") + testsuite.resourceGroupName = testutil.GetEnv("RESOURCE_GROUP_NAME", "scenarioTestTempGroup") + testsuite.subscriptionId = testutil.GetEnv("AZURE_SUBSCRIPTION_ID", "00000000-0000-0000-0000-000000000000") + resourceGroup, _, err := testutil.CreateResourceGroup(testsuite.ctx, testsuite.subscriptionId, testsuite.cred, testsuite.options, testsuite.location) + testsuite.Require().NoError(err) + testsuite.resourceGroupName = *resourceGroup.Name + testsuite.Prepare() +} + +func (testsuite *CapacityReservationTestSuite) TearDownSuite() { + testsuite.Cleanup() + _, err := testutil.DeleteResourceGroup(testsuite.ctx, testsuite.subscriptionId, testsuite.cred, testsuite.options, testsuite.resourceGroupName) + testsuite.Require().NoError(err) + testutil.StopRecording(testsuite.T()) +} + +func TestCapacityReservationTestSuite(t *testing.T) { + suite.Run(t, new(CapacityReservationTestSuite)) +} + +func (testsuite *CapacityReservationTestSuite) Prepare() { + var err error + // From step CapacityReservationGroups_CreateOrUpdate + fmt.Println("Call operation: CapacityReservationGroups_CreateOrUpdate") + capacityReservationGroupsClient, err := armcompute.NewCapacityReservationGroupsClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + _, err = capacityReservationGroupsClient.CreateOrUpdate(testsuite.ctx, testsuite.resourceGroupName, testsuite.capacityReservationGroupName, armcompute.CapacityReservationGroup{ + Location: to.Ptr(testsuite.location), + Tags: map[string]*string{ + "department": to.Ptr("finance"), + }, + Zones: []*string{ + to.Ptr("1"), + to.Ptr("2")}, + }, nil) + testsuite.Require().NoError(err) +} + +// Microsoft.Compute/capacityReservationGroups +func (testsuite *CapacityReservationTestSuite) TestCapacityReservationGroups() { + var err error + // From step CapacityReservationGroups_ListBySubscription + fmt.Println("Call operation: CapacityReservationGroups_ListBySubscription") + capacityReservationGroupsClient, err := armcompute.NewCapacityReservationGroupsClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + capacityReservationGroupsClientNewListBySubscriptionPager := capacityReservationGroupsClient.NewListBySubscriptionPager(&armcompute.CapacityReservationGroupsClientListBySubscriptionOptions{Expand: to.Ptr(armcompute.ExpandTypesForGetCapacityReservationGroupsVirtualMachinesRef)}) + for capacityReservationGroupsClientNewListBySubscriptionPager.More() { + _, err := capacityReservationGroupsClientNewListBySubscriptionPager.NextPage(testsuite.ctx) + testsuite.Require().NoError(err) + break + } + + // From step CapacityReservationGroups_ListByResourceGroup + fmt.Println("Call operation: CapacityReservationGroups_ListByResourceGroup") + capacityReservationGroupsClientNewListByResourceGroupPager := capacityReservationGroupsClient.NewListByResourceGroupPager(testsuite.resourceGroupName, &armcompute.CapacityReservationGroupsClientListByResourceGroupOptions{Expand: to.Ptr(armcompute.ExpandTypesForGetCapacityReservationGroupsVirtualMachinesRef)}) + for capacityReservationGroupsClientNewListByResourceGroupPager.More() { + _, err := capacityReservationGroupsClientNewListByResourceGroupPager.NextPage(testsuite.ctx) + testsuite.Require().NoError(err) + break + } + + // From step CapacityReservationGroups_Get + fmt.Println("Call operation: CapacityReservationGroups_Get") + _, err = capacityReservationGroupsClient.Get(testsuite.ctx, testsuite.resourceGroupName, testsuite.capacityReservationGroupName, &armcompute.CapacityReservationGroupsClientGetOptions{Expand: to.Ptr(armcompute.CapacityReservationGroupInstanceViewTypesInstanceView)}) + testsuite.Require().NoError(err) + + // From step CapacityReservationGroups_Update + fmt.Println("Call operation: CapacityReservationGroups_Update") + _, err = capacityReservationGroupsClient.Update(testsuite.ctx, testsuite.resourceGroupName, testsuite.capacityReservationGroupName, armcompute.CapacityReservationGroupUpdate{}, nil) + testsuite.Require().NoError(err) +} + +func (testsuite *CapacityReservationTestSuite) Cleanup() { + var err error + // From step CapacityReservationGroups_Delete + fmt.Println("Call operation: CapacityReservationGroups_Delete") + capacityReservationGroupsClient, err := armcompute.NewCapacityReservationGroupsClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + _, err = capacityReservationGroupsClient.Delete(testsuite.ctx, testsuite.resourceGroupName, testsuite.capacityReservationGroupName, nil) + testsuite.Require().NoError(err) +} diff --git a/sdk/resourcemanager/compute/armcompute/computerpcommon_live_test.go b/sdk/resourcemanager/compute/armcompute/computerpcommon_live_test.go new file mode 100644 index 000000000000..77ebfe856aca --- /dev/null +++ b/sdk/resourcemanager/compute/armcompute/computerpcommon_live_test.go @@ -0,0 +1,100 @@ +//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. +// Code generated by Microsoft (R) AutoRest Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. + +package armcompute_test + +import ( + "context" + "fmt" + "testing" + + "github.com/Azure/azure-sdk-for-go/sdk/azcore" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/arm" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v4" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/internal/testutil" + "github.com/stretchr/testify/suite" +) + +type ComputeRpCommonTestSuite struct { + suite.Suite + + ctx context.Context + cred azcore.TokenCredential + options *arm.ClientOptions + location string + resourceGroupName string + subscriptionId string +} + +func (testsuite *ComputeRpCommonTestSuite) SetupSuite() { + testutil.StartRecording(testsuite.T(), "sdk/resourcemanager/compute/armcompute/testdata") + + testsuite.ctx = context.Background() + testsuite.cred, testsuite.options = testutil.GetCredAndClientOptions(testsuite.T()) + testsuite.location = testutil.GetEnv("LOCATION", "eastus") + testsuite.resourceGroupName = testutil.GetEnv("RESOURCE_GROUP_NAME", "scenarioTestTempGroup") + testsuite.subscriptionId = testutil.GetEnv("AZURE_SUBSCRIPTION_ID", "00000000-0000-0000-0000-000000000000") + resourceGroup, _, err := testutil.CreateResourceGroup(testsuite.ctx, testsuite.subscriptionId, testsuite.cred, testsuite.options, testsuite.location) + testsuite.Require().NoError(err) + testsuite.resourceGroupName = *resourceGroup.Name +} + +func (testsuite *ComputeRpCommonTestSuite) TearDownSuite() { + _, err := testutil.DeleteResourceGroup(testsuite.ctx, testsuite.subscriptionId, testsuite.cred, testsuite.options, testsuite.resourceGroupName) + testsuite.Require().NoError(err) + testutil.StopRecording(testsuite.T()) +} + +func TestComputeRpCommonTestSuite(t *testing.T) { + suite.Run(t, new(ComputeRpCommonTestSuite)) +} + +// Microsoft.Compute/operations +func (testsuite *ComputeRpCommonTestSuite) TestOperations() { + var err error + // From step Operations_List + fmt.Println("Call operation: Operations_List") + operationsClient, err := armcompute.NewOperationsClient(testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + operationsClientNewListPager := operationsClient.NewListPager(nil) + for operationsClientNewListPager.More() { + _, err := operationsClientNewListPager.NextPage(testsuite.ctx) + testsuite.Require().NoError(err) + break + } +} + +// Microsoft.Compute/locations/{location}/usages +func (testsuite *ComputeRpCommonTestSuite) TestUsage() { + var err error + // From step Usage_List + fmt.Println("Call operation: Usage_List") + usageClient, err := armcompute.NewUsageClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + usageClientNewListPager := usageClient.NewListPager(testsuite.location, nil) + for usageClientNewListPager.More() { + _, err := usageClientNewListPager.NextPage(testsuite.ctx) + testsuite.Require().NoError(err) + break + } +} + +// Microsoft.Compute/locations/{location}/vmSizes +func (testsuite *ComputeRpCommonTestSuite) TestVirtualMachineSizes() { + var err error + // From step VirtualMachineSizes_List + fmt.Println("Call operation: VirtualMachineSizes_List") + virtualMachineSizesClient, err := armcompute.NewVirtualMachineSizesClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + virtualMachineSizesClientNewListPager := virtualMachineSizesClient.NewListPager(testsuite.location, nil) + for virtualMachineSizesClientNewListPager.More() { + _, err := virtualMachineSizesClientNewListPager.NextPage(testsuite.ctx) + testsuite.Require().NoError(err) + break + } +} diff --git a/sdk/resourcemanager/compute/armcompute/dedicatedhost_live_test.go b/sdk/resourcemanager/compute/armcompute/dedicatedhost_live_test.go new file mode 100644 index 000000000000..8852d1a2e308 --- /dev/null +++ b/sdk/resourcemanager/compute/armcompute/dedicatedhost_live_test.go @@ -0,0 +1,174 @@ +//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. +// Code generated by Microsoft (R) AutoRest Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. + +package armcompute_test + +import ( + "context" + "fmt" + "testing" + + "github.com/Azure/azure-sdk-for-go/sdk/azcore" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/arm" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/to" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v4" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/internal/testutil" + "github.com/stretchr/testify/suite" +) + +type DedicatedHostTestSuite struct { + suite.Suite + + ctx context.Context + cred azcore.TokenCredential + options *arm.ClientOptions + hostGroupName string + location string + resourceGroupName string + subscriptionId string +} + +func (testsuite *DedicatedHostTestSuite) SetupSuite() { + testutil.StartRecording(testsuite.T(), "sdk/resourcemanager/compute/armcompute/testdata") + + testsuite.ctx = context.Background() + testsuite.cred, testsuite.options = testutil.GetCredAndClientOptions(testsuite.T()) + testsuite.hostGroupName = testutil.GenerateAlphaNumericID(testsuite.T(), "hostgroupn", 6) + testsuite.location = testutil.GetEnv("LOCATION", "eastus") + testsuite.resourceGroupName = testutil.GetEnv("RESOURCE_GROUP_NAME", "scenarioTestTempGroup") + testsuite.subscriptionId = testutil.GetEnv("AZURE_SUBSCRIPTION_ID", "00000000-0000-0000-0000-000000000000") + resourceGroup, _, err := testutil.CreateResourceGroup(testsuite.ctx, testsuite.subscriptionId, testsuite.cred, testsuite.options, testsuite.location) + testsuite.Require().NoError(err) + testsuite.resourceGroupName = *resourceGroup.Name + testsuite.Prepare() +} + +func (testsuite *DedicatedHostTestSuite) TearDownSuite() { + _, err := testutil.DeleteResourceGroup(testsuite.ctx, testsuite.subscriptionId, testsuite.cred, testsuite.options, testsuite.resourceGroupName) + testsuite.Require().NoError(err) + testutil.StopRecording(testsuite.T()) +} + +func TestDedicatedHostTestSuite(t *testing.T) { + suite.Run(t, new(DedicatedHostTestSuite)) +} + +func (testsuite *DedicatedHostTestSuite) Prepare() { + var err error + // From step DedicatedHostGroups_CreateOrUpdate + fmt.Println("Call operation: DedicatedHostGroups_CreateOrUpdate") + dedicatedHostGroupsClient, err := armcompute.NewDedicatedHostGroupsClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + _, err = dedicatedHostGroupsClient.CreateOrUpdate(testsuite.ctx, testsuite.resourceGroupName, testsuite.hostGroupName, armcompute.DedicatedHostGroup{ + Location: to.Ptr(testsuite.location), + Tags: map[string]*string{ + "department": to.Ptr("finance"), + }, + Properties: &armcompute.DedicatedHostGroupProperties{ + PlatformFaultDomainCount: to.Ptr[int32](3), + SupportAutomaticPlacement: to.Ptr(true), + }, + Zones: []*string{ + to.Ptr("1")}, + }, nil) + testsuite.Require().NoError(err) +} + +// Microsoft.Compute/hostGroups +func (testsuite *DedicatedHostTestSuite) TestDedicatedHostGroups() { + var err error + // From step DedicatedHostGroups_ListBySubscription + fmt.Println("Call operation: DedicatedHostGroups_ListBySubscription") + dedicatedHostGroupsClient, err := armcompute.NewDedicatedHostGroupsClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + dedicatedHostGroupsClientNewListBySubscriptionPager := dedicatedHostGroupsClient.NewListBySubscriptionPager(nil) + for dedicatedHostGroupsClientNewListBySubscriptionPager.More() { + _, err := dedicatedHostGroupsClientNewListBySubscriptionPager.NextPage(testsuite.ctx) + testsuite.Require().NoError(err) + break + } + + // From step DedicatedHostGroups_ListByResourceGroup + fmt.Println("Call operation: DedicatedHostGroups_ListByResourceGroup") + dedicatedHostGroupsClientNewListByResourceGroupPager := dedicatedHostGroupsClient.NewListByResourceGroupPager(testsuite.resourceGroupName, nil) + for dedicatedHostGroupsClientNewListByResourceGroupPager.More() { + _, err := dedicatedHostGroupsClientNewListByResourceGroupPager.NextPage(testsuite.ctx) + testsuite.Require().NoError(err) + break + } + + // From step DedicatedHostGroups_Get + fmt.Println("Call operation: DedicatedHostGroups_Get") + _, err = dedicatedHostGroupsClient.Get(testsuite.ctx, testsuite.resourceGroupName, testsuite.hostGroupName, &armcompute.DedicatedHostGroupsClientGetOptions{Expand: nil}) + testsuite.Require().NoError(err) + + // From step DedicatedHostGroups_Update + fmt.Println("Call operation: DedicatedHostGroups_Update") + _, err = dedicatedHostGroupsClient.Update(testsuite.ctx, testsuite.resourceGroupName, testsuite.hostGroupName, armcompute.DedicatedHostGroupUpdate{}, nil) + testsuite.Require().NoError(err) +} + +// Microsoft.Compute/hostGroups/hosts +func (testsuite *DedicatedHostTestSuite) TestDedicatedHosts() { + hostName := testutil.GenerateAlphaNumericID(testsuite.T(), "hostname", 6) + var err error + // From step DedicatedHosts_CreateOrUpdate + fmt.Println("Call operation: DedicatedHosts_CreateOrUpdate") + dedicatedHostsClient, err := armcompute.NewDedicatedHostsClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + dedicatedHostsClientCreateOrUpdateResponsePoller, err := dedicatedHostsClient.BeginCreateOrUpdate(testsuite.ctx, testsuite.resourceGroupName, testsuite.hostGroupName, hostName, armcompute.DedicatedHost{ + Location: to.Ptr(testsuite.location), + Tags: map[string]*string{ + "department": to.Ptr("HR"), + }, + Properties: &armcompute.DedicatedHostProperties{ + PlatformFaultDomain: to.Ptr[int32](1), + }, + SKU: &armcompute.SKU{ + Name: to.Ptr("DSv3-Type1"), + }, + }, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, dedicatedHostsClientCreateOrUpdateResponsePoller) + testsuite.Require().NoError(err) + + // From step DedicatedHosts_ListByHostGroup + fmt.Println("Call operation: DedicatedHosts_ListByHostGroup") + dedicatedHostsClientNewListByHostGroupPager := dedicatedHostsClient.NewListByHostGroupPager(testsuite.resourceGroupName, testsuite.hostGroupName, nil) + for dedicatedHostsClientNewListByHostGroupPager.More() { + _, err := dedicatedHostsClientNewListByHostGroupPager.NextPage(testsuite.ctx) + testsuite.Require().NoError(err) + break + } + + // From step DedicatedHosts_Get + fmt.Println("Call operation: DedicatedHosts_Get") + _, err = dedicatedHostsClient.Get(testsuite.ctx, testsuite.resourceGroupName, testsuite.hostGroupName, hostName, &armcompute.DedicatedHostsClientGetOptions{Expand: nil}) + testsuite.Require().NoError(err) + + // From step DedicatedHosts_Update + fmt.Println("Call operation: DedicatedHosts_Update") + dedicatedHostsClientUpdateResponsePoller, err := dedicatedHostsClient.BeginUpdate(testsuite.ctx, testsuite.resourceGroupName, testsuite.hostGroupName, hostName, armcompute.DedicatedHostUpdate{}, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, dedicatedHostsClientUpdateResponsePoller) + testsuite.Require().NoError(err) + + // From step DedicatedHosts_Restart + fmt.Println("Call operation: DedicatedHosts_Restart") + dedicatedHostsClientRestartResponsePoller, err := dedicatedHostsClient.BeginRestart(testsuite.ctx, testsuite.resourceGroupName, testsuite.hostGroupName, hostName, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, dedicatedHostsClientRestartResponsePoller) + testsuite.Require().NoError(err) + + // From step DedicatedHosts_Delete + fmt.Println("Call operation: DedicatedHosts_Delete") + dedicatedHostsClientDeleteResponsePoller, err := dedicatedHostsClient.BeginDelete(testsuite.ctx, testsuite.resourceGroupName, testsuite.hostGroupName, hostName, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, dedicatedHostsClientDeleteResponsePoller) + testsuite.Require().NoError(err) +} diff --git a/sdk/resourcemanager/compute/armcompute/disk_live_test.go b/sdk/resourcemanager/compute/armcompute/disk_live_test.go new file mode 100644 index 000000000000..bedc48da779c --- /dev/null +++ b/sdk/resourcemanager/compute/armcompute/disk_live_test.go @@ -0,0 +1,137 @@ +//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. +// Code generated by Microsoft (R) AutoRest Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. + +package armcompute_test + +import ( + "context" + "fmt" + "testing" + + "github.com/Azure/azure-sdk-for-go/sdk/azcore" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/arm" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/to" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v4" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/internal/testutil" + "github.com/stretchr/testify/suite" +) + +type DiskTestSuite struct { + suite.Suite + + ctx context.Context + cred azcore.TokenCredential + options *arm.ClientOptions + diskName string + location string + resourceGroupName string + subscriptionId string +} + +func (testsuite *DiskTestSuite) SetupSuite() { + testutil.StartRecording(testsuite.T(), "sdk/resourcemanager/compute/armcompute/testdata") + + testsuite.ctx = context.Background() + testsuite.cred, testsuite.options = testutil.GetCredAndClientOptions(testsuite.T()) + testsuite.diskName = testutil.GenerateAlphaNumericID(testsuite.T(), "diskname", 6) + testsuite.location = testutil.GetEnv("LOCATION", "eastus") + testsuite.resourceGroupName = testutil.GetEnv("RESOURCE_GROUP_NAME", "scenarioTestTempGroup") + testsuite.subscriptionId = testutil.GetEnv("AZURE_SUBSCRIPTION_ID", "00000000-0000-0000-0000-000000000000") + resourceGroup, _, err := testutil.CreateResourceGroup(testsuite.ctx, testsuite.subscriptionId, testsuite.cred, testsuite.options, testsuite.location) + testsuite.Require().NoError(err) + testsuite.resourceGroupName = *resourceGroup.Name +} + +func (testsuite *DiskTestSuite) TearDownSuite() { + _, err := testutil.DeleteResourceGroup(testsuite.ctx, testsuite.subscriptionId, testsuite.cred, testsuite.options, testsuite.resourceGroupName) + testsuite.Require().NoError(err) + testutil.StopRecording(testsuite.T()) +} + +func TestDiskTestSuite(t *testing.T) { + suite.Run(t, new(DiskTestSuite)) +} + +// Microsoft.Compute/disks/{diskName} +func (testsuite *DiskTestSuite) TestDisks() { + var err error + // From step Disks_CreateOrUpdate + fmt.Println("Call operation: Disks_CreateOrUpdate") + disksClient, err := armcompute.NewDisksClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + disksClientCreateOrUpdateResponsePoller, err := disksClient.BeginCreateOrUpdate(testsuite.ctx, testsuite.resourceGroupName, testsuite.diskName, armcompute.Disk{ + Location: to.Ptr(testsuite.location), + Properties: &armcompute.DiskProperties{ + CreationData: &armcompute.CreationData{ + CreateOption: to.Ptr(armcompute.DiskCreateOptionEmpty), + }, + DiskSizeGB: to.Ptr[int32](200), + }, + }, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, disksClientCreateOrUpdateResponsePoller) + testsuite.Require().NoError(err) + + // From step Disks_List + fmt.Println("Call operation: Disks_List") + disksClientNewListPager := disksClient.NewListPager(nil) + for disksClientNewListPager.More() { + _, err := disksClientNewListPager.NextPage(testsuite.ctx) + testsuite.Require().NoError(err) + break + } + + // From step Disks_ListByResourceGroup + fmt.Println("Call operation: Disks_ListByResourceGroup") + disksClientNewListByResourceGroupPager := disksClient.NewListByResourceGroupPager(testsuite.resourceGroupName, nil) + for disksClientNewListByResourceGroupPager.More() { + _, err := disksClientNewListByResourceGroupPager.NextPage(testsuite.ctx) + testsuite.Require().NoError(err) + break + } + + // From step Disks_Get + fmt.Println("Call operation: Disks_Get") + _, err = disksClient.Get(testsuite.ctx, testsuite.resourceGroupName, testsuite.diskName, nil) + testsuite.Require().NoError(err) + + // From step Disks_Update + fmt.Println("Call operation: Disks_Update") + disksClientUpdateResponsePoller, err := disksClient.BeginUpdate(testsuite.ctx, testsuite.resourceGroupName, testsuite.diskName, armcompute.DiskUpdate{ + Properties: &armcompute.DiskUpdateProperties{ + NetworkAccessPolicy: to.Ptr(armcompute.NetworkAccessPolicyAllowAll), + }, + }, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, disksClientUpdateResponsePoller) + testsuite.Require().NoError(err) + + // From step Disks_GrantAccess + fmt.Println("Call operation: Disks_GrantAccess") + disksClientGrantAccessResponsePoller, err := disksClient.BeginGrantAccess(testsuite.ctx, testsuite.resourceGroupName, testsuite.diskName, armcompute.GrantAccessData{ + Access: to.Ptr(armcompute.AccessLevelRead), + DurationInSeconds: to.Ptr[int32](300), + }, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, disksClientGrantAccessResponsePoller) + testsuite.Require().NoError(err) + + // From step Disks_RevokeAccess + fmt.Println("Call operation: Disks_RevokeAccess") + disksClientRevokeAccessResponsePoller, err := disksClient.BeginRevokeAccess(testsuite.ctx, testsuite.resourceGroupName, testsuite.diskName, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, disksClientRevokeAccessResponsePoller) + testsuite.Require().NoError(err) + + // From step Disks_Delete + fmt.Println("Call operation: Disks_Delete") + disksClientDeleteResponsePoller, err := disksClient.BeginDelete(testsuite.ctx, testsuite.resourceGroupName, testsuite.diskName, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, disksClientDeleteResponsePoller) + testsuite.Require().NoError(err) +} diff --git a/sdk/resourcemanager/compute/armcompute/diskaccess_live_test.go b/sdk/resourcemanager/compute/armcompute/diskaccess_live_test.go new file mode 100644 index 000000000000..8819fc58dd5c --- /dev/null +++ b/sdk/resourcemanager/compute/armcompute/diskaccess_live_test.go @@ -0,0 +1,129 @@ +//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. +// Code generated by Microsoft (R) AutoRest Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. + +package armcompute_test + +import ( + "context" + "fmt" + "testing" + + "github.com/Azure/azure-sdk-for-go/sdk/azcore" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/arm" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/to" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v4" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/internal/testutil" + "github.com/stretchr/testify/suite" +) + +type DiskAccessTestSuite struct { + suite.Suite + + ctx context.Context + cred azcore.TokenCredential + options *arm.ClientOptions + diskAccessName string + location string + resourceGroupName string + subscriptionId string +} + +func (testsuite *DiskAccessTestSuite) SetupSuite() { + testutil.StartRecording(testsuite.T(), "sdk/resourcemanager/compute/armcompute/testdata") + + testsuite.ctx = context.Background() + testsuite.cred, testsuite.options = testutil.GetCredAndClientOptions(testsuite.T()) + testsuite.diskAccessName = testutil.GenerateAlphaNumericID(testsuite.T(), "diskaccess", 6) + testsuite.location = testutil.GetEnv("LOCATION", "eastus") + testsuite.resourceGroupName = testutil.GetEnv("RESOURCE_GROUP_NAME", "scenarioTestTempGroup") + testsuite.subscriptionId = testutil.GetEnv("AZURE_SUBSCRIPTION_ID", "00000000-0000-0000-0000-000000000000") + resourceGroup, _, err := testutil.CreateResourceGroup(testsuite.ctx, testsuite.subscriptionId, testsuite.cred, testsuite.options, testsuite.location) + testsuite.Require().NoError(err) + testsuite.resourceGroupName = *resourceGroup.Name +} + +func (testsuite *DiskAccessTestSuite) TearDownSuite() { + _, err := testutil.DeleteResourceGroup(testsuite.ctx, testsuite.subscriptionId, testsuite.cred, testsuite.options, testsuite.resourceGroupName) + testsuite.Require().NoError(err) + testutil.StopRecording(testsuite.T()) +} + +func TestDiskAccessTestSuite(t *testing.T) { + suite.Run(t, new(DiskAccessTestSuite)) +} + +// Microsoft.Compute/diskAccesses/{diskAccessName} +func (testsuite *DiskAccessTestSuite) TestDiskAccesses() { + var err error + // From step DiskAccesses_CreateOrUpdate + fmt.Println("Call operation: DiskAccesses_CreateOrUpdate") + diskAccessesClient, err := armcompute.NewDiskAccessesClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + diskAccessesClientCreateOrUpdateResponsePoller, err := diskAccessesClient.BeginCreateOrUpdate(testsuite.ctx, testsuite.resourceGroupName, testsuite.diskAccessName, armcompute.DiskAccess{ + Location: to.Ptr(testsuite.location), + }, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, diskAccessesClientCreateOrUpdateResponsePoller) + testsuite.Require().NoError(err) + + // From step DiskAccesses_List + fmt.Println("Call operation: DiskAccesses_List") + diskAccessesClientNewListPager := diskAccessesClient.NewListPager(nil) + for diskAccessesClientNewListPager.More() { + _, err := diskAccessesClientNewListPager.NextPage(testsuite.ctx) + testsuite.Require().NoError(err) + break + } + + // From step DiskAccesses_ListPrivateEndpointConnections + fmt.Println("Call operation: DiskAccesses_ListPrivateEndpointConnections") + diskAccessesClientNewListPrivateEndpointConnectionsPager := diskAccessesClient.NewListPrivateEndpointConnectionsPager(testsuite.resourceGroupName, testsuite.diskAccessName, nil) + for diskAccessesClientNewListPrivateEndpointConnectionsPager.More() { + _, err := diskAccessesClientNewListPrivateEndpointConnectionsPager.NextPage(testsuite.ctx) + testsuite.Require().NoError(err) + break + } + + // From step DiskAccesses_GetPrivateLinkResources + fmt.Println("Call operation: DiskAccesses_GetPrivateLinkResources") + _, err = diskAccessesClient.GetPrivateLinkResources(testsuite.ctx, testsuite.resourceGroupName, testsuite.diskAccessName, nil) + testsuite.Require().NoError(err) + + // From step DiskAccesses_ListByResourceGroup + fmt.Println("Call operation: DiskAccesses_ListByResourceGroup") + diskAccessesClientNewListByResourceGroupPager := diskAccessesClient.NewListByResourceGroupPager(testsuite.resourceGroupName, nil) + for diskAccessesClientNewListByResourceGroupPager.More() { + _, err := diskAccessesClientNewListByResourceGroupPager.NextPage(testsuite.ctx) + testsuite.Require().NoError(err) + break + } + + // From step DiskAccesses_Get + fmt.Println("Call operation: DiskAccesses_Get") + _, err = diskAccessesClient.Get(testsuite.ctx, testsuite.resourceGroupName, testsuite.diskAccessName, nil) + testsuite.Require().NoError(err) + + // From step DiskAccesses_Update + fmt.Println("Call operation: DiskAccesses_Update") + diskAccessesClientUpdateResponsePoller, err := diskAccessesClient.BeginUpdate(testsuite.ctx, testsuite.resourceGroupName, testsuite.diskAccessName, armcompute.DiskAccessUpdate{ + Tags: map[string]*string{ + "department": to.Ptr("Development"), + "project": to.Ptr("PrivateEndpoints"), + }, + }, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, diskAccessesClientUpdateResponsePoller) + testsuite.Require().NoError(err) + + // From step DiskAccesses_Delete + fmt.Println("Call operation: DiskAccesses_Delete") + diskAccessesClientDeleteResponsePoller, err := diskAccessesClient.BeginDelete(testsuite.ctx, testsuite.resourceGroupName, testsuite.diskAccessName, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, diskAccessesClientDeleteResponsePoller) + testsuite.Require().NoError(err) +} diff --git a/sdk/resourcemanager/compute/armcompute/gallery_live_test.go b/sdk/resourcemanager/compute/armcompute/gallery_live_test.go new file mode 100644 index 000000000000..a62b519b428b --- /dev/null +++ b/sdk/resourcemanager/compute/armcompute/gallery_live_test.go @@ -0,0 +1,265 @@ +//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. +// Code generated by Microsoft (R) AutoRest Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. + +package armcompute_test + +import ( + "context" + "fmt" + "testing" + + "github.com/Azure/azure-sdk-for-go/sdk/azcore" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/arm" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/to" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v4" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/internal/testutil" + "github.com/stretchr/testify/suite" +) + +type GalleryTestSuite struct { + suite.Suite + + ctx context.Context + cred azcore.TokenCredential + options *arm.ClientOptions + galleryApplicationName string + galleryImageName string + galleryName string + location string + resourceGroupName string + subscriptionId string +} + +func (testsuite *GalleryTestSuite) SetupSuite() { + testutil.StartRecording(testsuite.T(), "sdk/resourcemanager/compute/armcompute/testdata") + + testsuite.ctx = context.Background() + testsuite.cred, testsuite.options = testutil.GetCredAndClientOptions(testsuite.T()) + testsuite.galleryApplicationName = testutil.GenerateAlphaNumericID(testsuite.T(), "galleryapp", 6) + testsuite.galleryImageName = testutil.GenerateAlphaNumericID(testsuite.T(), "galleryima", 6) + testsuite.galleryName = testutil.GenerateAlphaNumericID(testsuite.T(), "gallerynam", 6) + testsuite.location = testutil.GetEnv("LOCATION", "eastus") + testsuite.resourceGroupName = testutil.GetEnv("RESOURCE_GROUP_NAME", "scenarioTestTempGroup") + testsuite.subscriptionId = testutil.GetEnv("AZURE_SUBSCRIPTION_ID", "00000000-0000-0000-0000-000000000000") + resourceGroup, _, err := testutil.CreateResourceGroup(testsuite.ctx, testsuite.subscriptionId, testsuite.cred, testsuite.options, testsuite.location) + testsuite.Require().NoError(err) + testsuite.resourceGroupName = *resourceGroup.Name + testsuite.Prepare() +} + +func (testsuite *GalleryTestSuite) TearDownSuite() { + _, err := testutil.DeleteResourceGroup(testsuite.ctx, testsuite.subscriptionId, testsuite.cred, testsuite.options, testsuite.resourceGroupName) + testsuite.Require().NoError(err) + testutil.StopRecording(testsuite.T()) +} + +func TestGalleryTestSuite(t *testing.T) { + suite.Run(t, new(GalleryTestSuite)) +} + +func (testsuite *GalleryTestSuite) Prepare() { + var err error + // From step Galleries_CreateOrUpdate + fmt.Println("Call operation: Galleries_CreateOrUpdate") + galleriesClient, err := armcompute.NewGalleriesClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + galleriesClientCreateOrUpdateResponsePoller, err := galleriesClient.BeginCreateOrUpdate(testsuite.ctx, testsuite.resourceGroupName, testsuite.galleryName, armcompute.Gallery{ + Location: to.Ptr(testsuite.location), + Properties: &armcompute.GalleryProperties{ + Description: to.Ptr("This is the gallery description."), + }, + }, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, galleriesClientCreateOrUpdateResponsePoller) + testsuite.Require().NoError(err) +} + +// Microsoft.Compute/galleries/{galleryName} +func (testsuite *GalleryTestSuite) TestGalleries() { + var err error + // From step Galleries_List + fmt.Println("Call operation: Galleries_List") + galleriesClient, err := armcompute.NewGalleriesClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + galleriesClientNewListPager := galleriesClient.NewListPager(nil) + for galleriesClientNewListPager.More() { + _, err := galleriesClientNewListPager.NextPage(testsuite.ctx) + testsuite.Require().NoError(err) + break + } + + // From step Galleries_ListByResourceGroup + fmt.Println("Call operation: Galleries_ListByResourceGroup") + galleriesClientNewListByResourceGroupPager := galleriesClient.NewListByResourceGroupPager(testsuite.resourceGroupName, nil) + for galleriesClientNewListByResourceGroupPager.More() { + _, err := galleriesClientNewListByResourceGroupPager.NextPage(testsuite.ctx) + testsuite.Require().NoError(err) + break + } + + // From step Galleries_Get + fmt.Println("Call operation: Galleries_Get") + _, err = galleriesClient.Get(testsuite.ctx, testsuite.resourceGroupName, testsuite.galleryName, &armcompute.GalleriesClientGetOptions{Select: nil, + Expand: nil, + }) + testsuite.Require().NoError(err) + + // From step Galleries_Update + fmt.Println("Call operation: Galleries_Update") + galleriesClientUpdateResponsePoller, err := galleriesClient.BeginUpdate(testsuite.ctx, testsuite.resourceGroupName, testsuite.galleryName, armcompute.GalleryUpdate{ + Properties: &armcompute.GalleryProperties{ + Description: to.Ptr("This is the gallery description."), + }, + }, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, galleriesClientUpdateResponsePoller) + testsuite.Require().NoError(err) +} + +// Microsoft.Compute/galleries/{galleryName}/images/{galleryImageName} +func (testsuite *GalleryTestSuite) TestGalleryImages() { + var err error + // From step GalleryImages_CreateOrUpdate + fmt.Println("Call operation: GalleryImages_CreateOrUpdate") + galleryImagesClient, err := armcompute.NewGalleryImagesClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + galleryImagesClientCreateOrUpdateResponsePoller, err := galleryImagesClient.BeginCreateOrUpdate(testsuite.ctx, testsuite.resourceGroupName, testsuite.galleryName, testsuite.galleryImageName, armcompute.GalleryImage{ + Location: to.Ptr(testsuite.location), + Properties: &armcompute.GalleryImageProperties{ + HyperVGeneration: to.Ptr(armcompute.HyperVGenerationV1), + Identifier: &armcompute.GalleryImageIdentifier{ + Offer: to.Ptr("myOfferName"), + Publisher: to.Ptr("myPublisherName"), + SKU: to.Ptr("mySkuName"), + }, + OSState: to.Ptr(armcompute.OperatingSystemStateTypesGeneralized), + OSType: to.Ptr(armcompute.OperatingSystemTypesWindows), + }, + }, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, galleryImagesClientCreateOrUpdateResponsePoller) + testsuite.Require().NoError(err) + + // From step GalleryImages_ListByGallery + fmt.Println("Call operation: GalleryImages_ListByGallery") + galleryImagesClientNewListByGalleryPager := galleryImagesClient.NewListByGalleryPager(testsuite.resourceGroupName, testsuite.galleryName, nil) + for galleryImagesClientNewListByGalleryPager.More() { + _, err := galleryImagesClientNewListByGalleryPager.NextPage(testsuite.ctx) + testsuite.Require().NoError(err) + break + } + + // From step GalleryImages_Get + fmt.Println("Call operation: GalleryImages_Get") + _, err = galleryImagesClient.Get(testsuite.ctx, testsuite.resourceGroupName, testsuite.galleryName, testsuite.galleryImageName, nil) + testsuite.Require().NoError(err) + + // From step GalleryImages_Update + fmt.Println("Call operation: GalleryImages_Update") + galleryImagesClientUpdateResponsePoller, err := galleryImagesClient.BeginUpdate(testsuite.ctx, testsuite.resourceGroupName, testsuite.galleryName, testsuite.galleryImageName, armcompute.GalleryImageUpdate{ + Tags: map[string]*string{ + "0": to.Ptr("[object Object]"), + }, + }, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, galleryImagesClientUpdateResponsePoller) + testsuite.Require().NoError(err) + + // From step GalleryImages_Delete + fmt.Println("Call operation: GalleryImages_Delete") + galleryImagesClientDeleteResponsePoller, err := galleryImagesClient.BeginDelete(testsuite.ctx, testsuite.resourceGroupName, testsuite.galleryName, testsuite.galleryImageName, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, galleryImagesClientDeleteResponsePoller) + testsuite.Require().NoError(err) +} + +// Microsoft.Compute/galleries/{galleryName}/applications/{galleryApplicationName} +func (testsuite *GalleryTestSuite) TestGalleryApplications() { + var err error + // From step GalleryApplications_CreateOrUpdate + fmt.Println("Call operation: GalleryApplications_CreateOrUpdate") + galleryApplicationsClient, err := armcompute.NewGalleryApplicationsClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + galleryApplicationsClientCreateOrUpdateResponsePoller, err := galleryApplicationsClient.BeginCreateOrUpdate(testsuite.ctx, testsuite.resourceGroupName, testsuite.galleryName, testsuite.galleryApplicationName, armcompute.GalleryApplication{ + Location: to.Ptr(testsuite.location), + Properties: &armcompute.GalleryApplicationProperties{ + Description: to.Ptr("This is the gallery application description."), + CustomActions: []*armcompute.GalleryApplicationCustomAction{ + { + Name: to.Ptr("myCustomAction"), + Description: to.Ptr("This is the custom action description."), + Parameters: []*armcompute.GalleryApplicationCustomActionParameter{ + { + Name: to.Ptr("myCustomActionParameter"), + Type: to.Ptr(armcompute.GalleryApplicationCustomActionParameterTypeString), + Description: to.Ptr("This is the description of the parameter"), + DefaultValue: to.Ptr("default value of parameter."), + Required: to.Ptr(false), + }}, + Script: to.Ptr("myCustomActionScript"), + }}, + Eula: to.Ptr("This is the gallery application EULA."), + PrivacyStatementURI: to.Ptr("myPrivacyStatementUri}"), + ReleaseNoteURI: to.Ptr("myReleaseNoteUri"), + SupportedOSType: to.Ptr(armcompute.OperatingSystemTypesWindows), + }, + }, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, galleryApplicationsClientCreateOrUpdateResponsePoller) + testsuite.Require().NoError(err) + + // From step GalleryApplications_ListByGallery + fmt.Println("Call operation: GalleryApplications_ListByGallery") + galleryApplicationsClientNewListByGalleryPager := galleryApplicationsClient.NewListByGalleryPager(testsuite.resourceGroupName, testsuite.galleryName, nil) + for galleryApplicationsClientNewListByGalleryPager.More() { + _, err := galleryApplicationsClientNewListByGalleryPager.NextPage(testsuite.ctx) + testsuite.Require().NoError(err) + break + } + + // From step GalleryApplications_Get + fmt.Println("Call operation: GalleryApplications_Get") + _, err = galleryApplicationsClient.Get(testsuite.ctx, testsuite.resourceGroupName, testsuite.galleryName, testsuite.galleryApplicationName, nil) + testsuite.Require().NoError(err) + + // From step GalleryApplications_Update + fmt.Println("Call operation: GalleryApplications_Update") + galleryApplicationsClientUpdateResponsePoller, err := galleryApplicationsClient.BeginUpdate(testsuite.ctx, testsuite.resourceGroupName, testsuite.galleryName, testsuite.galleryApplicationName, armcompute.GalleryApplicationUpdate{ + Properties: &armcompute.GalleryApplicationProperties{ + Description: to.Ptr("This is the gallery application description."), + CustomActions: []*armcompute.GalleryApplicationCustomAction{ + { + Name: to.Ptr("myCustomAction"), + Description: to.Ptr("This is the custom action description."), + Parameters: []*armcompute.GalleryApplicationCustomActionParameter{ + { + Name: to.Ptr("myCustomActionParameter"), + Type: to.Ptr(armcompute.GalleryApplicationCustomActionParameterTypeString), + Description: to.Ptr("This is the description of the parameter"), + DefaultValue: to.Ptr("default value of parameter."), + Required: to.Ptr(false), + }}, + Script: to.Ptr("myCustomActionScript"), + }}, + Eula: to.Ptr("This is the gallery application EULA."), + PrivacyStatementURI: to.Ptr("myPrivacyStatementUri}"), + ReleaseNoteURI: to.Ptr("myReleaseNoteUri"), + SupportedOSType: to.Ptr(armcompute.OperatingSystemTypesWindows), + }, + }, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, galleryApplicationsClientUpdateResponsePoller) + testsuite.Require().NoError(err) + + // From step GalleryApplications_Delete + fmt.Println("Call operation: GalleryApplications_Delete") + galleryApplicationsClientDeleteResponsePoller, err := galleryApplicationsClient.BeginDelete(testsuite.ctx, testsuite.resourceGroupName, testsuite.galleryName, testsuite.galleryApplicationName, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, galleryApplicationsClientDeleteResponsePoller) + testsuite.Require().NoError(err) +} diff --git a/sdk/resourcemanager/compute/armcompute/go.mod b/sdk/resourcemanager/compute/armcompute/go.mod index 911c7d63ec64..3527d6bde3ca 100644 --- a/sdk/resourcemanager/compute/armcompute/go.mod +++ b/sdk/resourcemanager/compute/armcompute/go.mod @@ -6,13 +6,12 @@ require ( github.com/Azure/azure-sdk-for-go/sdk/azcore v1.4.0 github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.2.0 github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/internal v1.1.2 - github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork v1.0.0 + github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armresources v1.1.1 github.com/stretchr/testify v1.7.0 ) require ( github.com/Azure/azure-sdk-for-go/sdk/internal v1.2.0 // indirect - github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armresources v1.0.0 // indirect github.com/AzureAD/microsoft-authentication-library-for-go v0.7.0 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/dnaeon/go-vcr v1.1.0 // indirect diff --git a/sdk/resourcemanager/compute/armcompute/go.sum b/sdk/resourcemanager/compute/armcompute/go.sum index bf1cdbf4fff0..69e6a668b452 100644 --- a/sdk/resourcemanager/compute/armcompute/go.sum +++ b/sdk/resourcemanager/compute/armcompute/go.sum @@ -6,10 +6,9 @@ github.com/Azure/azure-sdk-for-go/sdk/internal v1.2.0 h1:leh5DwKv6Ihwi+h60uHtn6U github.com/Azure/azure-sdk-for-go/sdk/internal v1.2.0/go.mod h1:eWRD7oawr1Mu1sLCawqVc0CUiF43ia3qQMxLscsKQ9w= github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/internal v1.1.2 h1:mLY+pNLjCUeKhgnAJWAKhEUQM+RJQo2H1fuGSw1Ky1E= github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/internal v1.1.2/go.mod h1:FbdwsQ2EzwvXxOPcMFYO8ogEc9uMMIj3YkmCdXdAFmk= -github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork v1.0.0 h1:nBy98uKOIfun5z6wx6jwWLrULcM0+cjBalBFZlEZ7CA= -github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork v1.0.0/go.mod h1:243D9iHbcQXoFUtgHJwL7gl2zx1aDuDMjvBZVGr2uW0= -github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armresources v1.0.0 h1:ECsQtyERDVz3NP3kvDOTLvbQhqWp/x9EsGKtb4ogUr8= -github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armresources v1.0.0/go.mod h1:s1tW/At+xHqjNFvWU4G0c0Qv33KOhvbGNj0RCTQDV8s= +github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/managementgroups/armmanagementgroups v1.0.0 h1:pPvTJ1dY0sA35JOeFq6TsY2xj6Z85Yo23Pj4wCCvu4o= +github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armresources v1.1.1 h1:7CBQ+Ei8SP2c6ydQTGCCrS35bDxgTMfoP2miAwK++OU= +github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armresources v1.1.1/go.mod h1:c/wcGeGx5FUPbM/JltUYHZcKmigwyVLJlDq+4HdtXaw= github.com/AzureAD/microsoft-authentication-library-for-go v0.7.0 h1:VgSJlZH5u0k2qxSpqyghcFQKmvYckj46uymKK5XzkBM= github.com/AzureAD/microsoft-authentication-library-for-go v0.7.0/go.mod h1:BDJ5qMFKx9DugEg3+uQSDCdbYPr5s9vBTrL9P8TpqOU= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= diff --git a/sdk/resourcemanager/compute/armcompute/proximityplacementgroup_live_test.go b/sdk/resourcemanager/compute/armcompute/proximityplacementgroup_live_test.go new file mode 100644 index 000000000000..47694732ad4b --- /dev/null +++ b/sdk/resourcemanager/compute/armcompute/proximityplacementgroup_live_test.go @@ -0,0 +1,118 @@ +//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. +// Code generated by Microsoft (R) AutoRest Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. + +package armcompute_test + +import ( + "context" + "fmt" + "testing" + + "github.com/Azure/azure-sdk-for-go/sdk/azcore" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/arm" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/to" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v4" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/internal/testutil" + "github.com/stretchr/testify/suite" +) + +type ProximityPlacementGroupTestSuite struct { + suite.Suite + + ctx context.Context + cred azcore.TokenCredential + options *arm.ClientOptions + location string + proximityPlacementGroupName string + resourceGroupName string + subscriptionId string +} + +func (testsuite *ProximityPlacementGroupTestSuite) SetupSuite() { + testutil.StartRecording(testsuite.T(), "sdk/resourcemanager/compute/armcompute/testdata") + + testsuite.ctx = context.Background() + testsuite.cred, testsuite.options = testutil.GetCredAndClientOptions(testsuite.T()) + testsuite.proximityPlacementGroupName = testutil.GenerateAlphaNumericID(testsuite.T(), "proximityp", 6) + testsuite.location = testutil.GetEnv("LOCATION", "eastus") + testsuite.resourceGroupName = testutil.GetEnv("RESOURCE_GROUP_NAME", "scenarioTestTempGroup") + testsuite.subscriptionId = testutil.GetEnv("AZURE_SUBSCRIPTION_ID", "00000000-0000-0000-0000-000000000000") + resourceGroup, _, err := testutil.CreateResourceGroup(testsuite.ctx, testsuite.subscriptionId, testsuite.cred, testsuite.options, testsuite.location) + testsuite.Require().NoError(err) + testsuite.resourceGroupName = *resourceGroup.Name +} + +func (testsuite *ProximityPlacementGroupTestSuite) TearDownSuite() { + _, err := testutil.DeleteResourceGroup(testsuite.ctx, testsuite.subscriptionId, testsuite.cred, testsuite.options, testsuite.resourceGroupName) + testsuite.Require().NoError(err) + testutil.StopRecording(testsuite.T()) +} + +func TestProximityPlacementGroupTestSuite(t *testing.T) { + suite.Run(t, new(ProximityPlacementGroupTestSuite)) +} + +// Microsoft.Compute/proximityPlacementGroups +func (testsuite *ProximityPlacementGroupTestSuite) TestProximityPlacementGroups() { + var err error + // From step ProximityPlacementGroups_CreateOrUpdate + fmt.Println("Call operation: ProximityPlacementGroups_CreateOrUpdate") + proximityPlacementGroupsClient, err := armcompute.NewProximityPlacementGroupsClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + _, err = proximityPlacementGroupsClient.CreateOrUpdate(testsuite.ctx, testsuite.resourceGroupName, testsuite.proximityPlacementGroupName, armcompute.ProximityPlacementGroup{ + Location: to.Ptr(testsuite.location), + Properties: &armcompute.ProximityPlacementGroupProperties{ + Intent: &armcompute.ProximityPlacementGroupPropertiesIntent{ + VMSizes: []*string{ + to.Ptr("Basic_A0"), + to.Ptr("Basic_A2")}, + }, + ProximityPlacementGroupType: to.Ptr(armcompute.ProximityPlacementGroupTypeStandard), + }, + Zones: []*string{ + to.Ptr("1")}, + }, nil) + testsuite.Require().NoError(err) + + // From step ProximityPlacementGroups_ListBySubscription + fmt.Println("Call operation: ProximityPlacementGroups_ListBySubscription") + proximityPlacementGroupsClientNewListBySubscriptionPager := proximityPlacementGroupsClient.NewListBySubscriptionPager(nil) + for proximityPlacementGroupsClientNewListBySubscriptionPager.More() { + _, err := proximityPlacementGroupsClientNewListBySubscriptionPager.NextPage(testsuite.ctx) + testsuite.Require().NoError(err) + break + } + + // From step ProximityPlacementGroups_ListByResourceGroup + fmt.Println("Call operation: ProximityPlacementGroups_ListByResourceGroup") + proximityPlacementGroupsClientNewListByResourceGroupPager := proximityPlacementGroupsClient.NewListByResourceGroupPager(testsuite.resourceGroupName, nil) + for proximityPlacementGroupsClientNewListByResourceGroupPager.More() { + _, err := proximityPlacementGroupsClientNewListByResourceGroupPager.NextPage(testsuite.ctx) + testsuite.Require().NoError(err) + break + } + + // From step ProximityPlacementGroups_Get + fmt.Println("Call operation: ProximityPlacementGroups_Get") + _, err = proximityPlacementGroupsClient.Get(testsuite.ctx, testsuite.resourceGroupName, testsuite.proximityPlacementGroupName, &armcompute.ProximityPlacementGroupsClientGetOptions{IncludeColocationStatus: nil}) + testsuite.Require().NoError(err) + + // From step ProximityPlacementGroups_Update + fmt.Println("Call operation: ProximityPlacementGroups_Update") + _, err = proximityPlacementGroupsClient.Update(testsuite.ctx, testsuite.resourceGroupName, testsuite.proximityPlacementGroupName, armcompute.ProximityPlacementGroupUpdate{ + Tags: map[string]*string{ + "additionalProp1": to.Ptr("string"), + }, + }, nil) + testsuite.Require().NoError(err) + + // From step ProximityPlacementGroups_Delete + fmt.Println("Call operation: ProximityPlacementGroups_Delete") + _, err = proximityPlacementGroupsClient.Delete(testsuite.ctx, testsuite.resourceGroupName, testsuite.proximityPlacementGroupName, nil) + testsuite.Require().NoError(err) +} diff --git a/sdk/resourcemanager/compute/armcompute/restorepoint_live_test.go b/sdk/resourcemanager/compute/armcompute/restorepoint_live_test.go new file mode 100644 index 000000000000..cf14b432a779 --- /dev/null +++ b/sdk/resourcemanager/compute/armcompute/restorepoint_live_test.go @@ -0,0 +1,291 @@ +//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. +// Code generated by Microsoft (R) AutoRest Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. + +package armcompute_test + +import ( + "context" + "fmt" + "testing" + + "github.com/Azure/azure-sdk-for-go/sdk/azcore" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/arm" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/to" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v4" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/internal/testutil" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armresources" + "github.com/stretchr/testify/suite" +) + +type RestorePointTestSuite struct { + suite.Suite + + ctx context.Context + cred azcore.TokenCredential + options *arm.ClientOptions + adminUsername string + networkInterfaceId string + networkInterfaceName string + restorePointCollectionName string + virtaulMachineId string + virtualNetworksName string + vmName string + adminPassword string + location string + resourceGroupName string + subscriptionId string +} + +func (testsuite *RestorePointTestSuite) SetupSuite() { + testutil.StartRecording(testsuite.T(), "sdk/resourcemanager/compute/armcompute/testdata") + + testsuite.ctx = context.Background() + testsuite.cred, testsuite.options = testutil.GetCredAndClientOptions(testsuite.T()) + testsuite.adminUsername = testutil.GenerateAlphaNumericID(testsuite.T(), "rp", 6) + testsuite.networkInterfaceName = testutil.GenerateAlphaNumericID(testsuite.T(), "vmnicrp", 6) + testsuite.restorePointCollectionName = testutil.GenerateAlphaNumericID(testsuite.T(), "restorepoi", 6) + testsuite.virtualNetworksName = testutil.GenerateAlphaNumericID(testsuite.T(), "vmvnetrp", 6) + testsuite.vmName = testutil.GenerateAlphaNumericID(testsuite.T(), "vmnamerp", 6) + testsuite.adminPassword = testutil.GetEnv("ADMIN_PASSWORD", "") + testsuite.location = testutil.GetEnv("LOCATION", "eastus") + testsuite.resourceGroupName = testutil.GetEnv("RESOURCE_GROUP_NAME", "scenarioTestTempGroup") + testsuite.subscriptionId = testutil.GetEnv("AZURE_SUBSCRIPTION_ID", "00000000-0000-0000-0000-000000000000") + resourceGroup, _, err := testutil.CreateResourceGroup(testsuite.ctx, testsuite.subscriptionId, testsuite.cred, testsuite.options, testsuite.location) + testsuite.Require().NoError(err) + testsuite.resourceGroupName = *resourceGroup.Name + testsuite.Prepare() +} + +func (testsuite *RestorePointTestSuite) TearDownSuite() { + testsuite.Cleanup() + _, err := testutil.DeleteResourceGroup(testsuite.ctx, testsuite.subscriptionId, testsuite.cred, testsuite.options, testsuite.resourceGroupName) + testsuite.Require().NoError(err) + testutil.StopRecording(testsuite.T()) +} + +func TestRestorePointTestSuite(t *testing.T) { + suite.Run(t, new(RestorePointTestSuite)) +} + +func (testsuite *RestorePointTestSuite) Prepare() { + var err error + // From step Create_NetworkInterface + template := map[string]any{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "outputs": map[string]any{ + "networkInterfaceId": map[string]any{ + "type": "string", + "value": "[resourceId('Microsoft.Network/networkInterfaces', parameters('networkInterfaceName'))]", + }, + }, + "parameters": map[string]any{ + "location": map[string]any{ + "type": "string", + "defaultValue": testsuite.location, + }, + "networkInterfaceName": map[string]any{ + "type": "string", + "defaultValue": testsuite.networkInterfaceName, + }, + "virtualNetworksName": map[string]any{ + "type": "string", + "defaultValue": testsuite.virtualNetworksName, + }, + }, + "resources": []any{ + map[string]any{ + "name": "[parameters('virtualNetworksName')]", + "type": "Microsoft.Network/virtualNetworks", + "apiVersion": "2021-05-01", + "location": "[parameters('location')]", + "properties": map[string]any{ + "addressSpace": map[string]any{ + "addressPrefixes": []any{ + "10.0.0.0/16", + }, + }, + "subnets": []any{ + map[string]any{ + "name": "default", + "properties": map[string]any{ + "addressPrefix": "10.0.0.0/24", + }, + }, + }, + }, + }, + map[string]any{ + "name": "[parameters('networkInterfaceName')]", + "type": "Microsoft.Network/networkInterfaces", + "apiVersion": "2021-08-01", + "dependsOn": []any{ + "[resourceId('Microsoft.Network/virtualNetworks', parameters('virtualNetworksName'))]", + }, + "location": "[parameters('location')]", + "properties": map[string]any{ + "ipConfigurations": []any{ + map[string]any{ + "name": "Ipv4config", + "properties": map[string]any{ + "subnet": map[string]any{ + "id": "[resourceId('Microsoft.Network/virtualNetworks/subnets', parameters('virtualNetworksName'), 'default')]", + }, + }, + }, + }, + }, + }, + }, + } + deployment := armresources.Deployment{ + Properties: &armresources.DeploymentProperties{ + Template: template, + Mode: to.Ptr(armresources.DeploymentModeIncremental), + }, + } + deploymentExtend, err := testutil.CreateDeployment(testsuite.ctx, testsuite.subscriptionId, testsuite.cred, testsuite.options, testsuite.resourceGroupName, "Create_NetworkInterface", &deployment) + testsuite.Require().NoError(err) + testsuite.networkInterfaceId = deploymentExtend.Properties.Outputs.(map[string]interface{})["networkInterfaceId"].(map[string]interface{})["value"].(string) + + // From step VirtualMachines_CreateOrUpdate + fmt.Println("Call operation: VirtualMachines_CreateOrUpdate") + virtualMachinesClient, err := armcompute.NewVirtualMachinesClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + virtualMachinesClientCreateOrUpdateResponsePoller, err := virtualMachinesClient.BeginCreateOrUpdate(testsuite.ctx, testsuite.resourceGroupName, testsuite.vmName, armcompute.VirtualMachine{ + Location: to.Ptr(testsuite.location), + Properties: &armcompute.VirtualMachineProperties{ + HardwareProfile: &armcompute.HardwareProfile{ + VMSize: to.Ptr(armcompute.VirtualMachineSizeTypesStandardD1V2), + }, + NetworkProfile: &armcompute.NetworkProfile{ + NetworkInterfaces: []*armcompute.NetworkInterfaceReference{ + { + ID: to.Ptr(testsuite.networkInterfaceId), + Properties: &armcompute.NetworkInterfaceReferenceProperties{ + Primary: to.Ptr(true), + }, + }}, + }, + OSProfile: &armcompute.OSProfile{ + AdminPassword: to.Ptr(testsuite.adminPassword), + AdminUsername: to.Ptr(testsuite.adminUsername), + ComputerName: to.Ptr(testsuite.vmName), + }, + StorageProfile: &armcompute.StorageProfile{ + ImageReference: &armcompute.ImageReference{ + Offer: to.Ptr("WindowsServer"), + Publisher: to.Ptr("MicrosoftWindowsServer"), + SKU: to.Ptr("2016-Datacenter"), + Version: to.Ptr("latest"), + }, + OSDisk: &armcompute.OSDisk{ + Name: to.Ptr(testsuite.vmName + "osdisk"), + Caching: to.Ptr(armcompute.CachingTypesReadWrite), + CreateOption: to.Ptr(armcompute.DiskCreateOptionTypesFromImage), + ManagedDisk: &armcompute.ManagedDiskParameters{ + StorageAccountType: to.Ptr(armcompute.StorageAccountTypesStandardLRS), + }, + }, + }, + }, + }, nil) + testsuite.Require().NoError(err) + var virtualMachinesClientCreateOrUpdateResponse *armcompute.VirtualMachinesClientCreateOrUpdateResponse + virtualMachinesClientCreateOrUpdateResponse, err = testutil.PollForTest(testsuite.ctx, virtualMachinesClientCreateOrUpdateResponsePoller) + testsuite.Require().NoError(err) + testsuite.virtaulMachineId = *virtualMachinesClientCreateOrUpdateResponse.ID + + // From step RestorePointCollections_CreateOrUpdate + fmt.Println("Call operation: RestorePointCollections_CreateOrUpdate") + restorePointCollectionsClient, err := armcompute.NewRestorePointCollectionsClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + _, err = restorePointCollectionsClient.CreateOrUpdate(testsuite.ctx, testsuite.resourceGroupName, testsuite.restorePointCollectionName, armcompute.RestorePointCollection{ + Location: to.Ptr(testsuite.location), + Tags: map[string]*string{ + "myTag1": to.Ptr("tagValue1"), + }, + Properties: &armcompute.RestorePointCollectionProperties{ + Source: &armcompute.RestorePointCollectionSourceProperties{ + ID: to.Ptr(testsuite.virtaulMachineId), + }, + }, + }, nil) + testsuite.Require().NoError(err) +} + +// Microsoft.Compute/restorePointCollections +func (testsuite *RestorePointTestSuite) TestRestorePointCollections() { + var err error + // From step RestorePointCollections_ListAll + fmt.Println("Call operation: RestorePointCollections_ListAll") + restorePointCollectionsClient, err := armcompute.NewRestorePointCollectionsClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + restorePointCollectionsClientNewListAllPager := restorePointCollectionsClient.NewListAllPager(nil) + for restorePointCollectionsClientNewListAllPager.More() { + _, err := restorePointCollectionsClientNewListAllPager.NextPage(testsuite.ctx) + testsuite.Require().NoError(err) + break + } + + // From step RestorePointCollections_List + fmt.Println("Call operation: RestorePointCollections_List") + restorePointCollectionsClientNewListPager := restorePointCollectionsClient.NewListPager(testsuite.resourceGroupName, nil) + for restorePointCollectionsClientNewListPager.More() { + _, err := restorePointCollectionsClientNewListPager.NextPage(testsuite.ctx) + testsuite.Require().NoError(err) + break + } + + // From step RestorePointCollections_Get + fmt.Println("Call operation: RestorePointCollections_Get") + _, err = restorePointCollectionsClient.Get(testsuite.ctx, testsuite.resourceGroupName, testsuite.restorePointCollectionName, &armcompute.RestorePointCollectionsClientGetOptions{Expand: nil}) + testsuite.Require().NoError(err) +} + +// Microsoft.Compute/restorePointCollections/restorePoints +func (testsuite *RestorePointTestSuite) TestRestorePoints() { + restorePointName := testutil.GenerateAlphaNumericID(testsuite.T(), "restorepoi", 6) + var err error + // From step RestorePoints_Create + fmt.Println("Call operation: RestorePoints_Create") + restorePointsClient, err := armcompute.NewRestorePointsClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + restorePointsClientCreateResponsePoller, err := restorePointsClient.BeginCreate(testsuite.ctx, testsuite.resourceGroupName, testsuite.restorePointCollectionName, restorePointName, armcompute.RestorePoint{}, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, restorePointsClientCreateResponsePoller) + testsuite.Require().NoError(err) + + // From step RestorePoints_Get + fmt.Println("Call operation: RestorePoints_Get") + _, err = restorePointsClient.Get(testsuite.ctx, testsuite.resourceGroupName, testsuite.restorePointCollectionName, restorePointName, &armcompute.RestorePointsClientGetOptions{Expand: nil}) + testsuite.Require().NoError(err) + + // From step RestorePoints_Delete + fmt.Println("Call operation: RestorePoints_Delete") + restorePointsClientDeleteResponsePoller, err := restorePointsClient.BeginDelete(testsuite.ctx, testsuite.resourceGroupName, testsuite.restorePointCollectionName, restorePointName, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, restorePointsClientDeleteResponsePoller) + testsuite.Require().NoError(err) +} + +func (testsuite *RestorePointTestSuite) Cleanup() { + var err error + // From step RestorePointCollections_Update + restorePointCollectionsClient, err := armcompute.NewRestorePointCollectionsClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + fmt.Println("Call operation: RestorePointCollections_Update") + _, err = restorePointCollectionsClient.Update(testsuite.ctx, testsuite.resourceGroupName, testsuite.restorePointCollectionName, armcompute.RestorePointCollectionUpdate{}, nil) + testsuite.Require().NoError(err) + // From step RestorePointCollections_Delete + fmt.Println("Call operation: RestorePointCollections_Delete") + restorePointCollectionsClientDeleteResponsePoller, err := restorePointCollectionsClient.BeginDelete(testsuite.ctx, testsuite.resourceGroupName, testsuite.restorePointCollectionName, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, restorePointCollectionsClientDeleteResponsePoller) + testsuite.Require().NoError(err) +} diff --git a/sdk/resourcemanager/compute/armcompute/runcommand_live_test.go b/sdk/resourcemanager/compute/armcompute/runcommand_live_test.go new file mode 100644 index 000000000000..6f7874afa6d4 --- /dev/null +++ b/sdk/resourcemanager/compute/armcompute/runcommand_live_test.go @@ -0,0 +1,495 @@ +//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. +// Code generated by Microsoft (R) AutoRest Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. + +package armcompute_test + +import ( + "context" + "fmt" + "testing" + + "github.com/Azure/azure-sdk-for-go/sdk/azcore" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/arm" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/to" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v4" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/internal/testutil" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armresources" + "github.com/stretchr/testify/suite" +) + +type RunCommandTestSuite struct { + suite.Suite + + ctx context.Context + cred azcore.TokenCredential + options *arm.ClientOptions + adminUsername string + networkInterfaceId string + networkInterfaceName string + subnetId string + virtualNetworkSubnetName string + virtualNetworksName string + vmName string + vmScaleSetName string + vmRunCommandName string + vmssRunCommandName string + adminPassword string + location string + resourceGroupName string + subscriptionId string +} + +func (testsuite *RunCommandTestSuite) SetupSuite() { + testutil.StartRecording(testsuite.T(), "sdk/resourcemanager/compute/armcompute/testdata") + + testsuite.ctx = context.Background() + testsuite.cred, testsuite.options = testutil.GetCredAndClientOptions(testsuite.T()) + testsuite.adminUsername = testutil.GenerateAlphaNumericID(testsuite.T(), "rc", 6) + testsuite.networkInterfaceName = testutil.GenerateAlphaNumericID(testsuite.T(), "vmnicrc", 6) + testsuite.virtualNetworkSubnetName = testutil.GenerateAlphaNumericID(testsuite.T(), "vmssvnetnarc", 6) + testsuite.virtualNetworksName = testutil.GenerateAlphaNumericID(testsuite.T(), "vmvnetrc", 6) + testsuite.vmName = testutil.GenerateAlphaNumericID(testsuite.T(), "vmcommand", 6) + testsuite.vmScaleSetName = testutil.GenerateAlphaNumericID(testsuite.T(), "vmscalesetcommand", 6) + testsuite.vmRunCommandName = testutil.GenerateAlphaNumericID(testsuite.T(), "vmruncommand", 6) + testsuite.vmssRunCommandName = testutil.GenerateAlphaNumericID(testsuite.T(), "vmssruncommand", 6) + testsuite.adminPassword = testutil.GetEnv("ADMIN_PASSWORD", "") + testsuite.location = testutil.GetEnv("LOCATION", "eastus") + testsuite.resourceGroupName = testutil.GetEnv("RESOURCE_GROUP_NAME", "scenarioTestTempGroup") + testsuite.subscriptionId = testutil.GetEnv("AZURE_SUBSCRIPTION_ID", "00000000-0000-0000-0000-000000000000") + resourceGroup, _, err := testutil.CreateResourceGroup(testsuite.ctx, testsuite.subscriptionId, testsuite.cred, testsuite.options, testsuite.location) + testsuite.Require().NoError(err) + testsuite.resourceGroupName = *resourceGroup.Name + testsuite.Prepare() +} + +func (testsuite *RunCommandTestSuite) TearDownSuite() { + _, err := testutil.DeleteResourceGroup(testsuite.ctx, testsuite.subscriptionId, testsuite.cred, testsuite.options, testsuite.resourceGroupName) + testsuite.Require().NoError(err) + testutil.StopRecording(testsuite.T()) +} + +func TestRunCommandTestSuite(t *testing.T) { + suite.Run(t, new(RunCommandTestSuite)) +} + +func (testsuite *RunCommandTestSuite) Prepare() { + var err error + // From step Create_NetworkInterface + template := map[string]any{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "outputs": map[string]any{ + "networkInterfaceId": map[string]any{ + "type": "string", + "value": "[resourceId('Microsoft.Network/networkInterfaces', parameters('networkInterfaceName'))]", + }, + }, + "parameters": map[string]any{ + "location": map[string]any{ + "type": "string", + "defaultValue": testsuite.location, + }, + "networkInterfaceName": map[string]any{ + "type": "string", + "defaultValue": testsuite.networkInterfaceName, + }, + "virtualNetworksName": map[string]any{ + "type": "string", + "defaultValue": testsuite.virtualNetworksName, + }, + }, + "resources": []any{ + map[string]any{ + "name": "[parameters('virtualNetworksName')]", + "type": "Microsoft.Network/virtualNetworks", + "apiVersion": "2021-05-01", + "location": "[parameters('location')]", + "properties": map[string]any{ + "addressSpace": map[string]any{ + "addressPrefixes": []any{ + "10.0.0.0/16", + }, + }, + "subnets": []any{ + map[string]any{ + "name": "default", + "properties": map[string]any{ + "addressPrefix": "10.0.0.0/24", + }, + }, + }, + }, + }, + map[string]any{ + "name": "[parameters('networkInterfaceName')]", + "type": "Microsoft.Network/networkInterfaces", + "apiVersion": "2021-08-01", + "dependsOn": []any{ + "[resourceId('Microsoft.Network/virtualNetworks', parameters('virtualNetworksName'))]", + }, + "location": "[parameters('location')]", + "properties": map[string]any{ + "ipConfigurations": []any{ + map[string]any{ + "name": "Ipv4config", + "properties": map[string]any{ + "subnet": map[string]any{ + "id": "[resourceId('Microsoft.Network/virtualNetworks/subnets', parameters('virtualNetworksName'), 'default')]", + }, + }, + }, + }, + }, + }, + }, + } + deployment := armresources.Deployment{ + Properties: &armresources.DeploymentProperties{ + Template: template, + Mode: to.Ptr(armresources.DeploymentModeIncremental), + }, + } + deploymentExtend, err := testutil.CreateDeployment(testsuite.ctx, testsuite.subscriptionId, testsuite.cred, testsuite.options, testsuite.resourceGroupName, "Create_NetworkInterface", &deployment) + testsuite.Require().NoError(err) + testsuite.networkInterfaceId = deploymentExtend.Properties.Outputs.(map[string]interface{})["networkInterfaceId"].(map[string]interface{})["value"].(string) + + // From step VirtualMachines_CreateOrUpdate + fmt.Println("Call operation: VirtualMachines_CreateOrUpdate") + virtualMachinesClient, err := armcompute.NewVirtualMachinesClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + virtualMachinesClientCreateOrUpdateResponsePoller, err := virtualMachinesClient.BeginCreateOrUpdate(testsuite.ctx, testsuite.resourceGroupName, testsuite.vmName, armcompute.VirtualMachine{ + Location: to.Ptr(testsuite.location), + Properties: &armcompute.VirtualMachineProperties{ + HardwareProfile: &armcompute.HardwareProfile{ + VMSize: to.Ptr(armcompute.VirtualMachineSizeTypesStandardD1V2), + }, + NetworkProfile: &armcompute.NetworkProfile{ + NetworkInterfaces: []*armcompute.NetworkInterfaceReference{ + { + ID: to.Ptr(testsuite.networkInterfaceId), + Properties: &armcompute.NetworkInterfaceReferenceProperties{ + Primary: to.Ptr(true), + }, + }}, + }, + OSProfile: &armcompute.OSProfile{ + AdminPassword: to.Ptr(testsuite.adminPassword), + AdminUsername: to.Ptr(testsuite.adminUsername), + ComputerName: to.Ptr(testsuite.vmName), + }, + StorageProfile: &armcompute.StorageProfile{ + ImageReference: &armcompute.ImageReference{ + Offer: to.Ptr("WindowsServer"), + Publisher: to.Ptr("MicrosoftWindowsServer"), + SKU: to.Ptr("2016-Datacenter"), + Version: to.Ptr("latest"), + }, + OSDisk: &armcompute.OSDisk{ + Name: to.Ptr(testsuite.vmName + "osdisk"), + Caching: to.Ptr(armcompute.CachingTypesReadWrite), + CreateOption: to.Ptr(armcompute.DiskCreateOptionTypesFromImage), + ManagedDisk: &armcompute.ManagedDiskParameters{ + StorageAccountType: to.Ptr(armcompute.StorageAccountTypesStandardLRS), + }, + }, + }, + }, + }, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, virtualMachinesClientCreateOrUpdateResponsePoller) + testsuite.Require().NoError(err) + + // From step Create_NetworkAndSubnet + template = map[string]any{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "outputs": map[string]any{ + "subnetId": map[string]any{ + "type": "string", + "value": "[resourceId('Microsoft.Network/virtualNetworks/subnets', parameters('virtualNetworkSubnetName'), 'default')]", + }, + }, + "parameters": map[string]any{ + "location": map[string]any{ + "type": "string", + "defaultValue": testsuite.location, + }, + "virtualNetworkSubnetName": map[string]any{ + "type": "string", + "defaultValue": testsuite.virtualNetworkSubnetName, + }, + }, + "resources": []any{ + map[string]any{ + "name": "[parameters('virtualNetworkSubnetName')]", + "type": "Microsoft.Network/virtualNetworks", + "apiVersion": "2021-05-01", + "location": "[parameters('location')]", + "properties": map[string]any{ + "addressSpace": map[string]any{ + "addressPrefixes": []any{ + "10.0.0.0/16", + }, + }, + "subnets": []any{ + map[string]any{ + "name": "default", + "properties": map[string]any{ + "addressPrefix": "10.0.0.0/24", + }, + }, + }, + }, + }, + }, + } + deployment = armresources.Deployment{ + Properties: &armresources.DeploymentProperties{ + Template: template, + Mode: to.Ptr(armresources.DeploymentModeIncremental), + }, + } + deploymentExtend, err = testutil.CreateDeployment(testsuite.ctx, testsuite.subscriptionId, testsuite.cred, testsuite.options, testsuite.resourceGroupName, "Create_NetworkAndSubnet", &deployment) + testsuite.Require().NoError(err) + testsuite.subnetId = deploymentExtend.Properties.Outputs.(map[string]interface{})["subnetId"].(map[string]interface{})["value"].(string) + + // From step VirtualMachineScaleSets_CreateOrUpdate + fmt.Println("Call operation: VirtualMachineScaleSets_CreateOrUpdate") + virtualMachineScaleSetsClient, err := armcompute.NewVirtualMachineScaleSetsClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + virtualMachineScaleSetsClientCreateOrUpdateResponsePoller, err := virtualMachineScaleSetsClient.BeginCreateOrUpdate(testsuite.ctx, testsuite.resourceGroupName, testsuite.vmScaleSetName, armcompute.VirtualMachineScaleSet{ + Location: to.Ptr(testsuite.location), + Properties: &armcompute.VirtualMachineScaleSetProperties{ + Overprovision: to.Ptr(true), + UpgradePolicy: &armcompute.UpgradePolicy{ + Mode: to.Ptr(armcompute.UpgradeModeManual), + }, + VirtualMachineProfile: &armcompute.VirtualMachineScaleSetVMProfile{ + NetworkProfile: &armcompute.VirtualMachineScaleSetNetworkProfile{ + NetworkInterfaceConfigurations: []*armcompute.VirtualMachineScaleSetNetworkConfiguration{ + { + Name: to.Ptr(testsuite.vmScaleSetName), + Properties: &armcompute.VirtualMachineScaleSetNetworkConfigurationProperties{ + EnableIPForwarding: to.Ptr(true), + IPConfigurations: []*armcompute.VirtualMachineScaleSetIPConfiguration{ + { + Name: to.Ptr(testsuite.vmScaleSetName), + Properties: &armcompute.VirtualMachineScaleSetIPConfigurationProperties{ + Subnet: &armcompute.APIEntityReference{ + ID: to.Ptr(testsuite.subnetId), + }, + }, + }}, + Primary: to.Ptr(true), + }, + }}, + }, + OSProfile: &armcompute.VirtualMachineScaleSetOSProfile{ + AdminPassword: to.Ptr(testsuite.adminPassword), + AdminUsername: to.Ptr(testsuite.adminUsername), + ComputerNamePrefix: to.Ptr("vmss"), + }, + StorageProfile: &armcompute.VirtualMachineScaleSetStorageProfile{ + ImageReference: &armcompute.ImageReference{ + Offer: to.Ptr("WindowsServer"), + Publisher: to.Ptr("MicrosoftWindowsServer"), + SKU: to.Ptr("2016-Datacenter"), + Version: to.Ptr("latest"), + }, + OSDisk: &armcompute.VirtualMachineScaleSetOSDisk{ + Caching: to.Ptr(armcompute.CachingTypesReadWrite), + CreateOption: to.Ptr(armcompute.DiskCreateOptionTypesFromImage), + ManagedDisk: &armcompute.VirtualMachineScaleSetManagedDiskParameters{ + StorageAccountType: to.Ptr(armcompute.StorageAccountTypesStandardLRS), + }, + }, + }, + }, + }, + SKU: &armcompute.SKU{ + Name: to.Ptr("Standard_D1_v2"), + Capacity: to.Ptr[int64](3), + Tier: to.Ptr("Standard"), + }, + }, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, virtualMachineScaleSetsClientCreateOrUpdateResponsePoller) + testsuite.Require().NoError(err) +} + +// Microsoft.Compute/virtualMachines/{vmName}/runCommands/{runCommandName} +func (testsuite *RunCommandTestSuite) TestVirtualMachineRunCommands() { + var err error + // From step VirtualMachineRunCommands_CreateOrUpdate + fmt.Println("Call operation: VirtualMachineRunCommands_CreateOrUpdate") + virtualMachineRunCommandsClient, err := armcompute.NewVirtualMachineRunCommandsClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + virtualMachineRunCommandsClientCreateOrUpdateResponsePoller, err := virtualMachineRunCommandsClient.BeginCreateOrUpdate(testsuite.ctx, testsuite.resourceGroupName, testsuite.vmName, testsuite.vmRunCommandName, armcompute.VirtualMachineRunCommand{ + Location: to.Ptr(testsuite.location), + Properties: &armcompute.VirtualMachineRunCommandProperties{ + AsyncExecution: to.Ptr(false), + Parameters: []*armcompute.RunCommandInputParameter{ + { + Name: to.Ptr("param1"), + Value: to.Ptr("value1"), + }, + { + Name: to.Ptr("param2"), + Value: to.Ptr("value2"), + }}, + RunAsPassword: to.Ptr(""), + RunAsUser: to.Ptr("user1"), + Source: &armcompute.VirtualMachineRunCommandScriptSource{ + Script: to.Ptr("Write-Host Hello World!"), + }, + TimeoutInSeconds: to.Ptr[int32](3600), + }, + }, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, virtualMachineRunCommandsClientCreateOrUpdateResponsePoller) + testsuite.Require().NoError(err) + + // From step VirtualMachineRunCommands_List + fmt.Println("Call operation: VirtualMachineRunCommands_List") + virtualMachineRunCommandsClientNewListPager := virtualMachineRunCommandsClient.NewListPager(testsuite.location, nil) + for virtualMachineRunCommandsClientNewListPager.More() { + _, err := virtualMachineRunCommandsClientNewListPager.NextPage(testsuite.ctx) + testsuite.Require().NoError(err) + break + } + + // From step VirtualMachineRunCommands_Get + fmt.Println("Call operation: VirtualMachineRunCommands_Get") + _, err = virtualMachineRunCommandsClient.Get(testsuite.ctx, testsuite.location, "RunPowerShellScript", nil) + testsuite.Require().NoError(err) + + // From step VirtualMachineRunCommands_ListByVirtualMachine + fmt.Println("Call operation: VirtualMachineRunCommands_ListByVirtualMachine") + virtualMachineRunCommandsClientNewListByVirtualMachinePager := virtualMachineRunCommandsClient.NewListByVirtualMachinePager(testsuite.resourceGroupName, testsuite.vmName, &armcompute.VirtualMachineRunCommandsClientListByVirtualMachineOptions{Expand: nil}) + for virtualMachineRunCommandsClientNewListByVirtualMachinePager.More() { + _, err := virtualMachineRunCommandsClientNewListByVirtualMachinePager.NextPage(testsuite.ctx) + testsuite.Require().NoError(err) + break + } + + // From step VirtualMachineRunCommands_GetByVirtualMachine + fmt.Println("Call operation: VirtualMachineRunCommands_GetByVirtualMachine") + _, err = virtualMachineRunCommandsClient.GetByVirtualMachine(testsuite.ctx, testsuite.resourceGroupName, testsuite.vmName, testsuite.vmRunCommandName, &armcompute.VirtualMachineRunCommandsClientGetByVirtualMachineOptions{Expand: nil}) + testsuite.Require().NoError(err) + + // From step VirtualMachineRunCommands_Update + fmt.Println("Call operation: VirtualMachineRunCommands_Update") + virtualMachineRunCommandsClientUpdateResponsePoller, err := virtualMachineRunCommandsClient.BeginUpdate(testsuite.ctx, testsuite.resourceGroupName, testsuite.vmName, testsuite.vmRunCommandName, armcompute.VirtualMachineRunCommandUpdate{ + Properties: &armcompute.VirtualMachineRunCommandProperties{ + Source: &armcompute.VirtualMachineRunCommandScriptSource{ + Script: to.Ptr("Write-Host Script Source Updated!"), + }, + }, + }, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, virtualMachineRunCommandsClientUpdateResponsePoller) + testsuite.Require().NoError(err) + + // From step VirtualMachines_RunCommand + fmt.Println("Call operation: VirtualMachines_RunCommand") + virtualMachinesClient, err := armcompute.NewVirtualMachinesClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + virtualMachinesClientRunCommandResponsePoller, err := virtualMachinesClient.BeginRunCommand(testsuite.ctx, testsuite.resourceGroupName, testsuite.vmName, armcompute.RunCommandInput{ + CommandID: to.Ptr("RunPowerShellScript"), + }, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, virtualMachinesClientRunCommandResponsePoller) + testsuite.Require().NoError(err) + + // From step VirtualMachineRunCommands_Delete + fmt.Println("Call operation: VirtualMachineRunCommands_Delete") + virtualMachineRunCommandsClientDeleteResponsePoller, err := virtualMachineRunCommandsClient.BeginDelete(testsuite.ctx, testsuite.resourceGroupName, testsuite.vmName, testsuite.vmRunCommandName, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, virtualMachineRunCommandsClientDeleteResponsePoller) + testsuite.Require().NoError(err) +} + +// Microsoft.Compute/virtualMachineScaleSets/{vmScaleSetName}/virtualMachines/{instanceId}/runCommands/{runCommandName} +func (testsuite *RunCommandTestSuite) TestVirtualMachineScaleSetVmRunCommands() { + var err error + // From step VirtualMachineScaleSetVMRunCommands_CreateOrUpdate + fmt.Println("Call operation: VirtualMachineScaleSetVMRunCommands_CreateOrUpdate") + virtualMachineScaleSetVMRunCommandsClient, err := armcompute.NewVirtualMachineScaleSetVMRunCommandsClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + virtualMachineScaleSetVMRunCommandsClientCreateOrUpdateResponsePoller, err := virtualMachineScaleSetVMRunCommandsClient.BeginCreateOrUpdate(testsuite.ctx, testsuite.resourceGroupName, testsuite.vmScaleSetName, "0", testsuite.vmssRunCommandName, armcompute.VirtualMachineRunCommand{ + Location: to.Ptr(testsuite.location), + Properties: &armcompute.VirtualMachineRunCommandProperties{ + AsyncExecution: to.Ptr(false), + Parameters: []*armcompute.RunCommandInputParameter{ + { + Name: to.Ptr("param1"), + Value: to.Ptr("value1"), + }, + { + Name: to.Ptr("param2"), + Value: to.Ptr("value2"), + }}, + RunAsPassword: to.Ptr(""), + RunAsUser: to.Ptr("user1"), + Source: &armcompute.VirtualMachineRunCommandScriptSource{ + Script: to.Ptr("Write-Host Hello World!"), + }, + TimeoutInSeconds: to.Ptr[int32](3600), + }, + }, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, virtualMachineScaleSetVMRunCommandsClientCreateOrUpdateResponsePoller) + testsuite.Require().NoError(err) + + // From step VirtualMachineScaleSetVMRunCommands_List + fmt.Println("Call operation: VirtualMachineScaleSetVMRunCommands_List") + virtualMachineScaleSetVMRunCommandsClientNewListPager := virtualMachineScaleSetVMRunCommandsClient.NewListPager(testsuite.resourceGroupName, testsuite.vmScaleSetName, "0", &armcompute.VirtualMachineScaleSetVMRunCommandsClientListOptions{Expand: nil}) + for virtualMachineScaleSetVMRunCommandsClientNewListPager.More() { + _, err := virtualMachineScaleSetVMRunCommandsClientNewListPager.NextPage(testsuite.ctx) + testsuite.Require().NoError(err) + break + } + + // From step VirtualMachineScaleSetVMRunCommands_Get + fmt.Println("Call operation: VirtualMachineScaleSetVMRunCommands_Get") + _, err = virtualMachineScaleSetVMRunCommandsClient.Get(testsuite.ctx, testsuite.resourceGroupName, testsuite.vmScaleSetName, "0", testsuite.vmssRunCommandName, &armcompute.VirtualMachineScaleSetVMRunCommandsClientGetOptions{Expand: nil}) + testsuite.Require().NoError(err) + + // From step VirtualMachineScaleSetVMRunCommands_Update + fmt.Println("Call operation: VirtualMachineScaleSetVMRunCommands_Update") + virtualMachineScaleSetVMRunCommandsClientUpdateResponsePoller, err := virtualMachineScaleSetVMRunCommandsClient.BeginUpdate(testsuite.ctx, testsuite.resourceGroupName, testsuite.vmScaleSetName, "0", testsuite.vmssRunCommandName, armcompute.VirtualMachineRunCommandUpdate{ + Properties: &armcompute.VirtualMachineRunCommandProperties{ + Source: &armcompute.VirtualMachineRunCommandScriptSource{ + Script: to.Ptr("Write-Host Script Source Updated!"), + }, + }, + }, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, virtualMachineScaleSetVMRunCommandsClientUpdateResponsePoller) + testsuite.Require().NoError(err) + + // From step VirtualMachineScaleSetVMs_RunCommand + fmt.Println("Call operation: VirtualMachineScaleSetVMs_RunCommand") + virtualMachineScaleSetVMsClient, err := armcompute.NewVirtualMachineScaleSetVMsClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + virtualMachineScaleSetVMsClientRunCommandResponsePoller, err := virtualMachineScaleSetVMsClient.BeginRunCommand(testsuite.ctx, testsuite.resourceGroupName, testsuite.vmScaleSetName, "0", armcompute.RunCommandInput{ + CommandID: to.Ptr("RunPowerShellScript"), + Script: []*string{ + to.Ptr("Write-Host Hello World!")}, + }, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, virtualMachineScaleSetVMsClientRunCommandResponsePoller) + testsuite.Require().NoError(err) + + // From step VirtualMachineScaleSetVMRunCommands_Delete + fmt.Println("Call operation: VirtualMachineScaleSetVMRunCommands_Delete") + virtualMachineScaleSetVMRunCommandsClientDeleteResponsePoller, err := virtualMachineScaleSetVMRunCommandsClient.BeginDelete(testsuite.ctx, testsuite.resourceGroupName, testsuite.vmScaleSetName, "0", testsuite.vmssRunCommandName, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, virtualMachineScaleSetVMRunCommandsClientDeleteResponsePoller) + testsuite.Require().NoError(err) +} diff --git a/sdk/resourcemanager/compute/armcompute/skus_live_test.go b/sdk/resourcemanager/compute/armcompute/skus_live_test.go new file mode 100644 index 000000000000..89b12f6ec696 --- /dev/null +++ b/sdk/resourcemanager/compute/armcompute/skus_live_test.go @@ -0,0 +1,73 @@ +//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. +// Code generated by Microsoft (R) AutoRest Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. + +package armcompute_test + +import ( + "context" + "fmt" + "testing" + + "github.com/Azure/azure-sdk-for-go/sdk/azcore" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/arm" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/to" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v4" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/internal/testutil" + "github.com/stretchr/testify/suite" +) + +type SkusTestSuite struct { + suite.Suite + + ctx context.Context + cred azcore.TokenCredential + options *arm.ClientOptions + location string + resourceGroupName string + subscriptionId string +} + +func (testsuite *SkusTestSuite) SetupSuite() { + testutil.StartRecording(testsuite.T(), "sdk/resourcemanager/compute/armcompute/testdata") + + testsuite.ctx = context.Background() + testsuite.cred, testsuite.options = testutil.GetCredAndClientOptions(testsuite.T()) + testsuite.location = testutil.GetEnv("LOCATION", "eastus") + testsuite.resourceGroupName = testutil.GetEnv("RESOURCE_GROUP_NAME", "scenarioTestTempGroup") + testsuite.subscriptionId = testutil.GetEnv("AZURE_SUBSCRIPTION_ID", "00000000-0000-0000-0000-000000000000") + resourceGroup, _, err := testutil.CreateResourceGroup(testsuite.ctx, testsuite.subscriptionId, testsuite.cred, testsuite.options, testsuite.location) + testsuite.Require().NoError(err) + testsuite.resourceGroupName = *resourceGroup.Name +} + +func (testsuite *SkusTestSuite) TearDownSuite() { + _, err := testutil.DeleteResourceGroup(testsuite.ctx, testsuite.subscriptionId, testsuite.cred, testsuite.options, testsuite.resourceGroupName) + testsuite.Require().NoError(err) + testutil.StopRecording(testsuite.T()) +} + +func TestSkusTestSuite(t *testing.T) { + suite.Run(t, new(SkusTestSuite)) +} + +// Microsoft.Compute/skus +func (testsuite *SkusTestSuite) TestResourceSkus() { + var err error + // From step ResourceSkus_List + fmt.Println("Call operation: ResourceSKUs_List") + resourceSKUsClient, err := armcompute.NewResourceSKUsClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + resourceSKUsClientNewListPager := resourceSKUsClient.NewListPager(&armcompute.ResourceSKUsClientListOptions{ + Filter: to.Ptr("location eq 'westus2'"), + }) + for resourceSKUsClientNewListPager.More() { + _, err := resourceSKUsClientNewListPager.NextPage(testsuite.ctx) + testsuite.Require().NoError(err) + break + } +} diff --git a/sdk/resourcemanager/compute/armcompute/snapshot_live_test.go b/sdk/resourcemanager/compute/armcompute/snapshot_live_test.go new file mode 100644 index 000000000000..e664393005d1 --- /dev/null +++ b/sdk/resourcemanager/compute/armcompute/snapshot_live_test.go @@ -0,0 +1,141 @@ +//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. +// Code generated by Microsoft (R) AutoRest Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. + +package armcompute_test + +import ( + "context" + "fmt" + "testing" + + "github.com/Azure/azure-sdk-for-go/sdk/azcore" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/arm" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/to" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v4" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/internal/testutil" + "github.com/stretchr/testify/suite" +) + +type SnapshotTestSuite struct { + suite.Suite + + ctx context.Context + cred azcore.TokenCredential + options *arm.ClientOptions + snapshotName string + location string + resourceGroupName string + subscriptionId string +} + +func (testsuite *SnapshotTestSuite) SetupSuite() { + testutil.StartRecording(testsuite.T(), "sdk/resourcemanager/compute/armcompute/testdata") + + testsuite.ctx = context.Background() + testsuite.cred, testsuite.options = testutil.GetCredAndClientOptions(testsuite.T()) + testsuite.snapshotName = testutil.GenerateAlphaNumericID(testsuite.T(), "snapshotna", 6) + testsuite.location = testutil.GetEnv("LOCATION", "eastus") + testsuite.resourceGroupName = testutil.GetEnv("RESOURCE_GROUP_NAME", "scenarioTestTempGroup") + testsuite.subscriptionId = testutil.GetEnv("AZURE_SUBSCRIPTION_ID", "00000000-0000-0000-0000-000000000000") + resourceGroup, _, err := testutil.CreateResourceGroup(testsuite.ctx, testsuite.subscriptionId, testsuite.cred, testsuite.options, testsuite.location) + testsuite.Require().NoError(err) + testsuite.resourceGroupName = *resourceGroup.Name +} + +func (testsuite *SnapshotTestSuite) TearDownSuite() { + _, err := testutil.DeleteResourceGroup(testsuite.ctx, testsuite.subscriptionId, testsuite.cred, testsuite.options, testsuite.resourceGroupName) + testsuite.Require().NoError(err) + testutil.StopRecording(testsuite.T()) +} + +func TestSnapshotTestSuite(t *testing.T) { + suite.Run(t, new(SnapshotTestSuite)) +} + +// Microsoft.Compute/snapshots/{snapshotName} +func (testsuite *SnapshotTestSuite) TestSnapshots() { + var err error + // From step Snapshots_CreateOrUpdate + fmt.Println("Call operation: Snapshots_CreateOrUpdate") + snapshotsClient, err := armcompute.NewSnapshotsClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + snapshotsClientCreateOrUpdateResponsePoller, err := snapshotsClient.BeginCreateOrUpdate(testsuite.ctx, testsuite.resourceGroupName, testsuite.snapshotName, armcompute.Snapshot{ + Location: to.Ptr(testsuite.location), + Properties: &armcompute.SnapshotProperties{ + CreationData: &armcompute.CreationData{ + CreateOption: to.Ptr(armcompute.DiskCreateOptionEmpty), + }, + DiskSizeGB: to.Ptr[int32](10), + }, + }, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, snapshotsClientCreateOrUpdateResponsePoller) + testsuite.Require().NoError(err) + + // From step Snapshots_List + fmt.Println("Call operation: Snapshots_List") + snapshotsClientNewListPager := snapshotsClient.NewListPager(nil) + for snapshotsClientNewListPager.More() { + _, err := snapshotsClientNewListPager.NextPage(testsuite.ctx) + testsuite.Require().NoError(err) + break + } + + // From step Snapshots_ListByResourceGroup + fmt.Println("Call operation: Snapshots_ListByResourceGroup") + snapshotsClientNewListByResourceGroupPager := snapshotsClient.NewListByResourceGroupPager(testsuite.resourceGroupName, nil) + for snapshotsClientNewListByResourceGroupPager.More() { + _, err := snapshotsClientNewListByResourceGroupPager.NextPage(testsuite.ctx) + testsuite.Require().NoError(err) + break + } + + // From step Snapshots_Get + fmt.Println("Call operation: Snapshots_Get") + _, err = snapshotsClient.Get(testsuite.ctx, testsuite.resourceGroupName, testsuite.snapshotName, nil) + testsuite.Require().NoError(err) + + // From step Snapshots_Update + fmt.Println("Call operation: Snapshots_Update") + snapshotsClientUpdateResponsePoller, err := snapshotsClient.BeginUpdate(testsuite.ctx, testsuite.resourceGroupName, testsuite.snapshotName, armcompute.SnapshotUpdate{ + Properties: &armcompute.SnapshotUpdateProperties{ + DiskSizeGB: to.Ptr[int32](20), + }, + Tags: map[string]*string{ + "department": to.Ptr("Development"), + "project": to.Ptr("UpdateSnapshots"), + }, + }, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, snapshotsClientUpdateResponsePoller) + testsuite.Require().NoError(err) + + // From step Snapshots_GrantAccess + fmt.Println("Call operation: Snapshots_GrantAccess") + snapshotsClientGrantAccessResponsePoller, err := snapshotsClient.BeginGrantAccess(testsuite.ctx, testsuite.resourceGroupName, testsuite.snapshotName, armcompute.GrantAccessData{ + Access: to.Ptr(armcompute.AccessLevelRead), + DurationInSeconds: to.Ptr[int32](300), + }, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, snapshotsClientGrantAccessResponsePoller) + testsuite.Require().NoError(err) + + // From step Snapshots_RevokeAccess + fmt.Println("Call operation: Snapshots_RevokeAccess") + snapshotsClientRevokeAccessResponsePoller, err := snapshotsClient.BeginRevokeAccess(testsuite.ctx, testsuite.resourceGroupName, testsuite.snapshotName, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, snapshotsClientRevokeAccessResponsePoller) + testsuite.Require().NoError(err) + + // From step Snapshots_Delete + fmt.Println("Call operation: Snapshots_Delete") + snapshotsClientDeleteResponsePoller, err := snapshotsClient.BeginDelete(testsuite.ctx, testsuite.resourceGroupName, testsuite.snapshotName, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, snapshotsClientDeleteResponsePoller) + testsuite.Require().NoError(err) +} diff --git a/sdk/resourcemanager/compute/armcompute/sshpublickey_live_test.go b/sdk/resourcemanager/compute/armcompute/sshpublickey_live_test.go new file mode 100644 index 000000000000..3b5dc535b395 --- /dev/null +++ b/sdk/resourcemanager/compute/armcompute/sshpublickey_live_test.go @@ -0,0 +1,113 @@ +//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. +// Code generated by Microsoft (R) AutoRest Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. + +package armcompute_test + +import ( + "context" + "fmt" + "testing" + + "github.com/Azure/azure-sdk-for-go/sdk/azcore" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/arm" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/to" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v4" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/internal/testutil" + "github.com/stretchr/testify/suite" +) + +type SshPublicKeyTestSuite struct { + suite.Suite + + ctx context.Context + cred azcore.TokenCredential + options *arm.ClientOptions + sshPublicKeyName string + location string + resourceGroupName string + subscriptionId string +} + +func (testsuite *SshPublicKeyTestSuite) SetupSuite() { + testutil.StartRecording(testsuite.T(), "sdk/resourcemanager/compute/armcompute/testdata") + + testsuite.ctx = context.Background() + testsuite.cred, testsuite.options = testutil.GetCredAndClientOptions(testsuite.T()) + testsuite.sshPublicKeyName = testutil.GenerateAlphaNumericID(testsuite.T(), "sshpublick", 6) + testsuite.location = testutil.GetEnv("LOCATION", "eastus") + testsuite.resourceGroupName = testutil.GetEnv("RESOURCE_GROUP_NAME", "scenarioTestTempGroup") + testsuite.subscriptionId = testutil.GetEnv("AZURE_SUBSCRIPTION_ID", "00000000-0000-0000-0000-000000000000") + resourceGroup, _, err := testutil.CreateResourceGroup(testsuite.ctx, testsuite.subscriptionId, testsuite.cred, testsuite.options, testsuite.location) + testsuite.Require().NoError(err) + testsuite.resourceGroupName = *resourceGroup.Name +} + +func (testsuite *SshPublicKeyTestSuite) TearDownSuite() { + _, err := testutil.DeleteResourceGroup(testsuite.ctx, testsuite.subscriptionId, testsuite.cred, testsuite.options, testsuite.resourceGroupName) + testsuite.Require().NoError(err) + testutil.StopRecording(testsuite.T()) +} + +func TestSshPublicKeyTestSuite(t *testing.T) { + suite.Run(t, new(SshPublicKeyTestSuite)) +} + +// Microsoft.Compute/sshPublicKeys/{sshPublicKeyName} +func (testsuite *SshPublicKeyTestSuite) TestSshPublicKeys() { + var err error + // From step SshPublicKeys_Create + fmt.Println("Call operation: SSHPublicKeys_Create") + sSHPublicKeysClient, err := armcompute.NewSSHPublicKeysClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + _, err = sSHPublicKeysClient.Create(testsuite.ctx, testsuite.resourceGroupName, testsuite.sshPublicKeyName, armcompute.SSHPublicKeyResource{ + Location: to.Ptr(testsuite.location), + }, nil) + testsuite.Require().NoError(err) + + // From step SshPublicKeys_ListBySubscription + fmt.Println("Call operation: SSHPublicKeys_ListBySubscription") + sSHPublicKeysClientNewListBySubscriptionPager := sSHPublicKeysClient.NewListBySubscriptionPager(nil) + for sSHPublicKeysClientNewListBySubscriptionPager.More() { + _, err := sSHPublicKeysClientNewListBySubscriptionPager.NextPage(testsuite.ctx) + testsuite.Require().NoError(err) + break + } + + // From step SshPublicKeys_ListByResourceGroup + fmt.Println("Call operation: SSHPublicKeys_ListByResourceGroup") + sSHPublicKeysClientNewListByResourceGroupPager := sSHPublicKeysClient.NewListByResourceGroupPager(testsuite.resourceGroupName, nil) + for sSHPublicKeysClientNewListByResourceGroupPager.More() { + _, err := sSHPublicKeysClientNewListByResourceGroupPager.NextPage(testsuite.ctx) + testsuite.Require().NoError(err) + break + } + + // From step SshPublicKeys_Get + fmt.Println("Call operation: SSHPublicKeys_Get") + _, err = sSHPublicKeysClient.Get(testsuite.ctx, testsuite.resourceGroupName, testsuite.sshPublicKeyName, nil) + testsuite.Require().NoError(err) + + // From step SshPublicKeys_Update + fmt.Println("Call operation: SSHPublicKeys_Update") + _, err = sSHPublicKeysClient.Update(testsuite.ctx, testsuite.resourceGroupName, testsuite.sshPublicKeyName, armcompute.SSHPublicKeyUpdateResource{ + Tags: map[string]*string{ + "key2854": to.Ptr("a"), + }, + }, nil) + testsuite.Require().NoError(err) + + // From step SshPublicKeys_GenerateKeyPair + fmt.Println("Call operation: SSHPublicKeys_GenerateKeyPair") + _, err = sSHPublicKeysClient.GenerateKeyPair(testsuite.ctx, testsuite.resourceGroupName, testsuite.sshPublicKeyName, nil) + testsuite.Require().NoError(err) + + // From step SshPublicKeys_Delete + fmt.Println("Call operation: SSHPublicKeys_Delete") + _, err = sSHPublicKeysClient.Delete(testsuite.ctx, testsuite.resourceGroupName, testsuite.sshPublicKeyName, nil) + testsuite.Require().NoError(err) +} diff --git a/sdk/resourcemanager/compute/armcompute/virtualmachine_live_test.go b/sdk/resourcemanager/compute/armcompute/virtualmachine_live_test.go new file mode 100644 index 000000000000..987606b16747 --- /dev/null +++ b/sdk/resourcemanager/compute/armcompute/virtualmachine_live_test.go @@ -0,0 +1,348 @@ +//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. +// Code generated by Microsoft (R) AutoRest Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. + +package armcompute_test + +import ( + "context" + "fmt" + "testing" + + "github.com/Azure/azure-sdk-for-go/sdk/azcore" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/arm" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/to" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v4" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/internal/testutil" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armresources" + "github.com/stretchr/testify/suite" +) + +type VirtualMachineTestSuite struct { + suite.Suite + + ctx context.Context + cred azcore.TokenCredential + options *arm.ClientOptions + adminUsername string + networkInterfaceId string + networkInterfaceName string + virtualNetworksName string + vmName string + adminPassword string + location string + resourceGroupName string + subscriptionId string +} + +func (testsuite *VirtualMachineTestSuite) SetupSuite() { + testutil.StartRecording(testsuite.T(), "sdk/resourcemanager/compute/armcompute/testdata") + + testsuite.ctx = context.Background() + testsuite.cred, testsuite.options = testutil.GetCredAndClientOptions(testsuite.T()) + testsuite.adminUsername = testutil.GenerateAlphaNumericID(testsuite.T(), "vmuserna", 6) + testsuite.networkInterfaceName = testutil.GenerateAlphaNumericID(testsuite.T(), "vmnic", 6) + testsuite.virtualNetworksName = testutil.GenerateAlphaNumericID(testsuite.T(), "vmvnet", 6) + testsuite.vmName = testutil.GenerateAlphaNumericID(testsuite.T(), "vmname", 6) + testsuite.adminPassword = testutil.GetEnv("ADMIN_PASSWORD", "") + testsuite.location = testutil.GetEnv("LOCATION", "eastus") + testsuite.resourceGroupName = testutil.GetEnv("RESOURCE_GROUP_NAME", "scenarioTestTempGroup") + testsuite.subscriptionId = testutil.GetEnv("AZURE_SUBSCRIPTION_ID", "00000000-0000-0000-0000-000000000000") + resourceGroup, _, err := testutil.CreateResourceGroup(testsuite.ctx, testsuite.subscriptionId, testsuite.cred, testsuite.options, testsuite.location) + testsuite.Require().NoError(err) + testsuite.resourceGroupName = *resourceGroup.Name + testsuite.Prepare() +} + +func (testsuite *VirtualMachineTestSuite) TearDownSuite() { + testsuite.Cleanup() + _, err := testutil.DeleteResourceGroup(testsuite.ctx, testsuite.subscriptionId, testsuite.cred, testsuite.options, testsuite.resourceGroupName) + testsuite.Require().NoError(err) + testutil.StopRecording(testsuite.T()) +} + +func TestVirtualMachineTestSuite(t *testing.T) { + suite.Run(t, new(VirtualMachineTestSuite)) +} + +func (testsuite *VirtualMachineTestSuite) Prepare() { + var err error + // From step Create_NetworkInterface + template := map[string]any{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "outputs": map[string]any{ + "networkInterfaceId": map[string]any{ + "type": "string", + "value": "[resourceId('Microsoft.Network/networkInterfaces', parameters('networkInterfaceName'))]", + }, + }, + "parameters": map[string]any{ + "location": map[string]any{ + "type": "string", + "defaultValue": testsuite.location, + }, + "networkInterfaceName": map[string]any{ + "type": "string", + "defaultValue": testsuite.networkInterfaceName, + }, + "virtualNetworksName": map[string]any{ + "type": "string", + "defaultValue": testsuite.virtualNetworksName, + }, + }, + "resources": []any{ + map[string]any{ + "name": "[parameters('virtualNetworksName')]", + "type": "Microsoft.Network/virtualNetworks", + "apiVersion": "2021-05-01", + "location": "[parameters('location')]", + "properties": map[string]any{ + "addressSpace": map[string]any{ + "addressPrefixes": []any{ + "10.0.0.0/16", + }, + }, + "subnets": []any{ + map[string]any{ + "name": "default", + "properties": map[string]any{ + "addressPrefix": "10.0.0.0/24", + }, + }, + }, + }, + }, + map[string]any{ + "name": "[parameters('networkInterfaceName')]", + "type": "Microsoft.Network/networkInterfaces", + "apiVersion": "2021-08-01", + "dependsOn": []any{ + "[resourceId('Microsoft.Network/virtualNetworks', parameters('virtualNetworksName'))]", + }, + "location": "[parameters('location')]", + "properties": map[string]any{ + "ipConfigurations": []any{ + map[string]any{ + "name": "Ipv4config", + "properties": map[string]any{ + "subnet": map[string]any{ + "id": "[resourceId('Microsoft.Network/virtualNetworks/subnets', parameters('virtualNetworksName'), 'default')]", + }, + }, + }, + }, + }, + }, + }, + } + deployment := armresources.Deployment{ + Properties: &armresources.DeploymentProperties{ + Template: template, + Mode: to.Ptr(armresources.DeploymentModeIncremental), + }, + } + deploymentExtend, err := testutil.CreateDeployment(testsuite.ctx, testsuite.subscriptionId, testsuite.cred, testsuite.options, testsuite.resourceGroupName, "Create_NetworkInterface", &deployment) + testsuite.Require().NoError(err) + testsuite.networkInterfaceId = deploymentExtend.Properties.Outputs.(map[string]interface{})["networkInterfaceId"].(map[string]interface{})["value"].(string) + + // From step VirtualMachines_CreateOrUpdate + fmt.Println("Call operation: VirtualMachines_CreateOrUpdate") + virtualMachinesClient, err := armcompute.NewVirtualMachinesClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + virtualMachinesClientCreateOrUpdateResponsePoller, err := virtualMachinesClient.BeginCreateOrUpdate(testsuite.ctx, testsuite.resourceGroupName, testsuite.vmName, armcompute.VirtualMachine{ + Location: to.Ptr(testsuite.location), + Properties: &armcompute.VirtualMachineProperties{ + HardwareProfile: &armcompute.HardwareProfile{ + VMSize: to.Ptr(armcompute.VirtualMachineSizeTypesStandardD1V2), + }, + NetworkProfile: &armcompute.NetworkProfile{ + NetworkInterfaces: []*armcompute.NetworkInterfaceReference{ + { + ID: to.Ptr(testsuite.networkInterfaceId), + Properties: &armcompute.NetworkInterfaceReferenceProperties{ + Primary: to.Ptr(true), + }, + }}, + }, + OSProfile: &armcompute.OSProfile{ + AdminPassword: to.Ptr(testsuite.adminPassword), + AdminUsername: to.Ptr(testsuite.adminUsername), + ComputerName: to.Ptr(testsuite.vmName), + }, + StorageProfile: &armcompute.StorageProfile{ + ImageReference: &armcompute.ImageReference{ + Offer: to.Ptr("WindowsServer"), + Publisher: to.Ptr("MicrosoftWindowsServer"), + SKU: to.Ptr("2016-Datacenter"), + Version: to.Ptr("latest"), + }, + OSDisk: &armcompute.OSDisk{ + Name: to.Ptr(testsuite.vmName + "osdisk"), + Caching: to.Ptr(armcompute.CachingTypesReadWrite), + CreateOption: to.Ptr(armcompute.DiskCreateOptionTypesFromImage), + ManagedDisk: &armcompute.ManagedDiskParameters{ + StorageAccountType: to.Ptr(armcompute.StorageAccountTypesStandardLRS), + }, + }, + }, + }, + }, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, virtualMachinesClientCreateOrUpdateResponsePoller) + testsuite.Require().NoError(err) +} + +// Microsoft.Compute/virtualMachines/{vmName} +func (testsuite *VirtualMachineTestSuite) TestVirtualMachines() { + var err error + // From step VirtualMachines_ListByLocation + fmt.Println("Call operation: VirtualMachines_ListByLocation") + virtualMachinesClient, err := armcompute.NewVirtualMachinesClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + virtualMachinesClientNewListByLocationPager := virtualMachinesClient.NewListByLocationPager(testsuite.location, nil) + for virtualMachinesClientNewListByLocationPager.More() { + _, err := virtualMachinesClientNewListByLocationPager.NextPage(testsuite.ctx) + testsuite.Require().NoError(err) + break + } + + // From step VirtualMachines_InstanceView + fmt.Println("Call operation: VirtualMachines_InstanceView") + _, err = virtualMachinesClient.InstanceView(testsuite.ctx, testsuite.resourceGroupName, testsuite.vmName, nil) + testsuite.Require().NoError(err) + + // From step VirtualMachines_ListAll + fmt.Println("Call operation: VirtualMachines_ListAll") + virtualMachinesClientNewListAllPager := virtualMachinesClient.NewListAllPager(&armcompute.VirtualMachinesClientListAllOptions{StatusOnly: nil, + Filter: nil, + }) + for virtualMachinesClientNewListAllPager.More() { + _, err := virtualMachinesClientNewListAllPager.NextPage(testsuite.ctx) + testsuite.Require().NoError(err) + break + } + + // From step VirtualMachines_List + fmt.Println("Call operation: VirtualMachines_List") + virtualMachinesClientNewListPager := virtualMachinesClient.NewListPager(testsuite.resourceGroupName, &armcompute.VirtualMachinesClientListOptions{Filter: nil}) + for virtualMachinesClientNewListPager.More() { + _, err := virtualMachinesClientNewListPager.NextPage(testsuite.ctx) + testsuite.Require().NoError(err) + break + } + + // From step VirtualMachines_Get + fmt.Println("Call operation: VirtualMachines_Get") + _, err = virtualMachinesClient.Get(testsuite.ctx, testsuite.resourceGroupName, testsuite.vmName, &armcompute.VirtualMachinesClientGetOptions{Expand: to.Ptr(armcompute.InstanceViewTypesUserData)}) + testsuite.Require().NoError(err) + + // From step VirtualMachines_ListAvailableSizes + fmt.Println("Call operation: VirtualMachines_ListAvailableSizes") + virtualMachinesClientNewListAvailableSizesPager := virtualMachinesClient.NewListAvailableSizesPager(testsuite.resourceGroupName, testsuite.vmName, nil) + for virtualMachinesClientNewListAvailableSizesPager.More() { + _, err := virtualMachinesClientNewListAvailableSizesPager.NextPage(testsuite.ctx) + testsuite.Require().NoError(err) + break + } + + // From step VirtualMachines_Update + fmt.Println("Call operation: VirtualMachines_Update") + virtualMachinesClientUpdateResponsePoller, err := virtualMachinesClient.BeginUpdate(testsuite.ctx, testsuite.resourceGroupName, testsuite.vmName, armcompute.VirtualMachineUpdate{ + Tags: map[string]*string{ + "virtaulMachine": to.Ptr("vmupdate"), + }, + }, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, virtualMachinesClientUpdateResponsePoller) + testsuite.Require().NoError(err) + + // From step VirtualMachines_InstallPatches + fmt.Println("Call operation: VirtualMachines_InstallPatches") + virtualMachinesClientInstallPatchesResponsePoller, err := virtualMachinesClient.BeginInstallPatches(testsuite.ctx, testsuite.resourceGroupName, testsuite.vmName, armcompute.VirtualMachineInstallPatchesParameters{ + MaximumDuration: to.Ptr("PT4H"), + RebootSetting: to.Ptr(armcompute.VMGuestPatchRebootSettingIfRequired), + WindowsParameters: &armcompute.WindowsParameters{ + ClassificationsToInclude: []*armcompute.VMGuestPatchClassificationWindows{ + to.Ptr(armcompute.VMGuestPatchClassificationWindowsCritical), + to.Ptr(armcompute.VMGuestPatchClassificationWindowsSecurity)}, + }, + }, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, virtualMachinesClientInstallPatchesResponsePoller) + testsuite.Require().NoError(err) + + // From step VirtualMachines_Deallocate + fmt.Println("Call operation: VirtualMachines_Deallocate") + virtualMachinesClientDeallocateResponsePoller, err := virtualMachinesClient.BeginDeallocate(testsuite.ctx, testsuite.resourceGroupName, testsuite.vmName, &armcompute.VirtualMachinesClientBeginDeallocateOptions{Hibernate: nil}) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, virtualMachinesClientDeallocateResponsePoller) + testsuite.Require().NoError(err) + + // From step VirtualMachines_Start + fmt.Println("Call operation: VirtualMachines_Start") + virtualMachinesClientStartResponsePoller, err := virtualMachinesClient.BeginStart(testsuite.ctx, testsuite.resourceGroupName, testsuite.vmName, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, virtualMachinesClientStartResponsePoller) + testsuite.Require().NoError(err) + + // From step VirtualMachines_AssessPatches + fmt.Println("Call operation: VirtualMachines_AssessPatches") + virtualMachinesClientAssessPatchesResponsePoller, err := virtualMachinesClient.BeginAssessPatches(testsuite.ctx, testsuite.resourceGroupName, testsuite.vmName, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, virtualMachinesClientAssessPatchesResponsePoller) + testsuite.Require().NoError(err) + + // From step VirtualMachines_Restart + fmt.Println("Call operation: VirtualMachines_Restart") + virtualMachinesClientRestartResponsePoller, err := virtualMachinesClient.BeginRestart(testsuite.ctx, testsuite.resourceGroupName, testsuite.vmName, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, virtualMachinesClientRestartResponsePoller) + testsuite.Require().NoError(err) + + // From step VirtualMachines_Reapply + fmt.Println("Call operation: VirtualMachines_Reapply") + virtualMachinesClientReapplyResponsePoller, err := virtualMachinesClient.BeginReapply(testsuite.ctx, testsuite.resourceGroupName, testsuite.vmName, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, virtualMachinesClientReapplyResponsePoller) + testsuite.Require().NoError(err) + + // From step VirtualMachines_RunCommand + fmt.Println("Call operation: VirtualMachines_RunCommand") + virtualMachinesClientRunCommandResponsePoller, err := virtualMachinesClient.BeginRunCommand(testsuite.ctx, testsuite.resourceGroupName, testsuite.vmName, armcompute.RunCommandInput{ + CommandID: to.Ptr("RunPowerShellScript"), + }, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, virtualMachinesClientRunCommandResponsePoller) + testsuite.Require().NoError(err) + + // From step VirtualMachines_Redeploy + fmt.Println("Call operation: VirtualMachines_Redeploy") + virtualMachinesClientRedeployResponsePoller, err := virtualMachinesClient.BeginRedeploy(testsuite.ctx, testsuite.resourceGroupName, testsuite.vmName, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, virtualMachinesClientRedeployResponsePoller) + testsuite.Require().NoError(err) + + // From step VirtualMachines_PowerOff + fmt.Println("Call operation: VirtualMachines_PowerOff") + virtualMachinesClientPowerOffResponsePoller, err := virtualMachinesClient.BeginPowerOff(testsuite.ctx, testsuite.resourceGroupName, testsuite.vmName, &armcompute.VirtualMachinesClientBeginPowerOffOptions{SkipShutdown: nil}) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, virtualMachinesClientPowerOffResponsePoller) + testsuite.Require().NoError(err) +} + +func (testsuite *VirtualMachineTestSuite) Cleanup() { + var err error + // From step VirtualMachines_Delete + fmt.Println("Call operation: VirtualMachines_Delete") + virtualMachinesClient, err := armcompute.NewVirtualMachinesClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + virtualMachinesClientDeleteResponsePoller, err := virtualMachinesClient.BeginDelete(testsuite.ctx, testsuite.resourceGroupName, testsuite.vmName, &armcompute.VirtualMachinesClientBeginDeleteOptions{ForceDeletion: to.Ptr(true)}) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, virtualMachinesClientDeleteResponsePoller) + testsuite.Require().NoError(err) +} diff --git a/sdk/resourcemanager/compute/armcompute/virtualmachineextensionimage_live_test.go b/sdk/resourcemanager/compute/armcompute/virtualmachineextensionimage_live_test.go new file mode 100644 index 000000000000..c67c58321675 --- /dev/null +++ b/sdk/resourcemanager/compute/armcompute/virtualmachineextensionimage_live_test.go @@ -0,0 +1,82 @@ +//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. +// Code generated by Microsoft (R) AutoRest Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. + +package armcompute_test + +import ( + "context" + "fmt" + "testing" + + "github.com/Azure/azure-sdk-for-go/sdk/azcore" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/arm" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v4" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/internal/testutil" + "github.com/stretchr/testify/suite" +) + +type VirtualMachineExtensionImageTestSuite struct { + suite.Suite + + ctx context.Context + cred azcore.TokenCredential + options *arm.ClientOptions + location string + resourceGroupName string + subscriptionId string +} + +func (testsuite *VirtualMachineExtensionImageTestSuite) SetupSuite() { + testutil.StartRecording(testsuite.T(), "sdk/resourcemanager/compute/armcompute/testdata") + + testsuite.ctx = context.Background() + testsuite.cred, testsuite.options = testutil.GetCredAndClientOptions(testsuite.T()) + testsuite.location = testutil.GetEnv("LOCATION", "eastus") + testsuite.resourceGroupName = testutil.GetEnv("RESOURCE_GROUP_NAME", "scenarioTestTempGroup") + testsuite.subscriptionId = testutil.GetEnv("AZURE_SUBSCRIPTION_ID", "00000000-0000-0000-0000-000000000000") + resourceGroup, _, err := testutil.CreateResourceGroup(testsuite.ctx, testsuite.subscriptionId, testsuite.cred, testsuite.options, testsuite.location) + testsuite.Require().NoError(err) + testsuite.resourceGroupName = *resourceGroup.Name +} + +func (testsuite *VirtualMachineExtensionImageTestSuite) TearDownSuite() { + _, err := testutil.DeleteResourceGroup(testsuite.ctx, testsuite.subscriptionId, testsuite.cred, testsuite.options, testsuite.resourceGroupName) + testsuite.Require().NoError(err) + testutil.StopRecording(testsuite.T()) +} + +func TestVirtualMachineExtensionImageTestSuite(t *testing.T) { + suite.Run(t, new(VirtualMachineExtensionImageTestSuite)) +} + +// Microsoft.Compute/locations/{location}/publishers/{publisherName}/artifacttypes/vmextension/types +func (testsuite *VirtualMachineExtensionImageTestSuite) TestVirtualMachineExtensionImages() { + publisherName := "Microsoft.Compute" + typeParam := "CustomScriptExtension" + version := "1.9" + var err error + // From step VirtualMachineExtensionImages_ListTypes + fmt.Println("Call operation: VirtualMachineExtensionImages_ListTypes") + virtualMachineExtensionImagesClient, err := armcompute.NewVirtualMachineExtensionImagesClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + _, err = virtualMachineExtensionImagesClient.ListTypes(testsuite.ctx, testsuite.location, publisherName, nil) + testsuite.Require().NoError(err) + + // From step VirtualMachineExtensionImages_ListVersions + fmt.Println("Call operation: VirtualMachineExtensionImages_ListVersions") + _, err = virtualMachineExtensionImagesClient.ListVersions(testsuite.ctx, testsuite.location, publisherName, typeParam, &armcompute.VirtualMachineExtensionImagesClientListVersionsOptions{Filter: nil, + Top: nil, + Orderby: nil, + }) + testsuite.Require().NoError(err) + + // From step VirtualMachineExtensionImages_Get + fmt.Println("Call operation: VirtualMachineExtensionImages_Get") + _, err = virtualMachineExtensionImagesClient.Get(testsuite.ctx, testsuite.location, publisherName, typeParam, version, nil) + testsuite.Require().NoError(err) +} diff --git a/sdk/resourcemanager/compute/armcompute/virtualmachineimage_live_test.go b/sdk/resourcemanager/compute/armcompute/virtualmachineimage_live_test.go new file mode 100644 index 000000000000..8d2d799af082 --- /dev/null +++ b/sdk/resourcemanager/compute/armcompute/virtualmachineimage_live_test.go @@ -0,0 +1,93 @@ +//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. +// Code generated by Microsoft (R) AutoRest Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. + +package armcompute_test + +import ( + "context" + "fmt" + "testing" + + "github.com/Azure/azure-sdk-for-go/sdk/azcore" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/arm" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v4" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/internal/testutil" + "github.com/stretchr/testify/suite" +) + +type VirtualMachineImageTestSuite struct { + suite.Suite + + ctx context.Context + cred azcore.TokenCredential + options *arm.ClientOptions + location string + resourceGroupName string + subscriptionId string +} + +func (testsuite *VirtualMachineImageTestSuite) SetupSuite() { + testutil.StartRecording(testsuite.T(), "sdk/resourcemanager/compute/armcompute/testdata") + + testsuite.ctx = context.Background() + testsuite.cred, testsuite.options = testutil.GetCredAndClientOptions(testsuite.T()) + testsuite.location = testutil.GetEnv("LOCATION", "eastus") + testsuite.resourceGroupName = testutil.GetEnv("RESOURCE_GROUP_NAME", "scenarioTestTempGroup") + testsuite.subscriptionId = testutil.GetEnv("AZURE_SUBSCRIPTION_ID", "00000000-0000-0000-0000-000000000000") + resourceGroup, _, err := testutil.CreateResourceGroup(testsuite.ctx, testsuite.subscriptionId, testsuite.cred, testsuite.options, testsuite.location) + testsuite.Require().NoError(err) + testsuite.resourceGroupName = *resourceGroup.Name +} + +func (testsuite *VirtualMachineImageTestSuite) TearDownSuite() { + _, err := testutil.DeleteResourceGroup(testsuite.ctx, testsuite.subscriptionId, testsuite.cred, testsuite.options, testsuite.resourceGroupName) + testsuite.Require().NoError(err) + testutil.StopRecording(testsuite.T()) +} + +func TestVirtualMachineImageTestSuite(t *testing.T) { + suite.Run(t, new(VirtualMachineImageTestSuite)) +} + +// Microsoft.Compute/locations/publishers +func (testsuite *VirtualMachineImageTestSuite) TestVirtualMachineImages() { + offer := "office-365" + publisherName := "MicrosoftWindowsDesktop" + skus := "win11-22h2-avd-m365" + version := "22621.1105.230110" + var err error + // From step VirtualMachineImages_ListPublishers + fmt.Println("Call operation: VirtualMachineImages_ListPublishers") + virtualMachineImagesClient, err := armcompute.NewVirtualMachineImagesClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + _, err = virtualMachineImagesClient.ListPublishers(testsuite.ctx, testsuite.location, nil) + testsuite.Require().NoError(err) + + // From step VirtualMachineImages_ListOffers + fmt.Println("Call operation: VirtualMachineImages_ListOffers") + _, err = virtualMachineImagesClient.ListOffers(testsuite.ctx, testsuite.location, publisherName, nil) + testsuite.Require().NoError(err) + + // From step VirtualMachineImages_ListSkus + fmt.Println("Call operation: VirtualMachineImages_ListSKUs") + _, err = virtualMachineImagesClient.ListSKUs(testsuite.ctx, testsuite.location, publisherName, offer, nil) + testsuite.Require().NoError(err) + + // From step VirtualMachineImages_List + fmt.Println("Call operation: VirtualMachineImages_List") + _, err = virtualMachineImagesClient.List(testsuite.ctx, testsuite.location, publisherName, offer, skus, &armcompute.VirtualMachineImagesClientListOptions{Expand: nil, + Top: nil, + Orderby: nil, + }) + testsuite.Require().NoError(err) + + // From step VirtualMachineImages_Get + fmt.Println("Call operation: VirtualMachineImages_Get") + _, err = virtualMachineImagesClient.Get(testsuite.ctx, testsuite.location, publisherName, offer, skus, version, nil) + testsuite.Require().NoError(err) +} diff --git a/sdk/resourcemanager/compute/armcompute/virtualmachines_client_live_test.go b/sdk/resourcemanager/compute/armcompute/virtualmachines_client_live_test.go deleted file mode 100644 index 01d54b7ab595..000000000000 --- a/sdk/resourcemanager/compute/armcompute/virtualmachines_client_live_test.go +++ /dev/null @@ -1,312 +0,0 @@ -//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 armcompute_test - -import ( - "context" - "fmt" - "testing" - - "github.com/Azure/azure-sdk-for-go/sdk/azcore" - "github.com/Azure/azure-sdk-for-go/sdk/azcore/arm" - "github.com/Azure/azure-sdk-for-go/sdk/azcore/to" - "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v4" - "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/internal/testutil" - "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork" - "github.com/stretchr/testify/suite" -) - -type VirtualMachinesClientTestSuite struct { - suite.Suite - - ctx context.Context - cred azcore.TokenCredential - options *arm.ClientOptions - location string - resourceGroupName string - subscriptionID string -} - -func (testsuite *VirtualMachinesClientTestSuite) SetupSuite() { - testsuite.ctx = context.Background() - testsuite.cred, testsuite.options = testutil.GetCredAndClientOptions(testsuite.T()) - testsuite.location = testutil.GetEnv("LOCATION", "eastus") - testsuite.subscriptionID = testutil.GetEnv("AZURE_SUBSCRIPTION_ID", "00000000-0000-0000-0000-000000000000") - testutil.StartRecording(testsuite.T(), "sdk/resourcemanager/compute/armcompute/testdata") - resourceGroup, _, err := testutil.CreateResourceGroup(testsuite.ctx, testsuite.subscriptionID, testsuite.cred, testsuite.options, testsuite.location) - testsuite.Require().NoError(err) - testsuite.resourceGroupName = *resourceGroup.Name -} - -func (testsuite *VirtualMachinesClientTestSuite) TearDownSuite() { - _, err := testutil.DeleteResourceGroup(testsuite.ctx, testsuite.subscriptionID, testsuite.cred, testsuite.options, testsuite.resourceGroupName) - testsuite.Require().NoError(err) - testutil.StopRecording(testsuite.T()) -} - -func TestVirtualMachinesClient(t *testing.T) { - suite.Run(t, new(VirtualMachinesClientTestSuite)) -} - -func (testsuite *VirtualMachinesClientTestSuite) TestVirtualMachineCRUD() { - // create virtual network - vnClient, err := armnetwork.NewVirtualNetworksClient(testsuite.subscriptionID, testsuite.cred, testsuite.options) - testsuite.Require().NoError(err) - vnName := "go-test-network" - vnPoller, err := vnClient.BeginCreateOrUpdate( - testsuite.ctx, - testsuite.resourceGroupName, - vnName, - armnetwork.VirtualNetwork{ - Location: to.Ptr(testsuite.location), - Properties: &armnetwork.VirtualNetworkPropertiesFormat{ - AddressSpace: &armnetwork.AddressSpace{ - AddressPrefixes: []*string{ - to.Ptr("10.1.0.0/16"), - }, - }, - }, - }, - nil, - ) - testsuite.Require().NoError(err) - vnResp, err := testutil.PollForTest(testsuite.ctx, vnPoller) - testsuite.Require().NoError(err) - testsuite.Require().Equal(*vnResp.Name, vnName) - - // create subnet - subClient, err := armnetwork.NewSubnetsClient(testsuite.subscriptionID, testsuite.cred, testsuite.options) - testsuite.Require().NoError(err) - subName := "go-test-subnet" - subPoller, err := subClient.BeginCreateOrUpdate( - testsuite.ctx, - testsuite.resourceGroupName, - vnName, - subName, - armnetwork.Subnet{ - Properties: &armnetwork.SubnetPropertiesFormat{ - AddressPrefix: to.Ptr("10.1.10.0/24"), - }, - }, - nil, - ) - testsuite.Require().NoError(err) - subResp, err := testutil.PollForTest(testsuite.ctx, subPoller) - testsuite.Require().NoError(err) - subnetID := *subResp.ID - testsuite.Require().Equal(*subResp.Name, subName) - - // create public ip address - ipClient, err := armnetwork.NewPublicIPAddressesClient(testsuite.subscriptionID, testsuite.cred, testsuite.options) - testsuite.Require().NoError(err) - ipName := "go-test-ip" - testsuite.Require().NoError(err) - ipPoller, err := ipClient.BeginCreateOrUpdate( - testsuite.ctx, - testsuite.resourceGroupName, - ipName, - armnetwork.PublicIPAddress{ - Location: to.Ptr(testsuite.location), - Properties: &armnetwork.PublicIPAddressPropertiesFormat{ - PublicIPAllocationMethod: to.Ptr(armnetwork.IPAllocationMethodStatic), // Static or Dynamic - }, - }, - nil, - ) - testsuite.Require().NoError(err) - ipResp, err := testutil.PollForTest(testsuite.ctx, ipPoller) - testsuite.Require().NoError(err) - publicIPAddressID := *ipResp.ID - testsuite.Require().Equal(*ipResp.Name, ipName) - - // create network security group - nsgClient, err := armnetwork.NewSecurityGroupsClient(testsuite.subscriptionID, testsuite.cred, testsuite.options) - testsuite.Require().NoError(err) - nsgName := "go-test-nsg" - testsuite.Require().NoError(err) - nsgPoller, err := nsgClient.BeginCreateOrUpdate( - testsuite.ctx, - testsuite.resourceGroupName, - nsgName, - armnetwork.SecurityGroup{ - Location: to.Ptr(testsuite.location), - Properties: &armnetwork.SecurityGroupPropertiesFormat{ - SecurityRules: []*armnetwork.SecurityRule{ - { - Name: to.Ptr("sample_inbound_22"), - Properties: &armnetwork.SecurityRulePropertiesFormat{ - SourceAddressPrefix: to.Ptr("0.0.0.0/0"), - SourcePortRange: to.Ptr("*"), - DestinationAddressPrefix: to.Ptr("0.0.0.0/0"), - DestinationPortRange: to.Ptr("22"), - Protocol: to.Ptr(armnetwork.SecurityRuleProtocolTCP), - Access: to.Ptr(armnetwork.SecurityRuleAccessAllow), - Priority: to.Ptr[int32](100), - Description: to.Ptr("sample network security group inbound port 22"), - Direction: to.Ptr(armnetwork.SecurityRuleDirectionInbound), - }, - }, - // outbound - { - Name: to.Ptr("sample_outbound_22"), - Properties: &armnetwork.SecurityRulePropertiesFormat{ - SourceAddressPrefix: to.Ptr("0.0.0.0/0"), - SourcePortRange: to.Ptr("*"), - DestinationAddressPrefix: to.Ptr("0.0.0.0/0"), - DestinationPortRange: to.Ptr("22"), - Protocol: to.Ptr(armnetwork.SecurityRuleProtocolTCP), - Access: to.Ptr(armnetwork.SecurityRuleAccessAllow), - Priority: to.Ptr[int32](100), - Description: to.Ptr("sample network security group outbound port 22"), - Direction: to.Ptr(armnetwork.SecurityRuleDirectionOutbound), - }, - }, - }, - }, - }, - nil, - ) - testsuite.Require().NoError(err) - nsgResp, err := testutil.PollForTest(testsuite.ctx, nsgPoller) - testsuite.Require().NoError(err) - networkSecurityGroupID := *nsgResp.ID - testsuite.Require().Equal(*nsgResp.Name, nsgName) - - // create network interface - nicClient, err := armnetwork.NewInterfacesClient(testsuite.subscriptionID, testsuite.cred, testsuite.options) - testsuite.Require().NoError(err) - nicName := "go-test-nic" - testsuite.Require().NoError(err) - nicPoller, err := nicClient.BeginCreateOrUpdate( - testsuite.ctx, - testsuite.resourceGroupName, - nicName, - armnetwork.Interface{ - Location: to.Ptr(testsuite.location), - Properties: &armnetwork.InterfacePropertiesFormat{ - //NetworkSecurityGroup: - IPConfigurations: []*armnetwork.InterfaceIPConfiguration{ - { - Name: to.Ptr("ipConfig"), - Properties: &armnetwork.InterfaceIPConfigurationPropertiesFormat{ - PrivateIPAllocationMethod: to.Ptr(armnetwork.IPAllocationMethodDynamic), - Subnet: &armnetwork.Subnet{ - ID: to.Ptr(subnetID), - }, - PublicIPAddress: &armnetwork.PublicIPAddress{ - ID: to.Ptr(publicIPAddressID), - }, - }, - }, - }, - NetworkSecurityGroup: &armnetwork.SecurityGroup{ - ID: to.Ptr(networkSecurityGroupID), - }, - }, - }, - nil, - ) - testsuite.Require().NoError(err) - nicResp, err := testutil.PollForTest(testsuite.ctx, nicPoller) - testsuite.Require().NoError(err) - networkInterfaceID := *nicResp.ID - testsuite.Require().Equal(*nicResp.Name, nicName) - - // create virtual machine - fmt.Println("Call operation: VirtualMachines_CreateOrUpdate") - vmClient, err := armcompute.NewVirtualMachinesClient(testsuite.subscriptionID, testsuite.cred, testsuite.options) - testsuite.Require().NoError(err) - vmName := "go-test-vm" - testsuite.Require().NoError(err) - diskName := "go-test-disk" - testsuite.Require().NoError(err) - vmPoller, err := vmClient.BeginCreateOrUpdate( - testsuite.ctx, - testsuite.resourceGroupName, - vmName, - armcompute.VirtualMachine{ - Location: to.Ptr(testsuite.location), - Identity: &armcompute.VirtualMachineIdentity{ - Type: to.Ptr(armcompute.ResourceIdentityTypeNone), - }, - Properties: &armcompute.VirtualMachineProperties{ - StorageProfile: &armcompute.StorageProfile{ - ImageReference: &armcompute.ImageReference{ - Offer: to.Ptr("WindowsServer"), - Publisher: to.Ptr("MicrosoftWindowsServer"), - SKU: to.Ptr("2019-Datacenter"), - Version: to.Ptr("latest"), - }, - OSDisk: &armcompute.OSDisk{ - Name: to.Ptr(diskName), - CreateOption: to.Ptr(armcompute.DiskCreateOptionTypesFromImage), - Caching: to.Ptr(armcompute.CachingTypesReadWrite), - ManagedDisk: &armcompute.ManagedDiskParameters{ - StorageAccountType: to.Ptr(armcompute.StorageAccountTypesStandardLRS), // OSDisk type Standard/Premium HDD/SSD - }, - }, - }, - HardwareProfile: &armcompute.HardwareProfile{ - VMSize: to.Ptr(armcompute.VirtualMachineSizeTypesStandardF2S), // VM size include vCPUs,RAM,Data Disks,Temp storage. - }, - OSProfile: &armcompute.OSProfile{ - ComputerName: to.Ptr("sample-compute"), - AdminUsername: to.Ptr("sample-user"), - AdminPassword: to.Ptr("Password01!@#"), - }, - NetworkProfile: &armcompute.NetworkProfile{ - NetworkInterfaces: []*armcompute.NetworkInterfaceReference{ - { - ID: to.Ptr(networkInterfaceID), - }, - }, - }, - }, - }, - nil, - ) - testsuite.Require().NoError(err) - vmResp, err := testutil.PollForTest(testsuite.ctx, vmPoller) - testsuite.Require().NoError(err) - testsuite.Require().Equal(*vmResp.Name, vmName) - - // virtual machine update - fmt.Println("Call operation: VirtualMachines_Update") - updatePoller, err := vmClient.BeginUpdate( - testsuite.ctx, - testsuite.resourceGroupName, - vmName, - armcompute.VirtualMachineUpdate{ - Tags: map[string]*string{ - "tag": to.Ptr("value"), - }, - }, - nil, - ) - testsuite.Require().NoError(err) - updateResp, err := testutil.PollForTest(testsuite.ctx, updatePoller) - testsuite.Require().NoError(err) - testsuite.Require().Equal(*updateResp.Name, vmName) - - // virtual machine get - fmt.Println("Call operation: VirtualMachines_Get") - resp, err := vmClient.Get(testsuite.ctx, testsuite.resourceGroupName, vmName, nil) - testsuite.Require().NoError(err) - testsuite.Require().Equal(*resp.Name, vmName) - - // virtual machine list - fmt.Println("Call operation: VirtualMachines_List") - vmList := vmClient.NewListPager(testsuite.resourceGroupName, nil) - testsuite.Require().Equal(vmList.More(), true) - - // delete virtual machine - fmt.Println("Call operation: VirtualMachines_Delete") - delPoller, err := vmClient.BeginDelete(testsuite.ctx, testsuite.resourceGroupName, vmName, nil) - testsuite.Require().NoError(err) - _, err = testutil.PollForTest(testsuite.ctx, delPoller) - testsuite.Require().NoError(err) -} diff --git a/sdk/resourcemanager/compute/armcompute/virtualmachinescaleset_live_test.go b/sdk/resourcemanager/compute/armcompute/virtualmachinescaleset_live_test.go new file mode 100644 index 000000000000..d2e907027f7f --- /dev/null +++ b/sdk/resourcemanager/compute/armcompute/virtualmachinescaleset_live_test.go @@ -0,0 +1,399 @@ +//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. +// Code generated by Microsoft (R) AutoRest Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. + +package armcompute_test + +import ( + "context" + "fmt" + "testing" + + "github.com/Azure/azure-sdk-for-go/sdk/azcore" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/arm" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/to" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v4" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/internal/testutil" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armresources" + "github.com/stretchr/testify/suite" +) + +type VirtualMachineScaleSetTestSuite struct { + suite.Suite + + ctx context.Context + cred azcore.TokenCredential + options *arm.ClientOptions + adminUsername string + subnetId string + virtualNetworkSubnetName string + vmScaleSetName string + vmssExtensionName string + adminPassword string + location string + resourceGroupName string + subscriptionId string +} + +func (testsuite *VirtualMachineScaleSetTestSuite) SetupSuite() { + testutil.StartRecording(testsuite.T(), "sdk/resourcemanager/compute/armcompute/testdata") + + testsuite.ctx = context.Background() + testsuite.cred, testsuite.options = testutil.GetCredAndClientOptions(testsuite.T()) + testsuite.adminUsername = testutil.GenerateAlphaNumericID(testsuite.T(), "vmuserna", 6) + testsuite.virtualNetworkSubnetName = testutil.GenerateAlphaNumericID(testsuite.T(), "vmssvnetna", 6) + testsuite.vmScaleSetName = testutil.GenerateAlphaNumericID(testsuite.T(), "vmscaleset", 6) + testsuite.vmssExtensionName = testutil.GenerateAlphaNumericID(testsuite.T(), "vmssextens", 6) + testsuite.adminPassword = testutil.GetEnv("ADMIN_PASSWORD", "") + testsuite.location = testutil.GetEnv("LOCATION", "eastus") + testsuite.resourceGroupName = testutil.GetEnv("RESOURCE_GROUP_NAME", "scenarioTestTempGroup") + testsuite.subscriptionId = testutil.GetEnv("AZURE_SUBSCRIPTION_ID", "00000000-0000-0000-0000-000000000000") + resourceGroup, _, err := testutil.CreateResourceGroup(testsuite.ctx, testsuite.subscriptionId, testsuite.cred, testsuite.options, testsuite.location) + testsuite.Require().NoError(err) + testsuite.resourceGroupName = *resourceGroup.Name + testsuite.Prepare() +} + +func (testsuite *VirtualMachineScaleSetTestSuite) TearDownSuite() { + testsuite.Cleanup() + _, err := testutil.DeleteResourceGroup(testsuite.ctx, testsuite.subscriptionId, testsuite.cred, testsuite.options, testsuite.resourceGroupName) + testsuite.Require().NoError(err) + testutil.StopRecording(testsuite.T()) +} + +func TestVirtualMachineScaleSetTestSuite(t *testing.T) { + suite.Run(t, new(VirtualMachineScaleSetTestSuite)) +} + +func (testsuite *VirtualMachineScaleSetTestSuite) Prepare() { + var err error + // From step Create_NetworkAndSubnet + template := map[string]any{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "outputs": map[string]any{ + "subnetId": map[string]any{ + "type": "string", + "value": "[resourceId('Microsoft.Network/virtualNetworks/subnets', parameters('virtualNetworkSubnetName'), 'default')]", + }, + }, + "parameters": map[string]any{ + "location": map[string]any{ + "type": "string", + "defaultValue": testsuite.location, + }, + "virtualNetworkSubnetName": map[string]any{ + "type": "string", + "defaultValue": testsuite.virtualNetworkSubnetName, + }, + }, + "resources": []any{ + map[string]any{ + "name": "[parameters('virtualNetworkSubnetName')]", + "type": "Microsoft.Network/virtualNetworks", + "apiVersion": "2021-05-01", + "location": "[parameters('location')]", + "properties": map[string]any{ + "addressSpace": map[string]any{ + "addressPrefixes": []any{ + "10.0.0.0/16", + }, + }, + "subnets": []any{ + map[string]any{ + "name": "default", + "properties": map[string]any{ + "addressPrefix": "10.0.0.0/24", + }, + }, + }, + }, + }, + }, + } + deployment := armresources.Deployment{ + Properties: &armresources.DeploymentProperties{ + Template: template, + Mode: to.Ptr(armresources.DeploymentModeIncremental), + }, + } + deploymentExtend, err := testutil.CreateDeployment(testsuite.ctx, testsuite.subscriptionId, testsuite.cred, testsuite.options, testsuite.resourceGroupName, "Create_NetworkAndSubnet", &deployment) + testsuite.Require().NoError(err) + testsuite.subnetId = deploymentExtend.Properties.Outputs.(map[string]interface{})["subnetId"].(map[string]interface{})["value"].(string) + + // From step VirtualMachineScaleSets_CreateOrUpdate + fmt.Println("Call operation: VirtualMachineScaleSets_CreateOrUpdate") + virtualMachineScaleSetsClient, err := armcompute.NewVirtualMachineScaleSetsClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + virtualMachineScaleSetsClientCreateOrUpdateResponsePoller, err := virtualMachineScaleSetsClient.BeginCreateOrUpdate(testsuite.ctx, testsuite.resourceGroupName, testsuite.vmScaleSetName, armcompute.VirtualMachineScaleSet{ + Location: to.Ptr(testsuite.location), + Properties: &armcompute.VirtualMachineScaleSetProperties{ + Overprovision: to.Ptr(true), + UpgradePolicy: &armcompute.UpgradePolicy{ + Mode: to.Ptr(armcompute.UpgradeModeManual), + }, + VirtualMachineProfile: &armcompute.VirtualMachineScaleSetVMProfile{ + NetworkProfile: &armcompute.VirtualMachineScaleSetNetworkProfile{ + NetworkInterfaceConfigurations: []*armcompute.VirtualMachineScaleSetNetworkConfiguration{ + { + Name: to.Ptr(testsuite.vmScaleSetName), + Properties: &armcompute.VirtualMachineScaleSetNetworkConfigurationProperties{ + EnableIPForwarding: to.Ptr(true), + IPConfigurations: []*armcompute.VirtualMachineScaleSetIPConfiguration{ + { + Name: to.Ptr(testsuite.vmScaleSetName), + Properties: &armcompute.VirtualMachineScaleSetIPConfigurationProperties{ + Subnet: &armcompute.APIEntityReference{ + ID: to.Ptr(testsuite.subnetId), + }, + }, + }}, + Primary: to.Ptr(true), + }, + }}, + }, + OSProfile: &armcompute.VirtualMachineScaleSetOSProfile{ + AdminPassword: to.Ptr(testsuite.adminPassword), + AdminUsername: to.Ptr(testsuite.adminUsername), + ComputerNamePrefix: to.Ptr("vmss"), + }, + StorageProfile: &armcompute.VirtualMachineScaleSetStorageProfile{ + ImageReference: &armcompute.ImageReference{ + Offer: to.Ptr("WindowsServer"), + Publisher: to.Ptr("MicrosoftWindowsServer"), + SKU: to.Ptr("2016-Datacenter"), + Version: to.Ptr("latest"), + }, + OSDisk: &armcompute.VirtualMachineScaleSetOSDisk{ + Caching: to.Ptr(armcompute.CachingTypesReadWrite), + CreateOption: to.Ptr(armcompute.DiskCreateOptionTypesFromImage), + ManagedDisk: &armcompute.VirtualMachineScaleSetManagedDiskParameters{ + StorageAccountType: to.Ptr(armcompute.StorageAccountTypesStandardLRS), + }, + }, + }, + }, + }, + SKU: &armcompute.SKU{ + Name: to.Ptr("Standard_D1_v2"), + Capacity: to.Ptr[int64](3), + Tier: to.Ptr("Standard"), + }, + }, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, virtualMachineScaleSetsClientCreateOrUpdateResponsePoller) + testsuite.Require().NoError(err) +} + +// Microsoft.Compute/virtualMachineScaleSets/{vmScaleSetName} +func (testsuite *VirtualMachineScaleSetTestSuite) TestVirtualMachineScaleSets() { + var err error + // From step VirtualMachineScaleSets_ListByLocation + fmt.Println("Call operation: VirtualMachineScaleSets_ListByLocation") + virtualMachineScaleSetsClient, err := armcompute.NewVirtualMachineScaleSetsClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + virtualMachineScaleSetsClientNewListByLocationPager := virtualMachineScaleSetsClient.NewListByLocationPager(testsuite.location, nil) + for virtualMachineScaleSetsClientNewListByLocationPager.More() { + _, err := virtualMachineScaleSetsClientNewListByLocationPager.NextPage(testsuite.ctx) + testsuite.Require().NoError(err) + break + } + + // From step VirtualMachineScaleSets_GetInstanceView + fmt.Println("Call operation: VirtualMachineScaleSets_GetInstanceView") + _, err = virtualMachineScaleSetsClient.GetInstanceView(testsuite.ctx, testsuite.resourceGroupName, testsuite.vmScaleSetName, nil) + testsuite.Require().NoError(err) + + // From step VirtualMachineScaleSets_GetOSUpgradeHistory + fmt.Println("Call operation: VirtualMachineScaleSets_GetOSUpgradeHistory") + virtualMachineScaleSetsClientNewGetOSUpgradeHistoryPager := virtualMachineScaleSetsClient.NewGetOSUpgradeHistoryPager(testsuite.resourceGroupName, testsuite.vmScaleSetName, nil) + for virtualMachineScaleSetsClientNewGetOSUpgradeHistoryPager.More() { + _, err := virtualMachineScaleSetsClientNewGetOSUpgradeHistoryPager.NextPage(testsuite.ctx) + testsuite.Require().NoError(err) + break + } + + // From step VirtualMachineScaleSets_ListAll + fmt.Println("Call operation: VirtualMachineScaleSets_ListAll") + virtualMachineScaleSetsClientNewListAllPager := virtualMachineScaleSetsClient.NewListAllPager(nil) + for virtualMachineScaleSetsClientNewListAllPager.More() { + _, err := virtualMachineScaleSetsClientNewListAllPager.NextPage(testsuite.ctx) + testsuite.Require().NoError(err) + break + } + + // From step VirtualMachineScaleSets_Get + fmt.Println("Call operation: VirtualMachineScaleSets_Get") + _, err = virtualMachineScaleSetsClient.Get(testsuite.ctx, testsuite.resourceGroupName, testsuite.vmScaleSetName, &armcompute.VirtualMachineScaleSetsClientGetOptions{Expand: nil}) + testsuite.Require().NoError(err) + + // From step VirtualMachineScaleSets_List + fmt.Println("Call operation: VirtualMachineScaleSets_List") + virtualMachineScaleSetsClientNewListPager := virtualMachineScaleSetsClient.NewListPager(testsuite.resourceGroupName, nil) + for virtualMachineScaleSetsClientNewListPager.More() { + _, err := virtualMachineScaleSetsClientNewListPager.NextPage(testsuite.ctx) + testsuite.Require().NoError(err) + break + } + + // From step VirtualMachineScaleSets_ListSkus + fmt.Println("Call operation: VirtualMachineScaleSets_ListSKUs") + virtualMachineScaleSetsClientNewListSKUsPager := virtualMachineScaleSetsClient.NewListSKUsPager(testsuite.resourceGroupName, testsuite.vmScaleSetName, nil) + for virtualMachineScaleSetsClientNewListSKUsPager.More() { + _, err := virtualMachineScaleSetsClientNewListSKUsPager.NextPage(testsuite.ctx) + testsuite.Require().NoError(err) + break + } + + // From step VirtualMachineScaleSets_Update + fmt.Println("Call operation: VirtualMachineScaleSets_Update") + virtualMachineScaleSetsClientUpdateResponsePoller, err := virtualMachineScaleSetsClient.BeginUpdate(testsuite.ctx, testsuite.resourceGroupName, testsuite.vmScaleSetName, armcompute.VirtualMachineScaleSetUpdate{}, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, virtualMachineScaleSetsClientUpdateResponsePoller) + testsuite.Require().NoError(err) + + // From step VirtualMachineScaleSets_Redeploy + fmt.Println("Call operation: VirtualMachineScaleSets_Redeploy") + virtualMachineScaleSetsClientRedeployResponsePoller, err := virtualMachineScaleSetsClient.BeginRedeploy(testsuite.ctx, testsuite.resourceGroupName, testsuite.vmScaleSetName, &armcompute.VirtualMachineScaleSetsClientBeginRedeployOptions{VMInstanceIDs: nil}) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, virtualMachineScaleSetsClientRedeployResponsePoller) + testsuite.Require().NoError(err) + + // From step VirtualMachineScaleSets_Deallocate + fmt.Println("Call operation: VirtualMachineScaleSets_Deallocate") + virtualMachineScaleSetsClientDeallocateResponsePoller, err := virtualMachineScaleSetsClient.BeginDeallocate(testsuite.ctx, testsuite.resourceGroupName, testsuite.vmScaleSetName, &armcompute.VirtualMachineScaleSetsClientBeginDeallocateOptions{VMInstanceIDs: nil}) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, virtualMachineScaleSetsClientDeallocateResponsePoller) + testsuite.Require().NoError(err) + + // From step VirtualMachineScaleSets_Start + fmt.Println("Call operation: VirtualMachineScaleSets_Start") + virtualMachineScaleSetsClientStartResponsePoller, err := virtualMachineScaleSetsClient.BeginStart(testsuite.ctx, testsuite.resourceGroupName, testsuite.vmScaleSetName, &armcompute.VirtualMachineScaleSetsClientBeginStartOptions{VMInstanceIDs: nil}) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, virtualMachineScaleSetsClientStartResponsePoller) + testsuite.Require().NoError(err) + + // From step VirtualMachineScaleSets_Reimage + fmt.Println("Call operation: VirtualMachineScaleSets_Reimage") + virtualMachineScaleSetsClientReimageResponsePoller, err := virtualMachineScaleSetsClient.BeginReimage(testsuite.ctx, testsuite.resourceGroupName, testsuite.vmScaleSetName, &armcompute.VirtualMachineScaleSetsClientBeginReimageOptions{VMScaleSetReimageInput: nil}) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, virtualMachineScaleSetsClientReimageResponsePoller) + testsuite.Require().NoError(err) + + // From step VirtualMachineScaleSets_Restart + fmt.Println("Call operation: VirtualMachineScaleSets_Restart") + virtualMachineScaleSetsClientRestartResponsePoller, err := virtualMachineScaleSetsClient.BeginRestart(testsuite.ctx, testsuite.resourceGroupName, testsuite.vmScaleSetName, &armcompute.VirtualMachineScaleSetsClientBeginRestartOptions{VMInstanceIDs: nil}) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, virtualMachineScaleSetsClientRestartResponsePoller) + testsuite.Require().NoError(err) + + // From step VirtualMachineScaleSets_ReimageAll + fmt.Println("Call operation: VirtualMachineScaleSets_ReimageAll") + virtualMachineScaleSetsClientReimageAllResponsePoller, err := virtualMachineScaleSetsClient.BeginReimageAll(testsuite.ctx, testsuite.resourceGroupName, testsuite.vmScaleSetName, &armcompute.VirtualMachineScaleSetsClientBeginReimageAllOptions{VMInstanceIDs: nil}) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, virtualMachineScaleSetsClientReimageAllResponsePoller) + testsuite.Require().NoError(err) +} + +// Microsoft.Compute/virtualMachineScaleSets/{vmScaleSetName}/virtualMachines/{instanceId} +func (testsuite *VirtualMachineScaleSetTestSuite) TestVirtualMachineScaleSetVMs() { + instanceId := "0" + var err error + // From step VirtualMachineScaleSetVMs_List + fmt.Println("Call operation: VirtualMachineScaleSetVMs_List") + virtualMachineScaleSetVMsClient, err := armcompute.NewVirtualMachineScaleSetVMsClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + virtualMachineScaleSetVMsClientNewListPager := virtualMachineScaleSetVMsClient.NewListPager(testsuite.resourceGroupName, testsuite.vmScaleSetName, &armcompute.VirtualMachineScaleSetVMsClientListOptions{Filter: nil, + Select: nil, + Expand: nil, + }) + for virtualMachineScaleSetVMsClientNewListPager.More() { + _, err := virtualMachineScaleSetVMsClientNewListPager.NextPage(testsuite.ctx) + testsuite.Require().NoError(err) + break + } + + // From step VirtualMachineScaleSetVMs_Get + fmt.Println("Call operation: VirtualMachineScaleSetVMs_Get") + _, err = virtualMachineScaleSetVMsClient.Get(testsuite.ctx, testsuite.resourceGroupName, testsuite.vmScaleSetName, instanceId, &armcompute.VirtualMachineScaleSetVMsClientGetOptions{Expand: nil}) + testsuite.Require().NoError(err) + + // From step VirtualMachineScaleSetVMs_GetInstanceView + fmt.Println("Call operation: VirtualMachineScaleSetVMs_GetInstanceView") + _, err = virtualMachineScaleSetVMsClient.GetInstanceView(testsuite.ctx, testsuite.resourceGroupName, testsuite.vmScaleSetName, instanceId, nil) + testsuite.Require().NoError(err) + + // From step VirtualMachineScaleSetVMs_Redeploy + fmt.Println("Call operation: VirtualMachineScaleSetVMs_Redeploy") + virtualMachineScaleSetVMsClientRedeployResponsePoller, err := virtualMachineScaleSetVMsClient.BeginRedeploy(testsuite.ctx, testsuite.resourceGroupName, testsuite.vmScaleSetName, instanceId, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, virtualMachineScaleSetVMsClientRedeployResponsePoller) + testsuite.Require().NoError(err) + + // From step VirtualMachineScaleSetVMs_Start + fmt.Println("Call operation: VirtualMachineScaleSetVMs_Start") + virtualMachineScaleSetVMsClientStartResponsePoller, err := virtualMachineScaleSetVMsClient.BeginStart(testsuite.ctx, testsuite.resourceGroupName, testsuite.vmScaleSetName, instanceId, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, virtualMachineScaleSetVMsClientStartResponsePoller) + testsuite.Require().NoError(err) + + // From step VirtualMachineScaleSetVMs_Restart + fmt.Println("Call operation: VirtualMachineScaleSetVMs_Restart") + virtualMachineScaleSetVMsClientRestartResponsePoller, err := virtualMachineScaleSetVMsClient.BeginRestart(testsuite.ctx, testsuite.resourceGroupName, testsuite.vmScaleSetName, instanceId, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, virtualMachineScaleSetVMsClientRestartResponsePoller) + testsuite.Require().NoError(err) + + // From step VirtualMachineScaleSetVMs_Deallocate + fmt.Println("Call operation: VirtualMachineScaleSetVMs_Deallocate") + virtualMachineScaleSetVMsClientDeallocateResponsePoller, err := virtualMachineScaleSetVMsClient.BeginDeallocate(testsuite.ctx, testsuite.resourceGroupName, testsuite.vmScaleSetName, instanceId, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, virtualMachineScaleSetVMsClientDeallocateResponsePoller) + testsuite.Require().NoError(err) + + // From step VirtualMachineScaleSetVMs_Reimage + fmt.Println("Call operation: VirtualMachineScaleSetVMs_Reimage") + virtualMachineScaleSetVMsClientReimageResponsePoller, err := virtualMachineScaleSetVMsClient.BeginReimage(testsuite.ctx, testsuite.resourceGroupName, testsuite.vmScaleSetName, instanceId, &armcompute.VirtualMachineScaleSetVMsClientBeginReimageOptions{VMScaleSetVMReimageInput: nil}) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, virtualMachineScaleSetVMsClientReimageResponsePoller) + testsuite.Require().NoError(err) + + // From step VirtualMachineScaleSetVMs_PowerOff + fmt.Println("Call operation: VirtualMachineScaleSetVMs_PowerOff") + virtualMachineScaleSetVMsClientPowerOffResponsePoller, err := virtualMachineScaleSetVMsClient.BeginPowerOff(testsuite.ctx, testsuite.resourceGroupName, testsuite.vmScaleSetName, instanceId, &armcompute.VirtualMachineScaleSetVMsClientBeginPowerOffOptions{SkipShutdown: nil}) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, virtualMachineScaleSetVMsClientPowerOffResponsePoller) + testsuite.Require().NoError(err) + + // From step VirtualMachineScaleSetVMs_Delete + fmt.Println("Call operation: VirtualMachineScaleSetVMs_Delete") + virtualMachineScaleSetVMsClientDeleteResponsePoller, err := virtualMachineScaleSetVMsClient.BeginDelete(testsuite.ctx, testsuite.resourceGroupName, testsuite.vmScaleSetName, instanceId, &armcompute.VirtualMachineScaleSetVMsClientBeginDeleteOptions{ForceDeletion: to.Ptr(true)}) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, virtualMachineScaleSetVMsClientDeleteResponsePoller) + testsuite.Require().NoError(err) +} + +func (testsuite *VirtualMachineScaleSetTestSuite) Cleanup() { + var err error + // From step VirtualMachineScaleSets_PowerOff + fmt.Println("Call operation: VirtualMachineScaleSets_PowerOff") + virtualMachineScaleSetsClient, err := armcompute.NewVirtualMachineScaleSetsClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + virtualMachineScaleSetsClientPowerOffResponsePoller, err := virtualMachineScaleSetsClient.BeginPowerOff(testsuite.ctx, testsuite.resourceGroupName, testsuite.vmScaleSetName, &armcompute.VirtualMachineScaleSetsClientBeginPowerOffOptions{SkipShutdown: nil, + VMInstanceIDs: nil, + }) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, virtualMachineScaleSetsClientPowerOffResponsePoller) + testsuite.Require().NoError(err) + + // From step VirtualMachineScaleSets_Delete + fmt.Println("Call operation: VirtualMachineScaleSets_Delete") + virtualMachineScaleSetsClientDeleteResponsePoller, err := virtualMachineScaleSetsClient.BeginDelete(testsuite.ctx, testsuite.resourceGroupName, testsuite.vmScaleSetName, &armcompute.VirtualMachineScaleSetsClientBeginDeleteOptions{ForceDeletion: to.Ptr(true)}) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, virtualMachineScaleSetsClientDeleteResponsePoller) + testsuite.Require().NoError(err) +} diff --git a/sdk/resourcemanager/compute/armcompute/virtualmachinescalesets_client_live_test.go b/sdk/resourcemanager/compute/armcompute/virtualmachinescalesets_client_live_test.go deleted file mode 100644 index e791fbfeef4e..000000000000 --- a/sdk/resourcemanager/compute/armcompute/virtualmachinescalesets_client_live_test.go +++ /dev/null @@ -1,195 +0,0 @@ -//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 armcompute_test - -import ( - "context" - "fmt" - "testing" - - "github.com/Azure/azure-sdk-for-go/sdk/azcore" - "github.com/Azure/azure-sdk-for-go/sdk/azcore/arm" - "github.com/Azure/azure-sdk-for-go/sdk/azcore/to" - "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v4" - "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/internal/testutil" - "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork" - "github.com/stretchr/testify/suite" -) - -type VirtualMachineScaleSetsClientTestSuite struct { - suite.Suite - - ctx context.Context - cred azcore.TokenCredential - options *arm.ClientOptions - location string - resourceGroupName string - subscriptionID string -} - -func (testsuite *VirtualMachineScaleSetsClientTestSuite) SetupSuite() { - testsuite.ctx = context.Background() - testsuite.cred, testsuite.options = testutil.GetCredAndClientOptions(testsuite.T()) - testsuite.location = testutil.GetEnv("LOCATION", "eastus") - testsuite.subscriptionID = testutil.GetEnv("AZURE_SUBSCRIPTION_ID", "00000000-0000-0000-0000-000000000000") - testutil.StartRecording(testsuite.T(), "sdk/resourcemanager/compute/armcompute/testdata") - resourceGroup, _, err := testutil.CreateResourceGroup(testsuite.ctx, testsuite.subscriptionID, testsuite.cred, testsuite.options, testsuite.location) - testsuite.Require().NoError(err) - testsuite.resourceGroupName = *resourceGroup.Name -} - -func (testsuite *VirtualMachineScaleSetsClientTestSuite) TearDownSuite() { - _, err := testutil.DeleteResourceGroup(testsuite.ctx, testsuite.subscriptionID, testsuite.cred, testsuite.options, testsuite.resourceGroupName) - testsuite.Require().NoError(err) - testutil.StopRecording(testsuite.T()) -} - -func TestVirtualMachineScaleSetsClient(t *testing.T) { - suite.Run(t, new(VirtualMachineScaleSetsClientTestSuite)) -} - -func (testsuite *VirtualMachineScaleSetsClientTestSuite) TestVirtualMachineScaleSetsCRUD() { - // create virtual network and subnet - vnClient, err := armnetwork.NewVirtualNetworksClient(testsuite.subscriptionID, testsuite.cred, testsuite.options) - testsuite.Require().NoError(err) - vnName := "go-test-network" - subName := "go-test-subnet" - vnPoller, err := vnClient.BeginCreateOrUpdate( - testsuite.ctx, - testsuite.resourceGroupName, - vnName, - armnetwork.VirtualNetwork{ - Location: to.Ptr(testsuite.location), - Properties: &armnetwork.VirtualNetworkPropertiesFormat{ - AddressSpace: &armnetwork.AddressSpace{ - AddressPrefixes: []*string{ - to.Ptr("10.1.0.0/16"), - }, - }, - Subnets: []*armnetwork.Subnet{ - { - Name: to.Ptr(subName), - Properties: &armnetwork.SubnetPropertiesFormat{ - AddressPrefix: to.Ptr("10.1.0.0/24"), - }, - }, - }, - }, - }, - nil, - ) - testsuite.Require().NoError(err) - vnResp, err := testutil.PollForTest(testsuite.ctx, vnPoller) - testsuite.Require().NoError(err) - testsuite.Require().Equal(vnName, *vnResp.Name) - - // create virtual machine scale set - fmt.Println("Call operation: VirtualMachineScaleSets_CreateOrUpdate") - vmssClient, err := armcompute.NewVirtualMachineScaleSetsClient(testsuite.subscriptionID, testsuite.cred, testsuite.options) - testsuite.Require().NoError(err) - vmssName := "go-test-vmss" - vmssPoller, err := vmssClient.BeginCreateOrUpdate( - testsuite.ctx, - testsuite.resourceGroupName, - vmssName, - armcompute.VirtualMachineScaleSet{ - Location: to.Ptr(testsuite.location), - SKU: &armcompute.SKU{ - //Name: to.Ptr("Basic_A0"), //armcompute.VirtualMachineSizeTypesBasicA0 - Name: to.Ptr("Standard_A0"), //armcompute.VirtualMachineSizeTypesBasicA0 - Capacity: to.Ptr[int64](1), - }, - Properties: &armcompute.VirtualMachineScaleSetProperties{ - Overprovision: to.Ptr(false), - UpgradePolicy: &armcompute.UpgradePolicy{ - Mode: to.Ptr(armcompute.UpgradeModeManual), - AutomaticOSUpgradePolicy: &armcompute.AutomaticOSUpgradePolicy{ - EnableAutomaticOSUpgrade: to.Ptr(false), - DisableAutomaticRollback: to.Ptr(false), - }, - }, - VirtualMachineProfile: &armcompute.VirtualMachineScaleSetVMProfile{ - OSProfile: &armcompute.VirtualMachineScaleSetOSProfile{ - ComputerNamePrefix: to.Ptr("vmss"), - AdminUsername: to.Ptr("sample-user"), - AdminPassword: to.Ptr("Password01!@#"), - }, - StorageProfile: &armcompute.VirtualMachineScaleSetStorageProfile{ - ImageReference: &armcompute.ImageReference{ - Offer: to.Ptr("WindowsServer"), - Publisher: to.Ptr("MicrosoftWindowsServer"), - SKU: to.Ptr("2019-Datacenter"), - Version: to.Ptr("latest"), - }, - }, - NetworkProfile: &armcompute.VirtualMachineScaleSetNetworkProfile{ - NetworkInterfaceConfigurations: []*armcompute.VirtualMachineScaleSetNetworkConfiguration{ - { - Name: to.Ptr(vmssName), - Properties: &armcompute.VirtualMachineScaleSetNetworkConfigurationProperties{ - Primary: to.Ptr(true), - EnableIPForwarding: to.Ptr(true), - IPConfigurations: []*armcompute.VirtualMachineScaleSetIPConfiguration{ - { - Name: to.Ptr(vmssName), - Properties: &armcompute.VirtualMachineScaleSetIPConfigurationProperties{ - Subnet: &armcompute.APIEntityReference{ - ID: to.Ptr(*vnResp.Properties.Subnets[0].ID), - }, - }, - }, - }, - }, - }, - }, - }, - }, - }, - }, - nil, - ) - testsuite.Require().NoError(err) - vmssResp, err := testutil.PollForTest(testsuite.ctx, vmssPoller) - testsuite.Require().NoError(err) - testsuite.Require().Equal(vmssName, *vmssResp.Name) - - // update - fmt.Println("Call operation: VirtualMachineScaleSets_Update") - updatePollerResp, err := vmssClient.BeginUpdate( - testsuite.ctx, - testsuite.resourceGroupName, - vmssName, - armcompute.VirtualMachineScaleSetUpdate{ - Tags: map[string]*string{ - "test": to.Ptr("live"), - }, - }, - nil, - ) - testsuite.Require().NoError(err) - updateResp, err := testutil.PollForTest(testsuite.ctx, updatePollerResp) - testsuite.Require().NoError(err) - testsuite.Require().Equal("live", *updateResp.Tags["test"]) - - // get - fmt.Println("Call operation: VirtualMachineScaleSets_Get") - getResp, err := vmssClient.Get(testsuite.ctx, testsuite.resourceGroupName, vmssName, nil) - testsuite.Require().NoError(err) - testsuite.Require().Equal(vmssName, *getResp.Name) - - // list - fmt.Println("Call operation: VirtualMachineScaleSets_List") - listResp := vmssClient.NewListPager(testsuite.resourceGroupName, nil) - testsuite.Require().True(listResp.More()) - - // delete - fmt.Println("Call operation: VirtualMachineScaleSets_Delete") - delPoller, err := vmssClient.BeginDelete(testsuite.ctx, testsuite.resourceGroupName, vmssName, nil) - testsuite.Require().NoError(err) - _, err = testutil.PollForTest(testsuite.ctx, delPoller) - testsuite.Require().NoError(err) -} diff --git a/sdk/resourcemanager/cosmos/armcosmos/assets.json b/sdk/resourcemanager/cosmos/armcosmos/assets.json index 583d0157f601..512680b33eee 100644 --- a/sdk/resourcemanager/cosmos/armcosmos/assets.json +++ b/sdk/resourcemanager/cosmos/armcosmos/assets.json @@ -2,5 +2,5 @@ "AssetsRepo": "Azure/azure-sdk-assets", "AssetsRepoPrefixPath": "go", "TagPrefix": "go/resourcemanager/cosmos/armcosmos", - "Tag": "go/resourcemanager/cosmos/armcosmos_f300ab67c7" + "Tag": "go/resourcemanager/cosmos/armcosmos_b256b80d8d" } diff --git a/sdk/resourcemanager/cosmos/armcosmos/cassandraresources_live_test.go b/sdk/resourcemanager/cosmos/armcosmos/cassandraresources_live_test.go new file mode 100644 index 000000000000..5d02a42eadb4 --- /dev/null +++ b/sdk/resourcemanager/cosmos/armcosmos/cassandraresources_live_test.go @@ -0,0 +1,266 @@ +//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 armcosmos_test + +import ( + "context" + "fmt" + "testing" + + "github.com/Azure/azure-sdk-for-go/sdk/azcore" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/arm" + "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/resourcemanager/cosmos/armcosmos/v2" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/internal/testutil" + "github.com/stretchr/testify/suite" +) + +type CassandraResourcesTestSuite struct { + suite.Suite + + ctx context.Context + cred azcore.TokenCredential + options *arm.ClientOptions + accountName string + keyspaceName string + tableName string + location string + resourceGroupName string + subscriptionId string +} + +func (testsuite *CassandraResourcesTestSuite) SetupSuite() { + testutil.StartRecording(testsuite.T(), "sdk/resourcemanager/cosmos/armcosmos/testdata") + + testsuite.ctx = context.Background() + testsuite.cred, testsuite.options = testutil.GetCredAndClientOptions(testsuite.T()) + testsuite.accountName, _ = recording.GenerateAlphaNumericID(testsuite.T(), "accountn", 14, true) + testsuite.keyspaceName, _ = recording.GenerateAlphaNumericID(testsuite.T(), "keyspace", 14, false) + testsuite.tableName, _ = recording.GenerateAlphaNumericID(testsuite.T(), "tablenam", 14, false) + testsuite.location = testutil.GetEnv("LOCATION", "westus") + testsuite.resourceGroupName = testutil.GetEnv("RESOURCE_GROUP_NAME", "scenarioTestTempGroup") + testsuite.subscriptionId = testutil.GetEnv("AZURE_SUBSCRIPTION_ID", "00000000-0000-0000-0000-000000000000") + resourceGroup, _, err := testutil.CreateResourceGroup(testsuite.ctx, testsuite.subscriptionId, testsuite.cred, testsuite.options, testsuite.location) + testsuite.Require().NoError(err) + testsuite.resourceGroupName = *resourceGroup.Name + testsuite.Prepare() +} + +func (testsuite *CassandraResourcesTestSuite) TearDownSuite() { + testsuite.Cleanup() + _, err := testutil.DeleteResourceGroup(testsuite.ctx, testsuite.subscriptionId, testsuite.cred, testsuite.options, testsuite.resourceGroupName) + testsuite.Require().NoError(err) + testutil.StopRecording(testsuite.T()) +} + +func TestCassandraResourcesTestSuite(t *testing.T) { + suite.Run(t, new(CassandraResourcesTestSuite)) +} + +func (testsuite *CassandraResourcesTestSuite) Prepare() { + var err error + // From step DatabaseAccounts_CreateOrUpdate + fmt.Println("Call operation: DatabaseAccounts_CreateOrUpdate") + databaseAccountsClient, err := armcosmos.NewDatabaseAccountsClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + databaseAccountsClientCreateOrUpdateResponsePoller, err := databaseAccountsClient.BeginCreateOrUpdate(testsuite.ctx, testsuite.resourceGroupName, testsuite.accountName, armcosmos.DatabaseAccountCreateUpdateParameters{ + Location: to.Ptr(testsuite.location), + Properties: &armcosmos.DatabaseAccountCreateUpdateProperties{ + Capabilities: []*armcosmos.Capability{ + { + Name: to.Ptr("EnableCassandra"), + }}, + CreateMode: to.Ptr(armcosmos.CreateModeDefault), + DatabaseAccountOfferType: to.Ptr("Standard"), + Locations: []*armcosmos.Location{ + { + FailoverPriority: to.Ptr[int32](0), + IsZoneRedundant: to.Ptr(false), + LocationName: to.Ptr(testsuite.location), + }}, + }, + }, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, databaseAccountsClientCreateOrUpdateResponsePoller) + testsuite.Require().NoError(err) +} + +// Microsoft.DocumentDB/databaseAccounts/{accountName}/cassandraKeyspaces/{keyspaceName} +func (testsuite *CassandraResourcesTestSuite) TestCassandraKeyspace() { + var err error + // From step CassandraResources_CreateUpdateCassandraKeyspace + fmt.Println("Call operation: CassandraResources_CreateUpdateCassandraKeyspace") + cassandraResourcesClient, err := armcosmos.NewCassandraResourcesClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + cassandraResourcesClientCreateUpdateCassandraKeyspaceResponsePoller, err := cassandraResourcesClient.BeginCreateUpdateCassandraKeyspace(testsuite.ctx, testsuite.resourceGroupName, testsuite.accountName, testsuite.keyspaceName, armcosmos.CassandraKeyspaceCreateUpdateParameters{ + Location: to.Ptr(testsuite.location), + Tags: map[string]*string{}, + Properties: &armcosmos.CassandraKeyspaceCreateUpdateProperties{ + Options: &armcosmos.CreateUpdateOptions{ + Throughput: to.Ptr[int32](2000), + }, + Resource: &armcosmos.CassandraKeyspaceResource{ + ID: to.Ptr(testsuite.keyspaceName), + }, + }, + }, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, cassandraResourcesClientCreateUpdateCassandraKeyspaceResponsePoller) + testsuite.Require().NoError(err) + + // From step CassandraResources_ListCassandraKeyspaces + fmt.Println("Call operation: CassandraResources_ListCassandraKeyspaces") + cassandraResourcesClientNewListCassandraKeyspacesPager := cassandraResourcesClient.NewListCassandraKeyspacesPager(testsuite.resourceGroupName, testsuite.accountName, nil) + for cassandraResourcesClientNewListCassandraKeyspacesPager.More() { + _, err := cassandraResourcesClientNewListCassandraKeyspacesPager.NextPage(testsuite.ctx) + testsuite.Require().NoError(err) + break + } + + // From step CassandraResources_GetCassandraKeyspaceThroughput + fmt.Println("Call operation: CassandraResources_GetCassandraKeyspaceThroughput") + _, err = cassandraResourcesClient.GetCassandraKeyspaceThroughput(testsuite.ctx, testsuite.resourceGroupName, testsuite.accountName, testsuite.keyspaceName, nil) + testsuite.Require().NoError(err) + + // From step CassandraResources_GetCassandraKeyspace + fmt.Println("Call operation: CassandraResources_GetCassandraKeyspace") + _, err = cassandraResourcesClient.GetCassandraKeyspace(testsuite.ctx, testsuite.resourceGroupName, testsuite.accountName, testsuite.keyspaceName, nil) + testsuite.Require().NoError(err) + + // From step CassandraResources_MigrateCassandraKeyspaceToAutoscale + fmt.Println("Call operation: CassandraResources_MigrateCassandraKeyspaceToAutoscale") + cassandraResourcesClientMigrateCassandraKeyspaceToAutoscaleResponsePoller, err := cassandraResourcesClient.BeginMigrateCassandraKeyspaceToAutoscale(testsuite.ctx, testsuite.resourceGroupName, testsuite.accountName, testsuite.keyspaceName, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, cassandraResourcesClientMigrateCassandraKeyspaceToAutoscaleResponsePoller) + testsuite.Require().NoError(err) + + // From step CassandraResources_MigrateCassandraKeyspaceToManualThroughput + fmt.Println("Call operation: CassandraResources_MigrateCassandraKeyspaceToManualThroughput") + cassandraResourcesClientMigrateCassandraKeyspaceToManualThroughputResponsePoller, err := cassandraResourcesClient.BeginMigrateCassandraKeyspaceToManualThroughput(testsuite.ctx, testsuite.resourceGroupName, testsuite.accountName, testsuite.keyspaceName, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, cassandraResourcesClientMigrateCassandraKeyspaceToManualThroughputResponsePoller) + testsuite.Require().NoError(err) + + // From step CassandraResources_UpdateCassandraKeyspaceThroughput + fmt.Println("Call operation: CassandraResources_UpdateCassandraKeyspaceThroughput") + cassandraResourcesClientUpdateCassandraKeyspaceThroughputResponsePoller, err := cassandraResourcesClient.BeginUpdateCassandraKeyspaceThroughput(testsuite.ctx, testsuite.resourceGroupName, testsuite.accountName, testsuite.keyspaceName, armcosmos.ThroughputSettingsUpdateParameters{ + Location: to.Ptr(testsuite.location), + Tags: map[string]*string{}, + Properties: &armcosmos.ThroughputSettingsUpdateProperties{ + Resource: &armcosmos.ThroughputSettingsResource{ + Throughput: to.Ptr[int32](400), + }, + }, + }, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, cassandraResourcesClientUpdateCassandraKeyspaceThroughputResponsePoller) + testsuite.Require().NoError(err) +} + +// Microsoft.DocumentDB/databaseAccounts/{accountName}/cassandraKeyspaces/{keyspaceName}/tables/{tableName} +func (testsuite *CassandraResourcesTestSuite) TestCassandraTable() { + var err error + // From step CassandraResources_CreateUpdateCassandraTable + fmt.Println("Call operation: CassandraResources_CreateUpdateCassandraTable") + cassandraResourcesClient, err := armcosmos.NewCassandraResourcesClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + cassandraResourcesClientCreateUpdateCassandraTableResponsePoller, err := cassandraResourcesClient.BeginCreateUpdateCassandraTable(testsuite.ctx, testsuite.resourceGroupName, testsuite.accountName, testsuite.keyspaceName, testsuite.tableName, armcosmos.CassandraTableCreateUpdateParameters{ + Location: to.Ptr(testsuite.location), + Tags: map[string]*string{}, + Properties: &armcosmos.CassandraTableCreateUpdateProperties{ + Options: &armcosmos.CreateUpdateOptions{ + Throughput: to.Ptr[int32](2000), + }, + Resource: &armcosmos.CassandraTableResource{ + Schema: &armcosmos.CassandraSchema{ + Columns: []*armcosmos.Column{ + { + Name: to.Ptr("columnA"), + Type: to.Ptr("Ascii"), + }}, + PartitionKeys: []*armcosmos.CassandraPartitionKey{ + { + Name: to.Ptr("columnA"), + }}, + }, + DefaultTTL: to.Ptr[int32](100), + ID: to.Ptr(testsuite.tableName), + }, + }, + }, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, cassandraResourcesClientCreateUpdateCassandraTableResponsePoller) + testsuite.Require().NoError(err) + + // From step CassandraResources_GetCassandraTable + fmt.Println("Call operation: CassandraResources_GetCassandraTable") + _, err = cassandraResourcesClient.GetCassandraTable(testsuite.ctx, testsuite.resourceGroupName, testsuite.accountName, testsuite.keyspaceName, testsuite.tableName, nil) + testsuite.Require().NoError(err) + + // From step CassandraResources_ListCassandraTables + fmt.Println("Call operation: CassandraResources_ListCassandraTables") + cassandraResourcesClientNewListCassandraTablesPager := cassandraResourcesClient.NewListCassandraTablesPager(testsuite.resourceGroupName, testsuite.accountName, testsuite.keyspaceName, nil) + for cassandraResourcesClientNewListCassandraTablesPager.More() { + _, err := cassandraResourcesClientNewListCassandraTablesPager.NextPage(testsuite.ctx) + testsuite.Require().NoError(err) + break + } + + // From step CassandraResources_GetCassandraTableThroughput + fmt.Println("Call operation: CassandraResources_GetCassandraTableThroughput") + _, err = cassandraResourcesClient.GetCassandraTableThroughput(testsuite.ctx, testsuite.resourceGroupName, testsuite.accountName, testsuite.keyspaceName, testsuite.tableName, nil) + testsuite.Require().NoError(err) + + // From step CassandraResources_MigrateCassandraTableToAutoscale + fmt.Println("Call operation: CassandraResources_MigrateCassandraTableToAutoscale") + cassandraResourcesClientMigrateCassandraTableToAutoscaleResponsePoller, err := cassandraResourcesClient.BeginMigrateCassandraTableToAutoscale(testsuite.ctx, testsuite.resourceGroupName, testsuite.accountName, testsuite.keyspaceName, testsuite.tableName, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, cassandraResourcesClientMigrateCassandraTableToAutoscaleResponsePoller) + testsuite.Require().NoError(err) + + // From step CassandraResources_MigrateCassandraTableToManualThroughput + fmt.Println("Call operation: CassandraResources_MigrateCassandraTableToManualThroughput") + cassandraResourcesClientMigrateCassandraTableToManualThroughputResponsePoller, err := cassandraResourcesClient.BeginMigrateCassandraTableToManualThroughput(testsuite.ctx, testsuite.resourceGroupName, testsuite.accountName, testsuite.keyspaceName, testsuite.tableName, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, cassandraResourcesClientMigrateCassandraTableToManualThroughputResponsePoller) + testsuite.Require().NoError(err) + + // From step CassandraResources_UpdateCassandraTableThroughput + fmt.Println("Call operation: CassandraResources_UpdateCassandraTableThroughput") + cassandraResourcesClientUpdateCassandraTableThroughputResponsePoller, err := cassandraResourcesClient.BeginUpdateCassandraTableThroughput(testsuite.ctx, testsuite.resourceGroupName, testsuite.accountName, testsuite.keyspaceName, testsuite.tableName, armcosmos.ThroughputSettingsUpdateParameters{ + Location: to.Ptr(testsuite.location), + Tags: map[string]*string{}, + Properties: &armcosmos.ThroughputSettingsUpdateProperties{ + Resource: &armcosmos.ThroughputSettingsResource{ + Throughput: to.Ptr[int32](400), + }, + }, + }, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, cassandraResourcesClientUpdateCassandraTableThroughputResponsePoller) + testsuite.Require().NoError(err) + + // From step CassandraResources_DeleteCassandraTable + fmt.Println("Call operation: CassandraResources_DeleteCassandraTable") + cassandraResourcesClientDeleteCassandraTableResponsePoller, err := cassandraResourcesClient.BeginDeleteCassandraTable(testsuite.ctx, testsuite.resourceGroupName, testsuite.accountName, testsuite.keyspaceName, testsuite.tableName, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, cassandraResourcesClientDeleteCassandraTableResponsePoller) + testsuite.Require().NoError(err) +} + +func (testsuite *CassandraResourcesTestSuite) Cleanup() { + var err error + // From step CassandraResources_DeleteCassandraKeyspace + fmt.Println("Call operation: CassandraResources_DeleteCassandraKeyspace") + cassandraResourcesClient, err := armcosmos.NewCassandraResourcesClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + cassandraResourcesClientDeleteCassandraKeyspaceResponsePoller, err := cassandraResourcesClient.BeginDeleteCassandraKeyspace(testsuite.ctx, testsuite.resourceGroupName, testsuite.accountName, testsuite.keyspaceName, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, cassandraResourcesClientDeleteCassandraKeyspaceResponsePoller) + testsuite.Require().NoError(err) +} diff --git a/sdk/resourcemanager/cosmos/armcosmos/databaseaccounts_live_test.go b/sdk/resourcemanager/cosmos/armcosmos/databaseaccounts_live_test.go new file mode 100644 index 000000000000..3a8064d476e4 --- /dev/null +++ b/sdk/resourcemanager/cosmos/armcosmos/databaseaccounts_live_test.go @@ -0,0 +1,223 @@ +//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 armcosmos_test + +import ( + "context" + "fmt" + "testing" + + "github.com/Azure/azure-sdk-for-go/sdk/azcore" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/arm" + "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/resourcemanager/cosmos/armcosmos/v2" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/internal/testutil" + "github.com/stretchr/testify/suite" +) + +type DatabaseAccountsTestSuite struct { + suite.Suite + + ctx context.Context + cred azcore.TokenCredential + options *arm.ClientOptions + accountName string + location string + resourceGroupName string + subscriptionId string +} + +func (testsuite *DatabaseAccountsTestSuite) SetupSuite() { + testutil.StartRecording(testsuite.T(), "sdk/resourcemanager/cosmos/armcosmos/testdata") + + testsuite.ctx = context.Background() + testsuite.cred, testsuite.options = testutil.GetCredAndClientOptions(testsuite.T()) + testsuite.accountName, _ = recording.GenerateAlphaNumericID(testsuite.T(), "accountn", 14, true) + testsuite.location = testutil.GetEnv("LOCATION", "westus") + testsuite.resourceGroupName = testutil.GetEnv("RESOURCE_GROUP_NAME", "scenarioTestTempGroup") + testsuite.subscriptionId = testutil.GetEnv("AZURE_SUBSCRIPTION_ID", "00000000-0000-0000-0000-000000000000") + resourceGroup, _, err := testutil.CreateResourceGroup(testsuite.ctx, testsuite.subscriptionId, testsuite.cred, testsuite.options, testsuite.location) + testsuite.Require().NoError(err) + testsuite.resourceGroupName = *resourceGroup.Name +} + +func (testsuite *DatabaseAccountsTestSuite) TearDownSuite() { + _, err := testutil.DeleteResourceGroup(testsuite.ctx, testsuite.subscriptionId, testsuite.cred, testsuite.options, testsuite.resourceGroupName) + testsuite.Require().NoError(err) + testutil.StopRecording(testsuite.T()) +} + +func TestDatabaseAccountsTestSuite(t *testing.T) { + suite.Run(t, new(DatabaseAccountsTestSuite)) +} + +// Microsoft.DocumentDB/databaseAccounts/{accountName} +func (testsuite *DatabaseAccountsTestSuite) TestDatabaseAccounts() { + var err error + // From step DatabaseAccounts_CheckNameExists + fmt.Println("Call operation: DatabaseAccounts_CheckNameExists") + databaseAccountsClient, err := armcosmos.NewDatabaseAccountsClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + _, err = databaseAccountsClient.CheckNameExists(testsuite.ctx, testsuite.accountName, nil) + testsuite.Require().NoError(err) + + // From step DatabaseAccounts_CreateOrUpdate + fmt.Println("Call operation: DatabaseAccounts_CreateOrUpdate") + databaseAccountsClientCreateOrUpdateResponsePoller, err := databaseAccountsClient.BeginCreateOrUpdate(testsuite.ctx, testsuite.resourceGroupName, testsuite.accountName, armcosmos.DatabaseAccountCreateUpdateParameters{ + Location: to.Ptr(testsuite.location), + Properties: &armcosmos.DatabaseAccountCreateUpdateProperties{ + CreateMode: to.Ptr(armcosmos.CreateModeDefault), + DatabaseAccountOfferType: to.Ptr("Standard"), + Locations: []*armcosmos.Location{ + { + FailoverPriority: to.Ptr[int32](2), + LocationName: to.Ptr("southcentralus"), + }, + { + FailoverPriority: to.Ptr[int32](1), + LocationName: to.Ptr("eastus"), + }, + { + FailoverPriority: to.Ptr[int32](0), + LocationName: to.Ptr("westus"), + }}, + }, + }, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, databaseAccountsClientCreateOrUpdateResponsePoller) + testsuite.Require().NoError(err) + + // From step DatabaseAccounts_List + fmt.Println("Call operation: DatabaseAccounts_List") + databaseAccountsClientNewListPager := databaseAccountsClient.NewListPager(nil) + for databaseAccountsClientNewListPager.More() { + _, err := databaseAccountsClientNewListPager.NextPage(testsuite.ctx) + testsuite.Require().NoError(err) + break + } + + // From step DatabaseAccounts_ListUsages + fmt.Println("Call operation: DatabaseAccounts_ListUsages") + databaseAccountsClientNewListUsagesPager := databaseAccountsClient.NewListUsagesPager(testsuite.resourceGroupName, testsuite.accountName, &armcosmos.DatabaseAccountsClientListUsagesOptions{Filter: to.Ptr("")}) + for databaseAccountsClientNewListUsagesPager.More() { + _, err := databaseAccountsClientNewListUsagesPager.NextPage(testsuite.ctx) + testsuite.Require().NoError(err) + break + } + + // From step DatabaseAccounts_GetReadOnlyKeys + fmt.Println("Call operation: DatabaseAccounts_GetReadOnlyKeys") + _, err = databaseAccountsClient.GetReadOnlyKeys(testsuite.ctx, testsuite.resourceGroupName, testsuite.accountName, nil) + testsuite.Require().NoError(err) + + // From step DatabaseAccounts_ListByResourceGroup + fmt.Println("Call operation: DatabaseAccounts_ListByResourceGroup") + databaseAccountsClientNewListByResourceGroupPager := databaseAccountsClient.NewListByResourceGroupPager(testsuite.resourceGroupName, nil) + for databaseAccountsClientNewListByResourceGroupPager.More() { + _, err := databaseAccountsClientNewListByResourceGroupPager.NextPage(testsuite.ctx) + testsuite.Require().NoError(err) + break + } + + // From step DatabaseAccounts_ListMetricDefinitions + fmt.Println("Call operation: DatabaseAccounts_ListMetricDefinitions") + databaseAccountsClientNewListMetricDefinitionsPager := databaseAccountsClient.NewListMetricDefinitionsPager(testsuite.resourceGroupName, testsuite.accountName, nil) + for databaseAccountsClientNewListMetricDefinitionsPager.More() { + _, err := databaseAccountsClientNewListMetricDefinitionsPager.NextPage(testsuite.ctx) + testsuite.Require().NoError(err) + break + } + + // From step DatabaseAccounts_Get + fmt.Println("Call operation: DatabaseAccounts_Get") + _, err = databaseAccountsClient.Get(testsuite.ctx, testsuite.resourceGroupName, testsuite.accountName, nil) + testsuite.Require().NoError(err) + + // From step DatabaseAccounts_Update + fmt.Println("Call operation: DatabaseAccounts_Update") + databaseAccountsClientUpdateResponsePoller, err := databaseAccountsClient.BeginUpdate(testsuite.ctx, testsuite.resourceGroupName, testsuite.accountName, armcosmos.DatabaseAccountUpdateParameters{ + Tags: map[string]*string{ + "dept": to.Ptr("finance"), + }, + }, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, databaseAccountsClientUpdateResponsePoller) + testsuite.Require().NoError(err) + + // From step DatabaseAccounts_RegenerateKey + fmt.Println("Call operation: DatabaseAccounts_RegenerateKey") + databaseAccountsClientRegenerateKeyResponsePoller, err := databaseAccountsClient.BeginRegenerateKey(testsuite.ctx, testsuite.resourceGroupName, testsuite.accountName, armcosmos.DatabaseAccountRegenerateKeyParameters{ + KeyKind: to.Ptr(armcosmos.KeyKindPrimary), + }, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, databaseAccountsClientRegenerateKeyResponsePoller) + testsuite.Require().NoError(err) + + // From step DatabaseAccounts_ListReadOnlyKeys + fmt.Println("Call operation: DatabaseAccounts_ListReadOnlyKeys") + _, err = databaseAccountsClient.ListReadOnlyKeys(testsuite.ctx, testsuite.resourceGroupName, testsuite.accountName, nil) + testsuite.Require().NoError(err) + + // From step DatabaseAccounts_ListConnectionStrings + fmt.Println("Call operation: DatabaseAccounts_ListConnectionStrings") + _, err = databaseAccountsClient.ListConnectionStrings(testsuite.ctx, testsuite.resourceGroupName, testsuite.accountName, nil) + testsuite.Require().NoError(err) + + // From step DatabaseAccounts_ListKeys + fmt.Println("Call operation: DatabaseAccounts_ListKeys") + _, err = databaseAccountsClient.ListKeys(testsuite.ctx, testsuite.resourceGroupName, testsuite.accountName, nil) + testsuite.Require().NoError(err) + + // From step DatabaseAccounts_FailoverPriorityChange + fmt.Println("Call operation: DatabaseAccounts_FailoverPriorityChange") + databaseAccountsClientFailoverPriorityChangeResponsePoller, err := databaseAccountsClient.BeginFailoverPriorityChange(testsuite.ctx, testsuite.resourceGroupName, testsuite.accountName, armcosmos.FailoverPolicies{ + FailoverPolicies: []*armcosmos.FailoverPolicy{ + { + FailoverPriority: to.Ptr[int32](0), + LocationName: to.Ptr("eastus"), + }, + { + FailoverPriority: to.Ptr[int32](2), + LocationName: to.Ptr("southcentralus"), + }, + { + FailoverPriority: to.Ptr[int32](1), + LocationName: to.Ptr("westus"), + }}, + }, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, databaseAccountsClientFailoverPriorityChangeResponsePoller) + testsuite.Require().NoError(err) + + // From step RestorableDatabaseAccounts_ListByLocation + fmt.Println("Call operation: RestorableDatabaseAccounts_ListByLocation") + restorableDatabaseAccountsClient, err := armcosmos.NewRestorableDatabaseAccountsClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + restorableDatabaseAccountsClientNewListByLocationPager := restorableDatabaseAccountsClient.NewListByLocationPager(testsuite.location, nil) + for restorableDatabaseAccountsClientNewListByLocationPager.More() { + _, err := restorableDatabaseAccountsClientNewListByLocationPager.NextPage(testsuite.ctx) + testsuite.Require().NoError(err) + break + } + + // From step RestorableDatabaseAccounts_List + fmt.Println("Call operation: RestorableDatabaseAccounts_List") + restorableDatabaseAccountsClientNewListPager := restorableDatabaseAccountsClient.NewListPager(nil) + for restorableDatabaseAccountsClientNewListPager.More() { + _, err := restorableDatabaseAccountsClientNewListPager.NextPage(testsuite.ctx) + testsuite.Require().NoError(err) + break + } + + // From step DatabaseAccounts_Delete + fmt.Println("Call operation: DatabaseAccounts_Delete") + databaseAccountsClientDeleteResponsePoller, err := databaseAccountsClient.BeginDelete(testsuite.ctx, testsuite.resourceGroupName, testsuite.accountName, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, databaseAccountsClientDeleteResponsePoller) + testsuite.Require().NoError(err) +} diff --git a/sdk/resourcemanager/cosmos/armcosmos/go.mod b/sdk/resourcemanager/cosmos/armcosmos/go.mod index 7e1ccc0fbbd8..635ba01cfcae 100644 --- a/sdk/resourcemanager/cosmos/armcosmos/go.mod +++ b/sdk/resourcemanager/cosmos/armcosmos/go.mod @@ -3,19 +3,27 @@ module github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/cosmos/armcosmos/v2 go 1.18 require ( - github.com/Azure/azure-sdk-for-go/sdk/azcore v1.4.0 + github.com/Azure/azure-sdk-for-go/sdk/azcore v1.5.0 github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.2.2 + github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0 + github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/internal v1.1.2 + github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armresources v1.1.1 + github.com/stretchr/testify v1.8.2 ) require ( - github.com/Azure/azure-sdk-for-go/sdk/internal v1.2.0 // indirect github.com/AzureAD/microsoft-authentication-library-for-go v0.9.0 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/dnaeon/go-vcr v1.1.0 // indirect github.com/golang-jwt/jwt/v4 v4.5.0 // indirect github.com/google/uuid v1.3.0 // indirect github.com/kylelemons/godebug v1.1.0 // indirect github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect golang.org/x/crypto v0.6.0 // indirect - golang.org/x/net v0.7.0 // indirect - golang.org/x/sys v0.5.0 // indirect - golang.org/x/text v0.7.0 // indirect + golang.org/x/net v0.8.0 // indirect + golang.org/x/sys v0.6.0 // indirect + golang.org/x/text v0.8.0 // indirect + gopkg.in/yaml.v2 v2.4.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/sdk/resourcemanager/cosmos/armcosmos/go.sum b/sdk/resourcemanager/cosmos/armcosmos/go.sum index 8ba445a8c4da..e625fa8fa1b9 100644 --- a/sdk/resourcemanager/cosmos/armcosmos/go.sum +++ b/sdk/resourcemanager/cosmos/armcosmos/go.sum @@ -1,31 +1,53 @@ -github.com/Azure/azure-sdk-for-go/sdk/azcore v1.4.0 h1:rTnT/Jrcm+figWlYz4Ixzt0SJVR2cMC8lvZcimipiEY= -github.com/Azure/azure-sdk-for-go/sdk/azcore v1.4.0/go.mod h1:ON4tFdPTwRcgWEaVDrN3584Ef+b7GgSJaXxe5fW9t4M= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.5.0 h1:xGLAFFd9D3iLGxYiUGPdITSzsFmU1K8VtfuUHWAoN7M= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.5.0/go.mod h1:bjGvMhVMb+EEm3VRNQawDMUyMMjo+S5ewNjflkep/0Q= github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.2.2 h1:uqM+VoHjVH6zdlkLF2b6O0ZANcHoj3rO0PoQ3jglUJA= github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.2.2/go.mod h1:twTKAa1E6hLmSDjLhaCkbTMQKc7p/rNLU40rLxGEOCI= -github.com/Azure/azure-sdk-for-go/sdk/internal v1.2.0 h1:leh5DwKv6Ihwi+h60uHtn6UWAxBbZ0q8DwQVMzf61zw= -github.com/Azure/azure-sdk-for-go/sdk/internal v1.2.0/go.mod h1:eWRD7oawr1Mu1sLCawqVc0CUiF43ia3qQMxLscsKQ9w= +github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0 h1:sXr+ck84g/ZlZUOZiNELInmMgOsuGwdjjVkEIde0OtY= +github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0/go.mod h1:okt5dMMTOFjX/aovMlrjvvXoPMBVSPzk9185BT0+eZM= +github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/internal v1.1.2 h1:mLY+pNLjCUeKhgnAJWAKhEUQM+RJQo2H1fuGSw1Ky1E= +github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/internal v1.1.2/go.mod h1:FbdwsQ2EzwvXxOPcMFYO8ogEc9uMMIj3YkmCdXdAFmk= +github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/managementgroups/armmanagementgroups v1.0.0 h1:pPvTJ1dY0sA35JOeFq6TsY2xj6Z85Yo23Pj4wCCvu4o= +github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armresources v1.1.1 h1:7CBQ+Ei8SP2c6ydQTGCCrS35bDxgTMfoP2miAwK++OU= +github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armresources v1.1.1/go.mod h1:c/wcGeGx5FUPbM/JltUYHZcKmigwyVLJlDq+4HdtXaw= github.com/AzureAD/microsoft-authentication-library-for-go v0.9.0 h1:UE9n9rkJF62ArLb1F3DEjRt8O3jLwMWdSoypKV4f3MU= github.com/AzureAD/microsoft-authentication-library-for-go v0.9.0/go.mod h1:kgDmCTgBzIEPFElEF+FK0SdjAor06dRq2Go927dnQ6o= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/dnaeon/go-vcr v1.1.0 h1:ReYa/UBrRyQdant9B4fNHGoCNKw6qh6P0fsdGmZpR7c= +github.com/dnaeon/go-vcr v1.1.0/go.mod h1:M7tiix8f0r6mKKJ3Yq/kqU1OYf3MnfmBWVbPx/yU9ko= github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg= github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= +github.com/modocache/gover v0.0.0-20171022184752-b58185e213c5/go.mod h1:caMODM3PzxT8aQXRPkAt8xlV/e7d7w8GM5g0fa5F0D8= github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 h1:KoWmjvw+nsYOo29YJK9vDA65RGE3NrOnUtO7a+RF9HU= github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8/go.mod h1:HKlIX3XHQyzLZPlr7++PzdhaXEj94dEiJgZDTsxEqUI= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= -github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= +github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= golang.org/x/crypto v0.6.0 h1:qfktjS5LUO+fFKeJXZ+ikTRijMmljikvG68fpMMruSc= golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58= -golang.org/x/net v0.7.0 h1:rJrUqqhjsgNp7KqAIc25s9pZnjU7TUcSY7HcVZjdn1g= -golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.8.0 h1:Zrh2ngAOFYneWTAIAPethzeaQLuHwhuBkuV6ZiRnUaQ= +golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= golang.org/x/sys v0.0.0-20210616045830-e2b7044e8c71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU= -golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/text v0.7.0 h1:4BRB4x83lYWy72KwLD/qYDuTu7q9PjSagHvijDw7cLo= -golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/sys v0.6.0 h1:MVltZSvRTcU2ljQOhs94SXPftV6DCNnZViHeQps87pQ= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/text v0.8.0 h1:57P1ETyNKtuIjB4SRd15iJxuhj8Gc416Y78H3qgMh68= +golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= -gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/sdk/resourcemanager/cosmos/armcosmos/gremlinresources_live_test.go b/sdk/resourcemanager/cosmos/armcosmos/gremlinresources_live_test.go new file mode 100644 index 000000000000..aa932ebd6385 --- /dev/null +++ b/sdk/resourcemanager/cosmos/armcosmos/gremlinresources_live_test.go @@ -0,0 +1,293 @@ +//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 armcosmos_test + +import ( + "context" + "fmt" + "testing" + + "github.com/Azure/azure-sdk-for-go/sdk/azcore" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/arm" + "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/resourcemanager/cosmos/armcosmos/v2" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/internal/testutil" + "github.com/stretchr/testify/suite" +) + +type GremlinResourcesTestSuite struct { + suite.Suite + + ctx context.Context + cred azcore.TokenCredential + options *arm.ClientOptions + accountName string + databaseName string + graphName string + location string + resourceGroupName string + subscriptionId string +} + +func (testsuite *GremlinResourcesTestSuite) SetupSuite() { + testutil.StartRecording(testsuite.T(), "sdk/resourcemanager/cosmos/armcosmos/testdata") + + testsuite.ctx = context.Background() + testsuite.cred, testsuite.options = testutil.GetCredAndClientOptions(testsuite.T()) + testsuite.accountName, _ = recording.GenerateAlphaNumericID(testsuite.T(), "accountn", 14, true) + testsuite.databaseName, _ = recording.GenerateAlphaNumericID(testsuite.T(), "gremlindb", 15, false) + testsuite.graphName, _ = recording.GenerateAlphaNumericID(testsuite.T(), "graphnam", 14, false) + testsuite.location = testutil.GetEnv("LOCATION", "westus") + testsuite.resourceGroupName = testutil.GetEnv("RESOURCE_GROUP_NAME", "scenarioTestTempGroup") + testsuite.subscriptionId = testutil.GetEnv("AZURE_SUBSCRIPTION_ID", "00000000-0000-0000-0000-000000000000") + resourceGroup, _, err := testutil.CreateResourceGroup(testsuite.ctx, testsuite.subscriptionId, testsuite.cred, testsuite.options, testsuite.location) + testsuite.Require().NoError(err) + testsuite.resourceGroupName = *resourceGroup.Name + testsuite.Prepare() +} + +func (testsuite *GremlinResourcesTestSuite) TearDownSuite() { + testsuite.Cleanup() + _, err := testutil.DeleteResourceGroup(testsuite.ctx, testsuite.subscriptionId, testsuite.cred, testsuite.options, testsuite.resourceGroupName) + testsuite.Require().NoError(err) + testutil.StopRecording(testsuite.T()) +} + +func TestGremlinResourcesTestSuite(t *testing.T) { + suite.Run(t, new(GremlinResourcesTestSuite)) +} + +func (testsuite *GremlinResourcesTestSuite) Prepare() { + var err error + // From step DatabaseAccounts_CreateOrUpdate + fmt.Println("Call operation: DatabaseAccounts_CreateOrUpdate") + databaseAccountsClient, err := armcosmos.NewDatabaseAccountsClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + databaseAccountsClientCreateOrUpdateResponsePoller, err := databaseAccountsClient.BeginCreateOrUpdate(testsuite.ctx, testsuite.resourceGroupName, testsuite.accountName, armcosmos.DatabaseAccountCreateUpdateParameters{ + Location: to.Ptr(testsuite.location), + Properties: &armcosmos.DatabaseAccountCreateUpdateProperties{ + Capabilities: []*armcosmos.Capability{ + { + Name: to.Ptr("EnableGremlin"), + }}, + CreateMode: to.Ptr(armcosmos.CreateModeDefault), + DatabaseAccountOfferType: to.Ptr("Standard"), + Locations: []*armcosmos.Location{ + { + FailoverPriority: to.Ptr[int32](0), + IsZoneRedundant: to.Ptr(false), + LocationName: to.Ptr(testsuite.location), + }}, + }, + }, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, databaseAccountsClientCreateOrUpdateResponsePoller) + testsuite.Require().NoError(err) + + // From step GremlinResources_CreateUpdateGremlinDatabase + fmt.Println("Call operation: GremlinResources_CreateUpdateGremlinDatabase") + gremlinResourcesClient, err := armcosmos.NewGremlinResourcesClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + gremlinResourcesClientCreateUpdateGremlinDatabaseResponsePoller, err := gremlinResourcesClient.BeginCreateUpdateGremlinDatabase(testsuite.ctx, testsuite.resourceGroupName, testsuite.accountName, testsuite.databaseName, armcosmos.GremlinDatabaseCreateUpdateParameters{ + Location: to.Ptr(testsuite.location), + Tags: map[string]*string{}, + Properties: &armcosmos.GremlinDatabaseCreateUpdateProperties{ + Options: &armcosmos.CreateUpdateOptions{ + Throughput: to.Ptr[int32](2000), + }, + Resource: &armcosmos.GremlinDatabaseResource{ + ID: to.Ptr(testsuite.databaseName), + }, + }, + }, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, gremlinResourcesClientCreateUpdateGremlinDatabaseResponsePoller) + testsuite.Require().NoError(err) +} + +// Microsoft.DocumentDB/databaseAccounts/{accountName}/gremlinDatabases/{databaseName} +func (testsuite *GremlinResourcesTestSuite) TestGremlinDatabase() { + var err error + // From step GremlinResources_ListGremlinDatabases + fmt.Println("Call operation: GremlinResources_ListGremlinDatabases") + gremlinResourcesClient, err := armcosmos.NewGremlinResourcesClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + gremlinResourcesClientNewListGremlinDatabasesPager := gremlinResourcesClient.NewListGremlinDatabasesPager(testsuite.resourceGroupName, testsuite.accountName, nil) + for gremlinResourcesClientNewListGremlinDatabasesPager.More() { + _, err := gremlinResourcesClientNewListGremlinDatabasesPager.NextPage(testsuite.ctx) + testsuite.Require().NoError(err) + break + } + + // From step GremlinResources_GetGremlinDatabaseThroughput + fmt.Println("Call operation: GremlinResources_GetGremlinDatabaseThroughput") + _, err = gremlinResourcesClient.GetGremlinDatabaseThroughput(testsuite.ctx, testsuite.resourceGroupName, testsuite.accountName, testsuite.databaseName, nil) + testsuite.Require().NoError(err) + + // From step GremlinResources_GetGremlinDatabase + fmt.Println("Call operation: GremlinResources_GetGremlinDatabase") + _, err = gremlinResourcesClient.GetGremlinDatabase(testsuite.ctx, testsuite.resourceGroupName, testsuite.accountName, testsuite.databaseName, nil) + testsuite.Require().NoError(err) + + // From step GremlinResources_MigrateGremlinDatabaseToAutoscale + fmt.Println("Call operation: GremlinResources_MigrateGremlinDatabaseToAutoscale") + gremlinResourcesClientMigrateGremlinDatabaseToAutoscaleResponsePoller, err := gremlinResourcesClient.BeginMigrateGremlinDatabaseToAutoscale(testsuite.ctx, testsuite.resourceGroupName, testsuite.accountName, testsuite.databaseName, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, gremlinResourcesClientMigrateGremlinDatabaseToAutoscaleResponsePoller) + testsuite.Require().NoError(err) + + // From step GremlinResources_MigrateGremlinDatabaseToManualThroughput + fmt.Println("Call operation: GremlinResources_MigrateGremlinDatabaseToManualThroughput") + gremlinResourcesClientMigrateGremlinDatabaseToManualThroughputResponsePoller, err := gremlinResourcesClient.BeginMigrateGremlinDatabaseToManualThroughput(testsuite.ctx, testsuite.resourceGroupName, testsuite.accountName, testsuite.databaseName, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, gremlinResourcesClientMigrateGremlinDatabaseToManualThroughputResponsePoller) + testsuite.Require().NoError(err) + + // From step GremlinResources_UpdateGremlinDatabaseThroughput + fmt.Println("Call operation: GremlinResources_UpdateGremlinDatabaseThroughput") + gremlinResourcesClientUpdateGremlinDatabaseThroughputResponsePoller, err := gremlinResourcesClient.BeginUpdateGremlinDatabaseThroughput(testsuite.ctx, testsuite.resourceGroupName, testsuite.accountName, testsuite.databaseName, armcosmos.ThroughputSettingsUpdateParameters{ + Location: to.Ptr(testsuite.location), + Tags: map[string]*string{}, + Properties: &armcosmos.ThroughputSettingsUpdateProperties{ + Resource: &armcosmos.ThroughputSettingsResource{ + Throughput: to.Ptr[int32](400), + }, + }, + }, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, gremlinResourcesClientUpdateGremlinDatabaseThroughputResponsePoller) + testsuite.Require().NoError(err) +} + +// Microsoft.DocumentDB/databaseAccounts/{accountName}/gremlinDatabases/{databaseName}/graphs/{graphName} +func (testsuite *GremlinResourcesTestSuite) TestGremlinGraph() { + var err error + // From step GremlinResources_CreateUpdateGremlinGraph + fmt.Println("Call operation: GremlinResources_CreateUpdateGremlinGraph") + gremlinResourcesClient, err := armcosmos.NewGremlinResourcesClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + gremlinResourcesClientCreateUpdateGremlinGraphResponsePoller, err := gremlinResourcesClient.BeginCreateUpdateGremlinGraph(testsuite.ctx, testsuite.resourceGroupName, testsuite.accountName, testsuite.databaseName, testsuite.graphName, armcosmos.GremlinGraphCreateUpdateParameters{ + Location: to.Ptr(testsuite.location), + Tags: map[string]*string{}, + Properties: &armcosmos.GremlinGraphCreateUpdateProperties{ + Options: &armcosmos.CreateUpdateOptions{ + Throughput: to.Ptr[int32](2000), + }, + Resource: &armcosmos.GremlinGraphResource{ + ConflictResolutionPolicy: &armcosmos.ConflictResolutionPolicy{ + ConflictResolutionPath: to.Ptr("/path"), + Mode: to.Ptr(armcosmos.ConflictResolutionModeLastWriterWins), + }, + DefaultTTL: to.Ptr[int32](100), + ID: to.Ptr(testsuite.graphName), + IndexingPolicy: &armcosmos.IndexingPolicy{ + Automatic: to.Ptr(true), + ExcludedPaths: []*armcosmos.ExcludedPath{}, + IncludedPaths: []*armcosmos.IncludedPath{ + { + Path: to.Ptr("/*"), + Indexes: []*armcosmos.Indexes{ + { + DataType: to.Ptr(armcosmos.DataTypeString), + Kind: to.Ptr(armcosmos.IndexKindRange), + Precision: to.Ptr[int32](-1), + }, + { + DataType: to.Ptr(armcosmos.DataTypeNumber), + Kind: to.Ptr(armcosmos.IndexKindRange), + Precision: to.Ptr[int32](-1), + }}, + }}, + IndexingMode: to.Ptr(armcosmos.IndexingModeConsistent), + }, + PartitionKey: &armcosmos.ContainerPartitionKey{ + Kind: to.Ptr(armcosmos.PartitionKindHash), + Paths: []*string{ + to.Ptr("/AccountNumber")}, + }, + UniqueKeyPolicy: &armcosmos.UniqueKeyPolicy{ + UniqueKeys: []*armcosmos.UniqueKey{ + { + Paths: []*string{ + to.Ptr("/testPath")}, + }}, + }, + }, + }, + }, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, gremlinResourcesClientCreateUpdateGremlinGraphResponsePoller) + testsuite.Require().NoError(err) + + // From step GremlinResources_GetGremlinGraph + fmt.Println("Call operation: GremlinResources_GetGremlinGraph") + _, err = gremlinResourcesClient.GetGremlinGraph(testsuite.ctx, testsuite.resourceGroupName, testsuite.accountName, testsuite.databaseName, testsuite.graphName, nil) + testsuite.Require().NoError(err) + + // From step GremlinResources_GetGremlinGraphThroughput + fmt.Println("Call operation: GremlinResources_GetGremlinGraphThroughput") + _, err = gremlinResourcesClient.GetGremlinGraphThroughput(testsuite.ctx, testsuite.resourceGroupName, testsuite.accountName, testsuite.databaseName, testsuite.graphName, nil) + testsuite.Require().NoError(err) + + // From step GremlinResources_ListGremlinGraphs + fmt.Println("Call operation: GremlinResources_ListGremlinGraphs") + gremlinResourcesClientNewListGremlinGraphsPager := gremlinResourcesClient.NewListGremlinGraphsPager(testsuite.resourceGroupName, testsuite.accountName, testsuite.databaseName, nil) + for gremlinResourcesClientNewListGremlinGraphsPager.More() { + _, err := gremlinResourcesClientNewListGremlinGraphsPager.NextPage(testsuite.ctx) + testsuite.Require().NoError(err) + break + } + + // From step GremlinResources_MigrateGremlinGraphToAutoscale + fmt.Println("Call operation: GremlinResources_MigrateGremlinGraphToAutoscale") + gremlinResourcesClientMigrateGremlinGraphToAutoscaleResponsePoller, err := gremlinResourcesClient.BeginMigrateGremlinGraphToAutoscale(testsuite.ctx, testsuite.resourceGroupName, testsuite.accountName, testsuite.databaseName, testsuite.graphName, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, gremlinResourcesClientMigrateGremlinGraphToAutoscaleResponsePoller) + testsuite.Require().NoError(err) + + // From step GremlinResources_MigrateGremlinGraphToManualThroughput + fmt.Println("Call operation: GremlinResources_MigrateGremlinGraphToManualThroughput") + gremlinResourcesClientMigrateGremlinGraphToManualThroughputResponsePoller, err := gremlinResourcesClient.BeginMigrateGremlinGraphToManualThroughput(testsuite.ctx, testsuite.resourceGroupName, testsuite.accountName, testsuite.databaseName, testsuite.graphName, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, gremlinResourcesClientMigrateGremlinGraphToManualThroughputResponsePoller) + testsuite.Require().NoError(err) + + // From step GremlinResources_UpdateGremlinGraphThroughput + fmt.Println("Call operation: GremlinResources_UpdateGremlinGraphThroughput") + gremlinResourcesClientUpdateGremlinGraphThroughputResponsePoller, err := gremlinResourcesClient.BeginUpdateGremlinGraphThroughput(testsuite.ctx, testsuite.resourceGroupName, testsuite.accountName, testsuite.databaseName, testsuite.graphName, armcosmos.ThroughputSettingsUpdateParameters{ + Location: to.Ptr(testsuite.location), + Tags: map[string]*string{}, + Properties: &armcosmos.ThroughputSettingsUpdateProperties{ + Resource: &armcosmos.ThroughputSettingsResource{ + Throughput: to.Ptr[int32](400), + }, + }, + }, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, gremlinResourcesClientUpdateGremlinGraphThroughputResponsePoller) + testsuite.Require().NoError(err) + + // From step GremlinResources_DeleteGremlinGraph + fmt.Println("Call operation: GremlinResources_DeleteGremlinGraph") + gremlinResourcesClientDeleteGremlinGraphResponsePoller, err := gremlinResourcesClient.BeginDeleteGremlinGraph(testsuite.ctx, testsuite.resourceGroupName, testsuite.accountName, testsuite.databaseName, testsuite.graphName, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, gremlinResourcesClientDeleteGremlinGraphResponsePoller) + testsuite.Require().NoError(err) +} + +func (testsuite *GremlinResourcesTestSuite) Cleanup() { + var err error + // From step GremlinResources_DeleteGremlinDatabase + fmt.Println("Call operation: GremlinResources_DeleteGremlinDatabase") + gremlinResourcesClient, err := armcosmos.NewGremlinResourcesClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + gremlinResourcesClientDeleteGremlinDatabaseResponsePoller, err := gremlinResourcesClient.BeginDeleteGremlinDatabase(testsuite.ctx, testsuite.resourceGroupName, testsuite.accountName, testsuite.databaseName, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, gremlinResourcesClientDeleteGremlinDatabaseResponsePoller) + testsuite.Require().NoError(err) +} diff --git a/sdk/resourcemanager/cosmos/armcosmos/mongodbresources_live_test.go b/sdk/resourcemanager/cosmos/armcosmos/mongodbresources_live_test.go new file mode 100644 index 000000000000..bf4f8bbbab7c --- /dev/null +++ b/sdk/resourcemanager/cosmos/armcosmos/mongodbresources_live_test.go @@ -0,0 +1,256 @@ +//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 armcosmos_test + +import ( + "context" + "fmt" + "testing" + + "github.com/Azure/azure-sdk-for-go/sdk/azcore" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/arm" + "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/resourcemanager/cosmos/armcosmos/v2" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/internal/testutil" + "github.com/stretchr/testify/suite" +) + +type MongoDbResourcesTestSuite struct { + suite.Suite + + ctx context.Context + cred azcore.TokenCredential + options *arm.ClientOptions + accountName string + collectionName string + databaseName string + location string + resourceGroupName string + subscriptionId string +} + +func (testsuite *MongoDbResourcesTestSuite) SetupSuite() { + testutil.StartRecording(testsuite.T(), "sdk/resourcemanager/cosmos/armcosmos/testdata") + + testsuite.ctx = context.Background() + testsuite.cred, testsuite.options = testutil.GetCredAndClientOptions(testsuite.T()) + testsuite.accountName, _ = recording.GenerateAlphaNumericID(testsuite.T(), "accountn", 14, true) + testsuite.collectionName, _ = recording.GenerateAlphaNumericID(testsuite.T(), "collecti", 14, false) + testsuite.databaseName, _ = recording.GenerateAlphaNumericID(testsuite.T(), "mongodb", 14, false) + testsuite.location = testutil.GetEnv("LOCATION", "westus") + testsuite.resourceGroupName = testutil.GetEnv("RESOURCE_GROUP_NAME", "scenarioTestTempGroup") + testsuite.subscriptionId = testutil.GetEnv("AZURE_SUBSCRIPTION_ID", "00000000-0000-0000-0000-000000000000") + resourceGroup, _, err := testutil.CreateResourceGroup(testsuite.ctx, testsuite.subscriptionId, testsuite.cred, testsuite.options, testsuite.location) + testsuite.Require().NoError(err) + testsuite.resourceGroupName = *resourceGroup.Name + testsuite.Prepare() +} + +func (testsuite *MongoDbResourcesTestSuite) TearDownSuite() { + testsuite.Cleanup() + _, err := testutil.DeleteResourceGroup(testsuite.ctx, testsuite.subscriptionId, testsuite.cred, testsuite.options, testsuite.resourceGroupName) + testsuite.Require().NoError(err) + testutil.StopRecording(testsuite.T()) +} + +func TestMongoDbResourcesTestSuite(t *testing.T) { + suite.Run(t, new(MongoDbResourcesTestSuite)) +} + +func (testsuite *MongoDbResourcesTestSuite) Prepare() { + var err error + // From step DatabaseAccounts_CreateOrUpdate + fmt.Println("Call operation: DatabaseAccounts_CreateOrUpdate") + databaseAccountsClient, err := armcosmos.NewDatabaseAccountsClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + databaseAccountsClientCreateOrUpdateResponsePoller, err := databaseAccountsClient.BeginCreateOrUpdate(testsuite.ctx, testsuite.resourceGroupName, testsuite.accountName, armcosmos.DatabaseAccountCreateUpdateParameters{ + Location: to.Ptr(testsuite.location), + Kind: to.Ptr(armcosmos.DatabaseAccountKindMongoDB), + Properties: &armcosmos.DatabaseAccountCreateUpdateProperties{ + CreateMode: to.Ptr(armcosmos.CreateModeDefault), + DatabaseAccountOfferType: to.Ptr("Standard"), + Locations: []*armcosmos.Location{ + { + FailoverPriority: to.Ptr[int32](0), + IsZoneRedundant: to.Ptr(false), + LocationName: to.Ptr(testsuite.location), + }}, + }, + }, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, databaseAccountsClientCreateOrUpdateResponsePoller) + testsuite.Require().NoError(err) + + // From step MongoDBResources_CreateUpdateMongoDBDatabase + fmt.Println("Call operation: MongoDBResources_CreateUpdateMongoDBDatabase") + mongoDBResourcesClient, err := armcosmos.NewMongoDBResourcesClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + mongoDBResourcesClientCreateUpdateMongoDBDatabaseResponsePoller, err := mongoDBResourcesClient.BeginCreateUpdateMongoDBDatabase(testsuite.ctx, testsuite.resourceGroupName, testsuite.accountName, testsuite.databaseName, armcosmos.MongoDBDatabaseCreateUpdateParameters{ + Location: to.Ptr(testsuite.location), + Tags: map[string]*string{}, + Properties: &armcosmos.MongoDBDatabaseCreateUpdateProperties{ + Options: &armcosmos.CreateUpdateOptions{ + Throughput: to.Ptr[int32](2000), + }, + Resource: &armcosmos.MongoDBDatabaseResource{ + ID: to.Ptr(testsuite.databaseName), + }, + }, + }, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, mongoDBResourcesClientCreateUpdateMongoDBDatabaseResponsePoller) + testsuite.Require().NoError(err) +} + +// Microsoft.DocumentDB/databaseAccounts/{accountName}/mongodbDatabases/{databaseName} +func (testsuite *MongoDbResourcesTestSuite) TestMongoDbDatabase() { + var err error + // From step MongoDBResources_ListMongoDBDatabases + fmt.Println("Call operation: MongoDBResources_ListMongoDBDatabases") + mongoDBResourcesClient, err := armcosmos.NewMongoDBResourcesClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + mongoDBResourcesClientNewListMongoDBDatabasesPager := mongoDBResourcesClient.NewListMongoDBDatabasesPager(testsuite.resourceGroupName, testsuite.accountName, nil) + for mongoDBResourcesClientNewListMongoDBDatabasesPager.More() { + _, err := mongoDBResourcesClientNewListMongoDBDatabasesPager.NextPage(testsuite.ctx) + testsuite.Require().NoError(err) + break + } + + // From step MongoDBResources_GetMongoDBDatabase + fmt.Println("Call operation: MongoDBResources_GetMongoDBDatabase") + _, err = mongoDBResourcesClient.GetMongoDBDatabase(testsuite.ctx, testsuite.resourceGroupName, testsuite.accountName, testsuite.databaseName, nil) + testsuite.Require().NoError(err) + + // From step MongoDBResources_GetMongoDBDatabaseThroughput + fmt.Println("Call operation: MongoDBResources_GetMongoDBDatabaseThroughput") + _, err = mongoDBResourcesClient.GetMongoDBDatabaseThroughput(testsuite.ctx, testsuite.resourceGroupName, testsuite.accountName, testsuite.databaseName, nil) + testsuite.Require().NoError(err) + + // From step MongoDBResources_MigrateMongoDBDatabaseToAutoscale + fmt.Println("Call operation: MongoDBResources_MigrateMongoDBDatabaseToAutoscale") + mongoDBResourcesClientMigrateMongoDBDatabaseToAutoscaleResponsePoller, err := mongoDBResourcesClient.BeginMigrateMongoDBDatabaseToAutoscale(testsuite.ctx, testsuite.resourceGroupName, testsuite.accountName, testsuite.databaseName, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, mongoDBResourcesClientMigrateMongoDBDatabaseToAutoscaleResponsePoller) + testsuite.Require().NoError(err) + + // From step MongoDBResources_MigrateMongoDBDatabaseToManualThroughput + fmt.Println("Call operation: MongoDBResources_MigrateMongoDBDatabaseToManualThroughput") + mongoDBResourcesClientMigrateMongoDBDatabaseToManualThroughputResponsePoller, err := mongoDBResourcesClient.BeginMigrateMongoDBDatabaseToManualThroughput(testsuite.ctx, testsuite.resourceGroupName, testsuite.accountName, testsuite.databaseName, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, mongoDBResourcesClientMigrateMongoDBDatabaseToManualThroughputResponsePoller) + testsuite.Require().NoError(err) + + // From step MongoDBResources_UpdateMongoDBDatabaseThroughput + fmt.Println("Call operation: MongoDBResources_UpdateMongoDBDatabaseThroughput") + mongoDBResourcesClientUpdateMongoDBDatabaseThroughputResponsePoller, err := mongoDBResourcesClient.BeginUpdateMongoDBDatabaseThroughput(testsuite.ctx, testsuite.resourceGroupName, testsuite.accountName, testsuite.databaseName, armcosmos.ThroughputSettingsUpdateParameters{ + Location: to.Ptr(testsuite.location), + Tags: map[string]*string{}, + Properties: &armcosmos.ThroughputSettingsUpdateProperties{ + Resource: &armcosmos.ThroughputSettingsResource{ + Throughput: to.Ptr[int32](400), + }, + }, + }, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, mongoDBResourcesClientUpdateMongoDBDatabaseThroughputResponsePoller) + testsuite.Require().NoError(err) +} + +// Microsoft.DocumentDB/databaseAccounts/{accountName}/mongodbDatabases/{databaseName}/collections/{collectionName} +func (testsuite *MongoDbResourcesTestSuite) TestMongoDbCollection() { + var err error + // From step MongoDBResources_CreateUpdateMongoDBCollection + fmt.Println("Call operation: MongoDBResources_CreateUpdateMongoDBCollection") + mongoDBResourcesClient, err := armcosmos.NewMongoDBResourcesClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + mongoDBResourcesClientCreateUpdateMongoDBCollectionResponsePoller, err := mongoDBResourcesClient.BeginCreateUpdateMongoDBCollection(testsuite.ctx, testsuite.resourceGroupName, testsuite.accountName, testsuite.databaseName, testsuite.collectionName, armcosmos.MongoDBCollectionCreateUpdateParameters{ + Location: to.Ptr(testsuite.location), + Tags: map[string]*string{}, + Properties: &armcosmos.MongoDBCollectionCreateUpdateProperties{ + Options: &armcosmos.CreateUpdateOptions{ + Throughput: to.Ptr[int32](2000), + }, + Resource: &armcosmos.MongoDBCollectionResource{ + ID: to.Ptr(testsuite.collectionName), + ShardKey: map[string]*string{ + "testKey": to.Ptr("Hash"), + }, + }, + }, + }, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, mongoDBResourcesClientCreateUpdateMongoDBCollectionResponsePoller) + testsuite.Require().NoError(err) + + // From step MongoDBResources_ListMongoDBCollections + fmt.Println("Call operation: MongoDBResources_ListMongoDBCollections") + mongoDBResourcesClientNewListMongoDBCollectionsPager := mongoDBResourcesClient.NewListMongoDBCollectionsPager(testsuite.resourceGroupName, testsuite.accountName, testsuite.databaseName, nil) + for mongoDBResourcesClientNewListMongoDBCollectionsPager.More() { + _, err := mongoDBResourcesClientNewListMongoDBCollectionsPager.NextPage(testsuite.ctx) + testsuite.Require().NoError(err) + break + } + + // From step MongoDBResources_GetMongoDBCollection + fmt.Println("Call operation: MongoDBResources_GetMongoDBCollection") + _, err = mongoDBResourcesClient.GetMongoDBCollection(testsuite.ctx, testsuite.resourceGroupName, testsuite.accountName, testsuite.databaseName, testsuite.collectionName, nil) + testsuite.Require().NoError(err) + + // From step MongoDBResources_GetMongoDBCollectionThroughput + fmt.Println("Call operation: MongoDBResources_GetMongoDBCollectionThroughput") + _, err = mongoDBResourcesClient.GetMongoDBCollectionThroughput(testsuite.ctx, testsuite.resourceGroupName, testsuite.accountName, testsuite.databaseName, testsuite.collectionName, nil) + testsuite.Require().NoError(err) + + // From step MongoDBResources_MigrateMongoDBCollectionToAutoscale + fmt.Println("Call operation: MongoDBResources_MigrateMongoDBCollectionToAutoscale") + mongoDBResourcesClientMigrateMongoDBCollectionToAutoscaleResponsePoller, err := mongoDBResourcesClient.BeginMigrateMongoDBCollectionToAutoscale(testsuite.ctx, testsuite.resourceGroupName, testsuite.accountName, testsuite.databaseName, testsuite.collectionName, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, mongoDBResourcesClientMigrateMongoDBCollectionToAutoscaleResponsePoller) + testsuite.Require().NoError(err) + + // From step MongoDBResources_MigrateMongoDBCollectionToManualThroughput + fmt.Println("Call operation: MongoDBResources_MigrateMongoDBCollectionToManualThroughput") + mongoDBResourcesClientMigrateMongoDBCollectionToManualThroughputResponsePoller, err := mongoDBResourcesClient.BeginMigrateMongoDBCollectionToManualThroughput(testsuite.ctx, testsuite.resourceGroupName, testsuite.accountName, testsuite.databaseName, testsuite.collectionName, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, mongoDBResourcesClientMigrateMongoDBCollectionToManualThroughputResponsePoller) + testsuite.Require().NoError(err) + + // From step MongoDBResources_UpdateMongoDBCollectionThroughput + fmt.Println("Call operation: MongoDBResources_UpdateMongoDBCollectionThroughput") + mongoDBResourcesClientUpdateMongoDBCollectionThroughputResponsePoller, err := mongoDBResourcesClient.BeginUpdateMongoDBCollectionThroughput(testsuite.ctx, testsuite.resourceGroupName, testsuite.accountName, testsuite.databaseName, testsuite.collectionName, armcosmos.ThroughputSettingsUpdateParameters{ + Location: to.Ptr(testsuite.location), + Tags: map[string]*string{}, + Properties: &armcosmos.ThroughputSettingsUpdateProperties{ + Resource: &armcosmos.ThroughputSettingsResource{ + Throughput: to.Ptr[int32](400), + }, + }, + }, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, mongoDBResourcesClientUpdateMongoDBCollectionThroughputResponsePoller) + testsuite.Require().NoError(err) + + // From step MongoDBResources_DeleteMongoDBCollection + fmt.Println("Call operation: MongoDBResources_DeleteMongoDBCollection") + mongoDBResourcesClientDeleteMongoDBCollectionResponsePoller, err := mongoDBResourcesClient.BeginDeleteMongoDBCollection(testsuite.ctx, testsuite.resourceGroupName, testsuite.accountName, testsuite.databaseName, testsuite.collectionName, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, mongoDBResourcesClientDeleteMongoDBCollectionResponsePoller) + testsuite.Require().NoError(err) +} + +func (testsuite *MongoDbResourcesTestSuite) Cleanup() { + var err error + // From step MongoDBResources_DeleteMongoDBDatabase + fmt.Println("Call operation: MongoDBResources_DeleteMongoDBDatabase") + mongoDBResourcesClient, err := armcosmos.NewMongoDBResourcesClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + mongoDBResourcesClientDeleteMongoDBDatabaseResponsePoller, err := mongoDBResourcesClient.BeginDeleteMongoDBDatabase(testsuite.ctx, testsuite.resourceGroupName, testsuite.accountName, testsuite.databaseName, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, mongoDBResourcesClientDeleteMongoDBDatabaseResponsePoller) + testsuite.Require().NoError(err) +} diff --git a/sdk/resourcemanager/cosmos/armcosmos/operations_live_test.go b/sdk/resourcemanager/cosmos/armcosmos/operations_live_test.go new file mode 100644 index 000000000000..adb91b40c504 --- /dev/null +++ b/sdk/resourcemanager/cosmos/armcosmos/operations_live_test.go @@ -0,0 +1,88 @@ +//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 armcosmos_test + +import ( + "context" + "fmt" + "testing" + + "github.com/Azure/azure-sdk-for-go/sdk/azcore" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/arm" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/cosmos/armcosmos/v2" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/internal/testutil" + "github.com/stretchr/testify/suite" +) + +type OperationsTestSuite struct { + suite.Suite + + ctx context.Context + cred azcore.TokenCredential + options *arm.ClientOptions + location string + resourceGroupName string + subscriptionId string +} + +func (testsuite *OperationsTestSuite) SetupSuite() { + testutil.StartRecording(testsuite.T(), "sdk/resourcemanager/cosmos/armcosmos/testdata") + + testsuite.ctx = context.Background() + testsuite.cred, testsuite.options = testutil.GetCredAndClientOptions(testsuite.T()) + testsuite.location = testutil.GetEnv("LOCATION", "westus") + testsuite.resourceGroupName = testutil.GetEnv("RESOURCE_GROUP_NAME", "scenarioTestTempGroup") + testsuite.subscriptionId = testutil.GetEnv("AZURE_SUBSCRIPTION_ID", "00000000-0000-0000-0000-000000000000") + resourceGroup, _, err := testutil.CreateResourceGroup(testsuite.ctx, testsuite.subscriptionId, testsuite.cred, testsuite.options, testsuite.location) + testsuite.Require().NoError(err) + testsuite.resourceGroupName = *resourceGroup.Name +} + +func (testsuite *OperationsTestSuite) TearDownSuite() { + _, err := testutil.DeleteResourceGroup(testsuite.ctx, testsuite.subscriptionId, testsuite.cred, testsuite.options, testsuite.resourceGroupName) + testsuite.Require().NoError(err) + testutil.StopRecording(testsuite.T()) +} + +func TestOperationsTestSuite(t *testing.T) { + suite.Run(t, new(OperationsTestSuite)) +} + +// Microsoft.DocumentDB/operations +func (testsuite *OperationsTestSuite) TestOperations() { + var err error + // From step Operations_List + fmt.Println("Call operation: Operations_List") + operationsClient, err := armcosmos.NewOperationsClient(testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + operationsClientNewListPager := operationsClient.NewListPager(nil) + for operationsClientNewListPager.More() { + _, err := operationsClientNewListPager.NextPage(testsuite.ctx) + testsuite.Require().NoError(err) + break + } +} + +// Microsoft.DocumentDB/locations +func (testsuite *OperationsTestSuite) TestLocations() { + var err error + // From step Locations_List + fmt.Println("Call operation: Locations_List") + locationsClient, err := armcosmos.NewLocationsClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + locationsClientNewListPager := locationsClient.NewListPager(nil) + for locationsClientNewListPager.More() { + _, err := locationsClientNewListPager.NextPage(testsuite.ctx) + testsuite.Require().NoError(err) + break + } + + // From step Locations_Get + fmt.Println("Call operation: Locations_Get") + _, err = locationsClient.Get(testsuite.ctx, testsuite.location, nil) + testsuite.Require().NoError(err) +} diff --git a/sdk/resourcemanager/cosmos/armcosmos/privateendpointconnection_live_test.go b/sdk/resourcemanager/cosmos/armcosmos/privateendpointconnection_live_test.go new file mode 100644 index 000000000000..8d3c4a7819b7 --- /dev/null +++ b/sdk/resourcemanager/cosmos/armcosmos/privateendpointconnection_live_test.go @@ -0,0 +1,293 @@ +//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 armcosmos_test + +import ( + "context" + "fmt" + "testing" + + "github.com/Azure/azure-sdk-for-go/sdk/azcore" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/arm" + "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/resourcemanager/cosmos/armcosmos/v2" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/internal/testutil" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armresources" + "github.com/stretchr/testify/suite" +) + +type PrivateEndpointConnectionTestSuite struct { + suite.Suite + + ctx context.Context + cred azcore.TokenCredential + options *arm.ClientOptions + accountName string + cosmosAccountId string + privateEndpointConnectionName string + location string + resourceGroupName string + subscriptionId string +} + +func (testsuite *PrivateEndpointConnectionTestSuite) SetupSuite() { + testutil.StartRecording(testsuite.T(), "sdk/resourcemanager/cosmos/armcosmos/testdata") + + testsuite.ctx = context.Background() + testsuite.cred, testsuite.options = testutil.GetCredAndClientOptions(testsuite.T()) + testsuite.accountName, _ = recording.GenerateAlphaNumericID(testsuite.T(), "accountn", 14, true) + testsuite.location = testutil.GetEnv("LOCATION", "westus") + testsuite.resourceGroupName = testutil.GetEnv("RESOURCE_GROUP_NAME", "scenarioTestTempGroup") + testsuite.subscriptionId = testutil.GetEnv("AZURE_SUBSCRIPTION_ID", "00000000-0000-0000-0000-000000000000") + resourceGroup, _, err := testutil.CreateResourceGroup(testsuite.ctx, testsuite.subscriptionId, testsuite.cred, testsuite.options, testsuite.location) + testsuite.Require().NoError(err) + testsuite.resourceGroupName = *resourceGroup.Name + testsuite.Prepare() +} + +func (testsuite *PrivateEndpointConnectionTestSuite) TearDownSuite() { + _, err := testutil.DeleteResourceGroup(testsuite.ctx, testsuite.subscriptionId, testsuite.cred, testsuite.options, testsuite.resourceGroupName) + testsuite.Require().NoError(err) + testutil.StopRecording(testsuite.T()) +} + +func TestPrivateEndpointConnectionTestSuite(t *testing.T) { + suite.Run(t, new(PrivateEndpointConnectionTestSuite)) +} + +func (testsuite *PrivateEndpointConnectionTestSuite) Prepare() { + var err error + // From step DatabaseAccounts_CreateOrUpdate + fmt.Println("Call operation: DatabaseAccounts_CreateOrUpdate") + databaseAccountsClient, err := armcosmos.NewDatabaseAccountsClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + databaseAccountsClientCreateOrUpdateResponsePoller, err := databaseAccountsClient.BeginCreateOrUpdate(testsuite.ctx, testsuite.resourceGroupName, testsuite.accountName, armcosmos.DatabaseAccountCreateUpdateParameters{ + Location: to.Ptr(testsuite.location), + Properties: &armcosmos.DatabaseAccountCreateUpdateProperties{ + CreateMode: to.Ptr(armcosmos.CreateModeDefault), + DatabaseAccountOfferType: to.Ptr("Standard"), + Locations: []*armcosmos.Location{ + { + FailoverPriority: to.Ptr[int32](0), + IsZoneRedundant: to.Ptr(false), + LocationName: to.Ptr(testsuite.location), + }}, + }, + }, nil) + testsuite.Require().NoError(err) + var databaseAccountsClientCreateOrUpdateResponse *armcosmos.DatabaseAccountsClientCreateOrUpdateResponse + databaseAccountsClientCreateOrUpdateResponse, err = testutil.PollForTest(testsuite.ctx, databaseAccountsClientCreateOrUpdateResponsePoller) + testsuite.Require().NoError(err) + testsuite.cosmosAccountId = *databaseAccountsClientCreateOrUpdateResponse.ID + + // From step Create_PrivateEndpoint + template := map[string]any{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "outputs": map[string]any{ + "privateEndpointConnectionName": map[string]any{ + "type": "string", + "value": "[parameters('privateEndpointName')]", + }, + }, + "parameters": map[string]any{ + "cosmosAccountId": map[string]any{ + "type": "string", + "defaultValue": testsuite.cosmosAccountId, + }, + "location": map[string]any{ + "type": "string", + "defaultValue": testsuite.location, + }, + "networkInterfaceName": map[string]any{ + "type": "string", + "defaultValue": "epcosmos-nic", + }, + "privateEndpointName": map[string]any{ + "type": "string", + "defaultValue": "epcosmos", + }, + "virtualNetworksName": map[string]any{ + "type": "string", + "defaultValue": "epcosmos-vnet", + }, + }, + "resources": []any{ + map[string]any{ + "name": "[parameters('virtualNetworksName')]", + "type": "Microsoft.Network/virtualNetworks", + "apiVersion": "2020-11-01", + "location": "[parameters('location')]", + "properties": map[string]any{ + "addressSpace": map[string]any{ + "addressPrefixes": []any{ + "10.0.0.0/16", + }, + }, + "enableDdosProtection": false, + "subnets": []any{ + map[string]any{ + "name": "default", + "properties": map[string]any{ + "addressPrefix": "10.0.0.0/24", + "delegations": []any{}, + "privateEndpointNetworkPolicies": "Disabled", + "privateLinkServiceNetworkPolicies": "Enabled", + }, + }, + }, + "virtualNetworkPeerings": []any{}, + }, + }, + map[string]any{ + "name": "[parameters('networkInterfaceName')]", + "type": "Microsoft.Network/networkInterfaces", + "apiVersion": "2020-11-01", + "dependsOn": []any{ + "[resourceId('Microsoft.Network/virtualNetworks/subnets', parameters('virtualNetworksName'), 'default')]", + }, + "location": "[parameters('location')]", + "properties": map[string]any{ + "dnsSettings": map[string]any{ + "dnsServers": []any{}, + }, + "enableIPForwarding": false, + "ipConfigurations": []any{ + map[string]any{ + "name": "privateEndpointIpConfig", + "properties": map[string]any{ + "primary": true, + "privateIPAddress": "10.0.0.4", + "privateIPAddressVersion": "IPv4", + "privateIPAllocationMethod": "Dynamic", + "subnet": map[string]any{ + "id": "[resourceId('Microsoft.Network/virtualNetworks/subnets', parameters('virtualNetworksName'), 'default')]", + }, + }, + }, + }, + }, + }, + map[string]any{ + "name": "[parameters('privateEndpointName')]", + "type": "Microsoft.Network/privateEndpoints", + "apiVersion": "2020-11-01", + "dependsOn": []any{ + "[resourceId('Microsoft.Network/virtualNetworks/subnets', parameters('virtualNetworksName'), 'default')]", + }, + "location": "[parameters('location')]", + "properties": map[string]any{ + "customDnsConfigs": []any{}, + "manualPrivateLinkServiceConnections": []any{}, + "privateLinkServiceConnections": []any{ + map[string]any{ + "name": "[parameters('privateEndpointName')]", + "properties": map[string]any{ + "groupIds": []any{ + "Sql", + }, + "privateLinkServiceConnectionState": map[string]any{ + "description": "Auto-Approved", + "actionsRequired": "None", + "status": "Approved", + }, + "privateLinkServiceId": "[parameters('cosmosAccountId')]", + }, + }, + }, + "subnet": map[string]any{ + "id": "[resourceId('Microsoft.Network/virtualNetworks/subnets', parameters('virtualNetworksName'), 'default')]", + }, + }, + }, + map[string]any{ + "name": "[concat(parameters('virtualNetworksName'), '/default')]", + "type": "Microsoft.Network/virtualNetworks/subnets", + "apiVersion": "2020-11-01", + "dependsOn": []any{ + "[resourceId('Microsoft.Network/virtualNetworks', parameters('virtualNetworksName'))]", + }, + "properties": map[string]any{ + "addressPrefix": "10.0.0.0/24", + "delegations": []any{}, + "privateEndpointNetworkPolicies": "Disabled", + "privateLinkServiceNetworkPolicies": "Enabled", + }, + }, + }, + "variables": map[string]any{}, + } + deployment := armresources.Deployment{ + Properties: &armresources.DeploymentProperties{ + Template: template, + Mode: to.Ptr(armresources.DeploymentModeIncremental), + }, + } + deploymentExtend, err := testutil.CreateDeployment(testsuite.ctx, testsuite.subscriptionId, testsuite.cred, testsuite.options, testsuite.resourceGroupName, "Create_PrivateEndpoint", &deployment) + testsuite.Require().NoError(err) + testsuite.privateEndpointConnectionName = deploymentExtend.Properties.Outputs.(map[string]interface{})["privateEndpointConnectionName"].(map[string]interface{})["value"].(string) +} + +// Microsoft.DocumentDB/databaseAccounts/{accountName}/privateEndpointConnections/{privateEndpointConnectionName} +func (testsuite *PrivateEndpointConnectionTestSuite) TestPrivateEndpointConnections() { + var err error + // From step PrivateEndpointConnections_CreateOrUpdate + fmt.Println("Call operation: PrivateEndpointConnections_CreateOrUpdate") + privateEndpointConnectionsClient, err := armcosmos.NewPrivateEndpointConnectionsClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + privateEndpointConnectionsClientCreateOrUpdateResponsePoller, err := privateEndpointConnectionsClient.BeginCreateOrUpdate(testsuite.ctx, testsuite.resourceGroupName, testsuite.accountName, testsuite.privateEndpointConnectionName, armcosmos.PrivateEndpointConnection{ + Properties: &armcosmos.PrivateEndpointConnectionProperties{ + GroupID: to.Ptr("Sql"), + PrivateLinkServiceConnectionState: &armcosmos.PrivateLinkServiceConnectionStateProperty{ + Description: to.Ptr("Approved by johndoe@contoso.com"), + Status: to.Ptr("Approved"), + }, + ProvisioningState: to.Ptr("Succeeded"), + }, + }, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, privateEndpointConnectionsClientCreateOrUpdateResponsePoller) + testsuite.Require().NoError(err) + + // From step PrivateEndpointConnections_ListByDatabaseAccount + fmt.Println("Call operation: PrivateEndpointConnections_ListByDatabaseAccount") + privateEndpointConnectionsClientNewListByDatabaseAccountPager := privateEndpointConnectionsClient.NewListByDatabaseAccountPager(testsuite.resourceGroupName, testsuite.accountName, nil) + for privateEndpointConnectionsClientNewListByDatabaseAccountPager.More() { + _, err := privateEndpointConnectionsClientNewListByDatabaseAccountPager.NextPage(testsuite.ctx) + testsuite.Require().NoError(err) + break + } + + // From step PrivateEndpointConnections_Get + fmt.Println("Call operation: PrivateEndpointConnections_Get") + _, err = privateEndpointConnectionsClient.Get(testsuite.ctx, testsuite.resourceGroupName, testsuite.accountName, testsuite.privateEndpointConnectionName, nil) + testsuite.Require().NoError(err) + + // From step PrivateLinkResources_ListByDatabaseAccount + fmt.Println("Call operation: PrivateLinkResources_ListByDatabaseAccount") + privateLinkResourcesClient, err := armcosmos.NewPrivateLinkResourcesClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + privateLinkResourcesClientNewListByDatabaseAccountPager := privateLinkResourcesClient.NewListByDatabaseAccountPager(testsuite.resourceGroupName, testsuite.accountName, nil) + for privateLinkResourcesClientNewListByDatabaseAccountPager.More() { + _, err := privateLinkResourcesClientNewListByDatabaseAccountPager.NextPage(testsuite.ctx) + testsuite.Require().NoError(err) + break + } + + // From step PrivateLinkResources_Get + fmt.Println("Call operation: PrivateLinkResources_Get") + _, err = privateLinkResourcesClient.Get(testsuite.ctx, testsuite.resourceGroupName, testsuite.accountName, "sql", nil) + testsuite.Require().NoError(err) + + // From step PrivateEndpointConnections_Delete + fmt.Println("Call operation: PrivateEndpointConnections_Delete") + privateEndpointConnectionsClientDeleteResponsePoller, err := privateEndpointConnectionsClient.BeginDelete(testsuite.ctx, testsuite.resourceGroupName, testsuite.accountName, testsuite.privateEndpointConnectionName, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, privateEndpointConnectionsClientDeleteResponsePoller) + testsuite.Require().NoError(err) +} diff --git a/sdk/resourcemanager/cosmos/armcosmos/services_live_test.go b/sdk/resourcemanager/cosmos/armcosmos/services_live_test.go new file mode 100644 index 000000000000..0e5922b8ce43 --- /dev/null +++ b/sdk/resourcemanager/cosmos/armcosmos/services_live_test.go @@ -0,0 +1,122 @@ +//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 armcosmos_test + +import ( + "context" + "fmt" + "testing" + + "github.com/Azure/azure-sdk-for-go/sdk/azcore" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/arm" + "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/resourcemanager/cosmos/armcosmos/v2" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/internal/testutil" + "github.com/stretchr/testify/suite" +) + +type ServicesTestSuite struct { + suite.Suite + + ctx context.Context + cred azcore.TokenCredential + options *arm.ClientOptions + accountName string + location string + resourceGroupName string + subscriptionId string +} + +func (testsuite *ServicesTestSuite) SetupSuite() { + testutil.StartRecording(testsuite.T(), "sdk/resourcemanager/cosmos/armcosmos/testdata") + + testsuite.ctx = context.Background() + testsuite.cred, testsuite.options = testutil.GetCredAndClientOptions(testsuite.T()) + testsuite.accountName, _ = recording.GenerateAlphaNumericID(testsuite.T(), "accountn", 14, true) + testsuite.location = testutil.GetEnv("LOCATION", "westus") + testsuite.resourceGroupName = testutil.GetEnv("RESOURCE_GROUP_NAME", "scenarioTestTempGroup") + testsuite.subscriptionId = testutil.GetEnv("AZURE_SUBSCRIPTION_ID", "00000000-0000-0000-0000-000000000000") + resourceGroup, _, err := testutil.CreateResourceGroup(testsuite.ctx, testsuite.subscriptionId, testsuite.cred, testsuite.options, testsuite.location) + testsuite.Require().NoError(err) + testsuite.resourceGroupName = *resourceGroup.Name + testsuite.Prepare() +} + +func (testsuite *ServicesTestSuite) TearDownSuite() { + _, err := testutil.DeleteResourceGroup(testsuite.ctx, testsuite.subscriptionId, testsuite.cred, testsuite.options, testsuite.resourceGroupName) + testsuite.Require().NoError(err) + testutil.StopRecording(testsuite.T()) +} + +func TestServicesTestSuite(t *testing.T) { + suite.Run(t, new(ServicesTestSuite)) +} + +func (testsuite *ServicesTestSuite) Prepare() { + var err error + // From step DatabaseAccounts_CreateOrUpdate + fmt.Println("Call operation: DatabaseAccounts_CreateOrUpdate") + databaseAccountsClient, err := armcosmos.NewDatabaseAccountsClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + databaseAccountsClientCreateOrUpdateResponsePoller, err := databaseAccountsClient.BeginCreateOrUpdate(testsuite.ctx, testsuite.resourceGroupName, testsuite.accountName, armcosmos.DatabaseAccountCreateUpdateParameters{ + Location: to.Ptr(testsuite.location), + Properties: &armcosmos.DatabaseAccountCreateUpdateProperties{ + CreateMode: to.Ptr(armcosmos.CreateModeDefault), + DatabaseAccountOfferType: to.Ptr("Standard"), + Locations: []*armcosmos.Location{ + { + FailoverPriority: to.Ptr[int32](0), + IsZoneRedundant: to.Ptr(false), + LocationName: to.Ptr(testsuite.location), + }}, + }, + }, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, databaseAccountsClientCreateOrUpdateResponsePoller) + testsuite.Require().NoError(err) +} + +// Microsoft.DocumentDB/databaseAccounts/{accountName}/services/{serviceName} +func (testsuite *ServicesTestSuite) TestService() { + var err error + // From step Service_Create + fmt.Println("Call operation: Service_Create") + serviceClient, err := armcosmos.NewServiceClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + serviceClientCreateResponsePoller, err := serviceClient.BeginCreate(testsuite.ctx, testsuite.resourceGroupName, testsuite.accountName, "SqlDedicatedGateway", armcosmos.ServiceResourceCreateUpdateParameters{ + Properties: &armcosmos.ServiceResourceCreateUpdateProperties{ + InstanceCount: to.Ptr[int32](1), + InstanceSize: to.Ptr(armcosmos.ServiceSizeCosmosD4S), + ServiceType: to.Ptr(armcosmos.ServiceTypeSQLDedicatedGateway), + }, + }, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, serviceClientCreateResponsePoller) + testsuite.Require().NoError(err) + + // From step Service_List + fmt.Println("Call operation: Service_List") + serviceClientNewListPager := serviceClient.NewListPager(testsuite.resourceGroupName, testsuite.accountName, nil) + for serviceClientNewListPager.More() { + _, err := serviceClientNewListPager.NextPage(testsuite.ctx) + testsuite.Require().NoError(err) + break + } + + // From step Service_Get + fmt.Println("Call operation: Service_Get") + _, err = serviceClient.Get(testsuite.ctx, testsuite.resourceGroupName, testsuite.accountName, "SqlDedicatedGateway", nil) + testsuite.Require().NoError(err) + + // From step Service_Delete + fmt.Println("Call operation: Service_Delete") + serviceClientDeleteResponsePoller, err := serviceClient.BeginDelete(testsuite.ctx, testsuite.resourceGroupName, testsuite.accountName, "SqlDedicatedGateway", nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, serviceClientDeleteResponsePoller) + testsuite.Require().NoError(err) +} diff --git a/sdk/resourcemanager/cosmos/armcosmos/sqlresources_live_test.go b/sdk/resourcemanager/cosmos/armcosmos/sqlresources_live_test.go new file mode 100644 index 000000000000..0de386832bb0 --- /dev/null +++ b/sdk/resourcemanager/cosmos/armcosmos/sqlresources_live_test.go @@ -0,0 +1,465 @@ +//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 armcosmos_test + +import ( + "context" + "fmt" + "testing" + + "github.com/Azure/azure-sdk-for-go/sdk/azcore" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/arm" + "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/resourcemanager/cosmos/armcosmos/v2" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/internal/testutil" + "github.com/stretchr/testify/suite" +) + +type SqlResourcesTestSuite struct { + suite.Suite + + ctx context.Context + cred azcore.TokenCredential + options *arm.ClientOptions + accountName string + containerName string + databaseName string + triggerName string + storedProcedureName string + userDefinedFunctionName string + clientEncryptionKeyName string + location string + resourceGroupName string + subscriptionId string +} + +func (testsuite *SqlResourcesTestSuite) SetupSuite() { + testutil.StartRecording(testsuite.T(), "sdk/resourcemanager/cosmos/armcosmos/testdata") + + testsuite.ctx = context.Background() + testsuite.cred, testsuite.options = testutil.GetCredAndClientOptions(testsuite.T()) + testsuite.accountName, _ = recording.GenerateAlphaNumericID(testsuite.T(), "accountn", 14, true) + testsuite.containerName, _ = recording.GenerateAlphaNumericID(testsuite.T(), "sqlcontaine", 17, false) + testsuite.databaseName, _ = recording.GenerateAlphaNumericID(testsuite.T(), "sqldb", 11, false) + testsuite.triggerName, _ = recording.GenerateAlphaNumericID(testsuite.T(), "triggern", 14, false) + testsuite.storedProcedureName, _ = recording.GenerateAlphaNumericID(testsuite.T(), "storedpr", 14, true) + testsuite.userDefinedFunctionName, _ = recording.GenerateAlphaNumericID(testsuite.T(), "userdefi", 14, false) + testsuite.clientEncryptionKeyName, _ = recording.GenerateAlphaNumericID(testsuite.T(), "clienten", 14, false) + testsuite.location = testutil.GetEnv("LOCATION", "westus") + testsuite.resourceGroupName = testutil.GetEnv("RESOURCE_GROUP_NAME", "scenarioTestTempGroup") + testsuite.subscriptionId = testutil.GetEnv("AZURE_SUBSCRIPTION_ID", "00000000-0000-0000-0000-000000000000") + resourceGroup, _, err := testutil.CreateResourceGroup(testsuite.ctx, testsuite.subscriptionId, testsuite.cred, testsuite.options, testsuite.location) + testsuite.Require().NoError(err) + testsuite.resourceGroupName = *resourceGroup.Name + testsuite.Prepare() +} + +func (testsuite *SqlResourcesTestSuite) TearDownSuite() { + testsuite.Cleanup() + _, err := testutil.DeleteResourceGroup(testsuite.ctx, testsuite.subscriptionId, testsuite.cred, testsuite.options, testsuite.resourceGroupName) + testsuite.Require().NoError(err) + testutil.StopRecording(testsuite.T()) +} + +func TestSqlResourcesTestSuite(t *testing.T) { + suite.Run(t, new(SqlResourcesTestSuite)) +} + +func (testsuite *SqlResourcesTestSuite) Prepare() { + var err error + // From step DatabaseAccounts_CreateOrUpdate + fmt.Println("Call operation: DatabaseAccounts_CreateOrUpdate") + databaseAccountsClient, err := armcosmos.NewDatabaseAccountsClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + databaseAccountsClientCreateOrUpdateResponsePoller, err := databaseAccountsClient.BeginCreateOrUpdate(testsuite.ctx, testsuite.resourceGroupName, testsuite.accountName, armcosmos.DatabaseAccountCreateUpdateParameters{ + Location: to.Ptr(testsuite.location), + Properties: &armcosmos.DatabaseAccountCreateUpdateProperties{ + CreateMode: to.Ptr(armcosmos.CreateModeDefault), + DatabaseAccountOfferType: to.Ptr("Standard"), + Locations: []*armcosmos.Location{ + { + FailoverPriority: to.Ptr[int32](0), + IsZoneRedundant: to.Ptr(false), + LocationName: to.Ptr(testsuite.location), + }}, + }, + }, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, databaseAccountsClientCreateOrUpdateResponsePoller) + testsuite.Require().NoError(err) + + // From step SqlResources_CreateUpdateSqlDatabase + fmt.Println("Call operation: SQLResources_CreateUpdateSQLDatabase") + sQLResourcesClient, err := armcosmos.NewSQLResourcesClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + sQLResourcesClientCreateUpdateSQLDatabaseResponsePoller, err := sQLResourcesClient.BeginCreateUpdateSQLDatabase(testsuite.ctx, testsuite.resourceGroupName, testsuite.accountName, testsuite.databaseName, armcosmos.SQLDatabaseCreateUpdateParameters{ + Location: to.Ptr(testsuite.location), + Tags: map[string]*string{}, + Properties: &armcosmos.SQLDatabaseCreateUpdateProperties{ + Options: &armcosmos.CreateUpdateOptions{ + Throughput: to.Ptr[int32](2000), + }, + Resource: &armcosmos.SQLDatabaseResource{ + ID: to.Ptr(testsuite.databaseName), + }, + }, + }, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, sQLResourcesClientCreateUpdateSQLDatabaseResponsePoller) + testsuite.Require().NoError(err) + + // From step SqlResources_CreateUpdateSqlContainer + fmt.Println("Call operation: SQLResources_CreateUpdateSQLContainer") + sQLResourcesClientCreateUpdateSQLContainerResponsePoller, err := sQLResourcesClient.BeginCreateUpdateSQLContainer(testsuite.ctx, testsuite.resourceGroupName, testsuite.accountName, testsuite.databaseName, testsuite.containerName, armcosmos.SQLContainerCreateUpdateParameters{ + Location: to.Ptr(testsuite.location), + Tags: map[string]*string{}, + Properties: &armcosmos.SQLContainerCreateUpdateProperties{ + Options: &armcosmos.CreateUpdateOptions{ + Throughput: to.Ptr[int32](2000), + }, + Resource: &armcosmos.SQLContainerResource{ + ConflictResolutionPolicy: &armcosmos.ConflictResolutionPolicy{ + ConflictResolutionPath: to.Ptr("/path"), + Mode: to.Ptr(armcosmos.ConflictResolutionModeLastWriterWins), + }, + ID: to.Ptr(testsuite.containerName), + IndexingPolicy: &armcosmos.IndexingPolicy{ + Automatic: to.Ptr(true), + ExcludedPaths: []*armcosmos.ExcludedPath{}, + IncludedPaths: []*armcosmos.IncludedPath{ + { + Path: to.Ptr("/*"), + Indexes: []*armcosmos.Indexes{ + { + DataType: to.Ptr(armcosmos.DataTypeString), + Kind: to.Ptr(armcosmos.IndexKindRange), + Precision: to.Ptr[int32](-1), + }, + { + DataType: to.Ptr(armcosmos.DataTypeNumber), + Kind: to.Ptr(armcosmos.IndexKindRange), + Precision: to.Ptr[int32](-1), + }}, + }}, + IndexingMode: to.Ptr(armcosmos.IndexingModeConsistent), + }, + PartitionKey: &armcosmos.ContainerPartitionKey{ + Kind: to.Ptr(armcosmos.PartitionKindHash), + Paths: []*string{ + to.Ptr("/AccountNumber")}, + }, + UniqueKeyPolicy: &armcosmos.UniqueKeyPolicy{ + UniqueKeys: []*armcosmos.UniqueKey{ + { + Paths: []*string{ + to.Ptr("/testPath")}, + }}, + }, + }, + }, + }, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, sQLResourcesClientCreateUpdateSQLContainerResponsePoller) + testsuite.Require().NoError(err) +} + +// Microsoft.DocumentDB/databaseAccounts/{accountName}/sqlDatabases/{databaseName} +func (testsuite *SqlResourcesTestSuite) TestSqlDatabase() { + var err error + // From step SqlResources_ListSqlDatabases + fmt.Println("Call operation: SQLResources_ListSQLDatabases") + sQLResourcesClient, err := armcosmos.NewSQLResourcesClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + sQLResourcesClientNewListSQLDatabasesPager := sQLResourcesClient.NewListSQLDatabasesPager(testsuite.resourceGroupName, testsuite.accountName, nil) + for sQLResourcesClientNewListSQLDatabasesPager.More() { + _, err := sQLResourcesClientNewListSQLDatabasesPager.NextPage(testsuite.ctx) + testsuite.Require().NoError(err) + break + } + + // From step SqlResources_GetSqlDatabase + fmt.Println("Call operation: SQLResources_GetSQLDatabase") + _, err = sQLResourcesClient.GetSQLDatabase(testsuite.ctx, testsuite.resourceGroupName, testsuite.accountName, testsuite.databaseName, nil) + testsuite.Require().NoError(err) + + // From step SqlResources_GetSqlDatabaseThroughput + fmt.Println("Call operation: SQLResources_GetSQLDatabaseThroughput") + _, err = sQLResourcesClient.GetSQLDatabaseThroughput(testsuite.ctx, testsuite.resourceGroupName, testsuite.accountName, testsuite.databaseName, nil) + testsuite.Require().NoError(err) + + // From step SqlResources_UpdateSqlDatabaseThroughput + fmt.Println("Call operation: SQLResources_UpdateSQLDatabaseThroughput") + sQLResourcesClientUpdateSQLDatabaseThroughputResponsePoller, err := sQLResourcesClient.BeginUpdateSQLDatabaseThroughput(testsuite.ctx, testsuite.resourceGroupName, testsuite.accountName, testsuite.databaseName, armcosmos.ThroughputSettingsUpdateParameters{ + Location: to.Ptr(testsuite.location), + Tags: map[string]*string{}, + Properties: &armcosmos.ThroughputSettingsUpdateProperties{ + Resource: &armcosmos.ThroughputSettingsResource{ + Throughput: to.Ptr[int32](400), + }, + }, + }, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, sQLResourcesClientUpdateSQLDatabaseThroughputResponsePoller) + testsuite.Require().NoError(err) + + // From step SqlResources_MigrateSqlDatabaseToAutoscale + fmt.Println("Call operation: SQLResources_MigrateSQLDatabaseToAutoscale") + sQLResourcesClientMigrateSQLDatabaseToAutoscaleResponsePoller, err := sQLResourcesClient.BeginMigrateSQLDatabaseToAutoscale(testsuite.ctx, testsuite.resourceGroupName, testsuite.accountName, testsuite.databaseName, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, sQLResourcesClientMigrateSQLDatabaseToAutoscaleResponsePoller) + testsuite.Require().NoError(err) + + // From step SqlResources_MigrateSqlDatabaseToManualThroughput + fmt.Println("Call operation: SQLResources_MigrateSQLDatabaseToManualThroughput") + sQLResourcesClientMigrateSQLDatabaseToManualThroughputResponsePoller, err := sQLResourcesClient.BeginMigrateSQLDatabaseToManualThroughput(testsuite.ctx, testsuite.resourceGroupName, testsuite.accountName, testsuite.databaseName, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, sQLResourcesClientMigrateSQLDatabaseToManualThroughputResponsePoller) + testsuite.Require().NoError(err) +} + +// Microsoft.DocumentDB/databaseAccounts/{accountName}/sqlDatabases/{databaseName}/containers/{containerName} +func (testsuite *SqlResourcesTestSuite) TestSqlContainer() { + var err error + // From step SqlResources_GetSqlContainer + fmt.Println("Call operation: SQLResources_GetSQLContainer") + sQLResourcesClient, err := armcosmos.NewSQLResourcesClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + _, err = sQLResourcesClient.GetSQLContainer(testsuite.ctx, testsuite.resourceGroupName, testsuite.accountName, testsuite.databaseName, testsuite.containerName, nil) + testsuite.Require().NoError(err) + + // From step SqlResources_ListSqlContainers + fmt.Println("Call operation: SQLResources_ListSQLContainers") + sQLResourcesClientNewListSQLContainersPager := sQLResourcesClient.NewListSQLContainersPager(testsuite.resourceGroupName, testsuite.accountName, testsuite.databaseName, nil) + for sQLResourcesClientNewListSQLContainersPager.More() { + _, err := sQLResourcesClientNewListSQLContainersPager.NextPage(testsuite.ctx) + testsuite.Require().NoError(err) + break + } + + // From step SqlResources_GetSqlContainerThroughput + fmt.Println("Call operation: SQLResources_GetSQLContainerThroughput") + _, err = sQLResourcesClient.GetSQLContainerThroughput(testsuite.ctx, testsuite.resourceGroupName, testsuite.accountName, testsuite.databaseName, testsuite.containerName, nil) + testsuite.Require().NoError(err) + + // From step SqlResources_UpdateSqlContainerThroughput + fmt.Println("Call operation: SQLResources_UpdateSQLContainerThroughput") + sQLResourcesClientUpdateSQLContainerThroughputResponsePoller, err := sQLResourcesClient.BeginUpdateSQLContainerThroughput(testsuite.ctx, testsuite.resourceGroupName, testsuite.accountName, testsuite.databaseName, testsuite.containerName, armcosmos.ThroughputSettingsUpdateParameters{ + Location: to.Ptr(testsuite.location), + Tags: map[string]*string{}, + Properties: &armcosmos.ThroughputSettingsUpdateProperties{ + Resource: &armcosmos.ThroughputSettingsResource{ + Throughput: to.Ptr[int32](400), + }, + }, + }, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, sQLResourcesClientUpdateSQLContainerThroughputResponsePoller) + testsuite.Require().NoError(err) + + // From step SqlResources_MigrateSqlContainerToAutoscale + fmt.Println("Call operation: SQLResources_MigrateSQLContainerToAutoscale") + sQLResourcesClientMigrateSQLContainerToAutoscaleResponsePoller, err := sQLResourcesClient.BeginMigrateSQLContainerToAutoscale(testsuite.ctx, testsuite.resourceGroupName, testsuite.accountName, testsuite.databaseName, testsuite.containerName, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, sQLResourcesClientMigrateSQLContainerToAutoscaleResponsePoller) + testsuite.Require().NoError(err) + + // From step SqlResources_MigrateSqlContainerToManualThroughput + fmt.Println("Call operation: SQLResources_MigrateSQLContainerToManualThroughput") + sQLResourcesClientMigrateSQLContainerToManualThroughputResponsePoller, err := sQLResourcesClient.BeginMigrateSQLContainerToManualThroughput(testsuite.ctx, testsuite.resourceGroupName, testsuite.accountName, testsuite.databaseName, testsuite.containerName, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, sQLResourcesClientMigrateSQLContainerToManualThroughputResponsePoller) + testsuite.Require().NoError(err) +} + +// Microsoft.DocumentDB/databaseAccounts/{accountName}/sqlDatabases/{databaseName}/containers/{containerName}/triggers/{triggerName} +func (testsuite *SqlResourcesTestSuite) TestSqlTrigger() { + var err error + // From step SqlResources_CreateUpdateSqlTrigger + fmt.Println("Call operation: SQLResources_CreateUpdateSQLTrigger") + sQLResourcesClient, err := armcosmos.NewSQLResourcesClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + sQLResourcesClientCreateUpdateSQLTriggerResponsePoller, err := sQLResourcesClient.BeginCreateUpdateSQLTrigger(testsuite.ctx, testsuite.resourceGroupName, testsuite.accountName, testsuite.databaseName, testsuite.containerName, testsuite.triggerName, armcosmos.SQLTriggerCreateUpdateParameters{ + Properties: &armcosmos.SQLTriggerCreateUpdateProperties{ + Options: &armcosmos.CreateUpdateOptions{}, + Resource: &armcosmos.SQLTriggerResource{ + Body: to.Ptr("body"), + ID: to.Ptr(testsuite.triggerName), + TriggerOperation: to.Ptr(armcosmos.TriggerOperationAll), + TriggerType: to.Ptr(armcosmos.TriggerTypePre), + }, + }, + }, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, sQLResourcesClientCreateUpdateSQLTriggerResponsePoller) + testsuite.Require().NoError(err) + + // From step SqlResources_GetSqlTrigger + fmt.Println("Call operation: SQLResources_GetSQLTrigger") + _, err = sQLResourcesClient.GetSQLTrigger(testsuite.ctx, testsuite.resourceGroupName, testsuite.accountName, testsuite.databaseName, testsuite.containerName, testsuite.triggerName, nil) + testsuite.Require().NoError(err) + + // From step SqlResources_ListSqlTriggers + fmt.Println("Call operation: SQLResources_ListSQLTriggers") + sQLResourcesClientNewListSQLTriggersPager := sQLResourcesClient.NewListSQLTriggersPager(testsuite.resourceGroupName, testsuite.accountName, testsuite.databaseName, testsuite.containerName, nil) + for sQLResourcesClientNewListSQLTriggersPager.More() { + _, err := sQLResourcesClientNewListSQLTriggersPager.NextPage(testsuite.ctx) + testsuite.Require().NoError(err) + break + } + + // From step SqlResources_DeleteSqlTrigger + fmt.Println("Call operation: SQLResources_DeleteSQLTrigger") + sQLResourcesClientDeleteSQLTriggerResponsePoller, err := sQLResourcesClient.BeginDeleteSQLTrigger(testsuite.ctx, testsuite.resourceGroupName, testsuite.accountName, testsuite.databaseName, testsuite.containerName, testsuite.triggerName, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, sQLResourcesClientDeleteSQLTriggerResponsePoller) + testsuite.Require().NoError(err) +} + +// Microsoft.DocumentDB/databaseAccounts/{accountName}/sqlDatabases/{databaseName}/containers/{containerName}/storedProcedures/{storedProcedureName} +func (testsuite *SqlResourcesTestSuite) TestSqlStoredProcedure() { + var err error + // From step SqlResources_CreateUpdateSqlStoredProcedure + fmt.Println("Call operation: SQLResources_CreateUpdateSQLStoredProcedure") + sQLResourcesClient, err := armcosmos.NewSQLResourcesClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + sQLResourcesClientCreateUpdateSQLStoredProcedureResponsePoller, err := sQLResourcesClient.BeginCreateUpdateSQLStoredProcedure(testsuite.ctx, testsuite.resourceGroupName, testsuite.accountName, testsuite.databaseName, testsuite.containerName, testsuite.storedProcedureName, armcosmos.SQLStoredProcedureCreateUpdateParameters{ + Properties: &armcosmos.SQLStoredProcedureCreateUpdateProperties{ + Options: &armcosmos.CreateUpdateOptions{}, + Resource: &armcosmos.SQLStoredProcedureResource{ + Body: to.Ptr("body"), + ID: to.Ptr(testsuite.storedProcedureName), + }, + }, + }, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, sQLResourcesClientCreateUpdateSQLStoredProcedureResponsePoller) + testsuite.Require().NoError(err) + + // From step SqlResources_GetSqlStoredProcedure + fmt.Println("Call operation: SQLResources_GetSQLStoredProcedure") + _, err = sQLResourcesClient.GetSQLStoredProcedure(testsuite.ctx, testsuite.resourceGroupName, testsuite.accountName, testsuite.databaseName, testsuite.containerName, testsuite.storedProcedureName, nil) + testsuite.Require().NoError(err) + + // From step SqlResources_ListSqlStoredProcedures + fmt.Println("Call operation: SQLResources_ListSQLStoredProcedures") + sQLResourcesClientNewListSQLStoredProceduresPager := sQLResourcesClient.NewListSQLStoredProceduresPager(testsuite.resourceGroupName, testsuite.accountName, testsuite.databaseName, testsuite.containerName, nil) + for sQLResourcesClientNewListSQLStoredProceduresPager.More() { + _, err := sQLResourcesClientNewListSQLStoredProceduresPager.NextPage(testsuite.ctx) + testsuite.Require().NoError(err) + break + } + + // From step SqlResources_DeleteSqlStoredProcedure + fmt.Println("Call operation: SQLResources_DeleteSQLStoredProcedure") + sQLResourcesClientDeleteSQLStoredProcedureResponsePoller, err := sQLResourcesClient.BeginDeleteSQLStoredProcedure(testsuite.ctx, testsuite.resourceGroupName, testsuite.accountName, testsuite.databaseName, testsuite.containerName, testsuite.storedProcedureName, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, sQLResourcesClientDeleteSQLStoredProcedureResponsePoller) + testsuite.Require().NoError(err) +} + +// Microsoft.DocumentDB/databaseAccounts/{accountName}/sqlDatabases/{databaseName}/containers/{containerName}/userDefinedFunctions/{userDefinedFunctionName} +func (testsuite *SqlResourcesTestSuite) TestSqlUserDefinedFunction() { + var err error + // From step SqlResources_CreateUpdateSqlUserDefinedFunction + fmt.Println("Call operation: SQLResources_CreateUpdateSQLUserDefinedFunction") + sQLResourcesClient, err := armcosmos.NewSQLResourcesClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + sQLResourcesClientCreateUpdateSQLUserDefinedFunctionResponsePoller, err := sQLResourcesClient.BeginCreateUpdateSQLUserDefinedFunction(testsuite.ctx, testsuite.resourceGroupName, testsuite.accountName, testsuite.databaseName, testsuite.containerName, testsuite.userDefinedFunctionName, armcosmos.SQLUserDefinedFunctionCreateUpdateParameters{ + Properties: &armcosmos.SQLUserDefinedFunctionCreateUpdateProperties{ + Options: &armcosmos.CreateUpdateOptions{}, + Resource: &armcosmos.SQLUserDefinedFunctionResource{ + Body: to.Ptr("body"), + ID: to.Ptr(testsuite.userDefinedFunctionName), + }, + }, + }, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, sQLResourcesClientCreateUpdateSQLUserDefinedFunctionResponsePoller) + testsuite.Require().NoError(err) + + // From step SqlResources_GetSqlUserDefinedFunction + fmt.Println("Call operation: SQLResources_GetSQLUserDefinedFunction") + _, err = sQLResourcesClient.GetSQLUserDefinedFunction(testsuite.ctx, testsuite.resourceGroupName, testsuite.accountName, testsuite.databaseName, testsuite.containerName, testsuite.userDefinedFunctionName, nil) + testsuite.Require().NoError(err) + + // From step SqlResources_ListSqlUserDefinedFunctions + fmt.Println("Call operation: SQLResources_ListSQLUserDefinedFunctions") + sQLResourcesClientNewListSQLUserDefinedFunctionsPager := sQLResourcesClient.NewListSQLUserDefinedFunctionsPager(testsuite.resourceGroupName, testsuite.accountName, testsuite.databaseName, testsuite.containerName, nil) + for sQLResourcesClientNewListSQLUserDefinedFunctionsPager.More() { + _, err := sQLResourcesClientNewListSQLUserDefinedFunctionsPager.NextPage(testsuite.ctx) + testsuite.Require().NoError(err) + break + } + + // From step SqlResources_DeleteSqlUserDefinedFunction + fmt.Println("Call operation: SQLResources_DeleteSQLUserDefinedFunction") + sQLResourcesClientDeleteSQLUserDefinedFunctionResponsePoller, err := sQLResourcesClient.BeginDeleteSQLUserDefinedFunction(testsuite.ctx, testsuite.resourceGroupName, testsuite.accountName, testsuite.databaseName, testsuite.containerName, testsuite.userDefinedFunctionName, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, sQLResourcesClientDeleteSQLUserDefinedFunctionResponsePoller) + testsuite.Require().NoError(err) +} + +// Microsoft.DocumentDB/databaseAccounts/{accountName}/sqlDatabases/{databaseName}/clientEncryptionKeys/{clientEncryptionKeyName} +func (testsuite *SqlResourcesTestSuite) TestSqlClientEncryptionKey() { + var err error + // From step SqlResources_CreateUpdateClientEncryptionKey + fmt.Println("Call operation: SQLResources_CreateUpdateClientEncryptionKey") + sQLResourcesClient, err := armcosmos.NewSQLResourcesClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + sQLResourcesClientCreateUpdateClientEncryptionKeyResponsePoller, err := sQLResourcesClient.BeginCreateUpdateClientEncryptionKey(testsuite.ctx, testsuite.resourceGroupName, testsuite.accountName, testsuite.databaseName, testsuite.clientEncryptionKeyName, armcosmos.ClientEncryptionKeyCreateUpdateParameters{ + Properties: &armcosmos.ClientEncryptionKeyCreateUpdateProperties{ + Resource: &armcosmos.ClientEncryptionKeyResource{ + EncryptionAlgorithm: to.Ptr("AEAD_AES_256_CBC_HMAC_SHA256"), + ID: to.Ptr(testsuite.clientEncryptionKeyName), + KeyWrapMetadata: &armcosmos.KeyWrapMetadata{ + Name: to.Ptr("customerManagedKey"), + Type: to.Ptr("AzureKeyVault"), + Algorithm: to.Ptr("RSA-OAEP"), + Value: to.Ptr("AzureKeyVault Key URL"), + }, + WrappedDataEncryptionKey: []byte("U3dhZ2dlciByb2Nrcw=="), + }, + }, + }, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, sQLResourcesClientCreateUpdateClientEncryptionKeyResponsePoller) + testsuite.Require().NoError(err) + + // From step SqlResources_GetClientEncryptionKey + fmt.Println("Call operation: SQLResources_GetClientEncryptionKey") + _, err = sQLResourcesClient.GetClientEncryptionKey(testsuite.ctx, testsuite.resourceGroupName, testsuite.accountName, testsuite.databaseName, testsuite.clientEncryptionKeyName, nil) + testsuite.Require().NoError(err) + + // From step SqlResources_ListClientEncryptionKeys + fmt.Println("Call operation: SQLResources_ListClientEncryptionKeys") + sQLResourcesClientNewListClientEncryptionKeysPager := sQLResourcesClient.NewListClientEncryptionKeysPager(testsuite.resourceGroupName, testsuite.accountName, testsuite.databaseName, nil) + for sQLResourcesClientNewListClientEncryptionKeysPager.More() { + _, err := sQLResourcesClientNewListClientEncryptionKeysPager.NextPage(testsuite.ctx) + testsuite.Require().NoError(err) + break + } +} + +func (testsuite *SqlResourcesTestSuite) Cleanup() { + var err error + // From step SqlResources_DeleteSqlContainer + fmt.Println("Call operation: SQLResources_DeleteSQLContainer") + sQLResourcesClient, err := armcosmos.NewSQLResourcesClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + sQLResourcesClientDeleteSQLContainerResponsePoller, err := sQLResourcesClient.BeginDeleteSQLContainer(testsuite.ctx, testsuite.resourceGroupName, testsuite.accountName, testsuite.databaseName, testsuite.containerName, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, sQLResourcesClientDeleteSQLContainerResponsePoller) + testsuite.Require().NoError(err) + + // From step SqlResources_DeleteSqlDatabase + fmt.Println("Call operation: SQLResources_DeleteSQLDatabase") + sQLResourcesClientDeleteSQLDatabaseResponsePoller, err := sQLResourcesClient.BeginDeleteSQLDatabase(testsuite.ctx, testsuite.resourceGroupName, testsuite.accountName, testsuite.databaseName, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, sQLResourcesClientDeleteSQLDatabaseResponsePoller) + testsuite.Require().NoError(err) +} diff --git a/sdk/resourcemanager/cosmos/armcosmos/tableresources_live_test.go b/sdk/resourcemanager/cosmos/armcosmos/tableresources_live_test.go new file mode 100644 index 000000000000..3f72a33f3c5f --- /dev/null +++ b/sdk/resourcemanager/cosmos/armcosmos/tableresources_live_test.go @@ -0,0 +1,166 @@ +//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 armcosmos_test + +import ( + "context" + "fmt" + "testing" + + "github.com/Azure/azure-sdk-for-go/sdk/azcore" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/arm" + "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/resourcemanager/cosmos/armcosmos/v2" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/internal/testutil" + "github.com/stretchr/testify/suite" +) + +type TableResourcesTestSuite struct { + suite.Suite + + ctx context.Context + cred azcore.TokenCredential + options *arm.ClientOptions + accountName string + tableName string + location string + resourceGroupName string + subscriptionId string +} + +func (testsuite *TableResourcesTestSuite) SetupSuite() { + testutil.StartRecording(testsuite.T(), "sdk/resourcemanager/cosmos/armcosmos/testdata") + + testsuite.ctx = context.Background() + testsuite.cred, testsuite.options = testutil.GetCredAndClientOptions(testsuite.T()) + testsuite.accountName, _ = recording.GenerateAlphaNumericID(testsuite.T(), "accountn", 14, true) + testsuite.tableName, _ = recording.GenerateAlphaNumericID(testsuite.T(), "tablenam", 14, false) + testsuite.location = testutil.GetEnv("LOCATION", "westus") + testsuite.resourceGroupName = testutil.GetEnv("RESOURCE_GROUP_NAME", "scenarioTestTempGroup") + testsuite.subscriptionId = testutil.GetEnv("AZURE_SUBSCRIPTION_ID", "00000000-0000-0000-0000-000000000000") + resourceGroup, _, err := testutil.CreateResourceGroup(testsuite.ctx, testsuite.subscriptionId, testsuite.cred, testsuite.options, testsuite.location) + testsuite.Require().NoError(err) + testsuite.resourceGroupName = *resourceGroup.Name + testsuite.Prepare() +} + +func (testsuite *TableResourcesTestSuite) TearDownSuite() { + _, err := testutil.DeleteResourceGroup(testsuite.ctx, testsuite.subscriptionId, testsuite.cred, testsuite.options, testsuite.resourceGroupName) + testsuite.Require().NoError(err) + testutil.StopRecording(testsuite.T()) +} + +func TestTableResourcesTestSuite(t *testing.T) { + suite.Run(t, new(TableResourcesTestSuite)) +} + +func (testsuite *TableResourcesTestSuite) Prepare() { + var err error + // From step DatabaseAccounts_CreateOrUpdate + fmt.Println("Call operation: DatabaseAccounts_CreateOrUpdate") + databaseAccountsClient, err := armcosmos.NewDatabaseAccountsClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + databaseAccountsClientCreateOrUpdateResponsePoller, err := databaseAccountsClient.BeginCreateOrUpdate(testsuite.ctx, testsuite.resourceGroupName, testsuite.accountName, armcosmos.DatabaseAccountCreateUpdateParameters{ + Location: to.Ptr(testsuite.location), + Kind: to.Ptr(armcosmos.DatabaseAccountKindGlobalDocumentDB), + Properties: &armcosmos.DatabaseAccountCreateUpdateProperties{ + Capabilities: []*armcosmos.Capability{ + { + Name: to.Ptr("EnableTable"), + }}, + CreateMode: to.Ptr(armcosmos.CreateModeDefault), + DatabaseAccountOfferType: to.Ptr("Standard"), + Locations: []*armcosmos.Location{ + { + FailoverPriority: to.Ptr[int32](0), + IsZoneRedundant: to.Ptr(false), + LocationName: to.Ptr(testsuite.location), + }}, + }, + }, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, databaseAccountsClientCreateOrUpdateResponsePoller) + testsuite.Require().NoError(err) +} + +// Microsoft.DocumentDB/databaseAccounts/{accountName}/tables/{tableName} +func (testsuite *TableResourcesTestSuite) TestTableResources() { + var err error + // From step TableResources_CreateUpdateTable + fmt.Println("Call operation: TableResources_CreateUpdateTable") + tableResourcesClient, err := armcosmos.NewTableResourcesClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + tableResourcesClientCreateUpdateTableResponsePoller, err := tableResourcesClient.BeginCreateUpdateTable(testsuite.ctx, testsuite.resourceGroupName, testsuite.accountName, testsuite.tableName, armcosmos.TableCreateUpdateParameters{ + Location: to.Ptr(testsuite.location), + Tags: map[string]*string{}, + Properties: &armcosmos.TableCreateUpdateProperties{ + Options: &armcosmos.CreateUpdateOptions{}, + Resource: &armcosmos.TableResource{ + ID: to.Ptr(testsuite.tableName), + }, + }, + }, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, tableResourcesClientCreateUpdateTableResponsePoller) + testsuite.Require().NoError(err) + + // From step TableResources_ListTables + fmt.Println("Call operation: TableResources_ListTables") + tableResourcesClientNewListTablesPager := tableResourcesClient.NewListTablesPager(testsuite.resourceGroupName, testsuite.accountName, nil) + for tableResourcesClientNewListTablesPager.More() { + _, err := tableResourcesClientNewListTablesPager.NextPage(testsuite.ctx) + testsuite.Require().NoError(err) + break + } + + // From step TableResources_GetTableThroughput + fmt.Println("Call operation: TableResources_GetTableThroughput") + _, err = tableResourcesClient.GetTableThroughput(testsuite.ctx, testsuite.resourceGroupName, testsuite.accountName, testsuite.tableName, nil) + testsuite.Require().NoError(err) + + // From step TableResources_GetTable + fmt.Println("Call operation: TableResources_GetTable") + _, err = tableResourcesClient.GetTable(testsuite.ctx, testsuite.resourceGroupName, testsuite.accountName, testsuite.tableName, nil) + testsuite.Require().NoError(err) + + // From step TableResources_MigrateTableToAutoscale + fmt.Println("Call operation: TableResources_MigrateTableToAutoscale") + tableResourcesClientMigrateTableToAutoscaleResponsePoller, err := tableResourcesClient.BeginMigrateTableToAutoscale(testsuite.ctx, testsuite.resourceGroupName, testsuite.accountName, testsuite.tableName, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, tableResourcesClientMigrateTableToAutoscaleResponsePoller) + testsuite.Require().NoError(err) + + // From step TableResources_MigrateTableToManualThroughput + fmt.Println("Call operation: TableResources_MigrateTableToManualThroughput") + tableResourcesClientMigrateTableToManualThroughputResponsePoller, err := tableResourcesClient.BeginMigrateTableToManualThroughput(testsuite.ctx, testsuite.resourceGroupName, testsuite.accountName, testsuite.tableName, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, tableResourcesClientMigrateTableToManualThroughputResponsePoller) + testsuite.Require().NoError(err) + + // From step TableResources_UpdateTableThroughput + fmt.Println("Call operation: TableResources_UpdateTableThroughput") + tableResourcesClientUpdateTableThroughputResponsePoller, err := tableResourcesClient.BeginUpdateTableThroughput(testsuite.ctx, testsuite.resourceGroupName, testsuite.accountName, testsuite.tableName, armcosmos.ThroughputSettingsUpdateParameters{ + Location: to.Ptr(testsuite.location), + Tags: map[string]*string{}, + Properties: &armcosmos.ThroughputSettingsUpdateProperties{ + Resource: &armcosmos.ThroughputSettingsResource{ + Throughput: to.Ptr[int32](400), + }, + }, + }, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, tableResourcesClientUpdateTableThroughputResponsePoller) + testsuite.Require().NoError(err) + + // From step TableResources_DeleteTable + fmt.Println("Call operation: TableResources_DeleteTable") + tableResourcesClientDeleteTableResponsePoller, err := tableResourcesClient.BeginDeleteTable(testsuite.ctx, testsuite.resourceGroupName, testsuite.accountName, testsuite.tableName, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, tableResourcesClientDeleteTableResponsePoller) + testsuite.Require().NoError(err) +} diff --git a/sdk/resourcemanager/eventhub/armeventhub/assets.json b/sdk/resourcemanager/eventhub/armeventhub/assets.json index 7424094e97a0..0368812f7eee 100644 --- a/sdk/resourcemanager/eventhub/armeventhub/assets.json +++ b/sdk/resourcemanager/eventhub/armeventhub/assets.json @@ -2,5 +2,5 @@ "AssetsRepo": "Azure/azure-sdk-assets", "AssetsRepoPrefixPath": "go", "TagPrefix": "go/resourcemanager/eventhub/armeventhub", - "Tag": "go/resourcemanager/eventhub/armeventhub_05a4cd540a" + "Tag": "go/resourcemanager/eventhub/armeventhub_98cad0dc15" } diff --git a/sdk/resourcemanager/eventhub/armeventhub/disasterrecoveryconfigs_live_test.go b/sdk/resourcemanager/eventhub/armeventhub/disasterrecoveryconfigs_live_test.go index 54bab7d31945..eb698fc09059 100644 --- a/sdk/resourcemanager/eventhub/armeventhub/disasterrecoveryconfigs_live_test.go +++ b/sdk/resourcemanager/eventhub/armeventhub/disasterrecoveryconfigs_live_test.go @@ -14,6 +14,7 @@ import ( "github.com/Azure/azure-sdk-for-go/sdk/azcore" "github.com/Azure/azure-sdk-for-go/sdk/azcore/arm" "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/resourcemanager/eventhub/armeventhub" "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/internal/testutil" "github.com/stretchr/testify/suite" @@ -39,10 +40,10 @@ func (testsuite *DisasterrecoveryconfigsTestSuite) SetupSuite() { testutil.StartRecording(testsuite.T(), "sdk/resourcemanager/eventhub/armeventhub/testdata") testsuite.ctx = context.Background() testsuite.cred, testsuite.options = testutil.GetCredAndClientOptions(testsuite.T()) - testsuite.alias = testutil.GenerateAlphaNumericID(testsuite.T(), "alias2", 6) - testsuite.authorizationRuleName = testutil.GenerateAlphaNumericID(testsuite.T(), "authorizat2", 6) - testsuite.namespaceName = testutil.GenerateAlphaNumericID(testsuite.T(), "namespacen2", 6) - testsuite.namespaceNameSecond = testutil.GenerateAlphaNumericID(testsuite.T(), "namespacensecond", 6) + testsuite.alias, _ = recording.GenerateAlphaNumericID(testsuite.T(), "alias", 11, false) + testsuite.authorizationRuleName, _ = recording.GenerateAlphaNumericID(testsuite.T(), "authorizat", 16, false) + testsuite.namespaceName, _ = recording.GenerateAlphaNumericID(testsuite.T(), "namespacen", 16, false) + testsuite.namespaceNameSecond, _ = recording.GenerateAlphaNumericID(testsuite.T(), "namespacensecond", 22, false) testsuite.location = testutil.GetEnv("LOCATION", "westus") testsuite.resourceGroupName = testutil.GetEnv("RESOURCE_GROUP_NAME", "scenarioTestTempGroup") testsuite.subscriptionId = testutil.GetEnv("AZURE_SUBSCRIPTION_ID", "00000000-0000-0000-0000-000000000000") diff --git a/sdk/resourcemanager/eventhub/armeventhub/eventhub_live_test.go b/sdk/resourcemanager/eventhub/armeventhub/eventhub_live_test.go index c69fa9f2207c..dfac34291280 100644 --- a/sdk/resourcemanager/eventhub/armeventhub/eventhub_live_test.go +++ b/sdk/resourcemanager/eventhub/armeventhub/eventhub_live_test.go @@ -14,6 +14,7 @@ import ( "github.com/Azure/azure-sdk-for-go/sdk/azcore" "github.com/Azure/azure-sdk-for-go/sdk/azcore/arm" "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/resourcemanager/eventhub/armeventhub" "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/internal/testutil" "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armresources" @@ -43,12 +44,12 @@ func (testsuite *EventhubTestSuite) SetupSuite() { testutil.StartRecording(testsuite.T(), "sdk/resourcemanager/eventhub/armeventhub/testdata") testsuite.ctx = context.Background() testsuite.cred, testsuite.options = testutil.GetCredAndClientOptions(testsuite.T()) - testsuite.applicationGroupName = testutil.GenerateAlphaNumericID(testsuite.T(), "applicatio", 6) - testsuite.authorizationRuleName = testutil.GenerateAlphaNumericID(testsuite.T(), "authorizat", 6) - testsuite.consumerGroupName = testutil.GenerateAlphaNumericID(testsuite.T(), "consumergr", 6) - testsuite.eventHubName = testutil.GenerateAlphaNumericID(testsuite.T(), "eventhubna", 6) - testsuite.namespaceName = testutil.GenerateAlphaNumericID(testsuite.T(), "namespacen", 6) - testsuite.schemaGroupName = testutil.GenerateAlphaNumericID(testsuite.T(), "schemagrou", 6) + testsuite.applicationGroupName, _ = recording.GenerateAlphaNumericID(testsuite.T(), "applicatio", 16, false) + testsuite.authorizationRuleName, _ = recording.GenerateAlphaNumericID(testsuite.T(), "authorizat", 16, false) + testsuite.consumerGroupName, _ = recording.GenerateAlphaNumericID(testsuite.T(), "consumergr", 16, false) + testsuite.eventHubName, _ = recording.GenerateAlphaNumericID(testsuite.T(), "eventhubna", 16, false) + testsuite.namespaceName, _ = recording.GenerateAlphaNumericID(testsuite.T(), "namespacen", 16, false) + testsuite.schemaGroupName, _ = recording.GenerateAlphaNumericID(testsuite.T(), "schemagrou", 16, false) testsuite.storageAccountName = "storageeventhub2" testsuite.location = testutil.GetEnv("LOCATION", "westus") testsuite.resourceGroupName = testutil.GetEnv("RESOURCE_GROUP_NAME", "scenarioTestTempGroup") diff --git a/sdk/resourcemanager/eventhub/armeventhub/privateendpointconnections_live_test.go b/sdk/resourcemanager/eventhub/armeventhub/privateendpointconnections_live_test.go new file mode 100644 index 000000000000..0d88b84d568f --- /dev/null +++ b/sdk/resourcemanager/eventhub/armeventhub/privateendpointconnections_live_test.go @@ -0,0 +1,245 @@ +//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. +// Code generated by Microsoft (R) AutoRest Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. + +package armeventhub_test + +import ( + "context" + "fmt" + "testing" + + "github.com/Azure/azure-sdk-for-go/sdk/azcore" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/arm" + "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/resourcemanager/eventhub/armeventhub" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/internal/testutil" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armresources" + "github.com/stretchr/testify/suite" +) + +type PrivateEndpointConnectionsTestSuite struct { + suite.Suite + + ctx context.Context + cred azcore.TokenCredential + options *arm.ClientOptions + namespaceId string + namespaceName string + location string + resourceGroupName string + subscriptionId string +} + +func (testsuite *PrivateEndpointConnectionsTestSuite) SetupSuite() { + testutil.StartRecording(testsuite.T(), "sdk/resourcemanager/eventhub/armeventhub/testdata") + + testsuite.ctx = context.Background() + testsuite.cred, testsuite.options = testutil.GetCredAndClientOptions(testsuite.T()) + testsuite.namespaceName, _ = recording.GenerateAlphaNumericID(testsuite.T(), "namespac", 14, false) + testsuite.location = testutil.GetEnv("LOCATION", "westus") + testsuite.resourceGroupName = testutil.GetEnv("RESOURCE_GROUP_NAME", "scenarioTestTempGroup") + testsuite.subscriptionId = testutil.GetEnv("AZURE_SUBSCRIPTION_ID", "00000000-0000-0000-0000-000000000000") + resourceGroup, _, err := testutil.CreateResourceGroup(testsuite.ctx, testsuite.subscriptionId, testsuite.cred, testsuite.options, testsuite.location) + testsuite.Require().NoError(err) + testsuite.resourceGroupName = *resourceGroup.Name + testsuite.Prepare() +} + +func (testsuite *PrivateEndpointConnectionsTestSuite) TearDownSuite() { + _, err := testutil.DeleteResourceGroup(testsuite.ctx, testsuite.subscriptionId, testsuite.cred, testsuite.options, testsuite.resourceGroupName) + testsuite.Require().NoError(err) + testutil.StopRecording(testsuite.T()) +} + +func TestPrivateEndpointConnectionsTestSuite(t *testing.T) { + suite.Run(t, new(PrivateEndpointConnectionsTestSuite)) +} + +func (testsuite *PrivateEndpointConnectionsTestSuite) Prepare() { + var err error + // From step Namespaces_CreateOrUpdate + fmt.Println("Call operation: Namespaces_CreateOrUpdate") + namespacesClient, err := armeventhub.NewNamespacesClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + namespacesClientCreateOrUpdateResponsePoller, err := namespacesClient.BeginCreateOrUpdate(testsuite.ctx, testsuite.resourceGroupName, testsuite.namespaceName, armeventhub.EHNamespace{ + Location: to.Ptr(testsuite.location), + SKU: &armeventhub.SKU{ + Name: to.Ptr(armeventhub.SKUNamePremium), + Tier: to.Ptr(armeventhub.SKUTierPremium), + }, + }, nil) + testsuite.Require().NoError(err) + var namespacesClientCreateOrUpdateResponse *armeventhub.NamespacesClientCreateOrUpdateResponse + namespacesClientCreateOrUpdateResponse, err = testutil.PollForTest(testsuite.ctx, namespacesClientCreateOrUpdateResponsePoller) + testsuite.Require().NoError(err) + testsuite.namespaceId = *namespacesClientCreateOrUpdateResponse.ID + + // From step Create_PrivateEndpoint + template := map[string]any{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "parameters": map[string]any{ + "location": map[string]any{ + "type": "string", + "defaultValue": testsuite.location, + }, + "namespaceId": map[string]any{ + "type": "string", + "defaultValue": testsuite.namespaceId, + }, + "networkInterfaceName": map[string]any{ + "type": "string", + "defaultValue": "peeventhub-nic", + }, + "privateEndpointName": map[string]any{ + "type": "string", + "defaultValue": "peeventhub", + }, + "virtualNetworksName": map[string]any{ + "type": "string", + "defaultValue": "peeventhubvnet", + }, + }, + "resources": []any{ + map[string]any{ + "name": "[parameters('virtualNetworksName')]", + "type": "Microsoft.Network/virtualNetworks", + "apiVersion": "2020-11-01", + "location": "[parameters('location')]", + "properties": map[string]any{ + "addressSpace": map[string]any{ + "addressPrefixes": []any{ + "10.0.0.0/16", + }, + }, + "enableDdosProtection": false, + "subnets": []any{ + map[string]any{ + "name": "default", + "properties": map[string]any{ + "addressPrefix": "10.0.0.0/24", + "delegations": []any{}, + "privateEndpointNetworkPolicies": "Enabled", + "privateLinkServiceNetworkPolicies": "Enabled", + }, + }, + }, + "virtualNetworkPeerings": []any{}, + }, + }, + map[string]any{ + "name": "[parameters('networkInterfaceName')]", + "type": "Microsoft.Network/networkInterfaces", + "apiVersion": "2020-11-01", + "dependsOn": []any{ + "[resourceId('Microsoft.Network/virtualNetworks', parameters('virtualNetworksName'))]", + }, + "location": "[parameters('location')]", + "properties": map[string]any{ + "dnsSettings": map[string]any{ + "dnsServers": []any{}, + }, + "enableIPForwarding": false, + "ipConfigurations": []any{ + map[string]any{ + "name": "privateEndpointIpConfig", + "properties": map[string]any{ + "primary": true, + "privateIPAddress": "10.0.0.4", + "privateIPAddressVersion": "IPv4", + "privateIPAllocationMethod": "Dynamic", + "subnet": map[string]any{ + "id": "[resourceId('Microsoft.Network/virtualNetworks/subnets', parameters('virtualNetworksName'), 'default')]", + }, + }, + }, + }, + }, + }, + map[string]any{ + "name": "[parameters('privateEndpointName')]", + "type": "Microsoft.Network/privateEndpoints", + "apiVersion": "2020-11-01", + "dependsOn": []any{ + "[resourceId('Microsoft.Network/virtualNetworks', parameters('virtualNetworksName'))]", + }, + "location": "[parameters('location')]", + "properties": map[string]any{ + "customDnsConfigs": []any{}, + "manualPrivateLinkServiceConnections": []any{}, + "privateLinkServiceConnections": []any{ + map[string]any{ + "name": "[parameters('privateEndpointName')]", + "properties": map[string]any{ + "groupIds": []any{ + "namespace", + }, + "privateLinkServiceConnectionState": map[string]any{ + "description": "Auto-Approved", + "actionsRequired": "None", + "status": "Approved", + }, + "privateLinkServiceId": "[parameters('namespaceId')]", + }, + }, + }, + "subnet": map[string]any{ + "id": "[resourceId('Microsoft.Network/virtualNetworks/subnets', parameters('virtualNetworksName'), 'default')]", + }, + }, + }, + }, + "variables": map[string]any{}, + } + deployment := armresources.Deployment{ + Properties: &armresources.DeploymentProperties{ + Template: template, + Mode: to.Ptr(armresources.DeploymentModeIncremental), + }, + } + _, err = testutil.CreateDeployment(testsuite.ctx, testsuite.subscriptionId, testsuite.cred, testsuite.options, testsuite.resourceGroupName, "Create_PrivateEndpoint", &deployment) + testsuite.Require().NoError(err) +} + +// Microsoft.EventHub/namespaces/{namespaceName}/privateEndpointConnections/{privateEndpointConnectionName} +func (testsuite *PrivateEndpointConnectionsTestSuite) TestPrivateEndpointConnections() { + var privateEndpointConnectionName string + var err error + // From step PrivateEndpointConnections_List + fmt.Println("Call operation: PrivateEndpointConnections_List") + privateEndpointConnectionsClient, err := armeventhub.NewPrivateEndpointConnectionsClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + privateEndpointConnectionsClientNewListPager := privateEndpointConnectionsClient.NewListPager(testsuite.resourceGroupName, testsuite.namespaceName, nil) + for privateEndpointConnectionsClientNewListPager.More() { + nextResult, err := privateEndpointConnectionsClientNewListPager.NextPage(testsuite.ctx) + testsuite.Require().NoError(err) + + privateEndpointConnectionName = *nextResult.Value[0].Name + break + } + + // From step PrivateEndpointConnections_Get + fmt.Println("Call operation: PrivateEndpointConnections_Get") + _, err = privateEndpointConnectionsClient.Get(testsuite.ctx, testsuite.resourceGroupName, testsuite.namespaceName, privateEndpointConnectionName, nil) + testsuite.Require().NoError(err) + + // From step PrivateLinkResources_Get + fmt.Println("Call operation: PrivateLinkResources_Get") + privateLinkResourcesClient, err := armeventhub.NewPrivateLinkResourcesClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + _, err = privateLinkResourcesClient.Get(testsuite.ctx, testsuite.resourceGroupName, testsuite.namespaceName, nil) + testsuite.Require().NoError(err) + + // From step PrivateEndpointConnections_Delete + fmt.Println("Call operation: PrivateEndpointConnections_Delete") + privateEndpointConnectionsClientDeleteResponsePoller, err := privateEndpointConnectionsClient.BeginDelete(testsuite.ctx, testsuite.resourceGroupName, testsuite.namespaceName, privateEndpointConnectionName, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, privateEndpointConnectionsClientDeleteResponsePoller) + testsuite.Require().NoError(err) +} diff --git a/sdk/resourcemanager/network/armnetwork/applicationgatewaywafdynamicmanifests_live_test.go b/sdk/resourcemanager/network/armnetwork/applicationgatewaywafdynamicmanifests_live_test.go new file mode 100644 index 000000000000..bff0b0ce73fc --- /dev/null +++ b/sdk/resourcemanager/network/armnetwork/applicationgatewaywafdynamicmanifests_live_test.go @@ -0,0 +1,70 @@ +//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. +// Code generated by Microsoft (R) AutoRest Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. + +package armnetwork_test + +import ( + "context" + "fmt" + "testing" + + "github.com/Azure/azure-sdk-for-go/sdk/azcore" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/arm" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/internal/testutil" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork/v2" + "github.com/stretchr/testify/suite" +) + +type ApplicationGatewayWafDynamicManifestsTestSuite struct { + suite.Suite + + ctx context.Context + cred azcore.TokenCredential + options *arm.ClientOptions + location string + resourceGroupName string + subscriptionId string +} + +func (testsuite *ApplicationGatewayWafDynamicManifestsTestSuite) SetupSuite() { + testutil.StartRecording(testsuite.T(), "sdk/resourcemanager/network/armnetwork/testdata") + + testsuite.ctx = context.Background() + testsuite.cred, testsuite.options = testutil.GetCredAndClientOptions(testsuite.T()) + testsuite.location = testutil.GetEnv("LOCATION", "westus") + testsuite.resourceGroupName = testutil.GetEnv("RESOURCE_GROUP_NAME", "scenarioTestTempGroup") + testsuite.subscriptionId = testutil.GetEnv("AZURE_SUBSCRIPTION_ID", "00000000-0000-0000-0000-000000000000") + resourceGroup, _, err := testutil.CreateResourceGroup(testsuite.ctx, testsuite.subscriptionId, testsuite.cred, testsuite.options, testsuite.location) + testsuite.Require().NoError(err) + testsuite.resourceGroupName = *resourceGroup.Name +} + +func (testsuite *ApplicationGatewayWafDynamicManifestsTestSuite) TearDownSuite() { + _, err := testutil.DeleteResourceGroup(testsuite.ctx, testsuite.subscriptionId, testsuite.cred, testsuite.options, testsuite.resourceGroupName) + testsuite.Require().NoError(err) + testutil.StopRecording(testsuite.T()) +} + +func TestApplicationGatewayWafDynamicManifestsTestSuite(t *testing.T) { + suite.Run(t, new(ApplicationGatewayWafDynamicManifestsTestSuite)) +} + +// Microsoft.Network/locations/{location}/applicationGatewayWafDynamicManifests +func (testsuite *ApplicationGatewayWafDynamicManifestsTestSuite) TestApplicationGatewayWafDynamicManifests() { + var err error + // From step ApplicationGatewayWafDynamicManifests_Get + fmt.Println("Call operation: ApplicationGatewayWafDynamicManifests_Get") + applicationGatewayWafDynamicManifestsClient, err := armnetwork.NewApplicationGatewayWafDynamicManifestsClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + applicationGatewayWafDynamicManifestsClientNewGetPager := applicationGatewayWafDynamicManifestsClient.NewGetPager(testsuite.location, nil) + for applicationGatewayWafDynamicManifestsClientNewGetPager.More() { + _, err := applicationGatewayWafDynamicManifestsClientNewGetPager.NextPage(testsuite.ctx) + testsuite.Require().NoError(err) + break + } +} diff --git a/sdk/resourcemanager/network/armnetwork/applicationsecuritygroup_live_test.go b/sdk/resourcemanager/network/armnetwork/applicationsecuritygroup_live_test.go new file mode 100644 index 000000000000..bc0277742adb --- /dev/null +++ b/sdk/resourcemanager/network/armnetwork/applicationsecuritygroup_live_test.go @@ -0,0 +1,114 @@ +//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. +// Code generated by Microsoft (R) AutoRest Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. + +package armnetwork_test + +import ( + "context" + "fmt" + "testing" + + "github.com/Azure/azure-sdk-for-go/sdk/azcore" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/arm" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/to" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/internal/testutil" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork/v2" + "github.com/stretchr/testify/suite" +) + +type ApplicationSecurityGroupTestSuite struct { + suite.Suite + + ctx context.Context + cred azcore.TokenCredential + options *arm.ClientOptions + applicationSecurityGroupName string + location string + resourceGroupName string + subscriptionId string +} + +func (testsuite *ApplicationSecurityGroupTestSuite) SetupSuite() { + testutil.StartRecording(testsuite.T(), "sdk/resourcemanager/network/armnetwork/testdata") + + testsuite.ctx = context.Background() + testsuite.cred, testsuite.options = testutil.GetCredAndClientOptions(testsuite.T()) + testsuite.applicationSecurityGroupName = testutil.GenerateAlphaNumericID(testsuite.T(), "applicatio", 6) + testsuite.location = testutil.GetEnv("LOCATION", "westus") + testsuite.resourceGroupName = testutil.GetEnv("RESOURCE_GROUP_NAME", "scenarioTestTempGroup") + testsuite.subscriptionId = testutil.GetEnv("AZURE_SUBSCRIPTION_ID", "00000000-0000-0000-0000-000000000000") + resourceGroup, _, err := testutil.CreateResourceGroup(testsuite.ctx, testsuite.subscriptionId, testsuite.cred, testsuite.options, testsuite.location) + testsuite.Require().NoError(err) + testsuite.resourceGroupName = *resourceGroup.Name +} + +func (testsuite *ApplicationSecurityGroupTestSuite) TearDownSuite() { + _, err := testutil.DeleteResourceGroup(testsuite.ctx, testsuite.subscriptionId, testsuite.cred, testsuite.options, testsuite.resourceGroupName) + testsuite.Require().NoError(err) + testutil.StopRecording(testsuite.T()) +} + +func TestApplicationSecurityGroupTestSuite(t *testing.T) { + suite.Run(t, new(ApplicationSecurityGroupTestSuite)) +} + +// Microsoft.Network/applicationSecurityGroups/{applicationSecurityGroupName} +func (testsuite *ApplicationSecurityGroupTestSuite) TestApplicationSecurityGroups() { + var err error + // From step ApplicationSecurityGroups_CreateOrUpdate + fmt.Println("Call operation: ApplicationSecurityGroups_CreateOrUpdate") + applicationSecurityGroupsClient, err := armnetwork.NewApplicationSecurityGroupsClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + applicationSecurityGroupsClientCreateOrUpdateResponsePoller, err := applicationSecurityGroupsClient.BeginCreateOrUpdate(testsuite.ctx, testsuite.resourceGroupName, testsuite.applicationSecurityGroupName, armnetwork.ApplicationSecurityGroup{ + Location: to.Ptr(testsuite.location), + Properties: &armnetwork.ApplicationSecurityGroupPropertiesFormat{}, + }, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, applicationSecurityGroupsClientCreateOrUpdateResponsePoller) + testsuite.Require().NoError(err) + + // From step ApplicationSecurityGroups_ListAll + fmt.Println("Call operation: ApplicationSecurityGroups_ListAll") + applicationSecurityGroupsClientNewListAllPager := applicationSecurityGroupsClient.NewListAllPager(nil) + for applicationSecurityGroupsClientNewListAllPager.More() { + _, err := applicationSecurityGroupsClientNewListAllPager.NextPage(testsuite.ctx) + testsuite.Require().NoError(err) + break + } + + // From step ApplicationSecurityGroups_List + fmt.Println("Call operation: ApplicationSecurityGroups_List") + applicationSecurityGroupsClientNewListPager := applicationSecurityGroupsClient.NewListPager(testsuite.resourceGroupName, nil) + for applicationSecurityGroupsClientNewListPager.More() { + _, err := applicationSecurityGroupsClientNewListPager.NextPage(testsuite.ctx) + testsuite.Require().NoError(err) + break + } + + // From step ApplicationSecurityGroups_Get + fmt.Println("Call operation: ApplicationSecurityGroups_Get") + _, err = applicationSecurityGroupsClient.Get(testsuite.ctx, testsuite.resourceGroupName, testsuite.applicationSecurityGroupName, nil) + testsuite.Require().NoError(err) + + // From step ApplicationSecurityGroups_UpdateTags + fmt.Println("Call operation: ApplicationSecurityGroups_UpdateTags") + _, err = applicationSecurityGroupsClient.UpdateTags(testsuite.ctx, testsuite.resourceGroupName, testsuite.applicationSecurityGroupName, armnetwork.TagsObject{ + Tags: map[string]*string{ + "tag1": to.Ptr("value1"), + "tag2": to.Ptr("value2"), + }, + }, nil) + testsuite.Require().NoError(err) + + // From step ApplicationSecurityGroups_Delete + fmt.Println("Call operation: ApplicationSecurityGroups_Delete") + applicationSecurityGroupsClientDeleteResponsePoller, err := applicationSecurityGroupsClient.BeginDelete(testsuite.ctx, testsuite.resourceGroupName, testsuite.applicationSecurityGroupName, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, applicationSecurityGroupsClientDeleteResponsePoller) + testsuite.Require().NoError(err) +} diff --git a/sdk/resourcemanager/network/armnetwork/assets.json b/sdk/resourcemanager/network/armnetwork/assets.json index 04dbda1a080f..12d5b800368f 100644 --- a/sdk/resourcemanager/network/armnetwork/assets.json +++ b/sdk/resourcemanager/network/armnetwork/assets.json @@ -2,5 +2,5 @@ "AssetsRepo": "Azure/azure-sdk-assets", "AssetsRepoPrefixPath": "go", "TagPrefix": "go/resourcemanager/network/armnetwork", - "Tag": "go/resourcemanager/network/armnetwork_98a17ae925" + "Tag": "go/resourcemanager/network/armnetwork_f214e85fe5" } diff --git a/sdk/resourcemanager/network/armnetwork/availabledelegations_live_test.go b/sdk/resourcemanager/network/armnetwork/availabledelegations_live_test.go new file mode 100644 index 000000000000..543b5129a2e2 --- /dev/null +++ b/sdk/resourcemanager/network/armnetwork/availabledelegations_live_test.go @@ -0,0 +1,81 @@ +//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. +// Code generated by Microsoft (R) AutoRest Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. + +package armnetwork_test + +import ( + "context" + "fmt" + "testing" + + "github.com/Azure/azure-sdk-for-go/sdk/azcore" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/arm" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/internal/testutil" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork/v2" + "github.com/stretchr/testify/suite" +) + +type AvailableDelegationsTestSuite struct { + suite.Suite + + ctx context.Context + cred azcore.TokenCredential + options *arm.ClientOptions + location string + resourceGroupName string + subscriptionId string +} + +func (testsuite *AvailableDelegationsTestSuite) SetupSuite() { + testutil.StartRecording(testsuite.T(), "sdk/resourcemanager/network/armnetwork/testdata") + + testsuite.ctx = context.Background() + testsuite.cred, testsuite.options = testutil.GetCredAndClientOptions(testsuite.T()) + testsuite.location = testutil.GetEnv("LOCATION", "westus") + testsuite.resourceGroupName = testutil.GetEnv("RESOURCE_GROUP_NAME", "scenarioTestTempGroup") + testsuite.subscriptionId = testutil.GetEnv("AZURE_SUBSCRIPTION_ID", "00000000-0000-0000-0000-000000000000") + resourceGroup, _, err := testutil.CreateResourceGroup(testsuite.ctx, testsuite.subscriptionId, testsuite.cred, testsuite.options, testsuite.location) + testsuite.Require().NoError(err) + testsuite.resourceGroupName = *resourceGroup.Name +} + +func (testsuite *AvailableDelegationsTestSuite) TearDownSuite() { + _, err := testutil.DeleteResourceGroup(testsuite.ctx, testsuite.subscriptionId, testsuite.cred, testsuite.options, testsuite.resourceGroupName) + testsuite.Require().NoError(err) + testutil.StopRecording(testsuite.T()) +} + +func TestAvailableDelegationsTestSuite(t *testing.T) { + suite.Run(t, new(AvailableDelegationsTestSuite)) +} + +// Microsoft.Network/locations/{location}/availableDelegations +func (testsuite *AvailableDelegationsTestSuite) TestAvailableDelegations() { + var err error + // From step AvailableDelegations_List + fmt.Println("Call operation: AvailableDelegations_List") + availableDelegationsClient, err := armnetwork.NewAvailableDelegationsClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + availableDelegationsClientNewListPager := availableDelegationsClient.NewListPager(testsuite.location, nil) + for availableDelegationsClientNewListPager.More() { + _, err := availableDelegationsClientNewListPager.NextPage(testsuite.ctx) + testsuite.Require().NoError(err) + break + } + + // From step AvailableResourceGroupDelegations_List + fmt.Println("Call operation: AvailableResourceGroupDelegations_List") + availableResourceGroupDelegationsClient, err := armnetwork.NewAvailableResourceGroupDelegationsClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + availableResourceGroupDelegationsClientNewListPager := availableResourceGroupDelegationsClient.NewListPager(testsuite.location, testsuite.resourceGroupName, nil) + for availableResourceGroupDelegationsClientNewListPager.More() { + _, err := availableResourceGroupDelegationsClientNewListPager.NextPage(testsuite.ctx) + testsuite.Require().NoError(err) + break + } +} diff --git a/sdk/resourcemanager/network/armnetwork/availableservicealiases_live_test.go b/sdk/resourcemanager/network/armnetwork/availableservicealiases_live_test.go new file mode 100644 index 000000000000..c60243efbf90 --- /dev/null +++ b/sdk/resourcemanager/network/armnetwork/availableservicealiases_live_test.go @@ -0,0 +1,79 @@ +//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. +// Code generated by Microsoft (R) AutoRest Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. + +package armnetwork_test + +import ( + "context" + "fmt" + "testing" + + "github.com/Azure/azure-sdk-for-go/sdk/azcore" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/arm" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/internal/testutil" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork/v2" + "github.com/stretchr/testify/suite" +) + +type AvailableServiceAliasesTestSuite struct { + suite.Suite + + ctx context.Context + cred azcore.TokenCredential + options *arm.ClientOptions + location string + resourceGroupName string + subscriptionId string +} + +func (testsuite *AvailableServiceAliasesTestSuite) SetupSuite() { + testutil.StartRecording(testsuite.T(), "sdk/resourcemanager/network/armnetwork/testdata") + + testsuite.ctx = context.Background() + testsuite.cred, testsuite.options = testutil.GetCredAndClientOptions(testsuite.T()) + testsuite.location = testutil.GetEnv("LOCATION", "westus") + testsuite.resourceGroupName = testutil.GetEnv("RESOURCE_GROUP_NAME", "scenarioTestTempGroup") + testsuite.subscriptionId = testutil.GetEnv("AZURE_SUBSCRIPTION_ID", "00000000-0000-0000-0000-000000000000") + resourceGroup, _, err := testutil.CreateResourceGroup(testsuite.ctx, testsuite.subscriptionId, testsuite.cred, testsuite.options, testsuite.location) + testsuite.Require().NoError(err) + testsuite.resourceGroupName = *resourceGroup.Name +} + +func (testsuite *AvailableServiceAliasesTestSuite) TearDownSuite() { + _, err := testutil.DeleteResourceGroup(testsuite.ctx, testsuite.subscriptionId, testsuite.cred, testsuite.options, testsuite.resourceGroupName) + testsuite.Require().NoError(err) + testutil.StopRecording(testsuite.T()) +} + +func TestAvailableServiceAliasesTestSuite(t *testing.T) { + suite.Run(t, new(AvailableServiceAliasesTestSuite)) +} + +// Microsoft.Network/locations/{location}/availableServiceAliases +func (testsuite *AvailableServiceAliasesTestSuite) TestAvailableServiceAliases() { + var err error + // From step AvailableServiceAliases_List + fmt.Println("Call operation: AvailableServiceAliases_List") + availableServiceAliasesClient, err := armnetwork.NewAvailableServiceAliasesClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + availableServiceAliasesClientNewListPager := availableServiceAliasesClient.NewListPager(testsuite.location, nil) + for availableServiceAliasesClientNewListPager.More() { + _, err := availableServiceAliasesClientNewListPager.NextPage(testsuite.ctx) + testsuite.Require().NoError(err) + break + } + + // From step AvailableServiceAliases_ListByResourceGroup + fmt.Println("Call operation: AvailableServiceAliases_ListByResourceGroup") + availableServiceAliasesClientNewListByResourceGroupPager := availableServiceAliasesClient.NewListByResourceGroupPager(testsuite.resourceGroupName, testsuite.location, nil) + for availableServiceAliasesClientNewListByResourceGroupPager.More() { + _, err := availableServiceAliasesClientNewListByResourceGroupPager.NextPage(testsuite.ctx) + testsuite.Require().NoError(err) + break + } +} diff --git a/sdk/resourcemanager/network/armnetwork/azurefirewallfqdntag_live_test.go b/sdk/resourcemanager/network/armnetwork/azurefirewallfqdntag_live_test.go new file mode 100644 index 000000000000..ddda8e626302 --- /dev/null +++ b/sdk/resourcemanager/network/armnetwork/azurefirewallfqdntag_live_test.go @@ -0,0 +1,70 @@ +//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. +// Code generated by Microsoft (R) AutoRest Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. + +package armnetwork_test + +import ( + "context" + "fmt" + "testing" + + "github.com/Azure/azure-sdk-for-go/sdk/azcore" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/arm" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/internal/testutil" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork/v2" + "github.com/stretchr/testify/suite" +) + +type AzureFirewallFqdnTagTestSuite struct { + suite.Suite + + ctx context.Context + cred azcore.TokenCredential + options *arm.ClientOptions + location string + resourceGroupName string + subscriptionId string +} + +func (testsuite *AzureFirewallFqdnTagTestSuite) SetupSuite() { + testutil.StartRecording(testsuite.T(), "sdk/resourcemanager/network/armnetwork/testdata") + + testsuite.ctx = context.Background() + testsuite.cred, testsuite.options = testutil.GetCredAndClientOptions(testsuite.T()) + testsuite.location = testutil.GetEnv("LOCATION", "westus") + testsuite.resourceGroupName = testutil.GetEnv("RESOURCE_GROUP_NAME", "scenarioTestTempGroup") + testsuite.subscriptionId = testutil.GetEnv("AZURE_SUBSCRIPTION_ID", "00000000-0000-0000-0000-000000000000") + resourceGroup, _, err := testutil.CreateResourceGroup(testsuite.ctx, testsuite.subscriptionId, testsuite.cred, testsuite.options, testsuite.location) + testsuite.Require().NoError(err) + testsuite.resourceGroupName = *resourceGroup.Name +} + +func (testsuite *AzureFirewallFqdnTagTestSuite) TearDownSuite() { + _, err := testutil.DeleteResourceGroup(testsuite.ctx, testsuite.subscriptionId, testsuite.cred, testsuite.options, testsuite.resourceGroupName) + testsuite.Require().NoError(err) + testutil.StopRecording(testsuite.T()) +} + +func TestAzureFirewallFqdnTagTestSuite(t *testing.T) { + suite.Run(t, new(AzureFirewallFqdnTagTestSuite)) +} + +// Microsoft.Network/azureFirewallFqdnTags +func (testsuite *AzureFirewallFqdnTagTestSuite) TestAzureFirewallFqdnTags() { + var err error + // From step AzureFirewallFqdnTags_ListAll + fmt.Println("Call operation: AzureFirewallFqdnTags_ListAll") + azureFirewallFqdnTagsClient, err := armnetwork.NewAzureFirewallFqdnTagsClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + azureFirewallFqdnTagsClientNewListAllPager := azureFirewallFqdnTagsClient.NewListAllPager(nil) + for azureFirewallFqdnTagsClientNewListAllPager.More() { + _, err := azureFirewallFqdnTagsClientNewListAllPager.NextPage(testsuite.ctx) + testsuite.Require().NoError(err) + break + } +} diff --git a/sdk/resourcemanager/network/armnetwork/azurewebcategory_live_test.go b/sdk/resourcemanager/network/armnetwork/azurewebcategory_live_test.go new file mode 100644 index 000000000000..7de8e5fb8cb4 --- /dev/null +++ b/sdk/resourcemanager/network/armnetwork/azurewebcategory_live_test.go @@ -0,0 +1,70 @@ +//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. +// Code generated by Microsoft (R) AutoRest Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. + +package armnetwork_test + +import ( + "context" + "fmt" + "testing" + + "github.com/Azure/azure-sdk-for-go/sdk/azcore" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/arm" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/internal/testutil" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork/v2" + "github.com/stretchr/testify/suite" +) + +type AzureWebCategoryTestSuite struct { + suite.Suite + + ctx context.Context + cred azcore.TokenCredential + options *arm.ClientOptions + location string + resourceGroupName string + subscriptionId string +} + +func (testsuite *AzureWebCategoryTestSuite) SetupSuite() { + testutil.StartRecording(testsuite.T(), "sdk/resourcemanager/network/armnetwork/testdata") + + testsuite.ctx = context.Background() + testsuite.cred, testsuite.options = testutil.GetCredAndClientOptions(testsuite.T()) + testsuite.location = testutil.GetEnv("LOCATION", "westus") + testsuite.resourceGroupName = testutil.GetEnv("RESOURCE_GROUP_NAME", "scenarioTestTempGroup") + testsuite.subscriptionId = testutil.GetEnv("AZURE_SUBSCRIPTION_ID", "00000000-0000-0000-0000-000000000000") + resourceGroup, _, err := testutil.CreateResourceGroup(testsuite.ctx, testsuite.subscriptionId, testsuite.cred, testsuite.options, testsuite.location) + testsuite.Require().NoError(err) + testsuite.resourceGroupName = *resourceGroup.Name +} + +func (testsuite *AzureWebCategoryTestSuite) TearDownSuite() { + _, err := testutil.DeleteResourceGroup(testsuite.ctx, testsuite.subscriptionId, testsuite.cred, testsuite.options, testsuite.resourceGroupName) + testsuite.Require().NoError(err) + testutil.StopRecording(testsuite.T()) +} + +func TestAzureWebCategoryTestSuite(t *testing.T) { + suite.Run(t, new(AzureWebCategoryTestSuite)) +} + +// Microsoft.Network/azureWebCategories +func (testsuite *AzureWebCategoryTestSuite) TestWebCategories() { + var err error + // From step WebCategories_ListBySubscription + fmt.Println("Call operation: WebCategories_ListBySubscription") + webCategoriesClient, err := armnetwork.NewWebCategoriesClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + webCategoriesClientNewListBySubscriptionPager := webCategoriesClient.NewListBySubscriptionPager(nil) + for webCategoriesClientNewListBySubscriptionPager.More() { + _, err := webCategoriesClientNewListBySubscriptionPager.NextPage(testsuite.ctx) + testsuite.Require().NoError(err) + break + } +} diff --git a/sdk/resourcemanager/network/armnetwork/bastionhost_live_test.go b/sdk/resourcemanager/network/armnetwork/bastionhost_live_test.go new file mode 100644 index 000000000000..871dee50f565 --- /dev/null +++ b/sdk/resourcemanager/network/armnetwork/bastionhost_live_test.go @@ -0,0 +1,183 @@ +//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. +// Code generated by Microsoft (R) AutoRest Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. + +package armnetwork_test + +import ( + "context" + "fmt" + "testing" + + "github.com/Azure/azure-sdk-for-go/sdk/azcore" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/arm" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/to" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/internal/testutil" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork/v2" + "github.com/stretchr/testify/suite" +) + +type BastionHostTestSuite struct { + suite.Suite + + ctx context.Context + cred azcore.TokenCredential + options *arm.ClientOptions + bastionHostName string + publicIpAddressId string + subnetId string + location string + resourceGroupName string + subscriptionId string +} + +func (testsuite *BastionHostTestSuite) SetupSuite() { + testutil.StartRecording(testsuite.T(), "sdk/resourcemanager/network/armnetwork/testdata") + + testsuite.ctx = context.Background() + testsuite.cred, testsuite.options = testutil.GetCredAndClientOptions(testsuite.T()) + testsuite.bastionHostName = testutil.GenerateAlphaNumericID(testsuite.T(), "bastionhos", 6) + testsuite.location = testutil.GetEnv("LOCATION", "westus") + testsuite.resourceGroupName = testutil.GetEnv("RESOURCE_GROUP_NAME", "scenarioTestTempGroup") + testsuite.subscriptionId = testutil.GetEnv("AZURE_SUBSCRIPTION_ID", "00000000-0000-0000-0000-000000000000") + resourceGroup, _, err := testutil.CreateResourceGroup(testsuite.ctx, testsuite.subscriptionId, testsuite.cred, testsuite.options, testsuite.location) + testsuite.Require().NoError(err) + testsuite.resourceGroupName = *resourceGroup.Name + testsuite.Prepare() +} + +func (testsuite *BastionHostTestSuite) TearDownSuite() { + _, err := testutil.DeleteResourceGroup(testsuite.ctx, testsuite.subscriptionId, testsuite.cred, testsuite.options, testsuite.resourceGroupName) + testsuite.Require().NoError(err) + testutil.StopRecording(testsuite.T()) +} + +func TestBastionHostTestSuite(t *testing.T) { + suite.Run(t, new(BastionHostTestSuite)) +} + +func (testsuite *BastionHostTestSuite) Prepare() { + var err error + // From step VirtualNetworks_CreateOrUpdate + fmt.Println("Call operation: VirtualNetworks_CreateOrUpdate") + virtualNetworksClient, err := armnetwork.NewVirtualNetworksClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + virtualNetworksClientCreateOrUpdateResponsePoller, err := virtualNetworksClient.BeginCreateOrUpdate(testsuite.ctx, testsuite.resourceGroupName, "test-vnet", armnetwork.VirtualNetwork{ + Location: to.Ptr(testsuite.location), + Properties: &armnetwork.VirtualNetworkPropertiesFormat{ + AddressSpace: &armnetwork.AddressSpace{ + AddressPrefixes: []*string{ + to.Ptr("10.0.0.0/16")}, + }, + Subnets: []*armnetwork.Subnet{ + { + Name: to.Ptr("AzureBastionSubnet"), + Properties: &armnetwork.SubnetPropertiesFormat{ + AddressPrefix: to.Ptr("10.0.0.0/24"), + }, + }}, + }, + }, nil) + testsuite.Require().NoError(err) + var virtualNetworksClientCreateOrUpdateResponse *armnetwork.VirtualNetworksClientCreateOrUpdateResponse + virtualNetworksClientCreateOrUpdateResponse, err = testutil.PollForTest(testsuite.ctx, virtualNetworksClientCreateOrUpdateResponsePoller) + testsuite.Require().NoError(err) + testsuite.subnetId = *virtualNetworksClientCreateOrUpdateResponse.Properties.Subnets[0].ID + + // From step PublicIPAddresses_CreateOrUpdate + fmt.Println("Call operation: PublicIPAddresses_CreateOrUpdate") + publicIPAddressesClient, err := armnetwork.NewPublicIPAddressesClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + publicIPAddressesClientCreateOrUpdateResponsePoller, err := publicIPAddressesClient.BeginCreateOrUpdate(testsuite.ctx, testsuite.resourceGroupName, "test-ip", armnetwork.PublicIPAddress{ + Location: to.Ptr(testsuite.location), + Properties: &armnetwork.PublicIPAddressPropertiesFormat{ + IdleTimeoutInMinutes: to.Ptr[int32](10), + PublicIPAddressVersion: to.Ptr(armnetwork.IPVersionIPv4), + PublicIPAllocationMethod: to.Ptr(armnetwork.IPAllocationMethodStatic), + }, + SKU: &armnetwork.PublicIPAddressSKU{ + Name: to.Ptr(armnetwork.PublicIPAddressSKUNameStandard), + Tier: to.Ptr(armnetwork.PublicIPAddressSKUTierRegional), + }, + }, nil) + testsuite.Require().NoError(err) + var publicIPAddressesClientCreateOrUpdateResponse *armnetwork.PublicIPAddressesClientCreateOrUpdateResponse + publicIPAddressesClientCreateOrUpdateResponse, err = testutil.PollForTest(testsuite.ctx, publicIPAddressesClientCreateOrUpdateResponsePoller) + testsuite.Require().NoError(err) + testsuite.publicIpAddressId = *publicIPAddressesClientCreateOrUpdateResponse.ID +} + +// Microsoft.Network/bastionHosts/{bastionHostName} +func (testsuite *BastionHostTestSuite) TestBastionHosts() { + var err error + // From step BastionHosts_CreateOrUpdate + fmt.Println("Call operation: BastionHosts_CreateOrUpdate") + bastionHostsClient, err := armnetwork.NewBastionHostsClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + bastionHostsClientCreateOrUpdateResponsePoller, err := bastionHostsClient.BeginCreateOrUpdate(testsuite.ctx, testsuite.resourceGroupName, testsuite.bastionHostName, armnetwork.BastionHost{ + Location: to.Ptr(testsuite.location), + Properties: &armnetwork.BastionHostPropertiesFormat{ + IPConfigurations: []*armnetwork.BastionHostIPConfiguration{ + { + Name: to.Ptr("bastionHostIpConfiguration"), + Properties: &armnetwork.BastionHostIPConfigurationPropertiesFormat{ + PublicIPAddress: &armnetwork.SubResource{ + ID: to.Ptr(testsuite.publicIpAddressId), + }, + Subnet: &armnetwork.SubResource{ + ID: to.Ptr(testsuite.subnetId), + }, + }, + }}, + }, + }, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, bastionHostsClientCreateOrUpdateResponsePoller) + testsuite.Require().NoError(err) + + // From step BastionHosts_List + fmt.Println("Call operation: BastionHosts_List") + bastionHostsClientNewListPager := bastionHostsClient.NewListPager(nil) + for bastionHostsClientNewListPager.More() { + _, err := bastionHostsClientNewListPager.NextPage(testsuite.ctx) + testsuite.Require().NoError(err) + break + } + + // From step BastionHosts_ListByResourceGroup + fmt.Println("Call operation: BastionHosts_ListByResourceGroup") + bastionHostsClientNewListByResourceGroupPager := bastionHostsClient.NewListByResourceGroupPager(testsuite.resourceGroupName, nil) + for bastionHostsClientNewListByResourceGroupPager.More() { + _, err := bastionHostsClientNewListByResourceGroupPager.NextPage(testsuite.ctx) + testsuite.Require().NoError(err) + break + } + + // From step BastionHosts_Get + fmt.Println("Call operation: BastionHosts_Get") + _, err = bastionHostsClient.Get(testsuite.ctx, testsuite.resourceGroupName, testsuite.bastionHostName, nil) + testsuite.Require().NoError(err) + + // From step BastionHosts_UpdateTags + fmt.Println("Call operation: BastionHosts_UpdateTags") + bastionHostsClientUpdateTagsResponsePoller, err := bastionHostsClient.BeginUpdateTags(testsuite.ctx, testsuite.resourceGroupName, testsuite.bastionHostName, armnetwork.TagsObject{ + Tags: map[string]*string{ + "tag1": to.Ptr("value1"), + "tag2": to.Ptr("value2"), + }, + }, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, bastionHostsClientUpdateTagsResponsePoller) + testsuite.Require().NoError(err) + + // From step BastionHosts_Delete + fmt.Println("Call operation: BastionHosts_Delete") + bastionHostsClientDeleteResponsePoller, err := bastionHostsClient.BeginDelete(testsuite.ctx, testsuite.resourceGroupName, testsuite.bastionHostName, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, bastionHostsClientDeleteResponsePoller) + testsuite.Require().NoError(err) +} diff --git a/sdk/resourcemanager/network/armnetwork/checkdnsavailability_live_test.go b/sdk/resourcemanager/network/armnetwork/checkdnsavailability_live_test.go new file mode 100644 index 000000000000..ecb3f671014b --- /dev/null +++ b/sdk/resourcemanager/network/armnetwork/checkdnsavailability_live_test.go @@ -0,0 +1,66 @@ +//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. +// Code generated by Microsoft (R) AutoRest Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. + +package armnetwork_test + +import ( + "context" + "fmt" + "testing" + + "github.com/Azure/azure-sdk-for-go/sdk/azcore" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/arm" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/internal/testutil" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork/v2" + "github.com/stretchr/testify/suite" +) + +type CheckDnsAvailabilityTestSuite struct { + suite.Suite + + ctx context.Context + cred azcore.TokenCredential + options *arm.ClientOptions + location string + resourceGroupName string + subscriptionId string +} + +func (testsuite *CheckDnsAvailabilityTestSuite) SetupSuite() { + testutil.StartRecording(testsuite.T(), "sdk/resourcemanager/network/armnetwork/testdata") + + testsuite.ctx = context.Background() + testsuite.cred, testsuite.options = testutil.GetCredAndClientOptions(testsuite.T()) + testsuite.location = testutil.GetEnv("LOCATION", "westus") + testsuite.resourceGroupName = testutil.GetEnv("RESOURCE_GROUP_NAME", "scenarioTestTempGroup") + testsuite.subscriptionId = testutil.GetEnv("AZURE_SUBSCRIPTION_ID", "00000000-0000-0000-0000-000000000000") + resourceGroup, _, err := testutil.CreateResourceGroup(testsuite.ctx, testsuite.subscriptionId, testsuite.cred, testsuite.options, testsuite.location) + testsuite.Require().NoError(err) + testsuite.resourceGroupName = *resourceGroup.Name +} + +func (testsuite *CheckDnsAvailabilityTestSuite) TearDownSuite() { + _, err := testutil.DeleteResourceGroup(testsuite.ctx, testsuite.subscriptionId, testsuite.cred, testsuite.options, testsuite.resourceGroupName) + testsuite.Require().NoError(err) + testutil.StopRecording(testsuite.T()) +} + +func TestCheckDnsAvailabilityTestSuite(t *testing.T) { + suite.Run(t, new(CheckDnsAvailabilityTestSuite)) +} + +// Microsoft.Network/locations/{location}/CheckDnsNameAvailability +func (testsuite *CheckDnsAvailabilityTestSuite) TestCheckDnsNameAvailability() { + var err error + // From step CheckDnsNameAvailability + fmt.Println("Call operation: NetworkManagementClient_CheckDNSNameAvailability") + managementClient, err := armnetwork.NewManagementClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + _, err = managementClient.CheckDNSNameAvailability(testsuite.ctx, testsuite.location, "testdns", nil) + testsuite.Require().NoError(err) +} diff --git a/sdk/resourcemanager/network/armnetwork/customipprefix_live_test.go b/sdk/resourcemanager/network/armnetwork/customipprefix_live_test.go new file mode 100644 index 000000000000..4471382ba422 --- /dev/null +++ b/sdk/resourcemanager/network/armnetwork/customipprefix_live_test.go @@ -0,0 +1,109 @@ +//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. +// Code generated by Microsoft (R) AutoRest Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. + +package armnetwork_test + +import ( + "context" + "fmt" + "testing" + + "github.com/Azure/azure-sdk-for-go/sdk/azcore" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/arm" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/to" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/internal/testutil" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork/v2" + "github.com/stretchr/testify/suite" +) + +type CustomIpPrefixTestSuite struct { + suite.Suite + + ctx context.Context + cred azcore.TokenCredential + options *arm.ClientOptions + customIpPrefixName string + location string + resourceGroupName string + subscriptionId string +} + +func (testsuite *CustomIpPrefixTestSuite) SetupSuite() { + testutil.StartRecording(testsuite.T(), "sdk/resourcemanager/network/armnetwork/testdata") + + testsuite.ctx = context.Background() + testsuite.cred, testsuite.options = testutil.GetCredAndClientOptions(testsuite.T()) + testsuite.customIpPrefixName = testutil.GenerateAlphaNumericID(testsuite.T(), "customippr", 6) + testsuite.location = testutil.GetEnv("LOCATION", "westus") + testsuite.resourceGroupName = testutil.GetEnv("RESOURCE_GROUP_NAME", "scenarioTestTempGroup") + testsuite.subscriptionId = testutil.GetEnv("AZURE_SUBSCRIPTION_ID", "00000000-0000-0000-0000-000000000000") + resourceGroup, _, err := testutil.CreateResourceGroup(testsuite.ctx, testsuite.subscriptionId, testsuite.cred, testsuite.options, testsuite.location) + testsuite.Require().NoError(err) + testsuite.resourceGroupName = *resourceGroup.Name +} + +func (testsuite *CustomIpPrefixTestSuite) TearDownSuite() { + _, err := testutil.DeleteResourceGroup(testsuite.ctx, testsuite.subscriptionId, testsuite.cred, testsuite.options, testsuite.resourceGroupName) + testsuite.Require().NoError(err) + testutil.StopRecording(testsuite.T()) +} + +func TestCustomIpPrefixTestSuite(t *testing.T) { + suite.Run(t, new(CustomIpPrefixTestSuite)) +} + +// Microsoft.Network/customIpPrefixes/{customIpPrefixName} +func (testsuite *CustomIpPrefixTestSuite) TestCustomIpPrefixes() { + var err error + // From step CustomIPPrefixes_CreateOrUpdate + fmt.Println("Call operation: CustomIPPrefixes_CreateOrUpdate") + customIPPrefixesClient, err := armnetwork.NewCustomIPPrefixesClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + customIPPrefixesClientCreateOrUpdateResponsePoller, err := customIPPrefixesClient.BeginCreateOrUpdate(testsuite.ctx, testsuite.resourceGroupName, testsuite.customIpPrefixName, armnetwork.CustomIPPrefix{ + Location: to.Ptr(testsuite.location), + Properties: &armnetwork.CustomIPPrefixPropertiesFormat{ + Cidr: to.Ptr("0.0.0.0/24"), + }, + }, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, customIPPrefixesClientCreateOrUpdateResponsePoller) + testsuite.Require().NoError(err) + + // From step CustomIPPrefixes_ListAll + fmt.Println("Call operation: CustomIPPrefixes_ListAll") + customIPPrefixesClientNewListAllPager := customIPPrefixesClient.NewListAllPager(nil) + for customIPPrefixesClientNewListAllPager.More() { + _, err := customIPPrefixesClientNewListAllPager.NextPage(testsuite.ctx) + testsuite.Require().NoError(err) + break + } + + // From step CustomIPPrefixes_List + fmt.Println("Call operation: CustomIPPrefixes_List") + customIPPrefixesClientNewListPager := customIPPrefixesClient.NewListPager(testsuite.resourceGroupName, nil) + for customIPPrefixesClientNewListPager.More() { + _, err := customIPPrefixesClientNewListPager.NextPage(testsuite.ctx) + testsuite.Require().NoError(err) + break + } + + // From step CustomIPPrefixes_Get + fmt.Println("Call operation: CustomIPPrefixes_Get") + _, err = customIPPrefixesClient.Get(testsuite.ctx, testsuite.resourceGroupName, testsuite.customIpPrefixName, &armnetwork.CustomIPPrefixesClientGetOptions{Expand: nil}) + testsuite.Require().NoError(err) + + // From step CustomIPPrefixes_UpdateTags + fmt.Println("Call operation: CustomIPPrefixes_UpdateTags") + _, err = customIPPrefixesClient.UpdateTags(testsuite.ctx, testsuite.resourceGroupName, testsuite.customIpPrefixName, armnetwork.TagsObject{ + Tags: map[string]*string{ + "tag1": to.Ptr("value1"), + "tag2": to.Ptr("value2"), + }, + }, nil) + testsuite.Require().NoError(err) +} diff --git a/sdk/resourcemanager/network/armnetwork/ddosprotectionplan_live_test.go b/sdk/resourcemanager/network/armnetwork/ddosprotectionplan_live_test.go new file mode 100644 index 000000000000..03e8f5fe50f7 --- /dev/null +++ b/sdk/resourcemanager/network/armnetwork/ddosprotectionplan_live_test.go @@ -0,0 +1,114 @@ +//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. +// Code generated by Microsoft (R) AutoRest Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. + +package armnetwork_test + +import ( + "context" + "fmt" + "testing" + + "github.com/Azure/azure-sdk-for-go/sdk/azcore" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/arm" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/to" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/internal/testutil" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork/v2" + "github.com/stretchr/testify/suite" +) + +type DdosProtectionPlanTestSuite struct { + suite.Suite + + ctx context.Context + cred azcore.TokenCredential + options *arm.ClientOptions + ddosProtectionPlanName string + location string + resourceGroupName string + subscriptionId string +} + +func (testsuite *DdosProtectionPlanTestSuite) SetupSuite() { + testutil.StartRecording(testsuite.T(), "sdk/resourcemanager/network/armnetwork/testdata") + + testsuite.ctx = context.Background() + testsuite.cred, testsuite.options = testutil.GetCredAndClientOptions(testsuite.T()) + testsuite.ddosProtectionPlanName = testutil.GenerateAlphaNumericID(testsuite.T(), "ddosprotec", 6) + testsuite.location = testutil.GetEnv("LOCATION", "westus") + testsuite.resourceGroupName = testutil.GetEnv("RESOURCE_GROUP_NAME", "scenarioTestTempGroup") + testsuite.subscriptionId = testutil.GetEnv("AZURE_SUBSCRIPTION_ID", "00000000-0000-0000-0000-000000000000") + resourceGroup, _, err := testutil.CreateResourceGroup(testsuite.ctx, testsuite.subscriptionId, testsuite.cred, testsuite.options, testsuite.location) + testsuite.Require().NoError(err) + testsuite.resourceGroupName = *resourceGroup.Name +} + +func (testsuite *DdosProtectionPlanTestSuite) TearDownSuite() { + _, err := testutil.DeleteResourceGroup(testsuite.ctx, testsuite.subscriptionId, testsuite.cred, testsuite.options, testsuite.resourceGroupName) + testsuite.Require().NoError(err) + testutil.StopRecording(testsuite.T()) +} + +func TestDdosProtectionPlanTestSuite(t *testing.T) { + suite.Run(t, new(DdosProtectionPlanTestSuite)) +} + +// Microsoft.Network/ddosProtectionPlans/{ddosProtectionPlanName} +func (testsuite *DdosProtectionPlanTestSuite) TestDdosProtectionPlans() { + var err error + // From step DdosProtectionPlans_CreateOrUpdate + fmt.Println("Call operation: DdosProtectionPlans_CreateOrUpdate") + ddosProtectionPlansClient, err := armnetwork.NewDdosProtectionPlansClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + ddosProtectionPlansClientCreateOrUpdateResponsePoller, err := ddosProtectionPlansClient.BeginCreateOrUpdate(testsuite.ctx, testsuite.resourceGroupName, testsuite.ddosProtectionPlanName, armnetwork.DdosProtectionPlan{ + Location: to.Ptr(testsuite.location), + Properties: &armnetwork.DdosProtectionPlanPropertiesFormat{}, + }, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, ddosProtectionPlansClientCreateOrUpdateResponsePoller) + testsuite.Require().NoError(err) + + // From step DdosProtectionPlans_List + fmt.Println("Call operation: DdosProtectionPlans_List") + ddosProtectionPlansClientNewListPager := ddosProtectionPlansClient.NewListPager(nil) + for ddosProtectionPlansClientNewListPager.More() { + _, err := ddosProtectionPlansClientNewListPager.NextPage(testsuite.ctx) + testsuite.Require().NoError(err) + break + } + + // From step DdosProtectionPlans_ListByResourceGroup + fmt.Println("Call operation: DdosProtectionPlans_ListByResourceGroup") + ddosProtectionPlansClientNewListByResourceGroupPager := ddosProtectionPlansClient.NewListByResourceGroupPager(testsuite.resourceGroupName, nil) + for ddosProtectionPlansClientNewListByResourceGroupPager.More() { + _, err := ddosProtectionPlansClientNewListByResourceGroupPager.NextPage(testsuite.ctx) + testsuite.Require().NoError(err) + break + } + + // From step DdosProtectionPlans_Get + fmt.Println("Call operation: DdosProtectionPlans_Get") + _, err = ddosProtectionPlansClient.Get(testsuite.ctx, testsuite.resourceGroupName, testsuite.ddosProtectionPlanName, nil) + testsuite.Require().NoError(err) + + // From step DdosProtectionPlans_UpdateTags + fmt.Println("Call operation: DdosProtectionPlans_UpdateTags") + _, err = ddosProtectionPlansClient.UpdateTags(testsuite.ctx, testsuite.resourceGroupName, testsuite.ddosProtectionPlanName, armnetwork.TagsObject{ + Tags: map[string]*string{ + "tag1": to.Ptr("value1"), + "tag2": to.Ptr("value2"), + }, + }, nil) + testsuite.Require().NoError(err) + + // From step DdosProtectionPlans_Delete + fmt.Println("Call operation: DdosProtectionPlans_Delete") + ddosProtectionPlansClientDeleteResponsePoller, err := ddosProtectionPlansClient.BeginDelete(testsuite.ctx, testsuite.resourceGroupName, testsuite.ddosProtectionPlanName, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, ddosProtectionPlansClientDeleteResponsePoller) + testsuite.Require().NoError(err) +} diff --git a/sdk/resourcemanager/network/armnetwork/endpointservice_live_test.go b/sdk/resourcemanager/network/armnetwork/endpointservice_live_test.go new file mode 100644 index 000000000000..a59f57456946 --- /dev/null +++ b/sdk/resourcemanager/network/armnetwork/endpointservice_live_test.go @@ -0,0 +1,70 @@ +//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. +// Code generated by Microsoft (R) AutoRest Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. + +package armnetwork_test + +import ( + "context" + "fmt" + "testing" + + "github.com/Azure/azure-sdk-for-go/sdk/azcore" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/arm" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/internal/testutil" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork/v2" + "github.com/stretchr/testify/suite" +) + +type EndpointServiceTestSuite struct { + suite.Suite + + ctx context.Context + cred azcore.TokenCredential + options *arm.ClientOptions + location string + resourceGroupName string + subscriptionId string +} + +func (testsuite *EndpointServiceTestSuite) SetupSuite() { + testutil.StartRecording(testsuite.T(), "sdk/resourcemanager/network/armnetwork/testdata") + + testsuite.ctx = context.Background() + testsuite.cred, testsuite.options = testutil.GetCredAndClientOptions(testsuite.T()) + testsuite.location = testutil.GetEnv("LOCATION", "westus") + testsuite.resourceGroupName = testutil.GetEnv("RESOURCE_GROUP_NAME", "scenarioTestTempGroup") + testsuite.subscriptionId = testutil.GetEnv("AZURE_SUBSCRIPTION_ID", "00000000-0000-0000-0000-000000000000") + resourceGroup, _, err := testutil.CreateResourceGroup(testsuite.ctx, testsuite.subscriptionId, testsuite.cred, testsuite.options, testsuite.location) + testsuite.Require().NoError(err) + testsuite.resourceGroupName = *resourceGroup.Name +} + +func (testsuite *EndpointServiceTestSuite) TearDownSuite() { + _, err := testutil.DeleteResourceGroup(testsuite.ctx, testsuite.subscriptionId, testsuite.cred, testsuite.options, testsuite.resourceGroupName) + testsuite.Require().NoError(err) + testutil.StopRecording(testsuite.T()) +} + +func TestEndpointServiceTestSuite(t *testing.T) { + suite.Run(t, new(EndpointServiceTestSuite)) +} + +// Microsoft.Network/locations/{location}/virtualNetworkAvailableEndpointServices +func (testsuite *EndpointServiceTestSuite) TestAvailableEndpointServices() { + var err error + // From step AvailableEndpointServices_List + fmt.Println("Call operation: AvailableEndpointServices_List") + availableEndpointServicesClient, err := armnetwork.NewAvailableEndpointServicesClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + availableEndpointServicesClientNewListPager := availableEndpointServicesClient.NewListPager(testsuite.location, nil) + for availableEndpointServicesClientNewListPager.More() { + _, err := availableEndpointServicesClientNewListPager.NextPage(testsuite.ctx) + testsuite.Require().NoError(err) + break + } +} diff --git a/sdk/resourcemanager/network/armnetwork/expressroutecircuit_live_test.go b/sdk/resourcemanager/network/armnetwork/expressroutecircuit_live_test.go new file mode 100644 index 000000000000..f9862165100c --- /dev/null +++ b/sdk/resourcemanager/network/armnetwork/expressroutecircuit_live_test.go @@ -0,0 +1,251 @@ +//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. +// Code generated by Microsoft (R) AutoRest Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. + +package armnetwork_test + +import ( + "context" + "fmt" + "testing" + + "github.com/Azure/azure-sdk-for-go/sdk/azcore" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/arm" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/to" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/internal/testutil" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork/v2" + "github.com/stretchr/testify/suite" +) + +type ExpressRouteCircuitTestSuite struct { + suite.Suite + + ctx context.Context + cred azcore.TokenCredential + options *arm.ClientOptions + circuitName string + connectionName string + peeringName string + location string + resourceGroupName string + subscriptionId string +} + +func (testsuite *ExpressRouteCircuitTestSuite) SetupSuite() { + testutil.StartRecording(testsuite.T(), "sdk/resourcemanager/network/armnetwork/testdata") + + testsuite.ctx = context.Background() + testsuite.cred, testsuite.options = testutil.GetCredAndClientOptions(testsuite.T()) + testsuite.circuitName = testutil.GenerateAlphaNumericID(testsuite.T(), "circuitnam", 6) + testsuite.connectionName = testutil.GenerateAlphaNumericID(testsuite.T(), "connerc", 6) + testsuite.peeringName = "AzurePrivatePeering" + testsuite.location = testutil.GetEnv("LOCATION", "westus") + testsuite.resourceGroupName = testutil.GetEnv("RESOURCE_GROUP_NAME", "scenarioTestTempGroup") + testsuite.subscriptionId = testutil.GetEnv("AZURE_SUBSCRIPTION_ID", "00000000-0000-0000-0000-000000000000") + resourceGroup, _, err := testutil.CreateResourceGroup(testsuite.ctx, testsuite.subscriptionId, testsuite.cred, testsuite.options, testsuite.location) + testsuite.Require().NoError(err) + testsuite.resourceGroupName = *resourceGroup.Name + testsuite.Prepare() +} + +func (testsuite *ExpressRouteCircuitTestSuite) TearDownSuite() { + testsuite.Cleanup() + _, err := testutil.DeleteResourceGroup(testsuite.ctx, testsuite.subscriptionId, testsuite.cred, testsuite.options, testsuite.resourceGroupName) + testsuite.Require().NoError(err) + testutil.StopRecording(testsuite.T()) +} + +func TestExpressRouteCircuitTestSuite(t *testing.T) { + suite.Run(t, new(ExpressRouteCircuitTestSuite)) +} + +func (testsuite *ExpressRouteCircuitTestSuite) Prepare() { + var err error + // From step ExpressRouteCircuits_CreateOrUpdate + fmt.Println("Call operation: ExpressRouteCircuits_CreateOrUpdate") + expressRouteCircuitsClient, err := armnetwork.NewExpressRouteCircuitsClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + expressRouteCircuitsClientCreateOrUpdateResponsePoller, err := expressRouteCircuitsClient.BeginCreateOrUpdate(testsuite.ctx, testsuite.resourceGroupName, testsuite.circuitName, armnetwork.ExpressRouteCircuit{ + Location: to.Ptr(testsuite.location), + Properties: &armnetwork.ExpressRouteCircuitPropertiesFormat{ + AllowClassicOperations: to.Ptr(false), + Authorizations: []*armnetwork.ExpressRouteCircuitAuthorization{}, + Peerings: []*armnetwork.ExpressRouteCircuitPeering{}, + ServiceProviderProperties: &armnetwork.ExpressRouteCircuitServiceProviderProperties{ + BandwidthInMbps: to.Ptr[int32](200), + PeeringLocation: to.Ptr("Silicon Valley"), + ServiceProviderName: to.Ptr("Equinix"), + }, + }, + SKU: &armnetwork.ExpressRouteCircuitSKU{ + Name: to.Ptr("Standard_MeteredData"), + Family: to.Ptr(armnetwork.ExpressRouteCircuitSKUFamilyMeteredData), + Tier: to.Ptr(armnetwork.ExpressRouteCircuitSKUTierStandard), + }, + }, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, expressRouteCircuitsClientCreateOrUpdateResponsePoller) + testsuite.Require().NoError(err) + + // From step ExpressRouteCircuitPeerings_CreateOrUpdate + fmt.Println("Call operation: ExpressRouteCircuitPeerings_CreateOrUpdate") + expressRouteCircuitPeeringsClient, err := armnetwork.NewExpressRouteCircuitPeeringsClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + expressRouteCircuitPeeringsClientCreateOrUpdateResponsePoller, err := expressRouteCircuitPeeringsClient.BeginCreateOrUpdate(testsuite.ctx, testsuite.resourceGroupName, testsuite.circuitName, testsuite.peeringName, armnetwork.ExpressRouteCircuitPeering{ + Properties: &armnetwork.ExpressRouteCircuitPeeringPropertiesFormat{ + PeerASN: to.Ptr[int64](200), + PrimaryPeerAddressPrefix: to.Ptr("192.168.16.252/30"), + SecondaryPeerAddressPrefix: to.Ptr("192.168.18.252/30"), + VlanID: to.Ptr[int32](200), + }, + }, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, expressRouteCircuitPeeringsClientCreateOrUpdateResponsePoller) + testsuite.Require().NoError(err) +} + +// Microsoft.Network/expressRouteCircuits/{circuitName} +func (testsuite *ExpressRouteCircuitTestSuite) TestExpressRouteCircuits() { + var err error + // From step ExpressRouteCircuits_ListAll + fmt.Println("Call operation: ExpressRouteCircuits_ListAll") + expressRouteCircuitsClient, err := armnetwork.NewExpressRouteCircuitsClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + expressRouteCircuitsClientNewListAllPager := expressRouteCircuitsClient.NewListAllPager(nil) + for expressRouteCircuitsClientNewListAllPager.More() { + _, err := expressRouteCircuitsClientNewListAllPager.NextPage(testsuite.ctx) + testsuite.Require().NoError(err) + break + } + + // From step ExpressRouteCircuits_List + fmt.Println("Call operation: ExpressRouteCircuits_List") + expressRouteCircuitsClientNewListPager := expressRouteCircuitsClient.NewListPager(testsuite.resourceGroupName, nil) + for expressRouteCircuitsClientNewListPager.More() { + _, err := expressRouteCircuitsClientNewListPager.NextPage(testsuite.ctx) + testsuite.Require().NoError(err) + break + } + + // From step ExpressRouteCircuits_Get + fmt.Println("Call operation: ExpressRouteCircuits_Get") + _, err = expressRouteCircuitsClient.Get(testsuite.ctx, testsuite.resourceGroupName, testsuite.circuitName, nil) + testsuite.Require().NoError(err) + + // From step ExpressRouteCircuits_GetStats + fmt.Println("Call operation: ExpressRouteCircuits_GetStats") + _, err = expressRouteCircuitsClient.GetStats(testsuite.ctx, testsuite.resourceGroupName, testsuite.circuitName, nil) + testsuite.Require().NoError(err) + + // From step ExpressRouteCircuits_UpdateTags + fmt.Println("Call operation: ExpressRouteCircuits_UpdateTags") + _, err = expressRouteCircuitsClient.UpdateTags(testsuite.ctx, testsuite.resourceGroupName, testsuite.circuitName, armnetwork.TagsObject{ + Tags: map[string]*string{ + "tag1": to.Ptr("value1"), + "tag2": to.Ptr("value2"), + }, + }, nil) + testsuite.Require().NoError(err) + + // From step ExpressRouteCircuits_GetPeeringStats + fmt.Println("Call operation: ExpressRouteCircuits_GetPeeringStats") + _, err = expressRouteCircuitsClient.GetPeeringStats(testsuite.ctx, testsuite.resourceGroupName, testsuite.circuitName, testsuite.peeringName, nil) + testsuite.Require().NoError(err) +} + +// Microsoft.Network/expressRouteCircuits/{circuitName}/peerings/{peeringName} +func (testsuite *ExpressRouteCircuitTestSuite) TestExpressRouteCircuitPeerings() { + var err error + // From step ExpressRouteCircuitPeerings_List + fmt.Println("Call operation: ExpressRouteCircuitPeerings_List") + expressRouteCircuitPeeringsClient, err := armnetwork.NewExpressRouteCircuitPeeringsClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + expressRouteCircuitPeeringsClientNewListPager := expressRouteCircuitPeeringsClient.NewListPager(testsuite.resourceGroupName, testsuite.circuitName, nil) + for expressRouteCircuitPeeringsClientNewListPager.More() { + _, err := expressRouteCircuitPeeringsClientNewListPager.NextPage(testsuite.ctx) + testsuite.Require().NoError(err) + break + } + + // From step ExpressRouteCircuitPeerings_Get + fmt.Println("Call operation: ExpressRouteCircuitPeerings_Get") + _, err = expressRouteCircuitPeeringsClient.Get(testsuite.ctx, testsuite.resourceGroupName, testsuite.circuitName, testsuite.peeringName, nil) + testsuite.Require().NoError(err) +} + +// Microsoft.Network/expressRouteCircuits/{circuitName}/authorizations/{authorizationName} +func (testsuite *ExpressRouteCircuitTestSuite) TestExpressRouteCircuitAuthorizations() { + authorizationName := "ercauthorization" + var err error + // From step ExpressRouteCircuitAuthorizations_CreateOrUpdate + fmt.Println("Call operation: ExpressRouteCircuitAuthorizations_CreateOrUpdate") + expressRouteCircuitAuthorizationsClient, err := armnetwork.NewExpressRouteCircuitAuthorizationsClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + expressRouteCircuitAuthorizationsClientCreateOrUpdateResponsePoller, err := expressRouteCircuitAuthorizationsClient.BeginCreateOrUpdate(testsuite.ctx, testsuite.resourceGroupName, testsuite.circuitName, authorizationName, armnetwork.ExpressRouteCircuitAuthorization{ + Properties: &armnetwork.AuthorizationPropertiesFormat{}, + }, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, expressRouteCircuitAuthorizationsClientCreateOrUpdateResponsePoller) + testsuite.Require().NoError(err) + + // From step ExpressRouteCircuitAuthorizations_List + fmt.Println("Call operation: ExpressRouteCircuitAuthorizations_List") + expressRouteCircuitAuthorizationsClientNewListPager := expressRouteCircuitAuthorizationsClient.NewListPager(testsuite.resourceGroupName, testsuite.circuitName, nil) + for expressRouteCircuitAuthorizationsClientNewListPager.More() { + _, err := expressRouteCircuitAuthorizationsClientNewListPager.NextPage(testsuite.ctx) + testsuite.Require().NoError(err) + break + } + + // From step ExpressRouteCircuitAuthorizations_Get + fmt.Println("Call operation: ExpressRouteCircuitAuthorizations_Get") + _, err = expressRouteCircuitAuthorizationsClient.Get(testsuite.ctx, testsuite.resourceGroupName, testsuite.circuitName, authorizationName, nil) + testsuite.Require().NoError(err) + + // From step ExpressRouteCircuitAuthorizations_Delete + fmt.Println("Call operation: ExpressRouteCircuitAuthorizations_Delete") + expressRouteCircuitAuthorizationsClientDeleteResponsePoller, err := expressRouteCircuitAuthorizationsClient.BeginDelete(testsuite.ctx, testsuite.resourceGroupName, testsuite.circuitName, authorizationName, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, expressRouteCircuitAuthorizationsClientDeleteResponsePoller) + testsuite.Require().NoError(err) +} + +// Microsoft.Network/expressRouteServiceProviders +func (testsuite *ExpressRouteCircuitTestSuite) TestExpressRouteServiceProviders() { + var err error + // From step ExpressRouteServiceProviders_List + fmt.Println("Call operation: ExpressRouteServiceProviders_List") + expressRouteServiceProvidersClient, err := armnetwork.NewExpressRouteServiceProvidersClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + expressRouteServiceProvidersClientNewListPager := expressRouteServiceProvidersClient.NewListPager(nil) + for expressRouteServiceProvidersClientNewListPager.More() { + _, err := expressRouteServiceProvidersClientNewListPager.NextPage(testsuite.ctx) + testsuite.Require().NoError(err) + break + } +} + +func (testsuite *ExpressRouteCircuitTestSuite) Cleanup() { + var err error + // From step ExpressRouteCircuitPeerings_Delete + fmt.Println("Call operation: ExpressRouteCircuitPeerings_Delete") + expressRouteCircuitPeeringsClient, err := armnetwork.NewExpressRouteCircuitPeeringsClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + expressRouteCircuitPeeringsClientDeleteResponsePoller, err := expressRouteCircuitPeeringsClient.BeginDelete(testsuite.ctx, testsuite.resourceGroupName, testsuite.circuitName, testsuite.peeringName, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, expressRouteCircuitPeeringsClientDeleteResponsePoller) + testsuite.Require().NoError(err) + + // From step ExpressRouteCircuits_Delete + fmt.Println("Call operation: ExpressRouteCircuits_Delete") + expressRouteCircuitsClient, err := armnetwork.NewExpressRouteCircuitsClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + expressRouteCircuitsClientDeleteResponsePoller, err := expressRouteCircuitsClient.BeginDelete(testsuite.ctx, testsuite.resourceGroupName, testsuite.circuitName, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, expressRouteCircuitsClientDeleteResponsePoller) + testsuite.Require().NoError(err) +} diff --git a/sdk/resourcemanager/network/armnetwork/firewallpolicy_live_test.go b/sdk/resourcemanager/network/armnetwork/firewallpolicy_live_test.go new file mode 100644 index 000000000000..da077461f42c --- /dev/null +++ b/sdk/resourcemanager/network/armnetwork/firewallpolicy_live_test.go @@ -0,0 +1,176 @@ +//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. +// Code generated by Microsoft (R) AutoRest Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. + +package armnetwork_test + +import ( + "context" + "fmt" + "testing" + + "github.com/Azure/azure-sdk-for-go/sdk/azcore" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/arm" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/to" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/internal/testutil" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork/v2" + "github.com/stretchr/testify/suite" +) + +type FirewallPolicyTestSuite struct { + suite.Suite + + ctx context.Context + cred azcore.TokenCredential + options *arm.ClientOptions + firewallPolicyName string + ruleCollectionGroupName string + location string + resourceGroupName string + subscriptionId string +} + +func (testsuite *FirewallPolicyTestSuite) SetupSuite() { + testutil.StartRecording(testsuite.T(), "sdk/resourcemanager/network/armnetwork/testdata") + + testsuite.ctx = context.Background() + testsuite.cred, testsuite.options = testutil.GetCredAndClientOptions(testsuite.T()) + testsuite.firewallPolicyName = testutil.GenerateAlphaNumericID(testsuite.T(), "firewallpo", 6) + testsuite.ruleCollectionGroupName = testutil.GenerateAlphaNumericID(testsuite.T(), "rulecollec", 6) + testsuite.location = testutil.GetEnv("LOCATION", "westus") + testsuite.resourceGroupName = testutil.GetEnv("RESOURCE_GROUP_NAME", "scenarioTestTempGroup") + testsuite.subscriptionId = testutil.GetEnv("AZURE_SUBSCRIPTION_ID", "00000000-0000-0000-0000-000000000000") + resourceGroup, _, err := testutil.CreateResourceGroup(testsuite.ctx, testsuite.subscriptionId, testsuite.cred, testsuite.options, testsuite.location) + testsuite.Require().NoError(err) + testsuite.resourceGroupName = *resourceGroup.Name + testsuite.Prepare() +} + +func (testsuite *FirewallPolicyTestSuite) TearDownSuite() { + testsuite.Cleanup() + _, err := testutil.DeleteResourceGroup(testsuite.ctx, testsuite.subscriptionId, testsuite.cred, testsuite.options, testsuite.resourceGroupName) + testsuite.Require().NoError(err) + testutil.StopRecording(testsuite.T()) +} + +func TestFirewallPolicyTestSuite(t *testing.T) { + suite.Run(t, new(FirewallPolicyTestSuite)) +} + +func (testsuite *FirewallPolicyTestSuite) Prepare() { + var err error + // From step FirewallPolicies_CreateOrUpdate + fmt.Println("Call operation: FirewallPolicies_CreateOrUpdate") + firewallPoliciesClient, err := armnetwork.NewFirewallPoliciesClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + firewallPoliciesClientCreateOrUpdateResponsePoller, err := firewallPoliciesClient.BeginCreateOrUpdate(testsuite.ctx, testsuite.resourceGroupName, testsuite.firewallPolicyName, armnetwork.FirewallPolicy{ + Location: to.Ptr(testsuite.location), + Properties: &armnetwork.FirewallPolicyPropertiesFormat{ + SKU: &armnetwork.FirewallPolicySKU{ + Tier: to.Ptr(armnetwork.FirewallPolicySKUTierPremium), + }, + }, + }, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, firewallPoliciesClientCreateOrUpdateResponsePoller) + testsuite.Require().NoError(err) +} + +// Microsoft.Network/firewallPolicies/{firewallPolicyName} +func (testsuite *FirewallPolicyTestSuite) TestFirewallPolicies() { + var err error + // From step FirewallPolicies_ListAll + fmt.Println("Call operation: FirewallPolicies_ListAll") + firewallPoliciesClient, err := armnetwork.NewFirewallPoliciesClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + firewallPoliciesClientNewListAllPager := firewallPoliciesClient.NewListAllPager(nil) + for firewallPoliciesClientNewListAllPager.More() { + _, err := firewallPoliciesClientNewListAllPager.NextPage(testsuite.ctx) + testsuite.Require().NoError(err) + break + } + + // From step FirewallPolicies_List + fmt.Println("Call operation: FirewallPolicies_List") + firewallPoliciesClientNewListPager := firewallPoliciesClient.NewListPager(testsuite.resourceGroupName, nil) + for firewallPoliciesClientNewListPager.More() { + _, err := firewallPoliciesClientNewListPager.NextPage(testsuite.ctx) + testsuite.Require().NoError(err) + break + } + + // From step FirewallPolicies_Get + fmt.Println("Call operation: FirewallPolicies_Get") + _, err = firewallPoliciesClient.Get(testsuite.ctx, testsuite.resourceGroupName, testsuite.firewallPolicyName, &armnetwork.FirewallPoliciesClientGetOptions{Expand: nil}) + testsuite.Require().NoError(err) + + // From step FirewallPolicies_UpdateTags + fmt.Println("Call operation: FirewallPolicies_UpdateTags") + _, err = firewallPoliciesClient.UpdateTags(testsuite.ctx, testsuite.resourceGroupName, testsuite.firewallPolicyName, armnetwork.TagsObject{ + Tags: map[string]*string{ + "key1": to.Ptr("value1"), + "key2": to.Ptr("value2"), + }, + }, nil) + testsuite.Require().NoError(err) +} + +// Microsoft.Network/firewallPolicies/{firewallPolicyName}/ruleCollectionGroups/{ruleCollectionGroupName} +func (testsuite *FirewallPolicyTestSuite) TestFirewallPolicyRuleCollectionGroups() { + var err error + // From step FirewallPolicyRuleCollectionGroups_CreateOrUpdate + fmt.Println("Call operation: FirewallPolicyRuleCollectionGroups_CreateOrUpdate") + firewallPolicyRuleCollectionGroupsClient, err := armnetwork.NewFirewallPolicyRuleCollectionGroupsClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + firewallPolicyRuleCollectionGroupsClientCreateOrUpdateResponsePoller, err := firewallPolicyRuleCollectionGroupsClient.BeginCreateOrUpdate(testsuite.ctx, testsuite.resourceGroupName, testsuite.firewallPolicyName, testsuite.ruleCollectionGroupName, armnetwork.FirewallPolicyRuleCollectionGroup{ + Properties: &armnetwork.FirewallPolicyRuleCollectionGroupProperties{ + Priority: to.Ptr[int32](100), + RuleCollections: []armnetwork.FirewallPolicyRuleCollectionClassification{ + &armnetwork.FirewallPolicyFilterRuleCollection{ + Name: to.Ptr("Example-Filter-Rule-Collection"), + Priority: to.Ptr[int32](100), + RuleCollectionType: to.Ptr(armnetwork.FirewallPolicyRuleCollectionTypeFirewallPolicyFilterRuleCollection), + }}, + }, + }, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, firewallPolicyRuleCollectionGroupsClientCreateOrUpdateResponsePoller) + testsuite.Require().NoError(err) + + // From step FirewallPolicyRuleCollectionGroups_List + fmt.Println("Call operation: FirewallPolicyRuleCollectionGroups_List") + firewallPolicyRuleCollectionGroupsClientNewListPager := firewallPolicyRuleCollectionGroupsClient.NewListPager(testsuite.resourceGroupName, testsuite.firewallPolicyName, nil) + for firewallPolicyRuleCollectionGroupsClientNewListPager.More() { + _, err := firewallPolicyRuleCollectionGroupsClientNewListPager.NextPage(testsuite.ctx) + testsuite.Require().NoError(err) + break + } + + // From step FirewallPolicyRuleCollectionGroups_Get + fmt.Println("Call operation: FirewallPolicyRuleCollectionGroups_Get") + _, err = firewallPolicyRuleCollectionGroupsClient.Get(testsuite.ctx, testsuite.resourceGroupName, testsuite.firewallPolicyName, testsuite.ruleCollectionGroupName, nil) + testsuite.Require().NoError(err) + + // From step FirewallPolicyRuleCollectionGroups_Delete + fmt.Println("Call operation: FirewallPolicyRuleCollectionGroups_Delete") + firewallPolicyRuleCollectionGroupsClientDeleteResponsePoller, err := firewallPolicyRuleCollectionGroupsClient.BeginDelete(testsuite.ctx, testsuite.resourceGroupName, testsuite.firewallPolicyName, testsuite.ruleCollectionGroupName, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, firewallPolicyRuleCollectionGroupsClientDeleteResponsePoller) + testsuite.Require().NoError(err) +} + +func (testsuite *FirewallPolicyTestSuite) Cleanup() { + var err error + // From step FirewallPolicies_Delete + fmt.Println("Call operation: FirewallPolicies_Delete") + firewallPoliciesClient, err := armnetwork.NewFirewallPoliciesClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + firewallPoliciesClientDeleteResponsePoller, err := firewallPoliciesClient.BeginDelete(testsuite.ctx, testsuite.resourceGroupName, testsuite.firewallPolicyName, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, firewallPoliciesClientDeleteResponsePoller) + testsuite.Require().NoError(err) +} diff --git a/sdk/resourcemanager/network/armnetwork/go.mod b/sdk/resourcemanager/network/armnetwork/go.mod index 2c652bfc25eb..a2b1e1571462 100644 --- a/sdk/resourcemanager/network/armnetwork/go.mod +++ b/sdk/resourcemanager/network/armnetwork/go.mod @@ -3,27 +3,27 @@ module github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork/ go 1.18 require ( - github.com/Azure/azure-sdk-for-go/sdk/azcore v1.4.0 - github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.2.0 + github.com/Azure/azure-sdk-for-go/sdk/azcore v1.5.0 + github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.2.2 github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/internal v1.1.2 - github.com/stretchr/testify v1.7.0 + github.com/stretchr/testify v1.8.2 ) require ( - github.com/Azure/azure-sdk-for-go/sdk/internal v1.2.0 // indirect + github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0 // indirect github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armresources v1.0.0 // indirect - github.com/AzureAD/microsoft-authentication-library-for-go v0.7.0 // indirect + github.com/AzureAD/microsoft-authentication-library-for-go v0.9.0 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/dnaeon/go-vcr v1.1.0 // indirect - github.com/golang-jwt/jwt/v4 v4.4.2 // indirect - github.com/google/uuid v1.1.1 // indirect + github.com/golang-jwt/jwt/v4 v4.5.0 // indirect + github.com/google/uuid v1.3.0 // indirect github.com/kylelemons/godebug v1.1.0 // indirect - github.com/pkg/browser v0.0.0-20210115035449-ce105d075bb4 // indirect + github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - golang.org/x/crypto v0.0.0-20220511200225-c6db032c6c88 // indirect - golang.org/x/net v0.7.0 // indirect - golang.org/x/sys v0.5.0 // indirect - golang.org/x/text v0.7.0 // indirect + golang.org/x/crypto v0.6.0 // indirect + golang.org/x/net v0.8.0 // indirect + golang.org/x/sys v0.6.0 // indirect + golang.org/x/text v0.8.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect - gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/sdk/resourcemanager/network/armnetwork/go.sum b/sdk/resourcemanager/network/armnetwork/go.sum index b0f97586a165..6befdf11bc6e 100644 --- a/sdk/resourcemanager/network/armnetwork/go.sum +++ b/sdk/resourcemanager/network/armnetwork/go.sum @@ -1,47 +1,52 @@ -github.com/Azure/azure-sdk-for-go/sdk/azcore v1.4.0 h1:rTnT/Jrcm+figWlYz4Ixzt0SJVR2cMC8lvZcimipiEY= -github.com/Azure/azure-sdk-for-go/sdk/azcore v1.4.0/go.mod h1:ON4tFdPTwRcgWEaVDrN3584Ef+b7GgSJaXxe5fW9t4M= -github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.2.0 h1:t/W5MYAuQy81cvM8VUNfRLzhtKpXhVUAN7Cd7KVbTyc= -github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.2.0/go.mod h1:NBanQUfSWiWn3QEpWDTCU0IjBECKOYvl2R8xdRtMtiM= -github.com/Azure/azure-sdk-for-go/sdk/internal v1.2.0 h1:leh5DwKv6Ihwi+h60uHtn6UWAxBbZ0q8DwQVMzf61zw= -github.com/Azure/azure-sdk-for-go/sdk/internal v1.2.0/go.mod h1:eWRD7oawr1Mu1sLCawqVc0CUiF43ia3qQMxLscsKQ9w= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.5.0 h1:xGLAFFd9D3iLGxYiUGPdITSzsFmU1K8VtfuUHWAoN7M= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.5.0/go.mod h1:bjGvMhVMb+EEm3VRNQawDMUyMMjo+S5ewNjflkep/0Q= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.2.2 h1:uqM+VoHjVH6zdlkLF2b6O0ZANcHoj3rO0PoQ3jglUJA= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.2.2/go.mod h1:twTKAa1E6hLmSDjLhaCkbTMQKc7p/rNLU40rLxGEOCI= +github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0 h1:sXr+ck84g/ZlZUOZiNELInmMgOsuGwdjjVkEIde0OtY= +github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0/go.mod h1:okt5dMMTOFjX/aovMlrjvvXoPMBVSPzk9185BT0+eZM= github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/internal v1.1.2 h1:mLY+pNLjCUeKhgnAJWAKhEUQM+RJQo2H1fuGSw1Ky1E= github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/internal v1.1.2/go.mod h1:FbdwsQ2EzwvXxOPcMFYO8ogEc9uMMIj3YkmCdXdAFmk= github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armresources v1.0.0 h1:ECsQtyERDVz3NP3kvDOTLvbQhqWp/x9EsGKtb4ogUr8= github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armresources v1.0.0/go.mod h1:s1tW/At+xHqjNFvWU4G0c0Qv33KOhvbGNj0RCTQDV8s= -github.com/AzureAD/microsoft-authentication-library-for-go v0.7.0 h1:VgSJlZH5u0k2qxSpqyghcFQKmvYckj46uymKK5XzkBM= -github.com/AzureAD/microsoft-authentication-library-for-go v0.7.0/go.mod h1:BDJ5qMFKx9DugEg3+uQSDCdbYPr5s9vBTrL9P8TpqOU= +github.com/AzureAD/microsoft-authentication-library-for-go v0.9.0 h1:UE9n9rkJF62ArLb1F3DEjRt8O3jLwMWdSoypKV4f3MU= +github.com/AzureAD/microsoft-authentication-library-for-go v0.9.0/go.mod h1:kgDmCTgBzIEPFElEF+FK0SdjAor06dRq2Go927dnQ6o= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/dnaeon/go-vcr v1.1.0 h1:ReYa/UBrRyQdant9B4fNHGoCNKw6qh6P0fsdGmZpR7c= github.com/dnaeon/go-vcr v1.1.0/go.mod h1:M7tiix8f0r6mKKJ3Yq/kqU1OYf3MnfmBWVbPx/yU9ko= -github.com/golang-jwt/jwt/v4 v4.4.2 h1:rcc4lwaZgFMCZ5jxF9ABolDcIHdBytAFgqFPbSJQAYs= -github.com/golang-jwt/jwt/v4 v4.4.2/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= -github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY= -github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg= +github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= +github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= +github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= github.com/modocache/gover v0.0.0-20171022184752-b58185e213c5/go.mod h1:caMODM3PzxT8aQXRPkAt8xlV/e7d7w8GM5g0fa5F0D8= -github.com/pkg/browser v0.0.0-20210115035449-ce105d075bb4 h1:Qj1ukM4GlMWXNdMBuXcXfz/Kw9s1qm0CLY32QxuSImI= -github.com/pkg/browser v0.0.0-20210115035449-ce105d075bb4/go.mod h1:N6UoU20jOqggOuDwUaBQpluzLNDqif3kq9z2wpdYEfQ= +github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 h1:KoWmjvw+nsYOo29YJK9vDA65RGE3NrOnUtO7a+RF9HU= +github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8/go.mod h1:HKlIX3XHQyzLZPlr7++PzdhaXEj94dEiJgZDTsxEqUI= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= -github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -golang.org/x/crypto v0.0.0-20220511200225-c6db032c6c88 h1:Tgea0cVUD0ivh5ADBX4WwuI12DUd2to3nCYe2eayMIw= -golang.org/x/crypto v0.0.0-20220511200225-c6db032c6c88/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/net v0.7.0 h1:rJrUqqhjsgNp7KqAIc25s9pZnjU7TUcSY7HcVZjdn1g= -golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= -golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU= -golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/text v0.7.0 h1:4BRB4x83lYWy72KwLD/qYDuTu7q9PjSagHvijDw7cLo= -golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= +github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +golang.org/x/crypto v0.6.0 h1:qfktjS5LUO+fFKeJXZ+ikTRijMmljikvG68fpMMruSc= +golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58= +golang.org/x/net v0.8.0 h1:Zrh2ngAOFYneWTAIAPethzeaQLuHwhuBkuV6ZiRnUaQ= +golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= +golang.org/x/sys v0.0.0-20210616045830-e2b7044e8c71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0 h1:MVltZSvRTcU2ljQOhs94SXPftV6DCNnZViHeQps87pQ= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/text v0.8.0 h1:57P1ETyNKtuIjB4SRd15iJxuhj8Gc416Y78H3qgMh68= +golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo= -gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/sdk/resourcemanager/network/armnetwork/ipgroups_client_live_test.go b/sdk/resourcemanager/network/armnetwork/ipgroups_client_live_test.go deleted file mode 100644 index 8de9a0c68bea..000000000000 --- a/sdk/resourcemanager/network/armnetwork/ipgroups_client_live_test.go +++ /dev/null @@ -1,116 +0,0 @@ -//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 armnetwork_test - -import ( - "context" - "fmt" - "testing" - - "github.com/Azure/azure-sdk-for-go/sdk/azcore" - "github.com/Azure/azure-sdk-for-go/sdk/azcore/arm" - "github.com/Azure/azure-sdk-for-go/sdk/azcore/to" - "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/internal/testutil" - "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork/v2" - "github.com/stretchr/testify/suite" -) - -type IPGroupsClientTestSuite struct { - suite.Suite - - ctx context.Context - cred azcore.TokenCredential - options *arm.ClientOptions - location string - resourceGroupName string - subscriptionID string -} - -func (testsuite *IPGroupsClientTestSuite) SetupSuite() { - testsuite.ctx = context.Background() - testsuite.cred, testsuite.options = testutil.GetCredAndClientOptions(testsuite.T()) - testsuite.location = testutil.GetEnv("LOCATION", "eastus") - testsuite.subscriptionID = testutil.GetEnv("AZURE_SUBSCRIPTION_ID", "00000000-0000-0000-0000-000000000000") - testutil.StartRecording(testsuite.T(), "sdk/resourcemanager/network/armnetwork/testdata") - resourceGroup, _, err := testutil.CreateResourceGroup(testsuite.ctx, testsuite.subscriptionID, testsuite.cred, testsuite.options, testsuite.location) - testsuite.Require().NoError(err) - testsuite.resourceGroupName = *resourceGroup.Name -} - -func (testsuite *IPGroupsClientTestSuite) TearDownSuite() { - _, err := testutil.DeleteResourceGroup(testsuite.ctx, testsuite.subscriptionID, testsuite.cred, testsuite.options, testsuite.resourceGroupName) - testsuite.Require().NoError(err) - testutil.StopRecording(testsuite.T()) -} - -func TestIPGroupsClient(t *testing.T) { - suite.Run(t, new(IPGroupsClientTestSuite)) -} - -func (testsuite *IPGroupsClientTestSuite) TestIPGroupsCRUD() { - // create ip group - fmt.Println("Call operation: IpGroups_CreateOrUpdate") - ipgClient, err := armnetwork.NewIPGroupsClient(testsuite.subscriptionID, testsuite.cred, testsuite.options) - testsuite.Require().NoError(err) - ipgName := "go-test-ipg" - ipgPoller, err := ipgClient.BeginCreateOrUpdate( - testsuite.ctx, - testsuite.resourceGroupName, - ipgName, - armnetwork.IPGroup{ - Location: to.Ptr(testsuite.location), - Properties: &armnetwork.IPGroupPropertiesFormat{ - IPAddresses: []*string{ - to.Ptr("13.64.39.16/32"), - to.Ptr("40.74.146.80/31"), - to.Ptr("40.74.147.32/28"), - }, - }, - }, - nil, - ) - testsuite.Require().NoError(err) - resp, err := testutil.PollForTest(testsuite.ctx, ipgPoller) - testsuite.Require().NoError(err) - testsuite.Require().Equal(ipgName, *resp.Name) - - // update - fmt.Println("Call operation: IpGroups_UpdateGroups") - updateResp, err := ipgClient.UpdateGroups( - testsuite.ctx, - testsuite.resourceGroupName, - ipgName, - armnetwork.TagsObject{ - Tags: map[string]*string{ - "test": to.Ptr("live"), - }, - }, - nil, - ) - testsuite.Require().NoError(err) - testsuite.Require().Equal("live", *updateResp.Tags["test"]) - - // get ip group - fmt.Println("Call operation: IpGroups_Get") - getResp, err := ipgClient.Get(testsuite.ctx, testsuite.resourceGroupName, ipgName, nil) - testsuite.Require().NoError(err) - testsuite.Require().Equal(ipgName, *getResp.Name) - - // list ip group - fmt.Println("Call operation: IpGroups_List") - listPager := ipgClient.NewListPager(nil) - testsuite.Require().True(listPager.More()) - - // delete ip group - fmt.Println("Call operation: IpGroups_Delete") - delPoller, err := ipgClient.BeginDelete(testsuite.ctx, testsuite.resourceGroupName, ipgName, nil) - testsuite.Require().NoError(err) - delResp, err := testutil.PollForTest(testsuite.ctx, delPoller) - testsuite.Require().NoError(err) - //testsuite.Require().Equal(200, delResp.RawResponse.StatusCode) - _ = delResp -} diff --git a/sdk/resourcemanager/network/armnetwork/ipgroups_live_test.go b/sdk/resourcemanager/network/armnetwork/ipgroups_live_test.go new file mode 100644 index 000000000000..dfbe0b8e9287 --- /dev/null +++ b/sdk/resourcemanager/network/armnetwork/ipgroups_live_test.go @@ -0,0 +1,122 @@ +//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. +// Code generated by Microsoft (R) AutoRest Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. + +package armnetwork_test + +import ( + "context" + "fmt" + "testing" + + "github.com/Azure/azure-sdk-for-go/sdk/azcore" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/arm" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/to" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/internal/testutil" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork/v2" + "github.com/stretchr/testify/suite" +) + +type IpGroupsTestSuite struct { + suite.Suite + + ctx context.Context + cred azcore.TokenCredential + options *arm.ClientOptions + ipGroupsName string + location string + resourceGroupName string + subscriptionId string +} + +func (testsuite *IpGroupsTestSuite) SetupSuite() { + testutil.StartRecording(testsuite.T(), "sdk/resourcemanager/network/armnetwork/testdata") + + testsuite.ctx = context.Background() + testsuite.cred, testsuite.options = testutil.GetCredAndClientOptions(testsuite.T()) + testsuite.ipGroupsName = testutil.GenerateAlphaNumericID(testsuite.T(), "ipgroupsna", 6) + testsuite.location = testutil.GetEnv("LOCATION", "westus") + testsuite.resourceGroupName = testutil.GetEnv("RESOURCE_GROUP_NAME", "scenarioTestTempGroup") + testsuite.subscriptionId = testutil.GetEnv("AZURE_SUBSCRIPTION_ID", "00000000-0000-0000-0000-000000000000") + resourceGroup, _, err := testutil.CreateResourceGroup(testsuite.ctx, testsuite.subscriptionId, testsuite.cred, testsuite.options, testsuite.location) + testsuite.Require().NoError(err) + testsuite.resourceGroupName = *resourceGroup.Name +} + +func (testsuite *IpGroupsTestSuite) TearDownSuite() { + _, err := testutil.DeleteResourceGroup(testsuite.ctx, testsuite.subscriptionId, testsuite.cred, testsuite.options, testsuite.resourceGroupName) + testsuite.Require().NoError(err) + testutil.StopRecording(testsuite.T()) +} + +func TestIpGroupsTestSuite(t *testing.T) { + suite.Run(t, new(IpGroupsTestSuite)) +} + +// Microsoft.Network/ipGroups/{ipGroupsName} +func (testsuite *IpGroupsTestSuite) TestIpGroups() { + var err error + // From step IpGroups_CreateOrUpdate + fmt.Println("Call operation: IPGroups_CreateOrUpdate") + iPGroupsClient, err := armnetwork.NewIPGroupsClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + iPGroupsClientCreateOrUpdateResponsePoller, err := iPGroupsClient.BeginCreateOrUpdate(testsuite.ctx, testsuite.resourceGroupName, testsuite.ipGroupsName, armnetwork.IPGroup{ + Location: to.Ptr(testsuite.location), + Tags: map[string]*string{ + "key1": to.Ptr("value1"), + }, + Properties: &armnetwork.IPGroupPropertiesFormat{ + IPAddresses: []*string{ + to.Ptr("13.64.39.16/32"), + to.Ptr("40.74.146.80/31"), + to.Ptr("40.74.147.32/28")}, + }, + }, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, iPGroupsClientCreateOrUpdateResponsePoller) + testsuite.Require().NoError(err) + + // From step IpGroups_List + fmt.Println("Call operation: IPGroups_List") + iPGroupsClientNewListPager := iPGroupsClient.NewListPager(nil) + for iPGroupsClientNewListPager.More() { + _, err := iPGroupsClientNewListPager.NextPage(testsuite.ctx) + testsuite.Require().NoError(err) + break + } + + // From step IpGroups_ListByResourceGroup + fmt.Println("Call operation: IPGroups_ListByResourceGroup") + iPGroupsClientNewListByResourceGroupPager := iPGroupsClient.NewListByResourceGroupPager(testsuite.resourceGroupName, nil) + for iPGroupsClientNewListByResourceGroupPager.More() { + _, err := iPGroupsClientNewListByResourceGroupPager.NextPage(testsuite.ctx) + testsuite.Require().NoError(err) + break + } + + // From step IpGroups_Get + fmt.Println("Call operation: IPGroups_Get") + _, err = iPGroupsClient.Get(testsuite.ctx, testsuite.resourceGroupName, testsuite.ipGroupsName, &armnetwork.IPGroupsClientGetOptions{Expand: nil}) + testsuite.Require().NoError(err) + + // From step IpGroups_UpdateGroups + fmt.Println("Call operation: IPGroups_UpdateGroups") + _, err = iPGroupsClient.UpdateGroups(testsuite.ctx, testsuite.resourceGroupName, testsuite.ipGroupsName, armnetwork.TagsObject{ + Tags: map[string]*string{ + "key1": to.Ptr("value1"), + "key2": to.Ptr("value2"), + }, + }, nil) + testsuite.Require().NoError(err) + + // From step IpGroups_Delete + fmt.Println("Call operation: IPGroups_Delete") + iPGroupsClientDeleteResponsePoller, err := iPGroupsClient.BeginDelete(testsuite.ctx, testsuite.resourceGroupName, testsuite.ipGroupsName, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, iPGroupsClientDeleteResponsePoller) + testsuite.Require().NoError(err) +} diff --git a/sdk/resourcemanager/network/armnetwork/loadbalancer_live_test.go b/sdk/resourcemanager/network/armnetwork/loadbalancer_live_test.go new file mode 100644 index 000000000000..f6028154103a --- /dev/null +++ b/sdk/resourcemanager/network/armnetwork/loadbalancer_live_test.go @@ -0,0 +1,335 @@ +//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. +// Code generated by Microsoft (R) AutoRest Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. + +package armnetwork_test + +import ( + "context" + "fmt" + "testing" + + "github.com/Azure/azure-sdk-for-go/sdk/azcore" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/arm" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/to" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/internal/testutil" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork/v2" + "github.com/stretchr/testify/suite" +) + +type LoadBalancerTestSuite struct { + suite.Suite + + ctx context.Context + cred azcore.TokenCredential + options *arm.ClientOptions + backendAddressPoolName string + frontendIPConfigurationId string + inboundNatRuleName string + loadBalancerName string + subnetId string + location string + resourceGroupName string + subscriptionId string +} + +func (testsuite *LoadBalancerTestSuite) SetupSuite() { + testutil.StartRecording(testsuite.T(), "sdk/resourcemanager/network/armnetwork/testdata") + + testsuite.ctx = context.Background() + testsuite.cred, testsuite.options = testutil.GetCredAndClientOptions(testsuite.T()) + testsuite.backendAddressPoolName = testutil.GenerateAlphaNumericID(testsuite.T(), "backendadd", 6) + testsuite.inboundNatRuleName = testutil.GenerateAlphaNumericID(testsuite.T(), "inboundnat", 6) + testsuite.loadBalancerName = testutil.GenerateAlphaNumericID(testsuite.T(), "loadbalanc", 6) + testsuite.location = testutil.GetEnv("LOCATION", "westus") + testsuite.resourceGroupName = testutil.GetEnv("RESOURCE_GROUP_NAME", "scenarioTestTempGroup") + testsuite.subscriptionId = testutil.GetEnv("AZURE_SUBSCRIPTION_ID", "00000000-0000-0000-0000-000000000000") + resourceGroup, _, err := testutil.CreateResourceGroup(testsuite.ctx, testsuite.subscriptionId, testsuite.cred, testsuite.options, testsuite.location) + testsuite.Require().NoError(err) + testsuite.resourceGroupName = *resourceGroup.Name + testsuite.Prepare() +} + +func (testsuite *LoadBalancerTestSuite) TearDownSuite() { + testsuite.Cleanup() + _, err := testutil.DeleteResourceGroup(testsuite.ctx, testsuite.subscriptionId, testsuite.cred, testsuite.options, testsuite.resourceGroupName) + testsuite.Require().NoError(err) + testutil.StopRecording(testsuite.T()) +} + +func TestLoadBalancerTestSuite(t *testing.T) { + suite.Run(t, new(LoadBalancerTestSuite)) +} + +func (testsuite *LoadBalancerTestSuite) Prepare() { + var err error + // From step VirtualNetworks_CreateOrUpdate + fmt.Println("Call operation: VirtualNetworks_CreateOrUpdate") + virtualNetworksClient, err := armnetwork.NewVirtualNetworksClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + virtualNetworksClientCreateOrUpdateResponsePoller, err := virtualNetworksClient.BeginCreateOrUpdate(testsuite.ctx, testsuite.resourceGroupName, "test-vnet", armnetwork.VirtualNetwork{ + Location: to.Ptr(testsuite.location), + Properties: &armnetwork.VirtualNetworkPropertiesFormat{ + AddressSpace: &armnetwork.AddressSpace{ + AddressPrefixes: []*string{ + to.Ptr("10.0.0.0/16")}, + }, + Subnets: []*armnetwork.Subnet{ + { + Name: to.Ptr("test-1"), + Properties: &armnetwork.SubnetPropertiesFormat{ + AddressPrefix: to.Ptr("10.0.0.0/24"), + }, + }}, + }, + }, nil) + testsuite.Require().NoError(err) + var virtualNetworksClientCreateOrUpdateResponse *armnetwork.VirtualNetworksClientCreateOrUpdateResponse + virtualNetworksClientCreateOrUpdateResponse, err = testutil.PollForTest(testsuite.ctx, virtualNetworksClientCreateOrUpdateResponsePoller) + testsuite.Require().NoError(err) + testsuite.subnetId = *virtualNetworksClientCreateOrUpdateResponse.Properties.Subnets[0].ID + + // From step LoadBalancers_CreateOrUpdate + fmt.Println("Call operation: LoadBalancers_CreateOrUpdate") + loadBalancersClient, err := armnetwork.NewLoadBalancersClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + loadBalancersClientCreateOrUpdateResponsePoller, err := loadBalancersClient.BeginCreateOrUpdate(testsuite.ctx, testsuite.resourceGroupName, testsuite.loadBalancerName, armnetwork.LoadBalancer{ + Location: to.Ptr(testsuite.location), + Properties: &armnetwork.LoadBalancerPropertiesFormat{ + FrontendIPConfigurations: []*armnetwork.FrontendIPConfiguration{ + { + Name: to.Ptr("frontendipconf"), + Properties: &armnetwork.FrontendIPConfigurationPropertiesFormat{ + Subnet: &armnetwork.Subnet{ + ID: to.Ptr(testsuite.subnetId), + }, + }, + }}, + }, + SKU: &armnetwork.LoadBalancerSKU{ + Name: to.Ptr(armnetwork.LoadBalancerSKUNameStandard), + }, + }, nil) + testsuite.Require().NoError(err) + var loadBalancersClientCreateOrUpdateResponse *armnetwork.LoadBalancersClientCreateOrUpdateResponse + loadBalancersClientCreateOrUpdateResponse, err = testutil.PollForTest(testsuite.ctx, loadBalancersClientCreateOrUpdateResponsePoller) + testsuite.Require().NoError(err) + testsuite.frontendIPConfigurationId = *loadBalancersClientCreateOrUpdateResponse.Properties.FrontendIPConfigurations[0].ID +} + +// Microsoft.Network/loadBalancers/{loadBalancerName} +func (testsuite *LoadBalancerTestSuite) TestLoadBalancers() { + var err error + // From step LoadBalancers_ListAll + fmt.Println("Call operation: LoadBalancers_ListAll") + loadBalancersClient, err := armnetwork.NewLoadBalancersClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + loadBalancersClientNewListAllPager := loadBalancersClient.NewListAllPager(nil) + for loadBalancersClientNewListAllPager.More() { + _, err := loadBalancersClientNewListAllPager.NextPage(testsuite.ctx) + testsuite.Require().NoError(err) + break + } + + // From step LoadBalancers_List + fmt.Println("Call operation: LoadBalancers_List") + loadBalancersClientNewListPager := loadBalancersClient.NewListPager(testsuite.resourceGroupName, nil) + for loadBalancersClientNewListPager.More() { + _, err := loadBalancersClientNewListPager.NextPage(testsuite.ctx) + testsuite.Require().NoError(err) + break + } + + // From step LoadBalancers_Get + fmt.Println("Call operation: LoadBalancers_Get") + _, err = loadBalancersClient.Get(testsuite.ctx, testsuite.resourceGroupName, testsuite.loadBalancerName, &armnetwork.LoadBalancersClientGetOptions{Expand: nil}) + testsuite.Require().NoError(err) + + // From step LoadBalancers_UpdateTags + fmt.Println("Call operation: LoadBalancers_UpdateTags") + _, err = loadBalancersClient.UpdateTags(testsuite.ctx, testsuite.resourceGroupName, testsuite.loadBalancerName, armnetwork.TagsObject{ + Tags: map[string]*string{ + "tag1": to.Ptr("value1"), + "tag2": to.Ptr("value2"), + }, + }, nil) + testsuite.Require().NoError(err) +} + +// Microsoft.Network/loadBalancers/{loadBalancerName}/backendAddressPools/{backendAddressPoolName} +func (testsuite *LoadBalancerTestSuite) TestLoadBalancerBackendAddressPools() { + var err error + // From step LoadBalancerBackendAddressPools_CreateOrUpdate + fmt.Println("Call operation: LoadBalancerBackendAddressPools_CreateOrUpdate") + loadBalancerBackendAddressPoolsClient, err := armnetwork.NewLoadBalancerBackendAddressPoolsClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + loadBalancerBackendAddressPoolsClientCreateOrUpdateResponsePoller, err := loadBalancerBackendAddressPoolsClient.BeginCreateOrUpdate(testsuite.ctx, testsuite.resourceGroupName, testsuite.loadBalancerName, testsuite.backendAddressPoolName, armnetwork.BackendAddressPool{ + Properties: &armnetwork.BackendAddressPoolPropertiesFormat{}, + }, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, loadBalancerBackendAddressPoolsClientCreateOrUpdateResponsePoller) + testsuite.Require().NoError(err) + + // From step LoadBalancerBackendAddressPools_List + fmt.Println("Call operation: LoadBalancerBackendAddressPools_List") + loadBalancerBackendAddressPoolsClientNewListPager := loadBalancerBackendAddressPoolsClient.NewListPager(testsuite.resourceGroupName, testsuite.loadBalancerName, nil) + for loadBalancerBackendAddressPoolsClientNewListPager.More() { + _, err := loadBalancerBackendAddressPoolsClientNewListPager.NextPage(testsuite.ctx) + testsuite.Require().NoError(err) + break + } + + // From step LoadBalancerBackendAddressPools_Get + fmt.Println("Call operation: LoadBalancerBackendAddressPools_Get") + _, err = loadBalancerBackendAddressPoolsClient.Get(testsuite.ctx, testsuite.resourceGroupName, testsuite.loadBalancerName, testsuite.backendAddressPoolName, nil) + testsuite.Require().NoError(err) + + // From step LoadBalancerBackendAddressPools_Delete + fmt.Println("Call operation: LoadBalancerBackendAddressPools_Delete") + loadBalancerBackendAddressPoolsClientDeleteResponsePoller, err := loadBalancerBackendAddressPoolsClient.BeginDelete(testsuite.ctx, testsuite.resourceGroupName, testsuite.loadBalancerName, testsuite.backendAddressPoolName, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, loadBalancerBackendAddressPoolsClientDeleteResponsePoller) + testsuite.Require().NoError(err) +} + +// Microsoft.Network/loadBalancers/{loadBalancerName}/frontendIPConfigurations +func (testsuite *LoadBalancerTestSuite) TestLoadBalancerFrontendIpConfigurations() { + var err error + // From step LoadBalancerFrontendIPConfigurations_List + fmt.Println("Call operation: LoadBalancerFrontendIPConfigurations_List") + loadBalancerFrontendIPConfigurationsClient, err := armnetwork.NewLoadBalancerFrontendIPConfigurationsClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + loadBalancerFrontendIPConfigurationsClientNewListPager := loadBalancerFrontendIPConfigurationsClient.NewListPager(testsuite.resourceGroupName, testsuite.loadBalancerName, nil) + for loadBalancerFrontendIPConfigurationsClientNewListPager.More() { + _, err := loadBalancerFrontendIPConfigurationsClientNewListPager.NextPage(testsuite.ctx) + testsuite.Require().NoError(err) + break + } + + // From step LoadBalancerFrontendIPConfigurations_Get + fmt.Println("Call operation: LoadBalancerFrontendIPConfigurations_Get") + _, err = loadBalancerFrontendIPConfigurationsClient.Get(testsuite.ctx, testsuite.resourceGroupName, testsuite.loadBalancerName, "frontendipconf", nil) + testsuite.Require().NoError(err) +} + +// Microsoft.Network/loadBalancers/{loadBalancerName}/inboundNatRules/{inboundNatRuleName} +func (testsuite *LoadBalancerTestSuite) TestInboundNatRules() { + var err error + // From step InboundNatRules_CreateOrUpdate + fmt.Println("Call operation: InboundNatRules_CreateOrUpdate") + inboundNatRulesClient, err := armnetwork.NewInboundNatRulesClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + inboundNatRulesClientCreateOrUpdateResponsePoller, err := inboundNatRulesClient.BeginCreateOrUpdate(testsuite.ctx, testsuite.resourceGroupName, testsuite.loadBalancerName, testsuite.inboundNatRuleName, armnetwork.InboundNatRule{ + Properties: &armnetwork.InboundNatRulePropertiesFormat{ + BackendPort: to.Ptr[int32](3389), + EnableFloatingIP: to.Ptr(false), + EnableTCPReset: to.Ptr(false), + FrontendIPConfiguration: &armnetwork.SubResource{ + ID: to.Ptr(testsuite.frontendIPConfigurationId), + }, + FrontendPort: to.Ptr[int32](3390), + IdleTimeoutInMinutes: to.Ptr[int32](4), + Protocol: to.Ptr(armnetwork.TransportProtocolTCP), + }, + }, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, inboundNatRulesClientCreateOrUpdateResponsePoller) + testsuite.Require().NoError(err) + + // From step InboundNatRules_List + fmt.Println("Call operation: InboundNatRules_List") + inboundNatRulesClientNewListPager := inboundNatRulesClient.NewListPager(testsuite.resourceGroupName, testsuite.loadBalancerName, nil) + for inboundNatRulesClientNewListPager.More() { + _, err := inboundNatRulesClientNewListPager.NextPage(testsuite.ctx) + testsuite.Require().NoError(err) + break + } + + // From step InboundNatRules_Get + fmt.Println("Call operation: InboundNatRules_Get") + _, err = inboundNatRulesClient.Get(testsuite.ctx, testsuite.resourceGroupName, testsuite.loadBalancerName, testsuite.inboundNatRuleName, &armnetwork.InboundNatRulesClientGetOptions{Expand: nil}) + testsuite.Require().NoError(err) + + // From step InboundNatRules_Delete + fmt.Println("Call operation: InboundNatRules_Delete") + inboundNatRulesClientDeleteResponsePoller, err := inboundNatRulesClient.BeginDelete(testsuite.ctx, testsuite.resourceGroupName, testsuite.loadBalancerName, testsuite.inboundNatRuleName, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, inboundNatRulesClientDeleteResponsePoller) + testsuite.Require().NoError(err) +} + +// Microsoft.Network/loadBalancers/{loadBalancerName}/loadBalancingRules +func (testsuite *LoadBalancerTestSuite) TestLoadBalancerLoadBalancingRules() { + var err error + // From step LoadBalancerLoadBalancingRules_List + fmt.Println("Call operation: LoadBalancerLoadBalancingRules_List") + loadBalancerLoadBalancingRulesClient, err := armnetwork.NewLoadBalancerLoadBalancingRulesClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + loadBalancerLoadBalancingRulesClientNewListPager := loadBalancerLoadBalancingRulesClient.NewListPager(testsuite.resourceGroupName, testsuite.loadBalancerName, nil) + for loadBalancerLoadBalancingRulesClientNewListPager.More() { + _, err := loadBalancerLoadBalancingRulesClientNewListPager.NextPage(testsuite.ctx) + testsuite.Require().NoError(err) + break + } +} + +// Microsoft.Network/loadBalancers/{loadBalancerName}/outboundRules +func (testsuite *LoadBalancerTestSuite) TestLoadBalancerOutboundRules() { + var err error + // From step LoadBalancerOutboundRules_List + fmt.Println("Call operation: LoadBalancerOutboundRules_List") + loadBalancerOutboundRulesClient, err := armnetwork.NewLoadBalancerOutboundRulesClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + loadBalancerOutboundRulesClientNewListPager := loadBalancerOutboundRulesClient.NewListPager(testsuite.resourceGroupName, testsuite.loadBalancerName, nil) + for loadBalancerOutboundRulesClientNewListPager.More() { + _, err := loadBalancerOutboundRulesClientNewListPager.NextPage(testsuite.ctx) + testsuite.Require().NoError(err) + break + } +} + +// Microsoft.Network/loadBalancers/{loadBalancerName}/networkInterfaces +func (testsuite *LoadBalancerTestSuite) TestLoadBalancerNetworkInterfaces() { + var err error + // From step LoadBalancerNetworkInterfaces_List + fmt.Println("Call operation: LoadBalancerNetworkInterfaces_List") + loadBalancerNetworkInterfacesClient, err := armnetwork.NewLoadBalancerNetworkInterfacesClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + loadBalancerNetworkInterfacesClientNewListPager := loadBalancerNetworkInterfacesClient.NewListPager(testsuite.resourceGroupName, testsuite.loadBalancerName, nil) + for loadBalancerNetworkInterfacesClientNewListPager.More() { + _, err := loadBalancerNetworkInterfacesClientNewListPager.NextPage(testsuite.ctx) + testsuite.Require().NoError(err) + break + } +} + +// Microsoft.Network/loadBalancers/{loadBalancerName}/probes +func (testsuite *LoadBalancerTestSuite) TestLoadBalancerProbes() { + var err error + // From step LoadBalancerProbes_List + fmt.Println("Call operation: LoadBalancerProbes_List") + loadBalancerProbesClient, err := armnetwork.NewLoadBalancerProbesClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + loadBalancerProbesClientNewListPager := loadBalancerProbesClient.NewListPager(testsuite.resourceGroupName, testsuite.loadBalancerName, nil) + for loadBalancerProbesClientNewListPager.More() { + _, err := loadBalancerProbesClientNewListPager.NextPage(testsuite.ctx) + testsuite.Require().NoError(err) + break + } +} + +func (testsuite *LoadBalancerTestSuite) Cleanup() { + var err error + // From step LoadBalancers_Delete + fmt.Println("Call operation: LoadBalancers_Delete") + loadBalancersClient, err := armnetwork.NewLoadBalancersClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + loadBalancersClientDeleteResponsePoller, err := loadBalancersClient.BeginDelete(testsuite.ctx, testsuite.resourceGroupName, testsuite.loadBalancerName, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, loadBalancersClientDeleteResponsePoller) + testsuite.Require().NoError(err) +} diff --git a/sdk/resourcemanager/network/armnetwork/natgateway_live_test.go b/sdk/resourcemanager/network/armnetwork/natgateway_live_test.go new file mode 100644 index 000000000000..5f23690950c6 --- /dev/null +++ b/sdk/resourcemanager/network/armnetwork/natgateway_live_test.go @@ -0,0 +1,116 @@ +//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. +// Code generated by Microsoft (R) AutoRest Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. + +package armnetwork_test + +import ( + "context" + "fmt" + "testing" + + "github.com/Azure/azure-sdk-for-go/sdk/azcore" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/arm" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/to" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/internal/testutil" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork/v2" + "github.com/stretchr/testify/suite" +) + +type NatGatewayTestSuite struct { + suite.Suite + + ctx context.Context + cred azcore.TokenCredential + options *arm.ClientOptions + natGatewayName string + location string + resourceGroupName string + subscriptionId string +} + +func (testsuite *NatGatewayTestSuite) SetupSuite() { + testutil.StartRecording(testsuite.T(), "sdk/resourcemanager/network/armnetwork/testdata") + + testsuite.ctx = context.Background() + testsuite.cred, testsuite.options = testutil.GetCredAndClientOptions(testsuite.T()) + testsuite.natGatewayName = testutil.GenerateAlphaNumericID(testsuite.T(), "natgateway", 6) + testsuite.location = testutil.GetEnv("LOCATION", "westus") + testsuite.resourceGroupName = testutil.GetEnv("RESOURCE_GROUP_NAME", "scenarioTestTempGroup") + testsuite.subscriptionId = testutil.GetEnv("AZURE_SUBSCRIPTION_ID", "00000000-0000-0000-0000-000000000000") + resourceGroup, _, err := testutil.CreateResourceGroup(testsuite.ctx, testsuite.subscriptionId, testsuite.cred, testsuite.options, testsuite.location) + testsuite.Require().NoError(err) + testsuite.resourceGroupName = *resourceGroup.Name +} + +func (testsuite *NatGatewayTestSuite) TearDownSuite() { + _, err := testutil.DeleteResourceGroup(testsuite.ctx, testsuite.subscriptionId, testsuite.cred, testsuite.options, testsuite.resourceGroupName) + testsuite.Require().NoError(err) + testutil.StopRecording(testsuite.T()) +} + +func TestNatGatewayTestSuite(t *testing.T) { + suite.Run(t, new(NatGatewayTestSuite)) +} + +// Microsoft.Network/natGateways/{natGatewayName} +func (testsuite *NatGatewayTestSuite) TestNatGateways() { + var err error + // From step NatGateways_CreateOrUpdate + fmt.Println("Call operation: NatGateways_CreateOrUpdate") + natGatewaysClient, err := armnetwork.NewNatGatewaysClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + natGatewaysClientCreateOrUpdateResponsePoller, err := natGatewaysClient.BeginCreateOrUpdate(testsuite.ctx, testsuite.resourceGroupName, testsuite.natGatewayName, armnetwork.NatGateway{ + Location: to.Ptr(testsuite.location), + SKU: &armnetwork.NatGatewaySKU{ + Name: to.Ptr(armnetwork.NatGatewaySKUNameStandard), + }, + }, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, natGatewaysClientCreateOrUpdateResponsePoller) + testsuite.Require().NoError(err) + + // From step NatGateways_ListAll + fmt.Println("Call operation: NatGateways_ListAll") + natGatewaysClientNewListAllPager := natGatewaysClient.NewListAllPager(nil) + for natGatewaysClientNewListAllPager.More() { + _, err := natGatewaysClientNewListAllPager.NextPage(testsuite.ctx) + testsuite.Require().NoError(err) + break + } + + // From step NatGateways_Get + fmt.Println("Call operation: NatGateways_Get") + _, err = natGatewaysClient.Get(testsuite.ctx, testsuite.resourceGroupName, testsuite.natGatewayName, &armnetwork.NatGatewaysClientGetOptions{Expand: nil}) + testsuite.Require().NoError(err) + + // From step NatGateways_List + fmt.Println("Call operation: NatGateways_List") + natGatewaysClientNewListPager := natGatewaysClient.NewListPager(testsuite.resourceGroupName, nil) + for natGatewaysClientNewListPager.More() { + _, err := natGatewaysClientNewListPager.NextPage(testsuite.ctx) + testsuite.Require().NoError(err) + break + } + + // From step NatGateways_UpdateTags + fmt.Println("Call operation: NatGateways_UpdateTags") + _, err = natGatewaysClient.UpdateTags(testsuite.ctx, testsuite.resourceGroupName, testsuite.natGatewayName, armnetwork.TagsObject{ + Tags: map[string]*string{ + "tag1": to.Ptr("value1"), + "tag2": to.Ptr("value2"), + }, + }, nil) + testsuite.Require().NoError(err) + + // From step NatGateways_Delete + fmt.Println("Call operation: NatGateways_Delete") + natGatewaysClientDeleteResponsePoller, err := natGatewaysClient.BeginDelete(testsuite.ctx, testsuite.resourceGroupName, testsuite.natGatewayName, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, natGatewaysClientDeleteResponsePoller) + testsuite.Require().NoError(err) +} diff --git a/sdk/resourcemanager/network/armnetwork/networkinterface_live_test.go b/sdk/resourcemanager/network/armnetwork/networkinterface_live_test.go new file mode 100644 index 000000000000..6dd8fe27300a --- /dev/null +++ b/sdk/resourcemanager/network/armnetwork/networkinterface_live_test.go @@ -0,0 +1,185 @@ +//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. +// Code generated by Microsoft (R) AutoRest Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. + +package armnetwork_test + +import ( + "context" + "fmt" + "testing" + + "github.com/Azure/azure-sdk-for-go/sdk/azcore" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/arm" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/to" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/internal/testutil" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork/v2" + "github.com/stretchr/testify/suite" +) + +type NetworkInterfaceTestSuite struct { + suite.Suite + + ctx context.Context + cred azcore.TokenCredential + options *arm.ClientOptions + networkInterfaceName string + subnetId string + virtualNetworkName string + location string + resourceGroupName string + subscriptionId string +} + +func (testsuite *NetworkInterfaceTestSuite) SetupSuite() { + testutil.StartRecording(testsuite.T(), "sdk/resourcemanager/network/armnetwork/testdata") + + testsuite.ctx = context.Background() + testsuite.cred, testsuite.options = testutil.GetCredAndClientOptions(testsuite.T()) + testsuite.networkInterfaceName = testutil.GenerateAlphaNumericID(testsuite.T(), "networkint", 6) + testsuite.virtualNetworkName = testutil.GenerateAlphaNumericID(testsuite.T(), "vnetinterfacena", 6) + testsuite.location = testutil.GetEnv("LOCATION", "westus") + testsuite.resourceGroupName = testutil.GetEnv("RESOURCE_GROUP_NAME", "scenarioTestTempGroup") + testsuite.subscriptionId = testutil.GetEnv("AZURE_SUBSCRIPTION_ID", "00000000-0000-0000-0000-000000000000") + resourceGroup, _, err := testutil.CreateResourceGroup(testsuite.ctx, testsuite.subscriptionId, testsuite.cred, testsuite.options, testsuite.location) + testsuite.Require().NoError(err) + testsuite.resourceGroupName = *resourceGroup.Name + testsuite.Prepare() +} + +func (testsuite *NetworkInterfaceTestSuite) TearDownSuite() { + _, err := testutil.DeleteResourceGroup(testsuite.ctx, testsuite.subscriptionId, testsuite.cred, testsuite.options, testsuite.resourceGroupName) + testsuite.Require().NoError(err) + testutil.StopRecording(testsuite.T()) +} + +func TestNetworkInterfaceTestSuite(t *testing.T) { + suite.Run(t, new(NetworkInterfaceTestSuite)) +} + +func (testsuite *NetworkInterfaceTestSuite) Prepare() { + var err error + // From step VirtualNetworks_CreateOrUpdate + fmt.Println("Call operation: VirtualNetworks_CreateOrUpdate") + virtualNetworksClient, err := armnetwork.NewVirtualNetworksClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + virtualNetworksClientCreateOrUpdateResponsePoller, err := virtualNetworksClient.BeginCreateOrUpdate(testsuite.ctx, testsuite.resourceGroupName, testsuite.virtualNetworkName, armnetwork.VirtualNetwork{ + Location: to.Ptr(testsuite.location), + Properties: &armnetwork.VirtualNetworkPropertiesFormat{ + AddressSpace: &armnetwork.AddressSpace{ + AddressPrefixes: []*string{ + to.Ptr("10.0.0.0/16")}, + }, + Subnets: []*armnetwork.Subnet{ + { + Name: to.Ptr("test-1"), + Properties: &armnetwork.SubnetPropertiesFormat{ + AddressPrefix: to.Ptr("10.0.0.0/24"), + }, + }}, + }, + }, nil) + testsuite.Require().NoError(err) + var virtualNetworksClientCreateOrUpdateResponse *armnetwork.VirtualNetworksClientCreateOrUpdateResponse + virtualNetworksClientCreateOrUpdateResponse, err = testutil.PollForTest(testsuite.ctx, virtualNetworksClientCreateOrUpdateResponsePoller) + testsuite.Require().NoError(err) + testsuite.subnetId = *virtualNetworksClientCreateOrUpdateResponse.Properties.Subnets[0].ID +} + +// Microsoft.Network/networkInterfaces/{networkInterfaceName} +func (testsuite *NetworkInterfaceTestSuite) TestNetworkInterfaces() { + var err error + // From step NetworkInterfaces_CreateOrUpdate + fmt.Println("Call operation: NetworkInterfaces_CreateOrUpdate") + interfacesClient, err := armnetwork.NewInterfacesClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + interfacesClientCreateOrUpdateResponsePoller, err := interfacesClient.BeginCreateOrUpdate(testsuite.ctx, testsuite.resourceGroupName, testsuite.networkInterfaceName, armnetwork.Interface{ + Location: to.Ptr(testsuite.location), + Properties: &armnetwork.InterfacePropertiesFormat{ + EnableAcceleratedNetworking: to.Ptr(true), + IPConfigurations: []*armnetwork.InterfaceIPConfiguration{ + { + Name: to.Ptr("ipconfig1"), + Properties: &armnetwork.InterfaceIPConfigurationPropertiesFormat{ + Subnet: &armnetwork.Subnet{ + ID: to.Ptr(testsuite.subnetId), + }, + }, + }}, + }, + }, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, interfacesClientCreateOrUpdateResponsePoller) + testsuite.Require().NoError(err) + + // From step NetworkInterfaces_Get + fmt.Println("Call operation: NetworkInterfaces_Get") + _, err = interfacesClient.Get(testsuite.ctx, testsuite.resourceGroupName, testsuite.networkInterfaceName, &armnetwork.InterfacesClientGetOptions{Expand: nil}) + testsuite.Require().NoError(err) + + // From step NetworkInterfaces_UpdateTags + fmt.Println("Call operation: NetworkInterfaces_UpdateTags") + _, err = interfacesClient.UpdateTags(testsuite.ctx, testsuite.resourceGroupName, testsuite.networkInterfaceName, armnetwork.TagsObject{ + Tags: map[string]*string{ + "tag1": to.Ptr("value1"), + "tag2": to.Ptr("value2"), + }, + }, nil) + testsuite.Require().NoError(err) + + // From step NetworkInterfaces_ListAll + fmt.Println("Call operation: NetworkInterfaces_ListAll") + interfacesClientNewListAllPager := interfacesClient.NewListAllPager(nil) + for interfacesClientNewListAllPager.More() { + _, err := interfacesClientNewListAllPager.NextPage(testsuite.ctx) + testsuite.Require().NoError(err) + break + } + + // From step NetworkInterfaces_List + fmt.Println("Call operation: NetworkInterfaces_List") + interfacesClientNewListPager := interfacesClient.NewListPager(testsuite.resourceGroupName, nil) + for interfacesClientNewListPager.More() { + _, err := interfacesClientNewListPager.NextPage(testsuite.ctx) + testsuite.Require().NoError(err) + break + } + + // From step NetworkInterfaceIPConfigurations_List + fmt.Println("Call operation: NetworkInterfaceIPConfigurations_List") + interfaceIPConfigurationsClient, err := armnetwork.NewInterfaceIPConfigurationsClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + interfaceIPConfigurationsClientNewListPager := interfaceIPConfigurationsClient.NewListPager(testsuite.resourceGroupName, testsuite.networkInterfaceName, nil) + for interfaceIPConfigurationsClientNewListPager.More() { + _, err := interfaceIPConfigurationsClientNewListPager.NextPage(testsuite.ctx) + testsuite.Require().NoError(err) + break + } + + // From step NetworkInterfaceIPConfigurations_Get + fmt.Println("Call operation: NetworkInterfaceIPConfigurations_Get") + _, err = interfaceIPConfigurationsClient.Get(testsuite.ctx, testsuite.resourceGroupName, testsuite.networkInterfaceName, "ipconfig1", nil) + testsuite.Require().NoError(err) + + // From step NetworkInterfaceLoadBalancers_List + fmt.Println("Call operation: NetworkInterfaceLoadBalancers_List") + interfaceLoadBalancersClient, err := armnetwork.NewInterfaceLoadBalancersClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + interfaceLoadBalancersClientNewListPager := interfaceLoadBalancersClient.NewListPager(testsuite.resourceGroupName, testsuite.networkInterfaceName, nil) + for interfaceLoadBalancersClientNewListPager.More() { + _, err := interfaceLoadBalancersClientNewListPager.NextPage(testsuite.ctx) + testsuite.Require().NoError(err) + break + } + + // From step NetworkInterfaces_Delete + fmt.Println("Call operation: NetworkInterfaces_Delete") + interfacesClientDeleteResponsePoller, err := interfacesClient.BeginDelete(testsuite.ctx, testsuite.resourceGroupName, testsuite.networkInterfaceName, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, interfacesClientDeleteResponsePoller) + testsuite.Require().NoError(err) +} diff --git a/sdk/resourcemanager/network/armnetwork/networkmanager_live_test.go b/sdk/resourcemanager/network/armnetwork/networkmanager_live_test.go new file mode 100644 index 000000000000..b553a1f14a19 --- /dev/null +++ b/sdk/resourcemanager/network/armnetwork/networkmanager_live_test.go @@ -0,0 +1,169 @@ +//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. +// Code generated by Microsoft (R) AutoRest Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. + +package armnetwork_test + +import ( + "context" + "fmt" + "testing" + + "github.com/Azure/azure-sdk-for-go/sdk/azcore" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/arm" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/to" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/internal/testutil" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork/v2" + "github.com/stretchr/testify/suite" +) + +type NetworkManagerTestSuite struct { + suite.Suite + + ctx context.Context + cred azcore.TokenCredential + options *arm.ClientOptions + networkManagerName string + location string + resourceGroupName string + subscriptionId string +} + +func (testsuite *NetworkManagerTestSuite) SetupSuite() { + testutil.StartRecording(testsuite.T(), "sdk/resourcemanager/network/armnetwork/testdata") + + testsuite.ctx = context.Background() + testsuite.cred, testsuite.options = testutil.GetCredAndClientOptions(testsuite.T()) + testsuite.networkManagerName = testutil.GenerateAlphaNumericID(testsuite.T(), "networkman", 6) + testsuite.location = testutil.GetEnv("LOCATION", "westus") + testsuite.resourceGroupName = testutil.GetEnv("RESOURCE_GROUP_NAME", "scenarioTestTempGroup") + testsuite.subscriptionId = testutil.GetEnv("AZURE_SUBSCRIPTION_ID", "00000000-0000-0000-0000-000000000000") + resourceGroup, _, err := testutil.CreateResourceGroup(testsuite.ctx, testsuite.subscriptionId, testsuite.cred, testsuite.options, testsuite.location) + testsuite.Require().NoError(err) + testsuite.resourceGroupName = *resourceGroup.Name +} + +func (testsuite *NetworkManagerTestSuite) TearDownSuite() { + _, err := testutil.DeleteResourceGroup(testsuite.ctx, testsuite.subscriptionId, testsuite.cred, testsuite.options, testsuite.resourceGroupName) + testsuite.Require().NoError(err) + testutil.StopRecording(testsuite.T()) +} + +func TestNetworkManagerTestSuite(t *testing.T) { + suite.Run(t, new(NetworkManagerTestSuite)) +} + +// Microsoft.Network/networkManagers/{networkManagerName} +func (testsuite *NetworkManagerTestSuite) TestNetworkManagers() { + var err error + // From step NetworkManagers_CreateOrUpdate + fmt.Println("Call operation: NetworkManagers_CreateOrUpdate") + managersClient, err := armnetwork.NewManagersClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + _, err = managersClient.CreateOrUpdate(testsuite.ctx, testsuite.resourceGroupName, testsuite.networkManagerName, armnetwork.Manager{ + Location: to.Ptr(testsuite.location), + Properties: &armnetwork.ManagerProperties{ + Description: to.Ptr("My Test Network Manager"), + NetworkManagerScopeAccesses: []*armnetwork.ConfigurationType{ + to.Ptr(armnetwork.ConfigurationTypeConnectivity)}, + NetworkManagerScopes: &armnetwork.ManagerPropertiesNetworkManagerScopes{ + Subscriptions: []*string{ + to.Ptr("/subscriptions/" + testsuite.subscriptionId)}, + }, + }, + }, nil) + testsuite.Require().NoError(err) + + // From step NetworkManagers_ListBySubscription + fmt.Println("Call operation: NetworkManagers_ListBySubscription") + managersClientNewListBySubscriptionPager := managersClient.NewListBySubscriptionPager(&armnetwork.ManagersClientListBySubscriptionOptions{Top: nil, + SkipToken: nil, + }) + for managersClientNewListBySubscriptionPager.More() { + _, err := managersClientNewListBySubscriptionPager.NextPage(testsuite.ctx) + testsuite.Require().NoError(err) + break + } + + // From step NetworkManagers_List + fmt.Println("Call operation: NetworkManagers_List") + managersClientNewListPager := managersClient.NewListPager(testsuite.resourceGroupName, &armnetwork.ManagersClientListOptions{Top: nil, + SkipToken: nil, + }) + for managersClientNewListPager.More() { + _, err := managersClientNewListPager.NextPage(testsuite.ctx) + testsuite.Require().NoError(err) + break + } + + // From step NetworkManagers_Get + fmt.Println("Call operation: NetworkManagers_Get") + _, err = managersClient.Get(testsuite.ctx, testsuite.resourceGroupName, testsuite.networkManagerName, nil) + testsuite.Require().NoError(err) + + // From step NetworkManagers_Patch + fmt.Println("Call operation: NetworkManagers_Patch") + _, err = managersClient.Patch(testsuite.ctx, testsuite.resourceGroupName, testsuite.networkManagerName, armnetwork.PatchObject{ + Tags: map[string]*string{ + "tag1": to.Ptr("value1"), + "tag2": to.Ptr("value2"), + }, + }, nil) + testsuite.Require().NoError(err) + + // From step NetworkManagerCommits_Post + fmt.Println("Call operation: NetworkManagerCommits_Post") + managerCommitsClient, err := armnetwork.NewManagerCommitsClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + managerCommitsClientPostResponsePoller, err := managerCommitsClient.BeginPost(testsuite.ctx, testsuite.resourceGroupName, testsuite.networkManagerName, armnetwork.ManagerCommit{ + CommitType: to.Ptr(armnetwork.ConfigurationTypeConnectivity), + TargetLocations: []*string{ + to.Ptr("eastus")}, + }, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, managerCommitsClientPostResponsePoller) + testsuite.Require().NoError(err) + + // From step NetworkManagerDeploymentStatus_List + fmt.Println("Call operation: NetworkManagerDeploymentStatus_List") + managerDeploymentStatusClient, err := armnetwork.NewManagerDeploymentStatusClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + _, err = managerDeploymentStatusClient.List(testsuite.ctx, testsuite.resourceGroupName, testsuite.networkManagerName, armnetwork.ManagerDeploymentStatusParameter{ + DeploymentTypes: []*armnetwork.ConfigurationType{ + to.Ptr(armnetwork.ConfigurationTypeConnectivity), + to.Ptr(armnetwork.ConfigurationTypeSecurityAdmin)}, + Regions: []*string{ + to.Ptr("eastus"), + to.Ptr("westus")}, + }, &armnetwork.ManagerDeploymentStatusClientListOptions{Top: nil}) + testsuite.Require().NoError(err) + + // From step ListActiveConnectivityConfigurations + fmt.Println("Call operation: NetworkManagementClient_ListActiveConnectivityConfigurations") + managementClient, err := armnetwork.NewManagementClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + _, err = managementClient.ListActiveConnectivityConfigurations(testsuite.ctx, testsuite.resourceGroupName, testsuite.networkManagerName, armnetwork.ActiveConfigurationParameter{ + Regions: []*string{ + to.Ptr("westus")}, + }, &armnetwork.ManagementClientListActiveConnectivityConfigurationsOptions{Top: nil}) + testsuite.Require().NoError(err) + + // From step ListActiveSecurityAdminRules + fmt.Println("Call operation: NetworkManagementClient_ListActiveSecurityAdminRules") + _, err = managementClient.ListActiveSecurityAdminRules(testsuite.ctx, testsuite.resourceGroupName, testsuite.networkManagerName, armnetwork.ActiveConfigurationParameter{ + Regions: []*string{ + to.Ptr("westus")}, + }, &armnetwork.ManagementClientListActiveSecurityAdminRulesOptions{Top: nil}) + testsuite.Require().NoError(err) + + // From step NetworkManagers_Delete + fmt.Println("Call operation: NetworkManagers_Delete") + managersClientDeleteResponsePoller, err := managersClient.BeginDelete(testsuite.ctx, testsuite.resourceGroupName, testsuite.networkManagerName, &armnetwork.ManagersClientBeginDeleteOptions{Force: to.Ptr(true)}) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, managersClientDeleteResponsePoller) + testsuite.Require().NoError(err) +} diff --git a/sdk/resourcemanager/network/armnetwork/networkmanagerconnection_live_test.go b/sdk/resourcemanager/network/armnetwork/networkmanagerconnection_live_test.go new file mode 100644 index 000000000000..cedbb8812208 --- /dev/null +++ b/sdk/resourcemanager/network/armnetwork/networkmanagerconnection_live_test.go @@ -0,0 +1,121 @@ +//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. +// Code generated by Microsoft (R) AutoRest Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. + +package armnetwork_test + +import ( + "context" + "fmt" + "testing" + + "github.com/Azure/azure-sdk-for-go/sdk/azcore" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/arm" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/to" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/internal/testutil" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork/v2" + "github.com/stretchr/testify/suite" +) + +type NetworkManagerConnectionTestSuite struct { + suite.Suite + + ctx context.Context + cred azcore.TokenCredential + options *arm.ClientOptions + networkManagerConnectionName string + networkManagerId string + networkManagerName string + location string + resourceGroupName string + subscriptionId string +} + +func (testsuite *NetworkManagerConnectionTestSuite) SetupSuite() { + testutil.StartRecording(testsuite.T(), "sdk/resourcemanager/network/armnetwork/testdata") + + testsuite.ctx = context.Background() + testsuite.cred, testsuite.options = testutil.GetCredAndClientOptions(testsuite.T()) + testsuite.networkManagerConnectionName = testutil.GenerateAlphaNumericID(testsuite.T(), "netmanagerconnsub", 6) + testsuite.networkManagerName = testutil.GenerateAlphaNumericID(testsuite.T(), "networkmanagerconn", 6) + testsuite.location = testutil.GetEnv("LOCATION", "westus") + testsuite.resourceGroupName = testutil.GetEnv("RESOURCE_GROUP_NAME", "scenarioTestTempGroup") + testsuite.subscriptionId = testutil.GetEnv("AZURE_SUBSCRIPTION_ID", "00000000-0000-0000-0000-000000000000") + resourceGroup, _, err := testutil.CreateResourceGroup(testsuite.ctx, testsuite.subscriptionId, testsuite.cred, testsuite.options, testsuite.location) + testsuite.Require().NoError(err) + testsuite.resourceGroupName = *resourceGroup.Name + testsuite.Prepare() +} + +func (testsuite *NetworkManagerConnectionTestSuite) TearDownSuite() { + _, err := testutil.DeleteResourceGroup(testsuite.ctx, testsuite.subscriptionId, testsuite.cred, testsuite.options, testsuite.resourceGroupName) + testsuite.Require().NoError(err) + testutil.StopRecording(testsuite.T()) +} + +func TestNetworkManagerConnectionTestSuite(t *testing.T) { + suite.Run(t, new(NetworkManagerConnectionTestSuite)) +} + +func (testsuite *NetworkManagerConnectionTestSuite) Prepare() { + var err error + // From step NetworkManagers_CreateOrUpdate + fmt.Println("Call operation: NetworkManagers_CreateOrUpdate") + managersClient, err := armnetwork.NewManagersClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + managersClientCreateOrUpdateResponse, err := managersClient.CreateOrUpdate(testsuite.ctx, testsuite.resourceGroupName, testsuite.networkManagerName, armnetwork.Manager{ + Location: to.Ptr(testsuite.location), + Properties: &armnetwork.ManagerProperties{ + Description: to.Ptr("My Test Network Manager"), + NetworkManagerScopeAccesses: []*armnetwork.ConfigurationType{ + to.Ptr(armnetwork.ConfigurationTypeConnectivity)}, + NetworkManagerScopes: &armnetwork.ManagerPropertiesNetworkManagerScopes{ + Subscriptions: []*string{ + to.Ptr("/subscriptions/" + testsuite.subscriptionId), + }, + }, + }, + }, nil) + testsuite.Require().NoError(err) + testsuite.networkManagerId = *managersClientCreateOrUpdateResponse.ID +} + +// Microsoft.Network/networkManagerConnections/{networkManagerConnectionName} +func (testsuite *NetworkManagerConnectionTestSuite) TestSubscriptionNetworkManagerConnections() { + var err error + // From step SubscriptionNetworkManagerConnections_CreateOrUpdate + fmt.Println("Call operation: SubscriptionNetworkManagerConnections_CreateOrUpdate") + subscriptionNetworkManagerConnectionsClient, err := armnetwork.NewSubscriptionNetworkManagerConnectionsClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + _, err = subscriptionNetworkManagerConnectionsClient.CreateOrUpdate(testsuite.ctx, testsuite.networkManagerConnectionName, armnetwork.ManagerConnection{ + Properties: &armnetwork.ManagerConnectionProperties{ + NetworkManagerID: to.Ptr(testsuite.networkManagerId), + }, + }, nil) + testsuite.Require().NoError(err) + + // From step SubscriptionNetworkManagerConnections_List + fmt.Println("Call operation: SubscriptionNetworkManagerConnections_List") + subscriptionNetworkManagerConnectionsClientNewListPager := subscriptionNetworkManagerConnectionsClient.NewListPager(&armnetwork.SubscriptionNetworkManagerConnectionsClientListOptions{Top: nil, + SkipToken: nil, + }) + for subscriptionNetworkManagerConnectionsClientNewListPager.More() { + _, err := subscriptionNetworkManagerConnectionsClientNewListPager.NextPage(testsuite.ctx) + testsuite.Require().NoError(err) + break + } + + // From step SubscriptionNetworkManagerConnections_Get + fmt.Println("Call operation: SubscriptionNetworkManagerConnections_Get") + _, err = subscriptionNetworkManagerConnectionsClient.Get(testsuite.ctx, testsuite.networkManagerConnectionName, nil) + testsuite.Require().NoError(err) + + // From step SubscriptionNetworkManagerConnections_Delete + fmt.Println("Call operation: SubscriptionNetworkManagerConnections_Delete") + _, err = subscriptionNetworkManagerConnectionsClient.Delete(testsuite.ctx, testsuite.networkManagerConnectionName, nil) + testsuite.Require().NoError(err) +} diff --git a/sdk/resourcemanager/network/armnetwork/networkmanagerconnectivityconfiguration_live_test.go b/sdk/resourcemanager/network/armnetwork/networkmanagerconnectivityconfiguration_live_test.go new file mode 100644 index 000000000000..c76c78d04438 --- /dev/null +++ b/sdk/resourcemanager/network/armnetwork/networkmanagerconnectivityconfiguration_live_test.go @@ -0,0 +1,145 @@ +//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. +// Code generated by Microsoft (R) AutoRest Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. + +package armnetwork_test + +import ( + "context" + "fmt" + "testing" + + "github.com/Azure/azure-sdk-for-go/sdk/azcore" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/arm" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/to" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/internal/testutil" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork/v2" + "github.com/stretchr/testify/suite" +) + +type NetworkManagerConnectivityConfigurationTestSuite struct { + suite.Suite + + ctx context.Context + cred azcore.TokenCredential + options *arm.ClientOptions + configurationName string + networkGroupId string + networkGroupName string + networkManagerName string + location string + resourceGroupName string + subscriptionId string +} + +func (testsuite *NetworkManagerConnectivityConfigurationTestSuite) SetupSuite() { + testutil.StartRecording(testsuite.T(), "sdk/resourcemanager/network/armnetwork/testdata") + + testsuite.ctx = context.Background() + testsuite.cred, testsuite.options = testutil.GetCredAndClientOptions(testsuite.T()) + testsuite.configurationName = testutil.GenerateAlphaNumericID(testsuite.T(), "connectivityconf", 6) + testsuite.networkGroupName = testutil.GenerateAlphaNumericID(testsuite.T(), "networkgroconeconfig", 6) + testsuite.networkManagerName = testutil.GenerateAlphaNumericID(testsuite.T(), "networkmancc", 6) + testsuite.location = testutil.GetEnv("LOCATION", "westus") + testsuite.resourceGroupName = testutil.GetEnv("RESOURCE_GROUP_NAME", "scenarioTestTempGroup") + testsuite.subscriptionId = testutil.GetEnv("AZURE_SUBSCRIPTION_ID", "00000000-0000-0000-0000-000000000000") + resourceGroup, _, err := testutil.CreateResourceGroup(testsuite.ctx, testsuite.subscriptionId, testsuite.cred, testsuite.options, testsuite.location) + testsuite.Require().NoError(err) + testsuite.resourceGroupName = *resourceGroup.Name + testsuite.Prepare() +} + +func (testsuite *NetworkManagerConnectivityConfigurationTestSuite) TearDownSuite() { + _, err := testutil.DeleteResourceGroup(testsuite.ctx, testsuite.subscriptionId, testsuite.cred, testsuite.options, testsuite.resourceGroupName) + testsuite.Require().NoError(err) + testutil.StopRecording(testsuite.T()) +} + +func TestNetworkManagerConnectivityConfigurationTestSuite(t *testing.T) { + suite.Run(t, new(NetworkManagerConnectivityConfigurationTestSuite)) +} + +func (testsuite *NetworkManagerConnectivityConfigurationTestSuite) Prepare() { + var err error + // From step NetworkManagers_CreateOrUpdate + fmt.Println("Call operation: NetworkManagers_CreateOrUpdate") + managersClient, err := armnetwork.NewManagersClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + _, err = managersClient.CreateOrUpdate(testsuite.ctx, testsuite.resourceGroupName, testsuite.networkManagerName, armnetwork.Manager{ + Location: to.Ptr(testsuite.location), + Properties: &armnetwork.ManagerProperties{ + Description: to.Ptr("My Test Network Manager"), + NetworkManagerScopeAccesses: []*armnetwork.ConfigurationType{ + to.Ptr(armnetwork.ConfigurationTypeConnectivity)}, + NetworkManagerScopes: &armnetwork.ManagerPropertiesNetworkManagerScopes{ + Subscriptions: []*string{ + to.Ptr("/subscriptions/" + testsuite.subscriptionId)}, + }, + }, + }, nil) + testsuite.Require().NoError(err) + + // From step NetworkGroups_CreateOrUpdate + fmt.Println("Call operation: NetworkGroups_CreateOrUpdate") + groupsClient, err := armnetwork.NewGroupsClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + groupsClientCreateOrUpdateResponse, err := groupsClient.CreateOrUpdate(testsuite.ctx, testsuite.resourceGroupName, testsuite.networkManagerName, testsuite.networkGroupName, armnetwork.Group{ + Properties: &armnetwork.GroupProperties{ + Description: to.Ptr("A sample group"), + }, + }, &armnetwork.GroupsClientCreateOrUpdateOptions{IfMatch: nil}) + testsuite.Require().NoError(err) + testsuite.networkGroupId = *groupsClientCreateOrUpdateResponse.ID +} + +// Microsoft.Network/networkManagers/{networkManagerName}/connectivityConfigurations/{configurationName} +func (testsuite *NetworkManagerConnectivityConfigurationTestSuite) TestConnectivityConfigurations() { + var err error + // From step ConnectivityConfigurations_CreateOrUpdate + fmt.Println("Call operation: ConnectivityConfigurations_CreateOrUpdate") + connectivityConfigurationsClient, err := armnetwork.NewConnectivityConfigurationsClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + _, err = connectivityConfigurationsClient.CreateOrUpdate(testsuite.ctx, testsuite.resourceGroupName, testsuite.networkManagerName, testsuite.configurationName, armnetwork.ConnectivityConfiguration{ + Properties: &armnetwork.ConnectivityConfigurationProperties{ + Description: to.Ptr("Sample Configuration"), + AppliesToGroups: []*armnetwork.ConnectivityGroupItem{ + { + GroupConnectivity: to.Ptr(armnetwork.GroupConnectivityNone), + IsGlobal: to.Ptr(armnetwork.IsGlobalFalse), + NetworkGroupID: to.Ptr(testsuite.networkGroupId), + UseHubGateway: to.Ptr(armnetwork.UseHubGatewayTrue), + }}, + ConnectivityTopology: to.Ptr(armnetwork.ConnectivityTopologyMesh), + DeleteExistingPeering: to.Ptr(armnetwork.DeleteExistingPeeringTrue), + IsGlobal: to.Ptr(armnetwork.IsGlobalTrue), + }, + }, nil) + testsuite.Require().NoError(err) + + // From step ConnectivityConfigurations_List + fmt.Println("Call operation: ConnectivityConfigurations_List") + connectivityConfigurationsClientNewListPager := connectivityConfigurationsClient.NewListPager(testsuite.resourceGroupName, testsuite.networkManagerName, &armnetwork.ConnectivityConfigurationsClientListOptions{Top: nil, + SkipToken: nil, + }) + for connectivityConfigurationsClientNewListPager.More() { + _, err := connectivityConfigurationsClientNewListPager.NextPage(testsuite.ctx) + testsuite.Require().NoError(err) + break + } + + // From step ConnectivityConfigurations_Get + fmt.Println("Call operation: ConnectivityConfigurations_Get") + _, err = connectivityConfigurationsClient.Get(testsuite.ctx, testsuite.resourceGroupName, testsuite.networkManagerName, testsuite.configurationName, nil) + testsuite.Require().NoError(err) + + // From step ConnectivityConfigurations_Delete + fmt.Println("Call operation: ConnectivityConfigurations_Delete") + connectivityConfigurationsClientDeleteResponsePoller, err := connectivityConfigurationsClient.BeginDelete(testsuite.ctx, testsuite.resourceGroupName, testsuite.networkManagerName, testsuite.configurationName, &armnetwork.ConnectivityConfigurationsClientBeginDeleteOptions{Force: to.Ptr(false)}) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, connectivityConfigurationsClientDeleteResponsePoller) + testsuite.Require().NoError(err) +} diff --git a/sdk/resourcemanager/network/armnetwork/networkmanagergroup_live_test.go b/sdk/resourcemanager/network/armnetwork/networkmanagergroup_live_test.go new file mode 100644 index 000000000000..9d1e513855b7 --- /dev/null +++ b/sdk/resourcemanager/network/armnetwork/networkmanagergroup_live_test.go @@ -0,0 +1,188 @@ +//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. +// Code generated by Microsoft (R) AutoRest Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. + +package armnetwork_test + +import ( + "context" + "fmt" + "testing" + + "github.com/Azure/azure-sdk-for-go/sdk/azcore" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/arm" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/to" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/internal/testutil" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork/v2" + "github.com/stretchr/testify/suite" +) + +type NetworkManagerGroupTestSuite struct { + suite.Suite + + ctx context.Context + cred azcore.TokenCredential + options *arm.ClientOptions + networkGroupName string + networkManagerName string + staticMemberName string + location string + resourceGroupName string + subscriptionId string +} + +func (testsuite *NetworkManagerGroupTestSuite) SetupSuite() { + testutil.StartRecording(testsuite.T(), "sdk/resourcemanager/network/armnetwork/testdata") + + testsuite.ctx = context.Background() + testsuite.cred, testsuite.options = testutil.GetCredAndClientOptions(testsuite.T()) + testsuite.networkGroupName = testutil.GenerateAlphaNumericID(testsuite.T(), "networkgro", 6) + testsuite.networkManagerName = testutil.GenerateAlphaNumericID(testsuite.T(), "networkmanagergp", 6) + testsuite.staticMemberName = testutil.GenerateAlphaNumericID(testsuite.T(), "staticmemberna", 6) + testsuite.location = testutil.GetEnv("LOCATION", "westus") + testsuite.resourceGroupName = testutil.GetEnv("RESOURCE_GROUP_NAME", "scenarioTestTempGroup") + testsuite.subscriptionId = testutil.GetEnv("AZURE_SUBSCRIPTION_ID", "00000000-0000-0000-0000-000000000000") + resourceGroup, _, err := testutil.CreateResourceGroup(testsuite.ctx, testsuite.subscriptionId, testsuite.cred, testsuite.options, testsuite.location) + testsuite.Require().NoError(err) + testsuite.resourceGroupName = *resourceGroup.Name + testsuite.Prepare() +} + +func (testsuite *NetworkManagerGroupTestSuite) TearDownSuite() { + testsuite.Cleanup() + _, err := testutil.DeleteResourceGroup(testsuite.ctx, testsuite.subscriptionId, testsuite.cred, testsuite.options, testsuite.resourceGroupName) + testsuite.Require().NoError(err) + testutil.StopRecording(testsuite.T()) +} + +func TestNetworkManagerGroupTestSuite(t *testing.T) { + suite.Run(t, new(NetworkManagerGroupTestSuite)) +} + +func (testsuite *NetworkManagerGroupTestSuite) Prepare() { + var err error + // From step NetworkManagers_CreateOrUpdate + fmt.Println("Call operation: NetworkManagers_CreateOrUpdate") + managersClient, err := armnetwork.NewManagersClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + _, err = managersClient.CreateOrUpdate(testsuite.ctx, testsuite.resourceGroupName, testsuite.networkManagerName, armnetwork.Manager{ + Location: to.Ptr(testsuite.location), + Properties: &armnetwork.ManagerProperties{ + Description: to.Ptr("My Test Network Manager"), + NetworkManagerScopeAccesses: []*armnetwork.ConfigurationType{ + to.Ptr(armnetwork.ConfigurationTypeConnectivity)}, + NetworkManagerScopes: &armnetwork.ManagerPropertiesNetworkManagerScopes{ + Subscriptions: []*string{ + to.Ptr("/subscriptions/" + testsuite.subscriptionId)}, + }, + }, + }, nil) + testsuite.Require().NoError(err) + + // From step NetworkGroups_CreateOrUpdate + fmt.Println("Call operation: NetworkGroups_CreateOrUpdate") + groupsClient, err := armnetwork.NewGroupsClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + _, err = groupsClient.CreateOrUpdate(testsuite.ctx, testsuite.resourceGroupName, testsuite.networkManagerName, testsuite.networkGroupName, armnetwork.Group{ + Properties: &armnetwork.GroupProperties{ + Description: to.Ptr("A sample group"), + }, + }, &armnetwork.GroupsClientCreateOrUpdateOptions{IfMatch: nil}) + testsuite.Require().NoError(err) +} + +// Microsoft.Network/networkManagers/{networkManagerName}/networkGroups/{networkGroupName} +func (testsuite *NetworkManagerGroupTestSuite) TestNetworkGroups() { + var err error + // From step NetworkGroups_List + fmt.Println("Call operation: NetworkGroups_List") + groupsClient, err := armnetwork.NewGroupsClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + groupsClientNewListPager := groupsClient.NewListPager(testsuite.resourceGroupName, testsuite.networkManagerName, &armnetwork.GroupsClientListOptions{Top: nil, + SkipToken: nil, + }) + for groupsClientNewListPager.More() { + _, err := groupsClientNewListPager.NextPage(testsuite.ctx) + testsuite.Require().NoError(err) + break + } + + // From step NetworkGroups_Get + fmt.Println("Call operation: NetworkGroups_Get") + _, err = groupsClient.Get(testsuite.ctx, testsuite.resourceGroupName, testsuite.networkManagerName, testsuite.networkGroupName, nil) + testsuite.Require().NoError(err) +} + +// Microsoft.Network/networkManagers/{networkManagerName}/networkGroups/{networkGroupName}/staticMembers/{staticMemberName} +func (testsuite *NetworkManagerGroupTestSuite) TestStaticMembers() { + virtualNetworkName := testutil.GenerateAlphaNumericID(testsuite.T(), "networkgrovet", 6) + var virutalNetworkId string + var err error + // From step VirtualNetworks_CreateOrUpdate + fmt.Println("Call operation: VirtualNetworks_CreateOrUpdate") + virtualNetworksClient, err := armnetwork.NewVirtualNetworksClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + virtualNetworksClientCreateOrUpdateResponsePoller, err := virtualNetworksClient.BeginCreateOrUpdate(testsuite.ctx, testsuite.resourceGroupName, virtualNetworkName, armnetwork.VirtualNetwork{ + Location: to.Ptr(testsuite.location), + Properties: &armnetwork.VirtualNetworkPropertiesFormat{ + AddressSpace: &armnetwork.AddressSpace{ + AddressPrefixes: []*string{ + to.Ptr("10.0.0.0/16")}, + }, + FlowTimeoutInMinutes: to.Ptr[int32](10), + }, + }, nil) + testsuite.Require().NoError(err) + var virtualNetworksClientCreateOrUpdateResponse *armnetwork.VirtualNetworksClientCreateOrUpdateResponse + virtualNetworksClientCreateOrUpdateResponse, err = testutil.PollForTest(testsuite.ctx, virtualNetworksClientCreateOrUpdateResponsePoller) + testsuite.Require().NoError(err) + virutalNetworkId = *virtualNetworksClientCreateOrUpdateResponse.ID + + // From step StaticMembers_CreateOrUpdate + fmt.Println("Call operation: StaticMembers_CreateOrUpdate") + staticMembersClient, err := armnetwork.NewStaticMembersClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + _, err = staticMembersClient.CreateOrUpdate(testsuite.ctx, testsuite.resourceGroupName, testsuite.networkManagerName, testsuite.networkGroupName, testsuite.staticMemberName, armnetwork.StaticMember{ + Properties: &armnetwork.StaticMemberProperties{ + ResourceID: to.Ptr(virutalNetworkId), + }, + }, nil) + testsuite.Require().NoError(err) + + // From step StaticMembers_List + fmt.Println("Call operation: StaticMembers_List") + staticMembersClientNewListPager := staticMembersClient.NewListPager(testsuite.resourceGroupName, testsuite.networkManagerName, testsuite.networkGroupName, &armnetwork.StaticMembersClientListOptions{Top: nil, + SkipToken: nil, + }) + for staticMembersClientNewListPager.More() { + _, err := staticMembersClientNewListPager.NextPage(testsuite.ctx) + testsuite.Require().NoError(err) + break + } + + // From step StaticMembers_Get + fmt.Println("Call operation: StaticMembers_Get") + _, err = staticMembersClient.Get(testsuite.ctx, testsuite.resourceGroupName, testsuite.networkManagerName, testsuite.networkGroupName, testsuite.staticMemberName, nil) + testsuite.Require().NoError(err) + + // From step StaticMembers_Delete + fmt.Println("Call operation: StaticMembers_Delete") + _, err = staticMembersClient.Delete(testsuite.ctx, testsuite.resourceGroupName, testsuite.networkManagerName, testsuite.networkGroupName, testsuite.staticMemberName, nil) + testsuite.Require().NoError(err) +} + +func (testsuite *NetworkManagerGroupTestSuite) Cleanup() { + var err error + // From step NetworkGroups_Delete + fmt.Println("Call operation: NetworkGroups_Delete") + groupsClient, err := armnetwork.NewGroupsClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + groupsClientDeleteResponsePoller, err := groupsClient.BeginDelete(testsuite.ctx, testsuite.resourceGroupName, testsuite.networkManagerName, testsuite.networkGroupName, &armnetwork.GroupsClientBeginDeleteOptions{Force: to.Ptr(false)}) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, groupsClientDeleteResponsePoller) + testsuite.Require().NoError(err) +} diff --git a/sdk/resourcemanager/network/armnetwork/networkmanagersecurityadminconfiguration_live_test.go b/sdk/resourcemanager/network/armnetwork/networkmanagersecurityadminconfiguration_live_test.go new file mode 100644 index 000000000000..389e7bfa8603 --- /dev/null +++ b/sdk/resourcemanager/network/armnetwork/networkmanagersecurityadminconfiguration_live_test.go @@ -0,0 +1,252 @@ +//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. +// Code generated by Microsoft (R) AutoRest Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. + +package armnetwork_test + +import ( + "context" + "fmt" + "testing" + + "github.com/Azure/azure-sdk-for-go/sdk/azcore" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/arm" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/to" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/internal/testutil" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork/v2" + "github.com/stretchr/testify/suite" +) + +type NetworkManagerSecurityAdminConfigurationTestSuite struct { + suite.Suite + + ctx context.Context + cred azcore.TokenCredential + options *arm.ClientOptions + configurationName string + networkGroupId string + networkGroupName string + networkManagerName string + ruleCollectionName string + ruleName string + location string + resourceGroupName string + subscriptionId string +} + +func (testsuite *NetworkManagerSecurityAdminConfigurationTestSuite) SetupSuite() { + testutil.StartRecording(testsuite.T(), "sdk/resourcemanager/network/armnetwork/testdata") + + testsuite.ctx = context.Background() + testsuite.cred, testsuite.options = testutil.GetCredAndClientOptions(testsuite.T()) + testsuite.configurationName = testutil.GenerateAlphaNumericID(testsuite.T(), "configurationsecurity", 6) + testsuite.networkGroupName = testutil.GenerateAlphaNumericID(testsuite.T(), "networkgrosecurity", 6) + testsuite.networkManagerName = testutil.GenerateAlphaNumericID(testsuite.T(), "networkmanagersecurity", 6) + testsuite.ruleCollectionName = testutil.GenerateAlphaNumericID(testsuite.T(), "rulecollec", 6) + testsuite.ruleName = testutil.GenerateAlphaNumericID(testsuite.T(), "rulename", 6) + testsuite.location = testutil.GetEnv("LOCATION", "westus") + testsuite.resourceGroupName = testutil.GetEnv("RESOURCE_GROUP_NAME", "scenarioTestTempGroup") + testsuite.subscriptionId = testutil.GetEnv("AZURE_SUBSCRIPTION_ID", "00000000-0000-0000-0000-000000000000") + resourceGroup, _, err := testutil.CreateResourceGroup(testsuite.ctx, testsuite.subscriptionId, testsuite.cred, testsuite.options, testsuite.location) + testsuite.Require().NoError(err) + testsuite.resourceGroupName = *resourceGroup.Name + testsuite.Prepare() +} + +func (testsuite *NetworkManagerSecurityAdminConfigurationTestSuite) TearDownSuite() { + testsuite.Cleanup() + _, err := testutil.DeleteResourceGroup(testsuite.ctx, testsuite.subscriptionId, testsuite.cred, testsuite.options, testsuite.resourceGroupName) + testsuite.Require().NoError(err) + testutil.StopRecording(testsuite.T()) +} + +func TestNetworkManagerSecurityAdminConfigurationTestSuite(t *testing.T) { + suite.Run(t, new(NetworkManagerSecurityAdminConfigurationTestSuite)) +} + +func (testsuite *NetworkManagerSecurityAdminConfigurationTestSuite) Prepare() { + var err error + // From step NetworkManagers_CreateOrUpdate + fmt.Println("Call operation: NetworkManagers_CreateOrUpdate") + managersClient, err := armnetwork.NewManagersClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + _, err = managersClient.CreateOrUpdate(testsuite.ctx, testsuite.resourceGroupName, testsuite.networkManagerName, armnetwork.Manager{ + Location: to.Ptr(testsuite.location), + Properties: &armnetwork.ManagerProperties{ + Description: to.Ptr("My Test Network Manager"), + NetworkManagerScopeAccesses: []*armnetwork.ConfigurationType{ + to.Ptr(armnetwork.ConfigurationTypeSecurityAdmin)}, + NetworkManagerScopes: &armnetwork.ManagerPropertiesNetworkManagerScopes{ + Subscriptions: []*string{ + to.Ptr("/subscriptions/" + testsuite.subscriptionId)}, + }, + }, + }, nil) + testsuite.Require().NoError(err) + + // From step NetworkGroups_CreateOrUpdate + fmt.Println("Call operation: NetworkGroups_CreateOrUpdate") + groupsClient, err := armnetwork.NewGroupsClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + groupsClientCreateOrUpdateResponse, err := groupsClient.CreateOrUpdate(testsuite.ctx, testsuite.resourceGroupName, testsuite.networkManagerName, testsuite.networkGroupName, armnetwork.Group{ + Properties: &armnetwork.GroupProperties{ + Description: to.Ptr("A sample group"), + }, + }, &armnetwork.GroupsClientCreateOrUpdateOptions{IfMatch: nil}) + testsuite.Require().NoError(err) + testsuite.networkGroupId = *groupsClientCreateOrUpdateResponse.ID + + // From step SecurityAdminConfigurations_CreateOrUpdate + fmt.Println("Call operation: SecurityAdminConfigurations_CreateOrUpdate") + securityAdminConfigurationsClient, err := armnetwork.NewSecurityAdminConfigurationsClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + _, err = securityAdminConfigurationsClient.CreateOrUpdate(testsuite.ctx, testsuite.resourceGroupName, testsuite.networkManagerName, testsuite.configurationName, armnetwork.SecurityAdminConfiguration{ + Properties: &armnetwork.SecurityAdminConfigurationPropertiesFormat{ + Description: to.Ptr("A sample policy"), + ApplyOnNetworkIntentPolicyBasedServices: []*armnetwork.NetworkIntentPolicyBasedService{ + to.Ptr(armnetwork.NetworkIntentPolicyBasedServiceNone)}, + }, + }, nil) + testsuite.Require().NoError(err) + + // From step AdminRuleCollections_CreateOrUpdate + fmt.Println("Call operation: AdminRuleCollections_CreateOrUpdate") + adminRuleCollectionsClient, err := armnetwork.NewAdminRuleCollectionsClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + _, err = adminRuleCollectionsClient.CreateOrUpdate(testsuite.ctx, testsuite.resourceGroupName, testsuite.networkManagerName, testsuite.configurationName, testsuite.ruleCollectionName, armnetwork.AdminRuleCollection{ + Properties: &armnetwork.AdminRuleCollectionPropertiesFormat{ + Description: to.Ptr("A sample policy"), + AppliesToGroups: []*armnetwork.ManagerSecurityGroupItem{ + { + NetworkGroupID: to.Ptr(testsuite.networkGroupId), + }}, + }, + }, nil) + testsuite.Require().NoError(err) +} + +// Microsoft.Network/networkManagers/{networkManagerName}/securityAdminConfigurations/{configurationName} +func (testsuite *NetworkManagerSecurityAdminConfigurationTestSuite) TestSecurityAdminConfigurations() { + var err error + // From step SecurityAdminConfigurations_List + fmt.Println("Call operation: SecurityAdminConfigurations_List") + securityAdminConfigurationsClient, err := armnetwork.NewSecurityAdminConfigurationsClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + securityAdminConfigurationsClientNewListPager := securityAdminConfigurationsClient.NewListPager(testsuite.resourceGroupName, testsuite.networkManagerName, &armnetwork.SecurityAdminConfigurationsClientListOptions{Top: nil, + SkipToken: nil, + }) + for securityAdminConfigurationsClientNewListPager.More() { + _, err := securityAdminConfigurationsClientNewListPager.NextPage(testsuite.ctx) + testsuite.Require().NoError(err) + break + } + + // From step SecurityAdminConfigurations_Get + fmt.Println("Call operation: SecurityAdminConfigurations_Get") + _, err = securityAdminConfigurationsClient.Get(testsuite.ctx, testsuite.resourceGroupName, testsuite.networkManagerName, testsuite.configurationName, nil) + testsuite.Require().NoError(err) +} + +// Microsoft.Network/networkManagers/{networkManagerName}/securityAdminConfigurations/{configurationName}/ruleCollections/{ruleCollectionName} +func (testsuite *NetworkManagerSecurityAdminConfigurationTestSuite) TestAdminRuleCollections() { + var err error + // From step AdminRuleCollections_List + fmt.Println("Call operation: AdminRuleCollections_List") + adminRuleCollectionsClient, err := armnetwork.NewAdminRuleCollectionsClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + adminRuleCollectionsClientNewListPager := adminRuleCollectionsClient.NewListPager(testsuite.resourceGroupName, testsuite.networkManagerName, testsuite.configurationName, &armnetwork.AdminRuleCollectionsClientListOptions{Top: nil, + SkipToken: nil, + }) + for adminRuleCollectionsClientNewListPager.More() { + _, err := adminRuleCollectionsClientNewListPager.NextPage(testsuite.ctx) + testsuite.Require().NoError(err) + break + } + + // From step AdminRuleCollections_Get + fmt.Println("Call operation: AdminRuleCollections_Get") + _, err = adminRuleCollectionsClient.Get(testsuite.ctx, testsuite.resourceGroupName, testsuite.networkManagerName, testsuite.configurationName, testsuite.ruleCollectionName, nil) + testsuite.Require().NoError(err) +} + +// Microsoft.Network/networkManagers/{networkManagerName}/securityAdminConfigurations/{configurationName}/ruleCollections/{ruleCollectionName}/rules/{ruleName} +func (testsuite *NetworkManagerSecurityAdminConfigurationTestSuite) TestAdminRules() { + var err error + // From step AdminRules_CreateOrUpdate + fmt.Println("Call operation: AdminRules_CreateOrUpdate") + adminRulesClient, err := armnetwork.NewAdminRulesClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + _, err = adminRulesClient.CreateOrUpdate(testsuite.ctx, testsuite.resourceGroupName, testsuite.networkManagerName, testsuite.configurationName, testsuite.ruleCollectionName, testsuite.ruleName, &armnetwork.AdminRule{ + Kind: to.Ptr(armnetwork.AdminRuleKindCustom), + Properties: &armnetwork.AdminPropertiesFormat{ + Description: to.Ptr("This is Sample Admin Rule"), + Access: to.Ptr(armnetwork.SecurityConfigurationRuleAccessDeny), + DestinationPortRanges: []*string{ + to.Ptr("22")}, + Destinations: []*armnetwork.AddressPrefixItem{ + { + AddressPrefix: to.Ptr("*"), + AddressPrefixType: to.Ptr(armnetwork.AddressPrefixTypeIPPrefix), + }}, + Direction: to.Ptr(armnetwork.SecurityConfigurationRuleDirectionInbound), + Priority: to.Ptr[int32](1), + SourcePortRanges: []*string{ + to.Ptr("0-65535")}, + Sources: []*armnetwork.AddressPrefixItem{ + { + AddressPrefix: to.Ptr("Internet"), + AddressPrefixType: to.Ptr(armnetwork.AddressPrefixTypeServiceTag), + }}, + Protocol: to.Ptr(armnetwork.SecurityConfigurationRuleProtocolTCP), + }, + }, nil) + testsuite.Require().NoError(err) + + // From step AdminRules_List + fmt.Println("Call operation: AdminRules_List") + adminRulesClientNewListPager := adminRulesClient.NewListPager(testsuite.resourceGroupName, testsuite.networkManagerName, testsuite.configurationName, testsuite.ruleCollectionName, &armnetwork.AdminRulesClientListOptions{Top: nil, + SkipToken: nil, + }) + for adminRulesClientNewListPager.More() { + _, err := adminRulesClientNewListPager.NextPage(testsuite.ctx) + testsuite.Require().NoError(err) + break + } + + // From step AdminRules_Get + fmt.Println("Call operation: AdminRules_Get") + _, err = adminRulesClient.Get(testsuite.ctx, testsuite.resourceGroupName, testsuite.networkManagerName, testsuite.configurationName, testsuite.ruleCollectionName, testsuite.ruleName, nil) + testsuite.Require().NoError(err) + + // From step AdminRules_Delete + fmt.Println("Call operation: AdminRules_Delete") + adminRulesClientDeleteResponsePoller, err := adminRulesClient.BeginDelete(testsuite.ctx, testsuite.resourceGroupName, testsuite.networkManagerName, testsuite.configurationName, testsuite.ruleCollectionName, testsuite.ruleName, &armnetwork.AdminRulesClientBeginDeleteOptions{Force: to.Ptr(false)}) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, adminRulesClientDeleteResponsePoller) + testsuite.Require().NoError(err) +} + +func (testsuite *NetworkManagerSecurityAdminConfigurationTestSuite) Cleanup() { + var err error + // From step AdminRuleCollections_Delete + fmt.Println("Call operation: AdminRuleCollections_Delete") + adminRuleCollectionsClient, err := armnetwork.NewAdminRuleCollectionsClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + adminRuleCollectionsClientDeleteResponsePoller, err := adminRuleCollectionsClient.BeginDelete(testsuite.ctx, testsuite.resourceGroupName, testsuite.networkManagerName, testsuite.configurationName, testsuite.ruleCollectionName, &armnetwork.AdminRuleCollectionsClientBeginDeleteOptions{Force: to.Ptr(false)}) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, adminRuleCollectionsClientDeleteResponsePoller) + testsuite.Require().NoError(err) + + // From step SecurityAdminConfigurations_Delete + fmt.Println("Call operation: SecurityAdminConfigurations_Delete") + securityAdminConfigurationsClient, err := armnetwork.NewSecurityAdminConfigurationsClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + securityAdminConfigurationsClientDeleteResponsePoller, err := securityAdminConfigurationsClient.BeginDelete(testsuite.ctx, testsuite.resourceGroupName, testsuite.networkManagerName, testsuite.configurationName, &armnetwork.SecurityAdminConfigurationsClientBeginDeleteOptions{Force: to.Ptr(false)}) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, securityAdminConfigurationsClientDeleteResponsePoller) + testsuite.Require().NoError(err) +} diff --git a/sdk/resourcemanager/network/armnetwork/networkprofile_live_test.go b/sdk/resourcemanager/network/armnetwork/networkprofile_live_test.go new file mode 100644 index 000000000000..8e9874441868 --- /dev/null +++ b/sdk/resourcemanager/network/armnetwork/networkprofile_live_test.go @@ -0,0 +1,161 @@ +//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. +// Code generated by Microsoft (R) AutoRest Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. + +package armnetwork_test + +import ( + "context" + "fmt" + "testing" + + "github.com/Azure/azure-sdk-for-go/sdk/azcore" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/arm" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/to" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/internal/testutil" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork/v2" + "github.com/stretchr/testify/suite" +) + +type NetworkProfileTestSuite struct { + suite.Suite + + ctx context.Context + cred azcore.TokenCredential + options *arm.ClientOptions + networkProfileName string + subnetId string + virtualNetworkName string + location string + resourceGroupName string + subscriptionId string +} + +func (testsuite *NetworkProfileTestSuite) SetupSuite() { + testutil.StartRecording(testsuite.T(), "sdk/resourcemanager/network/armnetwork/testdata") + + testsuite.ctx = context.Background() + testsuite.cred, testsuite.options = testutil.GetCredAndClientOptions(testsuite.T()) + testsuite.networkProfileName = testutil.GenerateAlphaNumericID(testsuite.T(), "networkpro", 6) + testsuite.virtualNetworkName = testutil.GenerateAlphaNumericID(testsuite.T(), "vnetprofilena", 6) + testsuite.location = testutil.GetEnv("LOCATION", "westus") + testsuite.resourceGroupName = testutil.GetEnv("RESOURCE_GROUP_NAME", "scenarioTestTempGroup") + testsuite.subscriptionId = testutil.GetEnv("AZURE_SUBSCRIPTION_ID", "00000000-0000-0000-0000-000000000000") + resourceGroup, _, err := testutil.CreateResourceGroup(testsuite.ctx, testsuite.subscriptionId, testsuite.cred, testsuite.options, testsuite.location) + testsuite.Require().NoError(err) + testsuite.resourceGroupName = *resourceGroup.Name + testsuite.Prepare() +} + +func (testsuite *NetworkProfileTestSuite) TearDownSuite() { + _, err := testutil.DeleteResourceGroup(testsuite.ctx, testsuite.subscriptionId, testsuite.cred, testsuite.options, testsuite.resourceGroupName) + testsuite.Require().NoError(err) + testutil.StopRecording(testsuite.T()) +} + +func TestNetworkProfileTestSuite(t *testing.T) { + suite.Run(t, new(NetworkProfileTestSuite)) +} + +func (testsuite *NetworkProfileTestSuite) Prepare() { + var err error + // From step VirtualNetworks_CreateOrUpdate + fmt.Println("Call operation: VirtualNetworks_CreateOrUpdate") + virtualNetworksClient, err := armnetwork.NewVirtualNetworksClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + virtualNetworksClientCreateOrUpdateResponsePoller, err := virtualNetworksClient.BeginCreateOrUpdate(testsuite.ctx, testsuite.resourceGroupName, testsuite.virtualNetworkName, armnetwork.VirtualNetwork{ + Location: to.Ptr(testsuite.location), + Properties: &armnetwork.VirtualNetworkPropertiesFormat{ + AddressSpace: &armnetwork.AddressSpace{ + AddressPrefixes: []*string{ + to.Ptr("10.0.0.0/16")}, + }, + Subnets: []*armnetwork.Subnet{ + { + Name: to.Ptr("test-1"), + Properties: &armnetwork.SubnetPropertiesFormat{ + AddressPrefix: to.Ptr("10.0.0.0/24"), + }, + }}, + }, + }, nil) + testsuite.Require().NoError(err) + var virtualNetworksClientCreateOrUpdateResponse *armnetwork.VirtualNetworksClientCreateOrUpdateResponse + virtualNetworksClientCreateOrUpdateResponse, err = testutil.PollForTest(testsuite.ctx, virtualNetworksClientCreateOrUpdateResponsePoller) + testsuite.Require().NoError(err) + testsuite.subnetId = *virtualNetworksClientCreateOrUpdateResponse.Properties.Subnets[0].ID +} + +// Microsoft.Network/networkProfiles/{networkProfileName} +func (testsuite *NetworkProfileTestSuite) TestNetworkProfiles() { + var err error + // From step NetworkProfiles_CreateOrUpdate + fmt.Println("Call operation: NetworkProfiles_CreateOrUpdate") + profilesClient, err := armnetwork.NewProfilesClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + _, err = profilesClient.CreateOrUpdate(testsuite.ctx, testsuite.resourceGroupName, testsuite.networkProfileName, armnetwork.Profile{ + Location: to.Ptr(testsuite.location), + Properties: &armnetwork.ProfilePropertiesFormat{ + ContainerNetworkInterfaceConfigurations: []*armnetwork.ContainerNetworkInterfaceConfiguration{ + { + Name: to.Ptr("eth1"), + Properties: &armnetwork.ContainerNetworkInterfaceConfigurationPropertiesFormat{ + IPConfigurations: []*armnetwork.IPConfigurationProfile{ + { + Name: to.Ptr("ipconfig1"), + Properties: &armnetwork.IPConfigurationProfilePropertiesFormat{ + Subnet: &armnetwork.Subnet{ + ID: to.Ptr(testsuite.subnetId), + }, + }, + }}, + }, + }}, + }, + }, nil) + testsuite.Require().NoError(err) + + // From step NetworkProfiles_ListAll + fmt.Println("Call operation: NetworkProfiles_ListAll") + profilesClientNewListAllPager := profilesClient.NewListAllPager(nil) + for profilesClientNewListAllPager.More() { + _, err := profilesClientNewListAllPager.NextPage(testsuite.ctx) + testsuite.Require().NoError(err) + break + } + + // From step NetworkProfiles_List + fmt.Println("Call operation: NetworkProfiles_List") + profilesClientNewListPager := profilesClient.NewListPager(testsuite.resourceGroupName, nil) + for profilesClientNewListPager.More() { + _, err := profilesClientNewListPager.NextPage(testsuite.ctx) + testsuite.Require().NoError(err) + break + } + + // From step NetworkProfiles_Get + fmt.Println("Call operation: NetworkProfiles_Get") + _, err = profilesClient.Get(testsuite.ctx, testsuite.resourceGroupName, testsuite.networkProfileName, &armnetwork.ProfilesClientGetOptions{Expand: nil}) + testsuite.Require().NoError(err) + + // From step NetworkProfiles_UpdateTags + fmt.Println("Call operation: NetworkProfiles_UpdateTags") + _, err = profilesClient.UpdateTags(testsuite.ctx, testsuite.resourceGroupName, testsuite.networkProfileName, armnetwork.TagsObject{ + Tags: map[string]*string{ + "tag1": to.Ptr("value1"), + "tag2": to.Ptr("value2"), + }, + }, nil) + testsuite.Require().NoError(err) + + // From step NetworkProfiles_Delete + fmt.Println("Call operation: NetworkProfiles_Delete") + profilesClientDeleteResponsePoller, err := profilesClient.BeginDelete(testsuite.ctx, testsuite.resourceGroupName, testsuite.networkProfileName, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, profilesClientDeleteResponsePoller) + testsuite.Require().NoError(err) +} diff --git a/sdk/resourcemanager/network/armnetwork/networksecuritygroup_live_test.go b/sdk/resourcemanager/network/armnetwork/networksecuritygroup_live_test.go new file mode 100644 index 000000000000..750388bc491f --- /dev/null +++ b/sdk/resourcemanager/network/armnetwork/networksecuritygroup_live_test.go @@ -0,0 +1,191 @@ +//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. +// Code generated by Microsoft (R) AutoRest Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. + +package armnetwork_test + +import ( + "context" + "fmt" + "testing" + + "github.com/Azure/azure-sdk-for-go/sdk/azcore" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/arm" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/to" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/internal/testutil" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork/v2" + "github.com/stretchr/testify/suite" +) + +type NetworkSecurityGroupTestSuite struct { + suite.Suite + + ctx context.Context + cred azcore.TokenCredential + options *arm.ClientOptions + networkSecurityGroupName string + securityRuleName string + location string + resourceGroupName string + subscriptionId string +} + +func (testsuite *NetworkSecurityGroupTestSuite) SetupSuite() { + testutil.StartRecording(testsuite.T(), "sdk/resourcemanager/network/armnetwork/testdata") + + testsuite.ctx = context.Background() + testsuite.cred, testsuite.options = testutil.GetCredAndClientOptions(testsuite.T()) + testsuite.networkSecurityGroupName = testutil.GenerateAlphaNumericID(testsuite.T(), "networksec", 6) + testsuite.securityRuleName = testutil.GenerateAlphaNumericID(testsuite.T(), "securityru", 6) + testsuite.location = testutil.GetEnv("LOCATION", "westus") + testsuite.resourceGroupName = testutil.GetEnv("RESOURCE_GROUP_NAME", "scenarioTestTempGroup") + testsuite.subscriptionId = testutil.GetEnv("AZURE_SUBSCRIPTION_ID", "00000000-0000-0000-0000-000000000000") + resourceGroup, _, err := testutil.CreateResourceGroup(testsuite.ctx, testsuite.subscriptionId, testsuite.cred, testsuite.options, testsuite.location) + testsuite.Require().NoError(err) + testsuite.resourceGroupName = *resourceGroup.Name + testsuite.Prepare() +} + +func (testsuite *NetworkSecurityGroupTestSuite) TearDownSuite() { + testsuite.Cleanup() + _, err := testutil.DeleteResourceGroup(testsuite.ctx, testsuite.subscriptionId, testsuite.cred, testsuite.options, testsuite.resourceGroupName) + testsuite.Require().NoError(err) + testutil.StopRecording(testsuite.T()) +} + +func TestNetworkSecurityGroupTestSuite(t *testing.T) { + suite.Run(t, new(NetworkSecurityGroupTestSuite)) +} + +func (testsuite *NetworkSecurityGroupTestSuite) Prepare() { + var err error + // From step NetworkSecurityGroups_CreateOrUpdate + fmt.Println("Call operation: NetworkSecurityGroups_CreateOrUpdate") + securityGroupsClient, err := armnetwork.NewSecurityGroupsClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + securityGroupsClientCreateOrUpdateResponsePoller, err := securityGroupsClient.BeginCreateOrUpdate(testsuite.ctx, testsuite.resourceGroupName, testsuite.networkSecurityGroupName, armnetwork.SecurityGroup{ + Location: to.Ptr(testsuite.location), + }, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, securityGroupsClientCreateOrUpdateResponsePoller) + testsuite.Require().NoError(err) +} + +// Microsoft.Network/networkSecurityGroups/{networkSecurityGroupName} +func (testsuite *NetworkSecurityGroupTestSuite) TestNetworkSecurityGroups() { + var err error + // From step NetworkSecurityGroups_ListAll + fmt.Println("Call operation: NetworkSecurityGroups_ListAll") + securityGroupsClient, err := armnetwork.NewSecurityGroupsClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + securityGroupsClientNewListAllPager := securityGroupsClient.NewListAllPager(nil) + for securityGroupsClientNewListAllPager.More() { + _, err := securityGroupsClientNewListAllPager.NextPage(testsuite.ctx) + testsuite.Require().NoError(err) + break + } + + // From step NetworkSecurityGroups_List + fmt.Println("Call operation: NetworkSecurityGroups_List") + securityGroupsClientNewListPager := securityGroupsClient.NewListPager(testsuite.resourceGroupName, nil) + for securityGroupsClientNewListPager.More() { + _, err := securityGroupsClientNewListPager.NextPage(testsuite.ctx) + testsuite.Require().NoError(err) + break + } + + // From step NetworkSecurityGroups_Get + fmt.Println("Call operation: NetworkSecurityGroups_Get") + _, err = securityGroupsClient.Get(testsuite.ctx, testsuite.resourceGroupName, testsuite.networkSecurityGroupName, &armnetwork.SecurityGroupsClientGetOptions{Expand: nil}) + testsuite.Require().NoError(err) + + // From step NetworkSecurityGroups_UpdateTags + fmt.Println("Call operation: NetworkSecurityGroups_UpdateTags") + _, err = securityGroupsClient.UpdateTags(testsuite.ctx, testsuite.resourceGroupName, testsuite.networkSecurityGroupName, armnetwork.TagsObject{ + Tags: map[string]*string{ + "tag1": to.Ptr("value1"), + "tag2": to.Ptr("value2"), + }, + }, nil) + testsuite.Require().NoError(err) +} + +// Microsoft.Network/networkSecurityGroups/{networkSecurityGroupName}/securityRules/{securityRuleName} +func (testsuite *NetworkSecurityGroupTestSuite) TestSecurityRules() { + var defaultSecurityRuleName string + var err error + // From step SecurityRules_CreateOrUpdate + fmt.Println("Call operation: SecurityRules_CreateOrUpdate") + securityRulesClient, err := armnetwork.NewSecurityRulesClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + securityRulesClientCreateOrUpdateResponsePoller, err := securityRulesClient.BeginCreateOrUpdate(testsuite.ctx, testsuite.resourceGroupName, testsuite.networkSecurityGroupName, testsuite.securityRuleName, armnetwork.SecurityRule{ + Properties: &armnetwork.SecurityRulePropertiesFormat{ + Access: to.Ptr(armnetwork.SecurityRuleAccessDeny), + DestinationAddressPrefix: to.Ptr("11.0.0.0/8"), + DestinationPortRange: to.Ptr("8080"), + Direction: to.Ptr(armnetwork.SecurityRuleDirectionOutbound), + Priority: to.Ptr[int32](100), + SourceAddressPrefix: to.Ptr("10.0.0.0/8"), + SourcePortRange: to.Ptr("*"), + Protocol: to.Ptr(armnetwork.SecurityRuleProtocolAsterisk), + }, + }, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, securityRulesClientCreateOrUpdateResponsePoller) + testsuite.Require().NoError(err) + + // From step SecurityRules_List + fmt.Println("Call operation: SecurityRules_List") + securityRulesClientNewListPager := securityRulesClient.NewListPager(testsuite.resourceGroupName, testsuite.networkSecurityGroupName, nil) + for securityRulesClientNewListPager.More() { + _, err := securityRulesClientNewListPager.NextPage(testsuite.ctx) + testsuite.Require().NoError(err) + break + } + + // From step SecurityRules_Get + fmt.Println("Call operation: SecurityRules_Get") + _, err = securityRulesClient.Get(testsuite.ctx, testsuite.resourceGroupName, testsuite.networkSecurityGroupName, testsuite.securityRuleName, nil) + testsuite.Require().NoError(err) + + // From step DefaultSecurityRules_List + fmt.Println("Call operation: DefaultSecurityRules_List") + defaultSecurityRulesClient, err := armnetwork.NewDefaultSecurityRulesClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + defaultSecurityRulesClientNewListPager := defaultSecurityRulesClient.NewListPager(testsuite.resourceGroupName, testsuite.networkSecurityGroupName, nil) + for defaultSecurityRulesClientNewListPager.More() { + nextResult, err := defaultSecurityRulesClientNewListPager.NextPage(testsuite.ctx) + testsuite.Require().NoError(err) + + defaultSecurityRuleName = *nextResult.Value[0].Name + break + } + + // From step DefaultSecurityRules_Get + fmt.Println("Call operation: DefaultSecurityRules_Get") + _, err = defaultSecurityRulesClient.Get(testsuite.ctx, testsuite.resourceGroupName, testsuite.networkSecurityGroupName, defaultSecurityRuleName, nil) + testsuite.Require().NoError(err) + + // From step SecurityRules_Delete + fmt.Println("Call operation: SecurityRules_Delete") + securityRulesClientDeleteResponsePoller, err := securityRulesClient.BeginDelete(testsuite.ctx, testsuite.resourceGroupName, testsuite.networkSecurityGroupName, testsuite.securityRuleName, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, securityRulesClientDeleteResponsePoller) + testsuite.Require().NoError(err) +} + +func (testsuite *NetworkSecurityGroupTestSuite) Cleanup() { + var err error + // From step NetworkSecurityGroups_Delete + fmt.Println("Call operation: NetworkSecurityGroups_Delete") + securityGroupsClient, err := armnetwork.NewSecurityGroupsClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + securityGroupsClientDeleteResponsePoller, err := securityGroupsClient.BeginDelete(testsuite.ctx, testsuite.resourceGroupName, testsuite.networkSecurityGroupName, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, securityGroupsClientDeleteResponsePoller) + testsuite.Require().NoError(err) +} diff --git a/sdk/resourcemanager/network/armnetwork/networkwatcher_live_test.go b/sdk/resourcemanager/network/armnetwork/networkwatcher_live_test.go new file mode 100644 index 000000000000..0af672b6402d --- /dev/null +++ b/sdk/resourcemanager/network/armnetwork/networkwatcher_live_test.go @@ -0,0 +1,113 @@ +//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. +// Code generated by Microsoft (R) AutoRest Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. + +package armnetwork_test + +import ( + "context" + "fmt" + "testing" + + "github.com/Azure/azure-sdk-for-go/sdk/azcore" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/arm" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/to" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/internal/testutil" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork/v2" + "github.com/stretchr/testify/suite" +) + +type NetworkWatcherTestSuite struct { + suite.Suite + + ctx context.Context + cred azcore.TokenCredential + options *arm.ClientOptions + networkWatcherName string + location string + resourceGroupName string + subscriptionId string +} + +func (testsuite *NetworkWatcherTestSuite) SetupSuite() { + testutil.StartRecording(testsuite.T(), "sdk/resourcemanager/network/armnetwork/testdata") + + testsuite.ctx = context.Background() + testsuite.cred, testsuite.options = testutil.GetCredAndClientOptions(testsuite.T()) + testsuite.networkWatcherName = testutil.GenerateAlphaNumericID(testsuite.T(), "networkwat", 6) + testsuite.location = testutil.GetEnv("LOCATION", "westus") + testsuite.resourceGroupName = testutil.GetEnv("RESOURCE_GROUP_NAME", "scenarioTestTempGroup") + testsuite.subscriptionId = testutil.GetEnv("AZURE_SUBSCRIPTION_ID", "00000000-0000-0000-0000-000000000000") + resourceGroup, _, err := testutil.CreateResourceGroup(testsuite.ctx, testsuite.subscriptionId, testsuite.cred, testsuite.options, testsuite.location) + testsuite.Require().NoError(err) + testsuite.resourceGroupName = *resourceGroup.Name +} + +func (testsuite *NetworkWatcherTestSuite) TearDownSuite() { + _, err := testutil.DeleteResourceGroup(testsuite.ctx, testsuite.subscriptionId, testsuite.cred, testsuite.options, testsuite.resourceGroupName) + testsuite.Require().NoError(err) + testutil.StopRecording(testsuite.T()) +} + +func TestNetworkWatcherTestSuite(t *testing.T) { + suite.Run(t, new(NetworkWatcherTestSuite)) +} + +// Microsoft.Network/networkWatchers/{networkWatcherName} +func (testsuite *NetworkWatcherTestSuite) TestNetworkWatchers() { + var err error + + // From step NetworkWatchers_CreateOrUpdate + watchersClient, err := armnetwork.NewWatchersClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + fmt.Println("Call operation: NetworkWatchers_CreateOrUpdate") + _, err = watchersClient.CreateOrUpdate(testsuite.ctx, testsuite.resourceGroupName, testsuite.networkWatcherName, armnetwork.Watcher{ + Location: to.Ptr(testsuite.location), + Properties: &armnetwork.WatcherPropertiesFormat{}, + }, nil) + testsuite.Require().NoError(err) + + // From step NetworkWatchers_ListAll + fmt.Println("Call operation: NetworkWatchers_ListAll") + watchersClientNewListAllPager := watchersClient.NewListAllPager(nil) + for watchersClientNewListAllPager.More() { + _, err := watchersClientNewListAllPager.NextPage(testsuite.ctx) + testsuite.Require().NoError(err) + break + } + + // From step NetworkWatchers_List + fmt.Println("Call operation: NetworkWatchers_List") + watchersClientNewListPager := watchersClient.NewListPager(testsuite.resourceGroupName, nil) + for watchersClientNewListPager.More() { + _, err := watchersClientNewListPager.NextPage(testsuite.ctx) + testsuite.Require().NoError(err) + break + } + + // From step NetworkWatchers_Get + fmt.Println("Call operation: NetworkWatchers_Get") + _, err = watchersClient.Get(testsuite.ctx, testsuite.resourceGroupName, testsuite.networkWatcherName, nil) + testsuite.Require().NoError(err) + + // From step NetworkWatchers_UpdateTags + fmt.Println("Call operation: NetworkWatchers_UpdateTags") + _, err = watchersClient.UpdateTags(testsuite.ctx, testsuite.resourceGroupName, testsuite.networkWatcherName, armnetwork.TagsObject{ + Tags: map[string]*string{ + "tag1": to.Ptr("value1"), + "tag2": to.Ptr("value2"), + }, + }, nil) + testsuite.Require().NoError(err) + + // From step NetworkWatchers_Delete + fmt.Println("Call operation: NetworkWatchers_Delete") + watchersClientDeleteResponsePoller, err := watchersClient.BeginDelete(testsuite.ctx, testsuite.resourceGroupName, testsuite.networkWatcherName, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, watchersClientDeleteResponsePoller) + testsuite.Require().NoError(err) +} diff --git a/sdk/resourcemanager/network/armnetwork/operation_live_test.go b/sdk/resourcemanager/network/armnetwork/operation_live_test.go new file mode 100644 index 000000000000..3d6327188031 --- /dev/null +++ b/sdk/resourcemanager/network/armnetwork/operation_live_test.go @@ -0,0 +1,70 @@ +//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. +// Code generated by Microsoft (R) AutoRest Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. + +package armnetwork_test + +import ( + "context" + "fmt" + "testing" + + "github.com/Azure/azure-sdk-for-go/sdk/azcore" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/arm" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/internal/testutil" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork/v2" + "github.com/stretchr/testify/suite" +) + +type OperationTestSuite struct { + suite.Suite + + ctx context.Context + cred azcore.TokenCredential + options *arm.ClientOptions + location string + resourceGroupName string + subscriptionId string +} + +func (testsuite *OperationTestSuite) SetupSuite() { + testutil.StartRecording(testsuite.T(), "sdk/resourcemanager/network/armnetwork/testdata") + + testsuite.ctx = context.Background() + testsuite.cred, testsuite.options = testutil.GetCredAndClientOptions(testsuite.T()) + testsuite.location = testutil.GetEnv("LOCATION", "westus") + testsuite.resourceGroupName = testutil.GetEnv("RESOURCE_GROUP_NAME", "scenarioTestTempGroup") + testsuite.subscriptionId = testutil.GetEnv("AZURE_SUBSCRIPTION_ID", "00000000-0000-0000-0000-000000000000") + resourceGroup, _, err := testutil.CreateResourceGroup(testsuite.ctx, testsuite.subscriptionId, testsuite.cred, testsuite.options, testsuite.location) + testsuite.Require().NoError(err) + testsuite.resourceGroupName = *resourceGroup.Name +} + +func (testsuite *OperationTestSuite) TearDownSuite() { + _, err := testutil.DeleteResourceGroup(testsuite.ctx, testsuite.subscriptionId, testsuite.cred, testsuite.options, testsuite.resourceGroupName) + testsuite.Require().NoError(err) + testutil.StopRecording(testsuite.T()) +} + +func TestOperationTestSuite(t *testing.T) { + suite.Run(t, new(OperationTestSuite)) +} + +// crosoft.Network/operations +func (testsuite *OperationTestSuite) TestOperations() { + var err error + // From step Operations_List + fmt.Println("Call operation: Operations_List") + operationsClient, err := armnetwork.NewOperationsClient(testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + operationsClientNewListPager := operationsClient.NewListPager(nil) + for operationsClientNewListPager.More() { + _, err := operationsClientNewListPager.NextPage(testsuite.ctx) + testsuite.Require().NoError(err) + break + } +} diff --git a/sdk/resourcemanager/network/armnetwork/publicipaddress_live_test.go b/sdk/resourcemanager/network/armnetwork/publicipaddress_live_test.go new file mode 100644 index 000000000000..1272f29835f5 --- /dev/null +++ b/sdk/resourcemanager/network/armnetwork/publicipaddress_live_test.go @@ -0,0 +1,113 @@ +//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. +// Code generated by Microsoft (R) AutoRest Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. + +package armnetwork_test + +import ( + "context" + "fmt" + "testing" + + "github.com/Azure/azure-sdk-for-go/sdk/azcore" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/arm" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/to" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/internal/testutil" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork/v2" + "github.com/stretchr/testify/suite" +) + +type PublicIpAddressTestSuite struct { + suite.Suite + + ctx context.Context + cred azcore.TokenCredential + options *arm.ClientOptions + publicIpAddressName string + location string + resourceGroupName string + subscriptionId string +} + +func (testsuite *PublicIpAddressTestSuite) SetupSuite() { + testutil.StartRecording(testsuite.T(), "sdk/resourcemanager/network/armnetwork/testdata") + + testsuite.ctx = context.Background() + testsuite.cred, testsuite.options = testutil.GetCredAndClientOptions(testsuite.T()) + testsuite.publicIpAddressName = testutil.GenerateAlphaNumericID(testsuite.T(), "publicipad", 6) + testsuite.location = testutil.GetEnv("LOCATION", "westus") + testsuite.resourceGroupName = testutil.GetEnv("RESOURCE_GROUP_NAME", "scenarioTestTempGroup") + testsuite.subscriptionId = testutil.GetEnv("AZURE_SUBSCRIPTION_ID", "00000000-0000-0000-0000-000000000000") + resourceGroup, _, err := testutil.CreateResourceGroup(testsuite.ctx, testsuite.subscriptionId, testsuite.cred, testsuite.options, testsuite.location) + testsuite.Require().NoError(err) + testsuite.resourceGroupName = *resourceGroup.Name +} + +func (testsuite *PublicIpAddressTestSuite) TearDownSuite() { + _, err := testutil.DeleteResourceGroup(testsuite.ctx, testsuite.subscriptionId, testsuite.cred, testsuite.options, testsuite.resourceGroupName) + testsuite.Require().NoError(err) + testutil.StopRecording(testsuite.T()) +} + +func TestPublicIpAddressTestSuite(t *testing.T) { + suite.Run(t, new(PublicIpAddressTestSuite)) +} + +// Microsoft.Network/publicIPAddresses/{publicIpAddressName} +func (testsuite *PublicIpAddressTestSuite) TestPublicIpAddresses() { + var err error + // From step PublicIPAddresses_CreateOrUpdate + fmt.Println("Call operation: PublicIPAddresses_CreateOrUpdate") + publicIPAddressesClient, err := armnetwork.NewPublicIPAddressesClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + publicIPAddressesClientCreateOrUpdateResponsePoller, err := publicIPAddressesClient.BeginCreateOrUpdate(testsuite.ctx, testsuite.resourceGroupName, testsuite.publicIpAddressName, armnetwork.PublicIPAddress{ + Location: to.Ptr(testsuite.location), + }, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, publicIPAddressesClientCreateOrUpdateResponsePoller) + testsuite.Require().NoError(err) + + // From step PublicIPAddresses_ListAll + fmt.Println("Call operation: PublicIPAddresses_ListAll") + publicIPAddressesClientNewListAllPager := publicIPAddressesClient.NewListAllPager(nil) + for publicIPAddressesClientNewListAllPager.More() { + _, err := publicIPAddressesClientNewListAllPager.NextPage(testsuite.ctx) + testsuite.Require().NoError(err) + break + } + + // From step PublicIPAddresses_List + fmt.Println("Call operation: PublicIPAddresses_List") + publicIPAddressesClientNewListPager := publicIPAddressesClient.NewListPager(testsuite.resourceGroupName, nil) + for publicIPAddressesClientNewListPager.More() { + _, err := publicIPAddressesClientNewListPager.NextPage(testsuite.ctx) + testsuite.Require().NoError(err) + break + } + + // From step PublicIPAddresses_Get + fmt.Println("Call operation: PublicIPAddresses_Get") + _, err = publicIPAddressesClient.Get(testsuite.ctx, testsuite.resourceGroupName, testsuite.publicIpAddressName, &armnetwork.PublicIPAddressesClientGetOptions{Expand: nil}) + testsuite.Require().NoError(err) + + // From step PublicIPAddresses_UpdateTags + fmt.Println("Call operation: PublicIPAddresses_UpdateTags") + _, err = publicIPAddressesClient.UpdateTags(testsuite.ctx, testsuite.resourceGroupName, testsuite.publicIpAddressName, armnetwork.TagsObject{ + Tags: map[string]*string{ + "tag1": to.Ptr("value1"), + "tag2": to.Ptr("value2"), + }, + }, nil) + testsuite.Require().NoError(err) + + // From step PublicIPAddresses_Delete + fmt.Println("Call operation: PublicIPAddresses_Delete") + publicIPAddressesClientDeleteResponsePoller, err := publicIPAddressesClient.BeginDelete(testsuite.ctx, testsuite.resourceGroupName, testsuite.publicIpAddressName, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, publicIPAddressesClientDeleteResponsePoller) + testsuite.Require().NoError(err) +} diff --git a/sdk/resourcemanager/network/armnetwork/publicipprefix_live_test.go b/sdk/resourcemanager/network/armnetwork/publicipprefix_live_test.go new file mode 100644 index 000000000000..e6e675a993f8 --- /dev/null +++ b/sdk/resourcemanager/network/armnetwork/publicipprefix_live_test.go @@ -0,0 +1,119 @@ +//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. +// Code generated by Microsoft (R) AutoRest Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. + +package armnetwork_test + +import ( + "context" + "fmt" + "testing" + + "github.com/Azure/azure-sdk-for-go/sdk/azcore" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/arm" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/to" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/internal/testutil" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork/v2" + "github.com/stretchr/testify/suite" +) + +type PublicIpPrefixTestSuite struct { + suite.Suite + + ctx context.Context + cred azcore.TokenCredential + options *arm.ClientOptions + publicIpPrefixName string + location string + resourceGroupName string + subscriptionId string +} + +func (testsuite *PublicIpPrefixTestSuite) SetupSuite() { + testutil.StartRecording(testsuite.T(), "sdk/resourcemanager/network/armnetwork/testdata") + + testsuite.ctx = context.Background() + testsuite.cred, testsuite.options = testutil.GetCredAndClientOptions(testsuite.T()) + testsuite.publicIpPrefixName = testutil.GenerateAlphaNumericID(testsuite.T(), "publicippr", 6) + testsuite.location = testutil.GetEnv("LOCATION", "westus") + testsuite.resourceGroupName = testutil.GetEnv("RESOURCE_GROUP_NAME", "scenarioTestTempGroup") + testsuite.subscriptionId = testutil.GetEnv("AZURE_SUBSCRIPTION_ID", "00000000-0000-0000-0000-000000000000") + resourceGroup, _, err := testutil.CreateResourceGroup(testsuite.ctx, testsuite.subscriptionId, testsuite.cred, testsuite.options, testsuite.location) + testsuite.Require().NoError(err) + testsuite.resourceGroupName = *resourceGroup.Name +} + +func (testsuite *PublicIpPrefixTestSuite) TearDownSuite() { + _, err := testutil.DeleteResourceGroup(testsuite.ctx, testsuite.subscriptionId, testsuite.cred, testsuite.options, testsuite.resourceGroupName) + testsuite.Require().NoError(err) + testutil.StopRecording(testsuite.T()) +} + +func TestPublicIpPrefixTestSuite(t *testing.T) { + suite.Run(t, new(PublicIpPrefixTestSuite)) +} + +// Microsoft.Network/publicIPPrefixes/{publicIpPrefixName} +func (testsuite *PublicIpPrefixTestSuite) TestPublicIpPrefixes() { + var err error + // From step PublicIPPrefixes_CreateOrUpdate + fmt.Println("Call operation: PublicIPPrefixes_CreateOrUpdate") + publicIPPrefixesClient, err := armnetwork.NewPublicIPPrefixesClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + publicIPPrefixesClientCreateOrUpdateResponsePoller, err := publicIPPrefixesClient.BeginCreateOrUpdate(testsuite.ctx, testsuite.resourceGroupName, testsuite.publicIpPrefixName, armnetwork.PublicIPPrefix{ + Location: to.Ptr(testsuite.location), + Properties: &armnetwork.PublicIPPrefixPropertiesFormat{ + PrefixLength: to.Ptr[int32](30), + }, + SKU: &armnetwork.PublicIPPrefixSKU{ + Name: to.Ptr(armnetwork.PublicIPPrefixSKUNameStandard), + }, + }, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, publicIPPrefixesClientCreateOrUpdateResponsePoller) + testsuite.Require().NoError(err) + + // From step PublicIPPrefixes_ListAll + fmt.Println("Call operation: PublicIPPrefixes_ListAll") + publicIPPrefixesClientNewListAllPager := publicIPPrefixesClient.NewListAllPager(nil) + for publicIPPrefixesClientNewListAllPager.More() { + _, err := publicIPPrefixesClientNewListAllPager.NextPage(testsuite.ctx) + testsuite.Require().NoError(err) + break + } + + // From step PublicIPPrefixes_List + fmt.Println("Call operation: PublicIPPrefixes_List") + publicIPPrefixesClientNewListPager := publicIPPrefixesClient.NewListPager(testsuite.resourceGroupName, nil) + for publicIPPrefixesClientNewListPager.More() { + _, err := publicIPPrefixesClientNewListPager.NextPage(testsuite.ctx) + testsuite.Require().NoError(err) + break + } + + // From step PublicIPPrefixes_Get + fmt.Println("Call operation: PublicIPPrefixes_Get") + _, err = publicIPPrefixesClient.Get(testsuite.ctx, testsuite.resourceGroupName, testsuite.publicIpPrefixName, &armnetwork.PublicIPPrefixesClientGetOptions{Expand: nil}) + testsuite.Require().NoError(err) + + // From step PublicIPPrefixes_UpdateTags + fmt.Println("Call operation: PublicIPPrefixes_UpdateTags") + _, err = publicIPPrefixesClient.UpdateTags(testsuite.ctx, testsuite.resourceGroupName, testsuite.publicIpPrefixName, armnetwork.TagsObject{ + Tags: map[string]*string{ + "tag1": to.Ptr("value1"), + "tag2": to.Ptr("value2"), + }, + }, nil) + testsuite.Require().NoError(err) + + // From step PublicIPPrefixes_Delete + fmt.Println("Call operation: PublicIPPrefixes_Delete") + publicIPPrefixesClientDeleteResponsePoller, err := publicIPPrefixesClient.BeginDelete(testsuite.ctx, testsuite.resourceGroupName, testsuite.publicIpPrefixName, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, publicIPPrefixesClientDeleteResponsePoller) + testsuite.Require().NoError(err) +} diff --git a/sdk/resourcemanager/network/armnetwork/routetable_live_test.go b/sdk/resourcemanager/network/armnetwork/routetable_live_test.go new file mode 100644 index 000000000000..2546237dc326 --- /dev/null +++ b/sdk/resourcemanager/network/armnetwork/routetable_live_test.go @@ -0,0 +1,165 @@ +//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. +// Code generated by Microsoft (R) AutoRest Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. + +package armnetwork_test + +import ( + "context" + "fmt" + "testing" + + "github.com/Azure/azure-sdk-for-go/sdk/azcore" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/arm" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/to" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/internal/testutil" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork/v2" + "github.com/stretchr/testify/suite" +) + +type RouteTableTestSuite struct { + suite.Suite + + ctx context.Context + cred azcore.TokenCredential + options *arm.ClientOptions + routeTableName string + location string + resourceGroupName string + subscriptionId string +} + +func (testsuite *RouteTableTestSuite) SetupSuite() { + testutil.StartRecording(testsuite.T(), "sdk/resourcemanager/network/armnetwork/testdata") + + testsuite.ctx = context.Background() + testsuite.cred, testsuite.options = testutil.GetCredAndClientOptions(testsuite.T()) + testsuite.routeTableName = testutil.GenerateAlphaNumericID(testsuite.T(), "routetable", 6) + testsuite.location = testutil.GetEnv("LOCATION", "westus") + testsuite.resourceGroupName = testutil.GetEnv("RESOURCE_GROUP_NAME", "scenarioTestTempGroup") + testsuite.subscriptionId = testutil.GetEnv("AZURE_SUBSCRIPTION_ID", "00000000-0000-0000-0000-000000000000") + resourceGroup, _, err := testutil.CreateResourceGroup(testsuite.ctx, testsuite.subscriptionId, testsuite.cred, testsuite.options, testsuite.location) + testsuite.Require().NoError(err) + testsuite.resourceGroupName = *resourceGroup.Name + testsuite.Prepare() +} + +func (testsuite *RouteTableTestSuite) TearDownSuite() { + testsuite.Cleanup() + _, err := testutil.DeleteResourceGroup(testsuite.ctx, testsuite.subscriptionId, testsuite.cred, testsuite.options, testsuite.resourceGroupName) + testsuite.Require().NoError(err) + testutil.StopRecording(testsuite.T()) +} + +func TestRouteTableTestSuite(t *testing.T) { + suite.Run(t, new(RouteTableTestSuite)) +} + +func (testsuite *RouteTableTestSuite) Prepare() { + var err error + // From step RouteTables_CreateOrUpdate + fmt.Println("Call operation: RouteTables_CreateOrUpdate") + routeTablesClient, err := armnetwork.NewRouteTablesClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + routeTablesClientCreateOrUpdateResponsePoller, err := routeTablesClient.BeginCreateOrUpdate(testsuite.ctx, testsuite.resourceGroupName, testsuite.routeTableName, armnetwork.RouteTable{ + Location: to.Ptr(testsuite.location), + }, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, routeTablesClientCreateOrUpdateResponsePoller) + testsuite.Require().NoError(err) +} + +// Microsoft.Network/routeTables/{routeTableName} +func (testsuite *RouteTableTestSuite) TestRouteTables() { + var err error + // From step RouteTables_ListAll + fmt.Println("Call operation: RouteTables_ListAll") + routeTablesClient, err := armnetwork.NewRouteTablesClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + routeTablesClientNewListAllPager := routeTablesClient.NewListAllPager(nil) + for routeTablesClientNewListAllPager.More() { + _, err := routeTablesClientNewListAllPager.NextPage(testsuite.ctx) + testsuite.Require().NoError(err) + break + } + + // From step RouteTables_List + fmt.Println("Call operation: RouteTables_List") + routeTablesClientNewListPager := routeTablesClient.NewListPager(testsuite.resourceGroupName, nil) + for routeTablesClientNewListPager.More() { + _, err := routeTablesClientNewListPager.NextPage(testsuite.ctx) + testsuite.Require().NoError(err) + break + } + + // From step RouteTables_Get + fmt.Println("Call operation: RouteTables_Get") + _, err = routeTablesClient.Get(testsuite.ctx, testsuite.resourceGroupName, testsuite.routeTableName, &armnetwork.RouteTablesClientGetOptions{Expand: nil}) + testsuite.Require().NoError(err) + + // From step RouteTables_UpdateTags + fmt.Println("Call operation: RouteTables_UpdateTags") + _, err = routeTablesClient.UpdateTags(testsuite.ctx, testsuite.resourceGroupName, testsuite.routeTableName, armnetwork.TagsObject{ + Tags: map[string]*string{ + "tag1": to.Ptr("value1"), + "tag2": to.Ptr("value2"), + }, + }, nil) + testsuite.Require().NoError(err) +} + +// Microsoft.Network/routeTables/{routeTableName}/routes/{routeName} +func (testsuite *RouteTableTestSuite) TestRoutes() { + routeName := testutil.GenerateAlphaNumericID(testsuite.T(), "routename", 6) + var err error + // From step Routes_CreateOrUpdate + fmt.Println("Call operation: Routes_CreateOrUpdate") + routesClient, err := armnetwork.NewRoutesClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + routesClientCreateOrUpdateResponsePoller, err := routesClient.BeginCreateOrUpdate(testsuite.ctx, testsuite.resourceGroupName, testsuite.routeTableName, routeName, armnetwork.Route{ + Properties: &armnetwork.RoutePropertiesFormat{ + AddressPrefix: to.Ptr("10.0.3.0/24"), + NextHopType: to.Ptr(armnetwork.RouteNextHopTypeVirtualNetworkGateway), + }, + }, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, routesClientCreateOrUpdateResponsePoller) + testsuite.Require().NoError(err) + + // From step Routes_List + fmt.Println("Call operation: Routes_List") + routesClientNewListPager := routesClient.NewListPager(testsuite.resourceGroupName, testsuite.routeTableName, nil) + for routesClientNewListPager.More() { + _, err := routesClientNewListPager.NextPage(testsuite.ctx) + testsuite.Require().NoError(err) + break + } + + // From step Routes_Get + fmt.Println("Call operation: Routes_Get") + _, err = routesClient.Get(testsuite.ctx, testsuite.resourceGroupName, testsuite.routeTableName, routeName, nil) + testsuite.Require().NoError(err) + + // From step Routes_Delete + fmt.Println("Call operation: Routes_Delete") + routesClientDeleteResponsePoller, err := routesClient.BeginDelete(testsuite.ctx, testsuite.resourceGroupName, testsuite.routeTableName, routeName, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, routesClientDeleteResponsePoller) + testsuite.Require().NoError(err) +} + +func (testsuite *RouteTableTestSuite) Cleanup() { + var err error + // From step RouteTables_Delete + fmt.Println("Call operation: RouteTables_Delete") + routeTablesClient, err := armnetwork.NewRouteTablesClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + routeTablesClientDeleteResponsePoller, err := routeTablesClient.BeginDelete(testsuite.ctx, testsuite.resourceGroupName, testsuite.routeTableName, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, routeTablesClientDeleteResponsePoller) + testsuite.Require().NoError(err) +} diff --git a/sdk/resourcemanager/network/armnetwork/servicecommunity_live_test.go b/sdk/resourcemanager/network/armnetwork/servicecommunity_live_test.go new file mode 100644 index 000000000000..b5dc4ec8fee1 --- /dev/null +++ b/sdk/resourcemanager/network/armnetwork/servicecommunity_live_test.go @@ -0,0 +1,70 @@ +//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. +// Code generated by Microsoft (R) AutoRest Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. + +package armnetwork_test + +import ( + "context" + "fmt" + "testing" + + "github.com/Azure/azure-sdk-for-go/sdk/azcore" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/arm" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/internal/testutil" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork/v2" + "github.com/stretchr/testify/suite" +) + +type ServiceCommunityTestSuite struct { + suite.Suite + + ctx context.Context + cred azcore.TokenCredential + options *arm.ClientOptions + location string + resourceGroupName string + subscriptionId string +} + +func (testsuite *ServiceCommunityTestSuite) SetupSuite() { + testutil.StartRecording(testsuite.T(), "sdk/resourcemanager/network/armnetwork/testdata") + + testsuite.ctx = context.Background() + testsuite.cred, testsuite.options = testutil.GetCredAndClientOptions(testsuite.T()) + testsuite.location = testutil.GetEnv("LOCATION", "westus") + testsuite.resourceGroupName = testutil.GetEnv("RESOURCE_GROUP_NAME", "scenarioTestTempGroup") + testsuite.subscriptionId = testutil.GetEnv("AZURE_SUBSCRIPTION_ID", "00000000-0000-0000-0000-000000000000") + resourceGroup, _, err := testutil.CreateResourceGroup(testsuite.ctx, testsuite.subscriptionId, testsuite.cred, testsuite.options, testsuite.location) + testsuite.Require().NoError(err) + testsuite.resourceGroupName = *resourceGroup.Name +} + +func (testsuite *ServiceCommunityTestSuite) TearDownSuite() { + _, err := testutil.DeleteResourceGroup(testsuite.ctx, testsuite.subscriptionId, testsuite.cred, testsuite.options, testsuite.resourceGroupName) + testsuite.Require().NoError(err) + testutil.StopRecording(testsuite.T()) +} + +func TestServiceCommunityTestSuite(t *testing.T) { + suite.Run(t, new(ServiceCommunityTestSuite)) +} + +// Microsoft.Network/bgpServiceCommunities +func (testsuite *ServiceCommunityTestSuite) TestBgpServiceCommunities() { + var err error + // From step BgpServiceCommunities_List + fmt.Println("Call operation: BgpServiceCommunities_List") + bgpServiceCommunitiesClient, err := armnetwork.NewBgpServiceCommunitiesClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + bgpServiceCommunitiesClientNewListPager := bgpServiceCommunitiesClient.NewListPager(nil) + for bgpServiceCommunitiesClientNewListPager.More() { + _, err := bgpServiceCommunitiesClientNewListPager.NextPage(testsuite.ctx) + testsuite.Require().NoError(err) + break + } +} diff --git a/sdk/resourcemanager/network/armnetwork/serviceendpointpolicy_live_test.go b/sdk/resourcemanager/network/armnetwork/serviceendpointpolicy_live_test.go new file mode 100644 index 000000000000..18027d942a6f --- /dev/null +++ b/sdk/resourcemanager/network/armnetwork/serviceendpointpolicy_live_test.go @@ -0,0 +1,167 @@ +//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. +// Code generated by Microsoft (R) AutoRest Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. + +package armnetwork_test + +import ( + "context" + "fmt" + "testing" + + "github.com/Azure/azure-sdk-for-go/sdk/azcore" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/arm" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/to" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/internal/testutil" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork/v2" + "github.com/stretchr/testify/suite" +) + +type ServiceEndpointPolicyTestSuite struct { + suite.Suite + + ctx context.Context + cred azcore.TokenCredential + options *arm.ClientOptions + serviceEndpointPolicyName string + location string + resourceGroupName string + subscriptionId string +} + +func (testsuite *ServiceEndpointPolicyTestSuite) SetupSuite() { + testutil.StartRecording(testsuite.T(), "sdk/resourcemanager/network/armnetwork/testdata") + + testsuite.ctx = context.Background() + testsuite.cred, testsuite.options = testutil.GetCredAndClientOptions(testsuite.T()) + testsuite.serviceEndpointPolicyName = testutil.GenerateAlphaNumericID(testsuite.T(), "serviceend", 6) + testsuite.location = testutil.GetEnv("LOCATION", "westus") + testsuite.resourceGroupName = testutil.GetEnv("RESOURCE_GROUP_NAME", "scenarioTestTempGroup") + testsuite.subscriptionId = testutil.GetEnv("AZURE_SUBSCRIPTION_ID", "00000000-0000-0000-0000-000000000000") + resourceGroup, _, err := testutil.CreateResourceGroup(testsuite.ctx, testsuite.subscriptionId, testsuite.cred, testsuite.options, testsuite.location) + testsuite.Require().NoError(err) + testsuite.resourceGroupName = *resourceGroup.Name + testsuite.Prepare() +} + +func (testsuite *ServiceEndpointPolicyTestSuite) TearDownSuite() { + testsuite.Cleanup() + _, err := testutil.DeleteResourceGroup(testsuite.ctx, testsuite.subscriptionId, testsuite.cred, testsuite.options, testsuite.resourceGroupName) + testsuite.Require().NoError(err) + testutil.StopRecording(testsuite.T()) +} + +func TestServiceEndpointPolicyTestSuite(t *testing.T) { + suite.Run(t, new(ServiceEndpointPolicyTestSuite)) +} + +func (testsuite *ServiceEndpointPolicyTestSuite) Prepare() { + var err error + // From step ServiceEndpointPolicies_CreateOrUpdate + fmt.Println("Call operation: ServiceEndpointPolicies_CreateOrUpdate") + serviceEndpointPoliciesClient, err := armnetwork.NewServiceEndpointPoliciesClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + serviceEndpointPoliciesClientCreateOrUpdateResponsePoller, err := serviceEndpointPoliciesClient.BeginCreateOrUpdate(testsuite.ctx, testsuite.resourceGroupName, testsuite.serviceEndpointPolicyName, armnetwork.ServiceEndpointPolicy{ + Location: to.Ptr(testsuite.location), + }, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, serviceEndpointPoliciesClientCreateOrUpdateResponsePoller) + testsuite.Require().NoError(err) +} + +// Microsoft.Network/serviceEndpointPolicies/{serviceEndpointPolicyName} +func (testsuite *ServiceEndpointPolicyTestSuite) TestServiceEndpointPolicies() { + var err error + // From step ServiceEndpointPolicies_List + fmt.Println("Call operation: ServiceEndpointPolicies_List") + serviceEndpointPoliciesClient, err := armnetwork.NewServiceEndpointPoliciesClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + serviceEndpointPoliciesClientNewListPager := serviceEndpointPoliciesClient.NewListPager(nil) + for serviceEndpointPoliciesClientNewListPager.More() { + _, err := serviceEndpointPoliciesClientNewListPager.NextPage(testsuite.ctx) + testsuite.Require().NoError(err) + break + } + + // From step ServiceEndpointPolicies_ListByResourceGroup + fmt.Println("Call operation: ServiceEndpointPolicies_ListByResourceGroup") + serviceEndpointPoliciesClientNewListByResourceGroupPager := serviceEndpointPoliciesClient.NewListByResourceGroupPager(testsuite.resourceGroupName, nil) + for serviceEndpointPoliciesClientNewListByResourceGroupPager.More() { + _, err := serviceEndpointPoliciesClientNewListByResourceGroupPager.NextPage(testsuite.ctx) + testsuite.Require().NoError(err) + break + } + + // From step ServiceEndpointPolicies_Get + fmt.Println("Call operation: ServiceEndpointPolicies_Get") + _, err = serviceEndpointPoliciesClient.Get(testsuite.ctx, testsuite.resourceGroupName, testsuite.serviceEndpointPolicyName, &armnetwork.ServiceEndpointPoliciesClientGetOptions{Expand: nil}) + testsuite.Require().NoError(err) + + // From step ServiceEndpointPolicies_UpdateTags + fmt.Println("Call operation: ServiceEndpointPolicies_UpdateTags") + _, err = serviceEndpointPoliciesClient.UpdateTags(testsuite.ctx, testsuite.resourceGroupName, testsuite.serviceEndpointPolicyName, armnetwork.TagsObject{ + Tags: map[string]*string{ + "tag1": to.Ptr("value1"), + "tag2": to.Ptr("value2"), + }, + }, nil) + testsuite.Require().NoError(err) +} + +// Microsoft.Network/serviceEndpointPolicies/{serviceEndpointPolicyName}/serviceEndpointPolicyDefinitions/{serviceEndpointPolicyDefinitionName} +func (testsuite *ServiceEndpointPolicyTestSuite) TestServiceEndpointPolicyDefinitions() { + serviceEndpointPolicyDefinitionName := testutil.GenerateAlphaNumericID(testsuite.T(), "serviceend", 6) + var err error + // From step ServiceEndpointPolicyDefinitions_CreateOrUpdate + fmt.Println("Call operation: ServiceEndpointPolicyDefinitions_CreateOrUpdate") + serviceEndpointPolicyDefinitionsClient, err := armnetwork.NewServiceEndpointPolicyDefinitionsClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + serviceEndpointPolicyDefinitionsClientCreateOrUpdateResponsePoller, err := serviceEndpointPolicyDefinitionsClient.BeginCreateOrUpdate(testsuite.ctx, testsuite.resourceGroupName, testsuite.serviceEndpointPolicyName, serviceEndpointPolicyDefinitionName, armnetwork.ServiceEndpointPolicyDefinition{ + Properties: &armnetwork.ServiceEndpointPolicyDefinitionPropertiesFormat{ + Description: to.Ptr("Storage Service EndpointPolicy Definition"), + Service: to.Ptr("Microsoft.Storage"), + ServiceResources: []*string{ + to.Ptr("/subscriptions/" + testsuite.subscriptionId)}, + }, + }, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, serviceEndpointPolicyDefinitionsClientCreateOrUpdateResponsePoller) + testsuite.Require().NoError(err) + + // From step ServiceEndpointPolicyDefinitions_ListByResourceGroup + fmt.Println("Call operation: ServiceEndpointPolicyDefinitions_ListByResourceGroup") + serviceEndpointPolicyDefinitionsClientNewListByResourceGroupPager := serviceEndpointPolicyDefinitionsClient.NewListByResourceGroupPager(testsuite.resourceGroupName, testsuite.serviceEndpointPolicyName, nil) + for serviceEndpointPolicyDefinitionsClientNewListByResourceGroupPager.More() { + _, err := serviceEndpointPolicyDefinitionsClientNewListByResourceGroupPager.NextPage(testsuite.ctx) + testsuite.Require().NoError(err) + break + } + + // From step ServiceEndpointPolicyDefinitions_Get + fmt.Println("Call operation: ServiceEndpointPolicyDefinitions_Get") + _, err = serviceEndpointPolicyDefinitionsClient.Get(testsuite.ctx, testsuite.resourceGroupName, testsuite.serviceEndpointPolicyName, serviceEndpointPolicyDefinitionName, nil) + testsuite.Require().NoError(err) + + // From step ServiceEndpointPolicyDefinitions_Delete + fmt.Println("Call operation: ServiceEndpointPolicyDefinitions_Delete") + serviceEndpointPolicyDefinitionsClientDeleteResponsePoller, err := serviceEndpointPolicyDefinitionsClient.BeginDelete(testsuite.ctx, testsuite.resourceGroupName, testsuite.serviceEndpointPolicyName, serviceEndpointPolicyDefinitionName, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, serviceEndpointPolicyDefinitionsClientDeleteResponsePoller) + testsuite.Require().NoError(err) +} + +func (testsuite *ServiceEndpointPolicyTestSuite) Cleanup() { + var err error + // From step ServiceEndpointPolicies_Delete + fmt.Println("Call operation: ServiceEndpointPolicies_Delete") + serviceEndpointPoliciesClient, err := armnetwork.NewServiceEndpointPoliciesClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + serviceEndpointPoliciesClientDeleteResponsePoller, err := serviceEndpointPoliciesClient.BeginDelete(testsuite.ctx, testsuite.resourceGroupName, testsuite.serviceEndpointPolicyName, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, serviceEndpointPoliciesClientDeleteResponsePoller) + testsuite.Require().NoError(err) +} diff --git a/sdk/resourcemanager/network/armnetwork/servicetags_live_test.go b/sdk/resourcemanager/network/armnetwork/servicetags_live_test.go new file mode 100644 index 000000000000..ab9d8a3a16b8 --- /dev/null +++ b/sdk/resourcemanager/network/armnetwork/servicetags_live_test.go @@ -0,0 +1,79 @@ +//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. +// Code generated by Microsoft (R) AutoRest Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. + +package armnetwork_test + +import ( + "context" + "fmt" + "testing" + + "github.com/Azure/azure-sdk-for-go/sdk/azcore" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/arm" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/internal/testutil" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork/v2" + "github.com/stretchr/testify/suite" +) + +type ServiceTagsTestSuite struct { + suite.Suite + + ctx context.Context + cred azcore.TokenCredential + options *arm.ClientOptions + location string + resourceGroupName string + subscriptionId string +} + +func (testsuite *ServiceTagsTestSuite) SetupSuite() { + testutil.StartRecording(testsuite.T(), "sdk/resourcemanager/network/armnetwork/testdata") + + testsuite.ctx = context.Background() + testsuite.cred, testsuite.options = testutil.GetCredAndClientOptions(testsuite.T()) + testsuite.location = testutil.GetEnv("LOCATION", "westus") + testsuite.resourceGroupName = testutil.GetEnv("RESOURCE_GROUP_NAME", "scenarioTestTempGroup") + testsuite.subscriptionId = testutil.GetEnv("AZURE_SUBSCRIPTION_ID", "00000000-0000-0000-0000-000000000000") + resourceGroup, _, err := testutil.CreateResourceGroup(testsuite.ctx, testsuite.subscriptionId, testsuite.cred, testsuite.options, testsuite.location) + testsuite.Require().NoError(err) + testsuite.resourceGroupName = *resourceGroup.Name +} + +func (testsuite *ServiceTagsTestSuite) TearDownSuite() { + _, err := testutil.DeleteResourceGroup(testsuite.ctx, testsuite.subscriptionId, testsuite.cred, testsuite.options, testsuite.resourceGroupName) + testsuite.Require().NoError(err) + testutil.StopRecording(testsuite.T()) +} + +func TestServiceTagsTestSuite(t *testing.T) { + suite.Run(t, new(ServiceTagsTestSuite)) +} + +// Microsoft.Network/locations/{location}/serviceTags +func (testsuite *ServiceTagsTestSuite) TestServiceTags() { + var err error + // From step ServiceTags_List + fmt.Println("Call operation: ServiceTags_List") + serviceTagsClient, err := armnetwork.NewServiceTagsClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + _, err = serviceTagsClient.List(testsuite.ctx, testsuite.location, nil) + testsuite.Require().NoError(err) + + // From step ServiceTagInformation_List + fmt.Println("Call operation: ServiceTagInformation_List") + serviceTagInformationClient, err := armnetwork.NewServiceTagInformationClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + serviceTagInformationClientNewListPager := serviceTagInformationClient.NewListPager(testsuite.location, &armnetwork.ServiceTagInformationClientListOptions{NoAddressPrefixes: nil, + TagName: nil, + }) + for serviceTagInformationClientNewListPager.More() { + _, err := serviceTagInformationClientNewListPager.NextPage(testsuite.ctx) + testsuite.Require().NoError(err) + break + } +} diff --git a/sdk/resourcemanager/network/armnetwork/subnets_client_live_test.go b/sdk/resourcemanager/network/armnetwork/subnets_client_live_test.go deleted file mode 100644 index 76fa83c5f6d6..000000000000 --- a/sdk/resourcemanager/network/armnetwork/subnets_client_live_test.go +++ /dev/null @@ -1,122 +0,0 @@ -//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 armnetwork_test - -import ( - "context" - "fmt" - "testing" - - "github.com/Azure/azure-sdk-for-go/sdk/azcore" - "github.com/Azure/azure-sdk-for-go/sdk/azcore/arm" - "github.com/Azure/azure-sdk-for-go/sdk/azcore/to" - "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/internal/testutil" - "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork/v2" - "github.com/stretchr/testify/suite" -) - -type SubnetsClientTestSuite struct { - suite.Suite - - ctx context.Context - cred azcore.TokenCredential - options *arm.ClientOptions - location string - resourceGroupName string - subscriptionID string -} - -func (testsuite *SubnetsClientTestSuite) SetupSuite() { - testsuite.ctx = context.Background() - testsuite.cred, testsuite.options = testutil.GetCredAndClientOptions(testsuite.T()) - testsuite.location = testutil.GetEnv("LOCATION", "eastus") - testsuite.subscriptionID = testutil.GetEnv("AZURE_SUBSCRIPTION_ID", "00000000-0000-0000-0000-000000000000") - testutil.StartRecording(testsuite.T(), "sdk/resourcemanager/network/armnetwork/testdata") - resourceGroup, _, err := testutil.CreateResourceGroup(testsuite.ctx, testsuite.subscriptionID, testsuite.cred, testsuite.options, testsuite.location) - testsuite.Require().NoError(err) - testsuite.resourceGroupName = *resourceGroup.Name -} - -func (testsuite *SubnetsClientTestSuite) TearDownSuite() { - _, err := testutil.DeleteResourceGroup(testsuite.ctx, testsuite.subscriptionID, testsuite.cred, testsuite.options, testsuite.resourceGroupName) - testsuite.Require().NoError(err) - testutil.StopRecording(testsuite.T()) -} - -func TestSubnetsClient(t *testing.T) { - suite.Run(t, new(SubnetsClientTestSuite)) -} - -func (testsuite *SubnetsClientTestSuite) TestSubnetsCRUD() { - // create virtual network - fmt.Println("Call operation: VirtualNetworks_CreateOrUpdate") - vnClient, err := armnetwork.NewVirtualNetworksClient(testsuite.subscriptionID, testsuite.cred, testsuite.options) - testsuite.Require().NoError(err) - vnName := "go-test-vn" - vnPoller, err := vnClient.BeginCreateOrUpdate( - testsuite.ctx, - testsuite.resourceGroupName, - vnName, - armnetwork.VirtualNetwork{ - Location: to.Ptr(testsuite.location), - Properties: &armnetwork.VirtualNetworkPropertiesFormat{ - AddressSpace: &armnetwork.AddressSpace{ - AddressPrefixes: []*string{ - to.Ptr("10.1.0.0/16"), - }, - }, - }, - }, - nil, - ) - testsuite.Require().NoError(err) - vnResp, err := testutil.PollForTest(testsuite.ctx, vnPoller) - testsuite.Require().NoError(err) - testsuite.Require().Equal(vnName, *vnResp.Name) - - // create subnet - fmt.Println("Call operation: Subnets_CreateOrUpdate") - subClient, err := armnetwork.NewSubnetsClient(testsuite.subscriptionID, testsuite.cred, testsuite.options) - testsuite.Require().NoError(err) - subName := "go-test-subnet" - subPoller, err := subClient.BeginCreateOrUpdate( - testsuite.ctx, - testsuite.resourceGroupName, - vnName, - subName, - armnetwork.Subnet{ - Properties: &armnetwork.SubnetPropertiesFormat{ - AddressPrefix: to.Ptr("10.1.10.0/24"), - }, - }, - nil, - ) - testsuite.Require().NoError(err) - subResp, err := testutil.PollForTest(testsuite.ctx, subPoller) - testsuite.Require().NoError(err) - testsuite.Require().Equal(subName, *subResp.Name) - - // get subnet - fmt.Println("Call operation: Subnets_Get") - getResp, err := subClient.Get(testsuite.ctx, testsuite.resourceGroupName, vnName, subName, nil) - testsuite.Require().NoError(err) - testsuite.Require().Equal(subName, *getResp.Name) - - // list subnet - fmt.Println("Call operation: Subnets_List") - listPager := subClient.NewListPager(testsuite.resourceGroupName, vnName, nil) - testsuite.Require().Equal(true, listPager.More()) - - // delete subnet - fmt.Println("Call operation: Subnets_Delete") - delPoller, err := subClient.BeginDelete(testsuite.ctx, testsuite.resourceGroupName, vnName, subName, nil) - testsuite.Require().NoError(err) - delResp, err := testutil.PollForTest(testsuite.ctx, delPoller) - testsuite.Require().NoError(err) - //testsuite.Require().Equal(200, delResp.RawResponse.StatusCode) - _ = delResp -} diff --git a/sdk/resourcemanager/network/armnetwork/usage_live_test.go b/sdk/resourcemanager/network/armnetwork/usage_live_test.go new file mode 100644 index 000000000000..f992f35161c5 --- /dev/null +++ b/sdk/resourcemanager/network/armnetwork/usage_live_test.go @@ -0,0 +1,70 @@ +//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. +// Code generated by Microsoft (R) AutoRest Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. + +package armnetwork_test + +import ( + "context" + "fmt" + "testing" + + "github.com/Azure/azure-sdk-for-go/sdk/azcore" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/arm" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/internal/testutil" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork/v2" + "github.com/stretchr/testify/suite" +) + +type UsageTestSuite struct { + suite.Suite + + ctx context.Context + cred azcore.TokenCredential + options *arm.ClientOptions + location string + resourceGroupName string + subscriptionId string +} + +func (testsuite *UsageTestSuite) SetupSuite() { + testutil.StartRecording(testsuite.T(), "sdk/resourcemanager/network/armnetwork/testdata") + + testsuite.ctx = context.Background() + testsuite.cred, testsuite.options = testutil.GetCredAndClientOptions(testsuite.T()) + testsuite.location = testutil.GetEnv("LOCATION", "westus") + testsuite.resourceGroupName = testutil.GetEnv("RESOURCE_GROUP_NAME", "scenarioTestTempGroup") + testsuite.subscriptionId = testutil.GetEnv("AZURE_SUBSCRIPTION_ID", "00000000-0000-0000-0000-000000000000") + resourceGroup, _, err := testutil.CreateResourceGroup(testsuite.ctx, testsuite.subscriptionId, testsuite.cred, testsuite.options, testsuite.location) + testsuite.Require().NoError(err) + testsuite.resourceGroupName = *resourceGroup.Name +} + +func (testsuite *UsageTestSuite) TearDownSuite() { + _, err := testutil.DeleteResourceGroup(testsuite.ctx, testsuite.subscriptionId, testsuite.cred, testsuite.options, testsuite.resourceGroupName) + testsuite.Require().NoError(err) + testutil.StopRecording(testsuite.T()) +} + +func TestUsageTestSuite(t *testing.T) { + suite.Run(t, new(UsageTestSuite)) +} + +// Microsoft.Network/locations/{location}/usages +func (testsuite *UsageTestSuite) TestUsages() { + var err error + // From step Usages_List + fmt.Println("Call operation: Usages_List") + usagesClient, err := armnetwork.NewUsagesClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + usagesClientNewListPager := usagesClient.NewListPager(testsuite.location, nil) + for usagesClientNewListPager.More() { + _, err := usagesClientNewListPager.NextPage(testsuite.ctx) + testsuite.Require().NoError(err) + break + } +} diff --git a/sdk/resourcemanager/network/armnetwork/virtualnetwork_live_test.go b/sdk/resourcemanager/network/armnetwork/virtualnetwork_live_test.go new file mode 100644 index 000000000000..3b7ed45a478c --- /dev/null +++ b/sdk/resourcemanager/network/armnetwork/virtualnetwork_live_test.go @@ -0,0 +1,258 @@ +//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. +// Code generated by Microsoft (R) AutoRest Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. + +package armnetwork_test + +import ( + "context" + "fmt" + "testing" + + "github.com/Azure/azure-sdk-for-go/sdk/azcore" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/arm" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/to" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/internal/testutil" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork/v2" + "github.com/stretchr/testify/suite" +) + +type VirtualNetworkTestSuite struct { + suite.Suite + + ctx context.Context + cred azcore.TokenCredential + options *arm.ClientOptions + virtualNetworkName string + location string + resourceGroupName string + subscriptionId string +} + +func (testsuite *VirtualNetworkTestSuite) SetupSuite() { + testutil.StartRecording(testsuite.T(), "sdk/resourcemanager/network/armnetwork/testdata") + + testsuite.ctx = context.Background() + testsuite.cred, testsuite.options = testutil.GetCredAndClientOptions(testsuite.T()) + testsuite.virtualNetworkName = testutil.GenerateAlphaNumericID(testsuite.T(), "virtualnet", 6) + testsuite.location = testutil.GetEnv("LOCATION", "westus") + testsuite.resourceGroupName = testutil.GetEnv("RESOURCE_GROUP_NAME", "scenarioTestTempGroup") + testsuite.subscriptionId = testutil.GetEnv("AZURE_SUBSCRIPTION_ID", "00000000-0000-0000-0000-000000000000") + resourceGroup, _, err := testutil.CreateResourceGroup(testsuite.ctx, testsuite.subscriptionId, testsuite.cred, testsuite.options, testsuite.location) + testsuite.Require().NoError(err) + testsuite.resourceGroupName = *resourceGroup.Name + testsuite.Prepare() +} + +func (testsuite *VirtualNetworkTestSuite) TearDownSuite() { + testsuite.Cleanup() + _, err := testutil.DeleteResourceGroup(testsuite.ctx, testsuite.subscriptionId, testsuite.cred, testsuite.options, testsuite.resourceGroupName) + testsuite.Require().NoError(err) + testutil.StopRecording(testsuite.T()) +} + +func TestVirtualNetworkTestSuite(t *testing.T) { + suite.Run(t, new(VirtualNetworkTestSuite)) +} + +func (testsuite *VirtualNetworkTestSuite) Prepare() { + var err error + // From step VirtualNetworks_CreateOrUpdate + fmt.Println("Call operation: VirtualNetworks_CreateOrUpdate") + virtualNetworksClient, err := armnetwork.NewVirtualNetworksClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + virtualNetworksClientCreateOrUpdateResponsePoller, err := virtualNetworksClient.BeginCreateOrUpdate(testsuite.ctx, testsuite.resourceGroupName, testsuite.virtualNetworkName, armnetwork.VirtualNetwork{ + Location: to.Ptr(testsuite.location), + Properties: &armnetwork.VirtualNetworkPropertiesFormat{ + AddressSpace: &armnetwork.AddressSpace{ + AddressPrefixes: []*string{ + to.Ptr("10.0.0.0/16")}, + }, + FlowTimeoutInMinutes: to.Ptr[int32](10), + }, + }, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, virtualNetworksClientCreateOrUpdateResponsePoller) + testsuite.Require().NoError(err) +} + +// Microsoft.Network/virtualNetworks/{virtualNetworkName} +func (testsuite *VirtualNetworkTestSuite) TestVirtualNetworks() { + var err error + // From step VirtualNetworks_ListAll + fmt.Println("Call operation: VirtualNetworks_ListAll") + virtualNetworksClient, err := armnetwork.NewVirtualNetworksClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + virtualNetworksClientNewListAllPager := virtualNetworksClient.NewListAllPager(nil) + for virtualNetworksClientNewListAllPager.More() { + _, err := virtualNetworksClientNewListAllPager.NextPage(testsuite.ctx) + testsuite.Require().NoError(err) + break + } + + // From step VirtualNetworks_List + fmt.Println("Call operation: VirtualNetworks_List") + virtualNetworksClientNewListPager := virtualNetworksClient.NewListPager(testsuite.resourceGroupName, nil) + for virtualNetworksClientNewListPager.More() { + _, err := virtualNetworksClientNewListPager.NextPage(testsuite.ctx) + testsuite.Require().NoError(err) + break + } + + // From step VirtualNetworks_Get + fmt.Println("Call operation: VirtualNetworks_Get") + _, err = virtualNetworksClient.Get(testsuite.ctx, testsuite.resourceGroupName, testsuite.virtualNetworkName, &armnetwork.VirtualNetworksClientGetOptions{Expand: nil}) + testsuite.Require().NoError(err) + + // From step VirtualNetworks_ListUsage + fmt.Println("Call operation: VirtualNetworks_ListUsage") + virtualNetworksClientNewListUsagePager := virtualNetworksClient.NewListUsagePager(testsuite.resourceGroupName, testsuite.virtualNetworkName, nil) + for virtualNetworksClientNewListUsagePager.More() { + _, err := virtualNetworksClientNewListUsagePager.NextPage(testsuite.ctx) + testsuite.Require().NoError(err) + break + } + + // From step VirtualNetworks_UpdateTags + fmt.Println("Call operation: VirtualNetworks_UpdateTags") + _, err = virtualNetworksClient.UpdateTags(testsuite.ctx, testsuite.resourceGroupName, testsuite.virtualNetworkName, armnetwork.TagsObject{ + Tags: map[string]*string{ + "tag1": to.Ptr("value1"), + "tag2": to.Ptr("value2"), + }, + }, nil) + testsuite.Require().NoError(err) + + // From step VirtualNetworks_ListDdosProtectionStatus + fmt.Println("Call operation: VirtualNetworks_ListDdosProtectionStatus") + virtualNetworksClientListDdosProtectionStatusResponsePoller, err := virtualNetworksClient.BeginListDdosProtectionStatus(testsuite.ctx, testsuite.resourceGroupName, testsuite.virtualNetworkName, &armnetwork.VirtualNetworksClientBeginListDdosProtectionStatusOptions{Top: to.Ptr[int32](75), + SkipToken: nil, + }) + testsuite.Require().NoError(err) + virtualNetworksClientListDdosProtectionStatusResponse, err := testutil.PollForTest(testsuite.ctx, virtualNetworksClientListDdosProtectionStatusResponsePoller) + testsuite.Require().NoError(err) + for (*virtualNetworksClientListDdosProtectionStatusResponse).More() { + _, err := virtualNetworksClientNewListUsagePager.NextPage(testsuite.ctx) + testsuite.Require().NoError(err) + break + } +} + +// Microsoft.Network/virtualNetworks/{virtualNetworkName}/subnets/{subnetName} +func (testsuite *VirtualNetworkTestSuite) TestSubnets() { + subnetName := testutil.GenerateAlphaNumericID(testsuite.T(), "subnetname", 6) + var err error + // From step Subnets_CreateOrUpdate + fmt.Println("Call operation: Subnets_CreateOrUpdate") + subnetsClient, err := armnetwork.NewSubnetsClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + subnetsClientCreateOrUpdateResponsePoller, err := subnetsClient.BeginCreateOrUpdate(testsuite.ctx, testsuite.resourceGroupName, testsuite.virtualNetworkName, subnetName, armnetwork.Subnet{ + Properties: &armnetwork.SubnetPropertiesFormat{ + AddressPrefix: to.Ptr("10.0.0.0/16"), + }, + }, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, subnetsClientCreateOrUpdateResponsePoller) + testsuite.Require().NoError(err) + + // From step Subnets_List + fmt.Println("Call operation: Subnets_List") + subnetsClientNewListPager := subnetsClient.NewListPager(testsuite.resourceGroupName, testsuite.virtualNetworkName, nil) + for subnetsClientNewListPager.More() { + _, err := subnetsClientNewListPager.NextPage(testsuite.ctx) + testsuite.Require().NoError(err) + break + } + + // From step Subnets_Get + fmt.Println("Call operation: Subnets_Get") + _, err = subnetsClient.Get(testsuite.ctx, testsuite.resourceGroupName, testsuite.virtualNetworkName, subnetName, &armnetwork.SubnetsClientGetOptions{Expand: nil}) + testsuite.Require().NoError(err) + + // From step Subnets_Delete + fmt.Println("Call operation: Subnets_Delete") + subnetsClientDeleteResponsePoller, err := subnetsClient.BeginDelete(testsuite.ctx, testsuite.resourceGroupName, testsuite.virtualNetworkName, subnetName, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, subnetsClientDeleteResponsePoller) + testsuite.Require().NoError(err) +} + +// Microsoft.Network/virtualNetworks/{virtualNetworkName}/virtualNetworkPeerings/{virtualNetworkPeeringName} +func (testsuite *VirtualNetworkTestSuite) TestVirtualNetworkPeerings() { + virtualNetworkPeeringName := testutil.GenerateAlphaNumericID(testsuite.T(), "virtualnet", 6) + var err error + // From step VirtualNetworks_CreateOrUpdate + fmt.Println("Call operation: VirtualNetworks_CreateOrUpdate") + virtualNetworksClient, err := armnetwork.NewVirtualNetworksClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + virtualNetworksClientCreateOrUpdateResponsePoller, err := virtualNetworksClient.BeginCreateOrUpdate(testsuite.ctx, testsuite.resourceGroupName, virtualNetworkPeeringName, armnetwork.VirtualNetwork{ + Location: to.Ptr(testsuite.location), + Properties: &armnetwork.VirtualNetworkPropertiesFormat{ + AddressSpace: &armnetwork.AddressSpace{ + AddressPrefixes: []*string{ + to.Ptr("11.0.0.0/16")}, + }, + FlowTimeoutInMinutes: to.Ptr[int32](10), + }, + }, nil) + testsuite.Require().NoError(err) + virtualNetworksClientCreateOrUpdateResponse, err := testutil.PollForTest(testsuite.ctx, virtualNetworksClientCreateOrUpdateResponsePoller) + testsuite.Require().NoError(err) + virtualNetworkSecondId := *virtualNetworksClientCreateOrUpdateResponse.ID + + // From step VirtualNetworkPeerings_CreateOrUpdate + fmt.Println("Call operation: VirtualNetworkPeerings_CreateOrUpdate") + virtualNetworkPeeringsClient, err := armnetwork.NewVirtualNetworkPeeringsClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + virtualNetworkPeeringsClientCreateOrUpdateResponsePoller, err := virtualNetworkPeeringsClient.BeginCreateOrUpdate(testsuite.ctx, testsuite.resourceGroupName, testsuite.virtualNetworkName, virtualNetworkPeeringName, armnetwork.VirtualNetworkPeering{ + Properties: &armnetwork.VirtualNetworkPeeringPropertiesFormat{ + AllowForwardedTraffic: to.Ptr(true), + AllowGatewayTransit: to.Ptr(false), + AllowVirtualNetworkAccess: to.Ptr(true), + RemoteVirtualNetwork: &armnetwork.SubResource{ + ID: to.Ptr(virtualNetworkSecondId), + }, + UseRemoteGateways: to.Ptr(false), + }, + }, &armnetwork.VirtualNetworkPeeringsClientBeginCreateOrUpdateOptions{SyncRemoteAddressSpace: nil}) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, virtualNetworkPeeringsClientCreateOrUpdateResponsePoller) + testsuite.Require().NoError(err) + + // From step VirtualNetworkPeerings_List + fmt.Println("Call operation: VirtualNetworkPeerings_List") + virtualNetworkPeeringsClientNewListPager := virtualNetworkPeeringsClient.NewListPager(testsuite.resourceGroupName, testsuite.virtualNetworkName, nil) + for virtualNetworkPeeringsClientNewListPager.More() { + _, err := virtualNetworkPeeringsClientNewListPager.NextPage(testsuite.ctx) + testsuite.Require().NoError(err) + break + } + + // From step VirtualNetworkPeerings_Get + fmt.Println("Call operation: VirtualNetworkPeerings_Get") + _, err = virtualNetworkPeeringsClient.Get(testsuite.ctx, testsuite.resourceGroupName, testsuite.virtualNetworkName, virtualNetworkPeeringName, nil) + testsuite.Require().NoError(err) + + // From step VirtualNetworkPeerings_Delete + fmt.Println("Call operation: VirtualNetworkPeerings_Delete") + virtualNetworkPeeringsClientDeleteResponsePoller, err := virtualNetworkPeeringsClient.BeginDelete(testsuite.ctx, testsuite.resourceGroupName, testsuite.virtualNetworkName, virtualNetworkPeeringName, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, virtualNetworkPeeringsClientDeleteResponsePoller) + testsuite.Require().NoError(err) +} + +func (testsuite *VirtualNetworkTestSuite) Cleanup() { + var err error + // From step VirtualNetworks_Delete + fmt.Println("Call operation: VirtualNetworks_Delete") + virtualNetworksClient, err := armnetwork.NewVirtualNetworksClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + virtualNetworksClientDeleteResponsePoller, err := virtualNetworksClient.BeginDelete(testsuite.ctx, testsuite.resourceGroupName, testsuite.virtualNetworkName, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, virtualNetworksClientDeleteResponsePoller) + testsuite.Require().NoError(err) +} diff --git a/sdk/resourcemanager/network/armnetwork/virtualnetworkgateway_live_test.go b/sdk/resourcemanager/network/armnetwork/virtualnetworkgateway_live_test.go new file mode 100644 index 000000000000..24d9d51edc26 --- /dev/null +++ b/sdk/resourcemanager/network/armnetwork/virtualnetworkgateway_live_test.go @@ -0,0 +1,237 @@ +//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. +// Code generated by Microsoft (R) AutoRest Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. + +package armnetwork_test + +import ( + "context" + "fmt" + "testing" + + "github.com/Azure/azure-sdk-for-go/sdk/azcore" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/arm" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/to" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/internal/testutil" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork/v2" + "github.com/stretchr/testify/suite" +) + +type VirtualNetworkGatewayTestSuite struct { + suite.Suite + + ctx context.Context + cred azcore.TokenCredential + options *arm.ClientOptions + publicIpAddressId string + publicIpAddressName string + subnetId string + virtualNetworkGatewayName string + virtualNetworkName string + location string + resourceGroupName string + subscriptionId string +} + +func (testsuite *VirtualNetworkGatewayTestSuite) SetupSuite() { + testutil.StartRecording(testsuite.T(), "sdk/resourcemanager/network/armnetwork/testdata") + + testsuite.ctx = context.Background() + testsuite.cred, testsuite.options = testutil.GetCredAndClientOptions(testsuite.T()) + testsuite.publicIpAddressName = testutil.GenerateAlphaNumericID(testsuite.T(), "publicipadgateway", 6) + testsuite.virtualNetworkGatewayName = testutil.GenerateAlphaNumericID(testsuite.T(), "virtualnetgateway", 6) + testsuite.virtualNetworkName = testutil.GenerateAlphaNumericID(testsuite.T(), "virtualnetgateway", 6) + testsuite.location = testutil.GetEnv("LOCATION", "westus") + testsuite.resourceGroupName = testutil.GetEnv("RESOURCE_GROUP_NAME", "scenarioTestTempGroup") + testsuite.subscriptionId = testutil.GetEnv("AZURE_SUBSCRIPTION_ID", "00000000-0000-0000-0000-000000000000") + resourceGroup, _, err := testutil.CreateResourceGroup(testsuite.ctx, testsuite.subscriptionId, testsuite.cred, testsuite.options, testsuite.location) + testsuite.Require().NoError(err) + testsuite.resourceGroupName = *resourceGroup.Name + testsuite.Prepare() +} + +func (testsuite *VirtualNetworkGatewayTestSuite) TearDownSuite() { + _, err := testutil.DeleteResourceGroup(testsuite.ctx, testsuite.subscriptionId, testsuite.cred, testsuite.options, testsuite.resourceGroupName) + testsuite.Require().NoError(err) + testutil.StopRecording(testsuite.T()) +} + +func TestVirtualNetworkGatewayTestSuite(t *testing.T) { + suite.Run(t, new(VirtualNetworkGatewayTestSuite)) +} + +func (testsuite *VirtualNetworkGatewayTestSuite) Prepare() { + var err error + // From step VirtualNetworks_CreateOrUpdate + fmt.Println("Call operation: VirtualNetworks_CreateOrUpdate") + virtualNetworksClient, err := armnetwork.NewVirtualNetworksClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + virtualNetworksClientCreateOrUpdateResponsePoller, err := virtualNetworksClient.BeginCreateOrUpdate(testsuite.ctx, testsuite.resourceGroupName, testsuite.virtualNetworkName, armnetwork.VirtualNetwork{ + Location: to.Ptr(testsuite.location), + Properties: &armnetwork.VirtualNetworkPropertiesFormat{ + AddressSpace: &armnetwork.AddressSpace{ + AddressPrefixes: []*string{ + to.Ptr("10.0.0.0/16")}, + }, + Subnets: []*armnetwork.Subnet{ + { + Name: to.Ptr("GatewaySubnet"), + Properties: &armnetwork.SubnetPropertiesFormat{ + AddressPrefix: to.Ptr("10.0.0.0/24"), + }, + }}, + }, + }, nil) + testsuite.Require().NoError(err) + var virtualNetworksClientCreateOrUpdateResponse *armnetwork.VirtualNetworksClientCreateOrUpdateResponse + virtualNetworksClientCreateOrUpdateResponse, err = testutil.PollForTest(testsuite.ctx, virtualNetworksClientCreateOrUpdateResponsePoller) + testsuite.Require().NoError(err) + testsuite.subnetId = *virtualNetworksClientCreateOrUpdateResponse.Properties.Subnets[0].ID + + // From step PublicIPAddresses_CreateOrUpdate + fmt.Println("Call operation: PublicIPAddresses_CreateOrUpdate") + publicIPAddressesClient, err := armnetwork.NewPublicIPAddressesClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + publicIPAddressesClientCreateOrUpdateResponsePoller, err := publicIPAddressesClient.BeginCreateOrUpdate(testsuite.ctx, testsuite.resourceGroupName, testsuite.publicIpAddressName, armnetwork.PublicIPAddress{ + Location: to.Ptr(testsuite.location), + }, nil) + testsuite.Require().NoError(err) + var publicIPAddressesClientCreateOrUpdateResponse *armnetwork.PublicIPAddressesClientCreateOrUpdateResponse + publicIPAddressesClientCreateOrUpdateResponse, err = testutil.PollForTest(testsuite.ctx, publicIPAddressesClientCreateOrUpdateResponsePoller) + testsuite.Require().NoError(err) + testsuite.publicIpAddressId = *publicIPAddressesClientCreateOrUpdateResponse.ID + + // From step VirtualNetworkGateways_CreateOrUpdate + fmt.Println("Call operation: VirtualNetworkGateways_CreateOrUpdate") + virtualNetworkGatewaysClient, err := armnetwork.NewVirtualNetworkGatewaysClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + virtualNetworkGatewaysClientCreateOrUpdateResponsePoller, err := virtualNetworkGatewaysClient.BeginCreateOrUpdate(testsuite.ctx, testsuite.resourceGroupName, testsuite.virtualNetworkGatewayName, armnetwork.VirtualNetworkGateway{ + Location: to.Ptr(testsuite.location), + Properties: &armnetwork.VirtualNetworkGatewayPropertiesFormat{ + GatewayType: to.Ptr(armnetwork.VirtualNetworkGatewayTypeVPN), + IPConfigurations: []*armnetwork.VirtualNetworkGatewayIPConfiguration{ + { + Name: to.Ptr("gwipconfig1"), + Properties: &armnetwork.VirtualNetworkGatewayIPConfigurationPropertiesFormat{ + PrivateIPAllocationMethod: to.Ptr(armnetwork.IPAllocationMethodDynamic), + PublicIPAddress: &armnetwork.SubResource{ + ID: to.Ptr(testsuite.publicIpAddressId), + }, + Subnet: &armnetwork.SubResource{ + ID: to.Ptr(testsuite.subnetId), + }, + }, + }}, + VPNType: to.Ptr(armnetwork.VPNTypeRouteBased), + }, + }, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, virtualNetworkGatewaysClientCreateOrUpdateResponsePoller) + testsuite.Require().NoError(err) +} + +// Microsoft.Network/virtualNetworkGateways/{virtualNetworkGatewayName} +func (testsuite *VirtualNetworkGatewayTestSuite) TestVirtualNetworkGateways() { + var err error + // From step VirtualNetworkGateways_List + fmt.Println("Call operation: VirtualNetworkGateways_List") + virtualNetworkGatewaysClient, err := armnetwork.NewVirtualNetworkGatewaysClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + virtualNetworkGatewaysClientNewListPager := virtualNetworkGatewaysClient.NewListPager(testsuite.resourceGroupName, nil) + for virtualNetworkGatewaysClientNewListPager.More() { + _, err := virtualNetworkGatewaysClientNewListPager.NextPage(testsuite.ctx) + testsuite.Require().NoError(err) + break + } + + // From step VirtualNetworkGateways_Get + fmt.Println("Call operation: VirtualNetworkGateways_Get") + _, err = virtualNetworkGatewaysClient.Get(testsuite.ctx, testsuite.resourceGroupName, testsuite.virtualNetworkGatewayName, nil) + testsuite.Require().NoError(err) + + // From step VirtualNetworkGateways_ListConnections + fmt.Println("Call operation: VirtualNetworkGateways_ListConnections") + virtualNetworkGatewaysClientNewListConnectionsPager := virtualNetworkGatewaysClient.NewListConnectionsPager(testsuite.resourceGroupName, testsuite.virtualNetworkGatewayName, nil) + for virtualNetworkGatewaysClientNewListConnectionsPager.More() { + _, err := virtualNetworkGatewaysClientNewListConnectionsPager.NextPage(testsuite.ctx) + testsuite.Require().NoError(err) + break + } + + // From step VirtualNetworkGateways_UpdateTags + fmt.Println("Call operation: VirtualNetworkGateways_UpdateTags") + virtualNetworkGatewaysClientUpdateTagsResponsePoller, err := virtualNetworkGatewaysClient.BeginUpdateTags(testsuite.ctx, testsuite.resourceGroupName, testsuite.virtualNetworkGatewayName, armnetwork.TagsObject{ + Tags: map[string]*string{ + "tag1": to.Ptr("value1"), + "tag2": to.Ptr("value2"), + }, + }, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, virtualNetworkGatewaysClientUpdateTagsResponsePoller) + testsuite.Require().NoError(err) + + // From step VirtualNetworkGateways_Delete + fmt.Println("Call operation: VirtualNetworkGateways_Delete") + virtualNetworkGatewaysClientDeleteResponsePoller, err := virtualNetworkGatewaysClient.BeginDelete(testsuite.ctx, testsuite.resourceGroupName, testsuite.virtualNetworkGatewayName, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, virtualNetworkGatewaysClientDeleteResponsePoller) + testsuite.Require().NoError(err) +} + +// Microsoft.Network/localNetworkGateways/{localNetworkGatewayName} +func (testsuite *VirtualNetworkGatewayTestSuite) TestLocalNetworkGateways() { + localNetworkGatewayName := testutil.GenerateAlphaNumericID(testsuite.T(), "localnetwo", 6) + var err error + // From step LocalNetworkGateways_CreateOrUpdate + fmt.Println("Call operation: LocalNetworkGateways_CreateOrUpdate") + localNetworkGatewaysClient, err := armnetwork.NewLocalNetworkGatewaysClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + localNetworkGatewaysClientCreateOrUpdateResponsePoller, err := localNetworkGatewaysClient.BeginCreateOrUpdate(testsuite.ctx, testsuite.resourceGroupName, localNetworkGatewayName, armnetwork.LocalNetworkGateway{ + Location: to.Ptr(testsuite.location), + Properties: &armnetwork.LocalNetworkGatewayPropertiesFormat{ + GatewayIPAddress: to.Ptr("11.12.13.14"), + LocalNetworkAddressSpace: &armnetwork.AddressSpace{ + AddressPrefixes: []*string{ + to.Ptr("10.1.0.0/16")}, + }, + }, + }, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, localNetworkGatewaysClientCreateOrUpdateResponsePoller) + testsuite.Require().NoError(err) + + // From step LocalNetworkGateways_List + fmt.Println("Call operation: LocalNetworkGateways_List") + localNetworkGatewaysClientNewListPager := localNetworkGatewaysClient.NewListPager(testsuite.resourceGroupName, nil) + for localNetworkGatewaysClientNewListPager.More() { + _, err := localNetworkGatewaysClientNewListPager.NextPage(testsuite.ctx) + testsuite.Require().NoError(err) + break + } + + // From step LocalNetworkGateways_Get + fmt.Println("Call operation: LocalNetworkGateways_Get") + _, err = localNetworkGatewaysClient.Get(testsuite.ctx, testsuite.resourceGroupName, localNetworkGatewayName, nil) + testsuite.Require().NoError(err) + + // From step LocalNetworkGateways_UpdateTags + fmt.Println("Call operation: LocalNetworkGateways_UpdateTags") + _, err = localNetworkGatewaysClient.UpdateTags(testsuite.ctx, testsuite.resourceGroupName, localNetworkGatewayName, armnetwork.TagsObject{ + Tags: map[string]*string{ + "tag1": to.Ptr("value1"), + "tag2": to.Ptr("value2"), + }, + }, nil) + testsuite.Require().NoError(err) + + // From step LocalNetworkGateways_Delete + fmt.Println("Call operation: LocalNetworkGateways_Delete") + localNetworkGatewaysClientDeleteResponsePoller, err := localNetworkGatewaysClient.BeginDelete(testsuite.ctx, testsuite.resourceGroupName, localNetworkGatewayName, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, localNetworkGatewaysClientDeleteResponsePoller) + testsuite.Require().NoError(err) +} diff --git a/sdk/resourcemanager/network/armnetwork/virtualnetworks_client_live_test.go b/sdk/resourcemanager/network/armnetwork/virtualnetworks_client_live_test.go deleted file mode 100644 index 178f7cd211ce..000000000000 --- a/sdk/resourcemanager/network/armnetwork/virtualnetworks_client_live_test.go +++ /dev/null @@ -1,117 +0,0 @@ -//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 armnetwork_test - -import ( - "context" - "fmt" - "testing" - - "github.com/Azure/azure-sdk-for-go/sdk/azcore" - "github.com/Azure/azure-sdk-for-go/sdk/azcore/arm" - "github.com/Azure/azure-sdk-for-go/sdk/azcore/to" - "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/internal/testutil" - "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork/v2" - "github.com/stretchr/testify/suite" -) - -type VirtualNetworksClientTestSuite struct { - suite.Suite - - ctx context.Context - cred azcore.TokenCredential - options *arm.ClientOptions - location string - resourceGroupName string - subscriptionID string -} - -func (testsuite *VirtualNetworksClientTestSuite) SetupSuite() { - testsuite.ctx = context.Background() - testsuite.cred, testsuite.options = testutil.GetCredAndClientOptions(testsuite.T()) - testsuite.location = testutil.GetEnv("LOCATION", "eastus") - testsuite.subscriptionID = testutil.GetEnv("AZURE_SUBSCRIPTION_ID", "00000000-0000-0000-0000-000000000000") - testutil.StartRecording(testsuite.T(), "sdk/resourcemanager/network/armnetwork/testdata") - resourceGroup, _, err := testutil.CreateResourceGroup(testsuite.ctx, testsuite.subscriptionID, testsuite.cred, testsuite.options, testsuite.location) - testsuite.Require().NoError(err) - testsuite.resourceGroupName = *resourceGroup.Name -} - -func (testsuite *VirtualNetworksClientTestSuite) TearDownSuite() { - _, err := testutil.DeleteResourceGroup(testsuite.ctx, testsuite.subscriptionID, testsuite.cred, testsuite.options, testsuite.resourceGroupName) - testsuite.Require().NoError(err) - testutil.StopRecording(testsuite.T()) -} - -func TestVirtualNetworksClient(t *testing.T) { - suite.Run(t, new(VirtualNetworksClientTestSuite)) -} - -func (testsuite *VirtualNetworksClientTestSuite) TestVirtualMachineCRUD() { - // create virtual network - fmt.Println("Call operation: VirtualNetworks_CreateOrUpdate") - vnClient, err := armnetwork.NewVirtualNetworksClient(testsuite.subscriptionID, testsuite.cred, testsuite.options) - testsuite.Require().NoError(err) - vnName := "go-test-vn" - vnPoller, err := vnClient.BeginCreateOrUpdate( - testsuite.ctx, - testsuite.resourceGroupName, - vnName, - armnetwork.VirtualNetwork{ - Location: to.Ptr(testsuite.location), - Properties: &armnetwork.VirtualNetworkPropertiesFormat{ - AddressSpace: &armnetwork.AddressSpace{ - AddressPrefixes: []*string{ - to.Ptr("10.1.0.0/16"), - }, - }, - }, - }, - nil, - ) - testsuite.Require().NoError(err) - vnResp, err := testutil.PollForTest(testsuite.ctx, vnPoller) - testsuite.Require().NoError(err) - testsuite.Require().Equal(vnName, *vnResp.Name) - - //virtual network update tags - fmt.Println("Call operation: VirtualNetworks_UpdateTags") - tagResp, err := vnClient.UpdateTags( - testsuite.ctx, - testsuite.resourceGroupName, - vnName, - armnetwork.TagsObject{ - Tags: map[string]*string{ - "tag1": to.Ptr("value1"), - "tag2": to.Ptr("value2"), - }, - }, - nil, - ) - testsuite.Require().NoError(err) - testsuite.Require().Equal("value1", *tagResp.Tags["tag1"]) - - // get virtual network - fmt.Println("Call operation: VirtualNetworks_Get") - vnResp2, err := vnClient.Get(testsuite.ctx, testsuite.resourceGroupName, vnName, nil) - testsuite.Require().NoError(err) - testsuite.Require().Equal(vnName, *vnResp2.Name) - - //virtual network list - fmt.Println("Call operation: VirtualNetworks_List") - listPager := vnClient.NewListPager(testsuite.resourceGroupName, nil) - testsuite.Require().Equal(true, listPager.More()) - - //virtual network delete - fmt.Println("Call operation: VirtualNetworks_Delete") - delPoller, err := vnClient.BeginDelete(testsuite.ctx, testsuite.resourceGroupName, vnName, nil) - testsuite.Require().NoError(err) - delResp, err := testutil.PollForTest(testsuite.ctx, delPoller) - testsuite.Require().NoError(err) - //testsuite.Require().Equal(200, delResp.RawResponse.StatusCode) - _ = delResp -} diff --git a/sdk/resourcemanager/network/armnetwork/virtualwan_live_test.go b/sdk/resourcemanager/network/armnetwork/virtualwan_live_test.go new file mode 100644 index 000000000000..717a0ae720bb --- /dev/null +++ b/sdk/resourcemanager/network/armnetwork/virtualwan_live_test.go @@ -0,0 +1,461 @@ +//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. +// Code generated by Microsoft (R) AutoRest Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. + +package armnetwork_test + +import ( + "context" + "fmt" + "testing" + + "github.com/Azure/azure-sdk-for-go/sdk/azcore" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/arm" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/to" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/internal/testutil" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork/v2" + "github.com/stretchr/testify/suite" +) + +type VirtualWanTestSuite struct { + suite.Suite + + ctx context.Context + cred azcore.TokenCredential + options *arm.ClientOptions + gatewayName string + virtualHubId string + virtualHubName string + virtualWANName string + virtualWanId string + vpnServerConfigurationName string + vpnSiteName string + location string + resourceGroupName string + subscriptionId string +} + +func (testsuite *VirtualWanTestSuite) SetupSuite() { + testutil.StartRecording(testsuite.T(), "sdk/resourcemanager/network/armnetwork/testdata") + + testsuite.ctx = context.Background() + testsuite.cred, testsuite.options = testutil.GetCredAndClientOptions(testsuite.T()) + testsuite.gatewayName = testutil.GenerateAlphaNumericID(testsuite.T(), "gatewaynam", 6) + testsuite.virtualHubName = testutil.GenerateAlphaNumericID(testsuite.T(), "virtualhub", 6) + testsuite.virtualWANName = testutil.GenerateAlphaNumericID(testsuite.T(), "virtualwan", 6) + testsuite.vpnServerConfigurationName = testutil.GenerateAlphaNumericID(testsuite.T(), "vpnserverc", 6) + testsuite.vpnSiteName = testutil.GenerateAlphaNumericID(testsuite.T(), "vpnsitenam", 6) + testsuite.location = testutil.GetEnv("LOCATION", "westus") + testsuite.resourceGroupName = testutil.GetEnv("RESOURCE_GROUP_NAME", "scenarioTestTempGroup") + testsuite.subscriptionId = testutil.GetEnv("AZURE_SUBSCRIPTION_ID", "00000000-0000-0000-0000-000000000000") + resourceGroup, _, err := testutil.CreateResourceGroup(testsuite.ctx, testsuite.subscriptionId, testsuite.cred, testsuite.options, testsuite.location) + testsuite.Require().NoError(err) + testsuite.resourceGroupName = *resourceGroup.Name + testsuite.Prepare() +} + +func (testsuite *VirtualWanTestSuite) TearDownSuite() { + testsuite.Cleanup() + _, err := testutil.DeleteResourceGroup(testsuite.ctx, testsuite.subscriptionId, testsuite.cred, testsuite.options, testsuite.resourceGroupName) + testsuite.Require().NoError(err) + testutil.StopRecording(testsuite.T()) +} + +func TestVirtualWanTestSuite(t *testing.T) { + suite.Run(t, new(VirtualWanTestSuite)) +} + +func (testsuite *VirtualWanTestSuite) Prepare() { + var err error + // From step VirtualWans_CreateOrUpdate + fmt.Println("Call operation: VirtualWans_CreateOrUpdate") + virtualWansClient, err := armnetwork.NewVirtualWansClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + virtualWansClientCreateOrUpdateResponsePoller, err := virtualWansClient.BeginCreateOrUpdate(testsuite.ctx, testsuite.resourceGroupName, "wan1", armnetwork.VirtualWAN{ + Location: to.Ptr(testsuite.location), + Tags: map[string]*string{ + "key1": to.Ptr("value1"), + }, + Properties: &armnetwork.VirtualWanProperties{ + Type: to.Ptr("Standard"), + DisableVPNEncryption: to.Ptr(false), + }, + }, nil) + testsuite.Require().NoError(err) + var virtualWansClientCreateOrUpdateResponse *armnetwork.VirtualWansClientCreateOrUpdateResponse + virtualWansClientCreateOrUpdateResponse, err = testutil.PollForTest(testsuite.ctx, virtualWansClientCreateOrUpdateResponsePoller) + testsuite.Require().NoError(err) + testsuite.virtualWanId = *virtualWansClientCreateOrUpdateResponse.ID + + // From step VpnSites_CreateOrUpdate + fmt.Println("Call operation: VPNSites_CreateOrUpdate") + vPNSitesClient, err := armnetwork.NewVPNSitesClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + vPNSitesClientCreateOrUpdateResponsePoller, err := vPNSitesClient.BeginCreateOrUpdate(testsuite.ctx, testsuite.resourceGroupName, testsuite.vpnSiteName, armnetwork.VPNSite{ + Location: to.Ptr(testsuite.location), + Tags: map[string]*string{ + "key1": to.Ptr("value1"), + }, + Properties: &armnetwork.VPNSiteProperties{ + AddressSpace: &armnetwork.AddressSpace{ + AddressPrefixes: []*string{ + to.Ptr("10.0.0.0/16")}, + }, + IsSecuritySite: to.Ptr(false), + O365Policy: &armnetwork.O365PolicyProperties{ + BreakOutCategories: &armnetwork.O365BreakOutCategoryPolicies{ + Default: to.Ptr(false), + Allow: to.Ptr(true), + Optimize: to.Ptr(true), + }, + }, + VirtualWan: &armnetwork.SubResource{ + ID: to.Ptr(testsuite.virtualWanId), + }, + VPNSiteLinks: []*armnetwork.VPNSiteLink{ + { + Name: to.Ptr("vpnSiteLink1"), + Properties: &armnetwork.VPNSiteLinkProperties{ + BgpProperties: &armnetwork.VPNLinkBgpSettings{ + Asn: to.Ptr[int64](1234), + BgpPeeringAddress: to.Ptr("192.168.0.0"), + }, + IPAddress: to.Ptr("50.50.50.56"), + LinkProperties: &armnetwork.VPNLinkProviderProperties{ + LinkProviderName: to.Ptr("vendor1"), + LinkSpeedInMbps: to.Ptr[int32](0), + }, + }, + }}, + }, + }, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, vPNSitesClientCreateOrUpdateResponsePoller) + testsuite.Require().NoError(err) + + // From step VirtualHubs_CreateOrUpdate + fmt.Println("Call operation: VirtualHubs_CreateOrUpdate") + virtualHubsClient, err := armnetwork.NewVirtualHubsClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + virtualHubsClientCreateOrUpdateResponsePoller, err := virtualHubsClient.BeginCreateOrUpdate(testsuite.ctx, testsuite.resourceGroupName, testsuite.virtualHubName, armnetwork.VirtualHub{ + Location: to.Ptr(testsuite.location), + Tags: map[string]*string{ + "key1": to.Ptr("value1"), + }, + Properties: &armnetwork.VirtualHubProperties{ + AddressPrefix: to.Ptr("10.168.0.0/24"), + SKU: to.Ptr("Standard"), + VirtualWan: &armnetwork.SubResource{ + ID: to.Ptr(testsuite.virtualWanId), + }, + }, + }, nil) + testsuite.Require().NoError(err) + var virtualHubsClientCreateOrUpdateResponse *armnetwork.VirtualHubsClientCreateOrUpdateResponse + virtualHubsClientCreateOrUpdateResponse, err = testutil.PollForTest(testsuite.ctx, virtualHubsClientCreateOrUpdateResponsePoller) + testsuite.Require().NoError(err) + testsuite.virtualHubId = *virtualHubsClientCreateOrUpdateResponse.ID +} + +// Microsoft.Network/virtualWans/{VirtualWANName} +func (testsuite *VirtualWanTestSuite) TestVirtualWans() { + var err error + // From step VirtualWans_List + fmt.Println("Call operation: VirtualWans_List") + virtualWansClient, err := armnetwork.NewVirtualWansClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + virtualWansClientNewListPager := virtualWansClient.NewListPager(nil) + for virtualWansClientNewListPager.More() { + _, err := virtualWansClientNewListPager.NextPage(testsuite.ctx) + testsuite.Require().NoError(err) + break + } + + // From step VirtualWans_ListByResourceGroup + fmt.Println("Call operation: VirtualWans_ListByResourceGroup") + virtualWansClientNewListByResourceGroupPager := virtualWansClient.NewListByResourceGroupPager(testsuite.resourceGroupName, nil) + for virtualWansClientNewListByResourceGroupPager.More() { + _, err := virtualWansClientNewListByResourceGroupPager.NextPage(testsuite.ctx) + testsuite.Require().NoError(err) + break + } + + // From step VirtualWans_Get + fmt.Println("Call operation: VirtualWans_Get") + _, err = virtualWansClient.Get(testsuite.ctx, testsuite.resourceGroupName, "wan1", nil) + testsuite.Require().NoError(err) + + // From step VirtualWans_UpdateTags + fmt.Println("Call operation: VirtualWans_UpdateTags") + _, err = virtualWansClient.UpdateTags(testsuite.ctx, testsuite.resourceGroupName, "wan1", armnetwork.TagsObject{ + Tags: map[string]*string{ + "key1": to.Ptr("value1"), + "key2": to.Ptr("value2"), + }, + }, nil) + testsuite.Require().NoError(err) +} + +// Microsoft.Network/vpnSites/{vpnSiteName} +func (testsuite *VirtualWanTestSuite) TestVpnSites() { + var vpnSiteLinkName string + var err error + // From step VpnSites_List + fmt.Println("Call operation: VPNSites_List") + vPNSitesClient, err := armnetwork.NewVPNSitesClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + vPNSitesClientNewListPager := vPNSitesClient.NewListPager(nil) + for vPNSitesClientNewListPager.More() { + _, err := vPNSitesClientNewListPager.NextPage(testsuite.ctx) + testsuite.Require().NoError(err) + break + } + + // From step VpnSites_ListByResourceGroup + fmt.Println("Call operation: VPNSites_ListByResourceGroup") + vPNSitesClientNewListByResourceGroupPager := vPNSitesClient.NewListByResourceGroupPager(testsuite.resourceGroupName, nil) + for vPNSitesClientNewListByResourceGroupPager.More() { + _, err := vPNSitesClientNewListByResourceGroupPager.NextPage(testsuite.ctx) + testsuite.Require().NoError(err) + break + } + + // From step VpnSites_Get + fmt.Println("Call operation: VPNSites_Get") + _, err = vPNSitesClient.Get(testsuite.ctx, testsuite.resourceGroupName, testsuite.vpnSiteName, nil) + testsuite.Require().NoError(err) + + // From step VpnSites_UpdateTags + fmt.Println("Call operation: VPNSites_UpdateTags") + _, err = vPNSitesClient.UpdateTags(testsuite.ctx, testsuite.resourceGroupName, testsuite.vpnSiteName, armnetwork.TagsObject{ + Tags: map[string]*string{ + "key1": to.Ptr("value1"), + "key2": to.Ptr("value2"), + }, + }, nil) + testsuite.Require().NoError(err) + + // From step VpnSiteLinks_ListByVpnSite + fmt.Println("Call operation: VPNSiteLinks_ListByVPNSite") + vPNSiteLinksClient, err := armnetwork.NewVPNSiteLinksClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + vPNSiteLinksClientNewListByVPNSitePager := vPNSiteLinksClient.NewListByVPNSitePager(testsuite.resourceGroupName, testsuite.vpnSiteName, nil) + for vPNSiteLinksClientNewListByVPNSitePager.More() { + nextResult, err := vPNSiteLinksClientNewListByVPNSitePager.NextPage(testsuite.ctx) + testsuite.Require().NoError(err) + + vpnSiteLinkName = *nextResult.Value[0].Name + break + } + + // From step VpnSiteLinks_Get + fmt.Println("Call operation: VPNSiteLinks_Get") + _, err = vPNSiteLinksClient.Get(testsuite.ctx, testsuite.resourceGroupName, testsuite.vpnSiteName, vpnSiteLinkName, nil) + testsuite.Require().NoError(err) +} + +// Microsoft.Network/virtualHubs/{virtualHubName} +func (testsuite *VirtualWanTestSuite) TestVirtualHubs() { + var err error + // From step VirtualHubs_List + fmt.Println("Call operation: VirtualHubs_List") + virtualHubsClient, err := armnetwork.NewVirtualHubsClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + virtualHubsClientNewListPager := virtualHubsClient.NewListPager(nil) + for virtualHubsClientNewListPager.More() { + _, err := virtualHubsClientNewListPager.NextPage(testsuite.ctx) + testsuite.Require().NoError(err) + break + } + + // From step VirtualHubs_ListByResourceGroup + fmt.Println("Call operation: VirtualHubs_ListByResourceGroup") + virtualHubsClientNewListByResourceGroupPager := virtualHubsClient.NewListByResourceGroupPager(testsuite.resourceGroupName, nil) + for virtualHubsClientNewListByResourceGroupPager.More() { + _, err := virtualHubsClientNewListByResourceGroupPager.NextPage(testsuite.ctx) + testsuite.Require().NoError(err) + break + } + + // From step VirtualHubs_Get + fmt.Println("Call operation: VirtualHubs_Get") + _, err = virtualHubsClient.Get(testsuite.ctx, testsuite.resourceGroupName, testsuite.virtualHubName, nil) + testsuite.Require().NoError(err) + + // From step VirtualHubs_UpdateTags + fmt.Println("Call operation: VirtualHubs_UpdateTags") + _, err = virtualHubsClient.UpdateTags(testsuite.ctx, testsuite.resourceGroupName, testsuite.virtualHubName, armnetwork.TagsObject{ + Tags: map[string]*string{ + "key1": to.Ptr("value1"), + "key2": to.Ptr("value2"), + }, + }, nil) + testsuite.Require().NoError(err) +} + +// Microsoft.Network/virtualHubs/{virtualHubName}/routeMaps/{routeMapName} +func (testsuite *VirtualWanTestSuite) TestRouteMaps() { + routeMapName := testutil.GenerateAlphaNumericID(testsuite.T(), "routemapna", 6) + var err error + // From step RouteMaps_CreateOrUpdate + fmt.Println("Call operation: RouteMaps_CreateOrUpdate") + routeMapsClient, err := armnetwork.NewRouteMapsClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + routeMapsClientCreateOrUpdateResponsePoller, err := routeMapsClient.BeginCreateOrUpdate(testsuite.ctx, testsuite.resourceGroupName, testsuite.virtualHubName, routeMapName, armnetwork.RouteMap{ + Properties: &armnetwork.RouteMapProperties{ + AssociatedInboundConnections: []*string{ + to.Ptr("/subscriptions/" + testsuite.subscriptionId + "/resourceGroups/" + testsuite.resourceGroupName + "/providers/Microsoft.Network/expressRouteGateways/exrGateway1/expressRouteConnections/exrConn1")}, + AssociatedOutboundConnections: []*string{}, + Rules: []*armnetwork.RouteMapRule{ + { + Name: to.Ptr("rule1"), + Actions: []*armnetwork.Action{ + { + Type: to.Ptr(armnetwork.RouteMapActionTypeAdd), + Parameters: []*armnetwork.Parameter{ + { + AsPath: []*string{ + to.Ptr("22334")}, + Community: []*string{}, + RoutePrefix: []*string{}, + }}, + }}, + MatchCriteria: []*armnetwork.Criterion{ + { + AsPath: []*string{}, + Community: []*string{}, + MatchCondition: to.Ptr(armnetwork.RouteMapMatchConditionContains), + RoutePrefix: []*string{ + to.Ptr("10.0.0.0/8")}, + }}, + NextStepIfMatched: to.Ptr(armnetwork.NextStepContinue), + }}, + }, + }, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, routeMapsClientCreateOrUpdateResponsePoller) + testsuite.Require().NoError(err) + + // From step RouteMaps_List + fmt.Println("Call operation: RouteMaps_List") + routeMapsClientNewListPager := routeMapsClient.NewListPager(testsuite.resourceGroupName, testsuite.virtualHubName, nil) + for routeMapsClientNewListPager.More() { + _, err := routeMapsClientNewListPager.NextPage(testsuite.ctx) + testsuite.Require().NoError(err) + break + } + + // From step RouteMaps_Get + fmt.Println("Call operation: RouteMaps_Get") + _, err = routeMapsClient.Get(testsuite.ctx, testsuite.resourceGroupName, testsuite.virtualHubName, routeMapName, nil) + testsuite.Require().NoError(err) + + // From step RouteMaps_Delete + fmt.Println("Call operation: RouteMaps_Delete") + routeMapsClientDeleteResponsePoller, err := routeMapsClient.BeginDelete(testsuite.ctx, testsuite.resourceGroupName, testsuite.virtualHubName, routeMapName, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, routeMapsClientDeleteResponsePoller) + testsuite.Require().NoError(err) +} + +// Microsoft.Network/virtualHubs/{virtualHubName}/hubRouteTables/{routeTableName} +func (testsuite *VirtualWanTestSuite) TestHubRouteTables() { + var err error + // From step HubRouteTables_CreateOrUpdate + fmt.Println("Call operation: HubRouteTables_CreateOrUpdate") + hubRouteTablesClient, err := armnetwork.NewHubRouteTablesClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + hubRouteTablesClientCreateOrUpdateResponsePoller, err := hubRouteTablesClient.BeginCreateOrUpdate(testsuite.ctx, testsuite.resourceGroupName, testsuite.virtualHubName, "hubRouteTable1", armnetwork.HubRouteTable{ + Properties: &armnetwork.HubRouteTableProperties{ + Labels: []*string{ + to.Ptr("label1"), + to.Ptr("label2"), + }, + }, + }, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, hubRouteTablesClientCreateOrUpdateResponsePoller) + testsuite.Require().NoError(err) + + // From step HubRouteTables_List + fmt.Println("Call operation: HubRouteTables_List") + hubRouteTablesClientNewListPager := hubRouteTablesClient.NewListPager(testsuite.resourceGroupName, testsuite.virtualHubName, nil) + for hubRouteTablesClientNewListPager.More() { + _, err := hubRouteTablesClientNewListPager.NextPage(testsuite.ctx) + testsuite.Require().NoError(err) + break + } + + // From step HubRouteTables_Get + fmt.Println("Call operation: HubRouteTables_Get") + _, err = hubRouteTablesClient.Get(testsuite.ctx, testsuite.resourceGroupName, testsuite.virtualHubName, "hubRouteTable1", nil) + testsuite.Require().NoError(err) + + // From step HubRouteTables_Delete + fmt.Println("Call operation: HubRouteTables_Delete") + hubRouteTablesClientDeleteResponsePoller, err := hubRouteTablesClient.BeginDelete(testsuite.ctx, testsuite.resourceGroupName, testsuite.virtualHubName, "hubRouteTable1", nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, hubRouteTablesClientDeleteResponsePoller) + testsuite.Require().NoError(err) +} + +// Microsoft.Network/virtualHubs/{virtualHubName}/routingIntent/{routingIntentName} +func (testsuite *VirtualWanTestSuite) TestRoutingIntent() { + var err error + // From step RoutingIntent_CreateOrUpdate + fmt.Println("Call operation: RoutingIntent_CreateOrUpdate") + routingIntentClient, err := armnetwork.NewRoutingIntentClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + routingIntentClientCreateOrUpdateResponsePoller, err := routingIntentClient.BeginCreateOrUpdate(testsuite.ctx, testsuite.resourceGroupName, testsuite.virtualHubName, "Intent1", armnetwork.RoutingIntent{ + Properties: &armnetwork.RoutingIntentProperties{}, + }, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, routingIntentClientCreateOrUpdateResponsePoller) + testsuite.Require().NoError(err) + + // From step RoutingIntent_List + fmt.Println("Call operation: RoutingIntent_List") + routingIntentClientNewListPager := routingIntentClient.NewListPager(testsuite.resourceGroupName, testsuite.virtualHubName, nil) + for routingIntentClientNewListPager.More() { + _, err := routingIntentClientNewListPager.NextPage(testsuite.ctx) + testsuite.Require().NoError(err) + break + } + + // From step RoutingIntent_Get + fmt.Println("Call operation: RoutingIntent_Get") + _, err = routingIntentClient.Get(testsuite.ctx, testsuite.resourceGroupName, testsuite.virtualHubName, "Intent1", nil) + testsuite.Require().NoError(err) + + // From step RoutingIntent_Delete + fmt.Println("Call operation: RoutingIntent_Delete") + routingIntentClientDeleteResponsePoller, err := routingIntentClient.BeginDelete(testsuite.ctx, testsuite.resourceGroupName, testsuite.virtualHubName, "Intent1", nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, routingIntentClientDeleteResponsePoller) + testsuite.Require().NoError(err) +} + +func (testsuite *VirtualWanTestSuite) Cleanup() { + var err error + // From step VpnSites_Delete + fmt.Println("Call operation: VPNSites_Delete") + vPNSitesClient, err := armnetwork.NewVPNSitesClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + vPNSitesClientDeleteResponsePoller, err := vPNSitesClient.BeginDelete(testsuite.ctx, testsuite.resourceGroupName, testsuite.vpnSiteName, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, vPNSitesClientDeleteResponsePoller) + testsuite.Require().NoError(err) + + // From step VirtualWans_Delete + fmt.Println("Call operation: VirtualWans_Delete") + virtualWansClient, err := armnetwork.NewVirtualWansClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + virtualWansClientDeleteResponsePoller, err := virtualWansClient.BeginDelete(testsuite.ctx, testsuite.resourceGroupName, "virtualWan1", nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, virtualWansClientDeleteResponsePoller) + testsuite.Require().NoError(err) +} diff --git a/sdk/resourcemanager/network/armnetwork/webapplicationfirewall_live_test.go b/sdk/resourcemanager/network/armnetwork/webapplicationfirewall_live_test.go new file mode 100644 index 000000000000..546757f835d7 --- /dev/null +++ b/sdk/resourcemanager/network/armnetwork/webapplicationfirewall_live_test.go @@ -0,0 +1,120 @@ +//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. +// Code generated by Microsoft (R) AutoRest Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. + +package armnetwork_test + +import ( + "context" + "fmt" + "testing" + + "github.com/Azure/azure-sdk-for-go/sdk/azcore" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/arm" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/to" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/internal/testutil" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork/v2" + "github.com/stretchr/testify/suite" +) + +type WebapplicationfirewallTestSuite struct { + suite.Suite + + ctx context.Context + cred azcore.TokenCredential + options *arm.ClientOptions + policyName string + location string + resourceGroupName string + subscriptionId string +} + +func (testsuite *WebapplicationfirewallTestSuite) SetupSuite() { + testutil.StartRecording(testsuite.T(), "sdk/resourcemanager/network/armnetwork/testdata") + + testsuite.ctx = context.Background() + testsuite.cred, testsuite.options = testutil.GetCredAndClientOptions(testsuite.T()) + testsuite.policyName = testutil.GenerateAlphaNumericID(testsuite.T(), "wafpolicyname", 6) + testsuite.location = testutil.GetEnv("LOCATION", "westus") + testsuite.resourceGroupName = testutil.GetEnv("RESOURCE_GROUP_NAME", "scenarioTestTempGroup") + testsuite.subscriptionId = testutil.GetEnv("AZURE_SUBSCRIPTION_ID", "00000000-0000-0000-0000-000000000000") + resourceGroup, _, err := testutil.CreateResourceGroup(testsuite.ctx, testsuite.subscriptionId, testsuite.cred, testsuite.options, testsuite.location) + testsuite.Require().NoError(err) + testsuite.resourceGroupName = *resourceGroup.Name +} + +func (testsuite *WebapplicationfirewallTestSuite) TearDownSuite() { + _, err := testutil.DeleteResourceGroup(testsuite.ctx, testsuite.subscriptionId, testsuite.cred, testsuite.options, testsuite.resourceGroupName) + testsuite.Require().NoError(err) + testutil.StopRecording(testsuite.T()) +} + +func TestWebapplicationfirewallTestSuite(t *testing.T) { + suite.Run(t, new(WebapplicationfirewallTestSuite)) +} + +// Microsoft.Network/ApplicationGatewayWebApplicationFirewallPolicies/{policyName} +func (testsuite *WebapplicationfirewallTestSuite) TestWebApplicationFirewallPolicies() { + var err error + // From step WebApplicationFirewallPolicies_CreateOrUpdate + fmt.Println("Call operation: WebApplicationFirewallPolicies_CreateOrUpdate") + webApplicationFirewallPoliciesClient, err := armnetwork.NewWebApplicationFirewallPoliciesClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + _, err = webApplicationFirewallPoliciesClient.CreateOrUpdate(testsuite.ctx, testsuite.resourceGroupName, testsuite.policyName, armnetwork.WebApplicationFirewallPolicy{ + Location: to.Ptr(testsuite.location), + Properties: &armnetwork.WebApplicationFirewallPolicyPropertiesFormat{ + ManagedRules: &armnetwork.ManagedRulesDefinition{ + ManagedRuleSets: []*armnetwork.ManagedRuleSet{ + { + RuleGroupOverrides: []*armnetwork.ManagedRuleGroupOverride{ + { + RuleGroupName: to.Ptr("REQUEST-931-APPLICATION-ATTACK-RFI"), + Rules: []*armnetwork.ManagedRuleOverride{ + { + Action: to.Ptr(armnetwork.ActionTypeLog), + RuleID: to.Ptr("931120"), + State: to.Ptr(armnetwork.ManagedRuleEnabledStateEnabled), + }}, + }}, + RuleSetType: to.Ptr("OWASP"), + RuleSetVersion: to.Ptr("3.2"), + }}, + }, + }, + }, nil) + testsuite.Require().NoError(err) + + // From step WebApplicationFirewallPolicies_List + fmt.Println("Call operation: WebApplicationFirewallPolicies_List") + webApplicationFirewallPoliciesClientNewListPager := webApplicationFirewallPoliciesClient.NewListPager(testsuite.resourceGroupName, nil) + for webApplicationFirewallPoliciesClientNewListPager.More() { + _, err := webApplicationFirewallPoliciesClientNewListPager.NextPage(testsuite.ctx) + testsuite.Require().NoError(err) + break + } + + // From step WebApplicationFirewallPolicies_ListAll + fmt.Println("Call operation: WebApplicationFirewallPolicies_ListAll") + webApplicationFirewallPoliciesClientNewListAllPager := webApplicationFirewallPoliciesClient.NewListAllPager(nil) + for webApplicationFirewallPoliciesClientNewListAllPager.More() { + _, err := webApplicationFirewallPoliciesClientNewListAllPager.NextPage(testsuite.ctx) + testsuite.Require().NoError(err) + break + } + + // From step WebApplicationFirewallPolicies_Get + fmt.Println("Call operation: WebApplicationFirewallPolicies_Get") + _, err = webApplicationFirewallPoliciesClient.Get(testsuite.ctx, testsuite.resourceGroupName, testsuite.policyName, nil) + testsuite.Require().NoError(err) + + // From step WebApplicationFirewallPolicies_Delete + fmt.Println("Call operation: WebApplicationFirewallPolicies_Delete") + webApplicationFirewallPoliciesClientDeleteResponsePoller, err := webApplicationFirewallPoliciesClient.BeginDelete(testsuite.ctx, testsuite.resourceGroupName, testsuite.policyName, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, webApplicationFirewallPoliciesClientDeleteResponsePoller) + testsuite.Require().NoError(err) +} diff --git a/sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/CHANGELOG.md b/sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/CHANGELOG.md new file mode 100644 index 000000000000..8033ec9495db --- /dev/null +++ b/sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/CHANGELOG.md @@ -0,0 +1,7 @@ +# Release History + +## 0.1.0 (2023-04-28) + +The package of `github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/paloaltonetworksngfw/armpanngfw` is using our [next generation design principles](https://azure.github.io/azure-sdk/general_introduction.html). + +To learn more, please refer to our documentation [Quick Start](https://aka.ms/azsdk/go/mgmt). \ No newline at end of file diff --git a/sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/LICENSE.txt b/sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/LICENSE.txt new file mode 100644 index 000000000000..dc0c2ffb3dc1 --- /dev/null +++ b/sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/LICENSE.txt @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) Microsoft Corporation. All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/README.md b/sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/README.md new file mode 100644 index 000000000000..da161be94d23 --- /dev/null +++ b/sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/README.md @@ -0,0 +1,85 @@ +# Azure PaloAltoNetworks Module for Go + +[![PkgGoDev](https://pkg.go.dev/badge/github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/paloaltonetworksngfw/armpanngfw)](https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/paloaltonetworksngfw/armpanngfw) + +The `armpanngfw` module provides operations for working with Azure PaloAltoNetworks. + +[Source code](https://github.com/Azure/azure-sdk-for-go/tree/main/sdk/resourcemanager/paloaltonetworksngfw/armpanngfw) + +# Getting started + +## Prerequisites + +- an [Azure subscription](https://azure.microsoft.com/free/) +- Go 1.18 or above (You could download and install the latest version of Go from [here](https://go.dev/doc/install). It will replace the existing Go on your machine. If you want to install multiple Go versions on the same machine, you could refer this [doc](https://go.dev/doc/manage-install).) + +## Install the package + +This project uses [Go modules](https://github.com/golang/go/wiki/Modules) for versioning and dependency management. + +Install the Azure PaloAltoNetworks module: + +```sh +go get github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/paloaltonetworksngfw/armpanngfw +``` + +## Authorization + +When creating a client, you will need to provide a credential for authenticating with Azure PaloAltoNetworks. The `azidentity` module provides facilities for various ways of authenticating with Azure including client/secret, certificate, managed identity, and more. + +```go +cred, err := azidentity.NewDefaultAzureCredential(nil) +``` + +For more information on authentication, please see the documentation for `azidentity` at [pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/azidentity](https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/azidentity). + +## Client Factory + +Azure PaloAltoNetworks module consists of one or more clients. We provide a client factory which could be used to create any client in this module. + +```go +clientFactory, err := armpanngfw.NewClientFactory(, cred, nil) +``` + +You can use `ClientOptions` in package `github.com/Azure/azure-sdk-for-go/sdk/azcore/arm` to set endpoint to connect with public and sovereign clouds as well as Azure Stack. For more information, please see the documentation for `azcore` at [pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/azcore](https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/azcore). + +```go +options := arm.ClientOptions { + ClientOptions: azcore.ClientOptions { + Cloud: cloud.AzureChina, + }, +} +clientFactory, err := armpanngfw.NewClientFactory(, cred, &options) +``` + +## Clients + +A client groups a set of related APIs, providing access to its functionality. Create one or more clients to access the APIs you require using client factory. + +```go +client := clientFactory.NewLocalRulesClient() +``` + +## Provide Feedback + +If you encounter bugs or have suggestions, please +[open an issue](https://github.com/Azure/azure-sdk-for-go/issues) and assign the `PaloAltoNetworks` label. + +# Contributing + +This project welcomes contributions and suggestions. Most contributions require +you to agree to a Contributor License Agreement (CLA) declaring that you have +the right to, and actually do, grant us the rights to use your contribution. +For details, visit [https://cla.microsoft.com](https://cla.microsoft.com). + +When you submit a pull request, a CLA-bot will automatically determine whether +you need to provide a CLA and decorate the PR appropriately (e.g., label, +comment). Simply follow the instructions provided by the bot. You will only +need to do this once across all repos using our CLA. + +This project has adopted the +[Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). +For more information, see the +[Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) +or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any +additional questions or comments. \ No newline at end of file diff --git a/sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/autorest.md b/sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/autorest.md new file mode 100644 index 000000000000..d3112cc93b6d --- /dev/null +++ b/sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/autorest.md @@ -0,0 +1,13 @@ +### AutoRest Configuration + +> see https://aka.ms/autorest + +``` yaml +azure-arm: true +require: +- https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/readme.md +- https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/readme.go.md +license-header: MICROSOFT_MIT_NO_VERSION +module-version: 0.1.0 + +``` \ No newline at end of file diff --git a/sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/build.go b/sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/build.go new file mode 100644 index 000000000000..ce99c5410442 --- /dev/null +++ b/sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/build.go @@ -0,0 +1,7 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See License.txt in the project root for license information. + +// This file enables 'go generate' to regenerate this specific SDK +//go:generate pwsh ../../../../eng/scripts/build.ps1 -skipBuild -cleanGenerated -format -tidy -generate -alwaysSetBodyParamRequired -removeUnreferencedTypes resourcemanager/paloaltonetworksngfw/armpanngfw + +package armpanngfw diff --git a/sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/certificateobjectglobalrulestack_client.go b/sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/certificateobjectglobalrulestack_client.go new file mode 100644 index 000000000000..b40ac8daa3d4 --- /dev/null +++ b/sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/certificateobjectglobalrulestack_client.go @@ -0,0 +1,284 @@ +//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. +// Code generated by Microsoft (R) AutoRest Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. +// DO NOT EDIT. + +package armpanngfw + +import ( + "context" + "errors" + "github.com/Azure/azure-sdk-for-go/sdk/azcore" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/arm" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/policy" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime" + "net/http" + "net/url" + "strings" +) + +// CertificateObjectGlobalRulestackClient contains the methods for the CertificateObjectGlobalRulestack group. +// Don't use this type directly, use NewCertificateObjectGlobalRulestackClient() instead. +type CertificateObjectGlobalRulestackClient struct { + internal *arm.Client +} + +// NewCertificateObjectGlobalRulestackClient creates a new instance of CertificateObjectGlobalRulestackClient with the specified values. +// - credential - used to authorize requests. Usually a credential from azidentity. +// - options - pass nil to accept the default values. +func NewCertificateObjectGlobalRulestackClient(credential azcore.TokenCredential, options *arm.ClientOptions) (*CertificateObjectGlobalRulestackClient, error) { + cl, err := arm.NewClient(moduleName+".CertificateObjectGlobalRulestackClient", moduleVersion, credential, options) + if err != nil { + return nil, err + } + client := &CertificateObjectGlobalRulestackClient{ + internal: cl, + } + return client, nil +} + +// BeginCreateOrUpdate - Create a CertificateObjectGlobalRulestackResource +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2022-08-29-preview +// - globalRulestackName - GlobalRulestack resource name +// - name - certificate name +// - resource - Resource create parameters. +// - options - CertificateObjectGlobalRulestackClientBeginCreateOrUpdateOptions contains the optional parameters for the CertificateObjectGlobalRulestackClient.BeginCreateOrUpdate +// method. +func (client *CertificateObjectGlobalRulestackClient) BeginCreateOrUpdate(ctx context.Context, globalRulestackName string, name string, resource CertificateObjectGlobalRulestackResource, options *CertificateObjectGlobalRulestackClientBeginCreateOrUpdateOptions) (*runtime.Poller[CertificateObjectGlobalRulestackClientCreateOrUpdateResponse], error) { + if options == nil || options.ResumeToken == "" { + resp, err := client.createOrUpdate(ctx, globalRulestackName, name, resource, options) + if err != nil { + return nil, err + } + return runtime.NewPoller(resp, client.internal.Pipeline(), &runtime.NewPollerOptions[CertificateObjectGlobalRulestackClientCreateOrUpdateResponse]{ + FinalStateVia: runtime.FinalStateViaAzureAsyncOp, + }) + } else { + return runtime.NewPollerFromResumeToken[CertificateObjectGlobalRulestackClientCreateOrUpdateResponse](options.ResumeToken, client.internal.Pipeline(), nil) + } +} + +// CreateOrUpdate - Create a CertificateObjectGlobalRulestackResource +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2022-08-29-preview +func (client *CertificateObjectGlobalRulestackClient) createOrUpdate(ctx context.Context, globalRulestackName string, name string, resource CertificateObjectGlobalRulestackResource, options *CertificateObjectGlobalRulestackClientBeginCreateOrUpdateOptions) (*http.Response, error) { + req, err := client.createOrUpdateCreateRequest(ctx, globalRulestackName, name, resource, options) + if err != nil { + return nil, err + } + resp, err := client.internal.Pipeline().Do(req) + if err != nil { + return nil, err + } + if !runtime.HasStatusCode(resp, http.StatusOK, http.StatusCreated) { + return nil, runtime.NewResponseError(resp) + } + return resp, nil +} + +// createOrUpdateCreateRequest creates the CreateOrUpdate request. +func (client *CertificateObjectGlobalRulestackClient) createOrUpdateCreateRequest(ctx context.Context, globalRulestackName string, name string, resource CertificateObjectGlobalRulestackResource, options *CertificateObjectGlobalRulestackClientBeginCreateOrUpdateOptions) (*policy.Request, error) { + urlPath := "/providers/PaloAltoNetworks.Cloudngfw/globalRulestacks/{globalRulestackName}/certificates/{name}" + if globalRulestackName == "" { + return nil, errors.New("parameter globalRulestackName cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{globalRulestackName}", url.PathEscape(globalRulestackName)) + if name == "" { + return nil, errors.New("parameter name cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{name}", url.PathEscape(name)) + req, err := runtime.NewRequest(ctx, http.MethodPut, runtime.JoinPaths(client.internal.Endpoint(), urlPath)) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("api-version", "2022-08-29-preview") + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["Accept"] = []string{"application/json"} + return req, runtime.MarshalAsJSON(req, resource) +} + +// BeginDelete - Delete a CertificateObjectGlobalRulestackResource +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2022-08-29-preview +// - globalRulestackName - GlobalRulestack resource name +// - name - certificate name +// - options - CertificateObjectGlobalRulestackClientBeginDeleteOptions contains the optional parameters for the CertificateObjectGlobalRulestackClient.BeginDelete +// method. +func (client *CertificateObjectGlobalRulestackClient) BeginDelete(ctx context.Context, globalRulestackName string, name string, options *CertificateObjectGlobalRulestackClientBeginDeleteOptions) (*runtime.Poller[CertificateObjectGlobalRulestackClientDeleteResponse], error) { + if options == nil || options.ResumeToken == "" { + resp, err := client.deleteOperation(ctx, globalRulestackName, name, options) + if err != nil { + return nil, err + } + return runtime.NewPoller(resp, client.internal.Pipeline(), &runtime.NewPollerOptions[CertificateObjectGlobalRulestackClientDeleteResponse]{ + FinalStateVia: runtime.FinalStateViaAzureAsyncOp, + }) + } else { + return runtime.NewPollerFromResumeToken[CertificateObjectGlobalRulestackClientDeleteResponse](options.ResumeToken, client.internal.Pipeline(), nil) + } +} + +// Delete - Delete a CertificateObjectGlobalRulestackResource +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2022-08-29-preview +func (client *CertificateObjectGlobalRulestackClient) deleteOperation(ctx context.Context, globalRulestackName string, name string, options *CertificateObjectGlobalRulestackClientBeginDeleteOptions) (*http.Response, error) { + req, err := client.deleteCreateRequest(ctx, globalRulestackName, name, options) + if err != nil { + return nil, err + } + resp, err := client.internal.Pipeline().Do(req) + if err != nil { + return nil, err + } + if !runtime.HasStatusCode(resp, http.StatusOK, http.StatusAccepted, http.StatusNoContent) { + return nil, runtime.NewResponseError(resp) + } + return resp, nil +} + +// deleteCreateRequest creates the Delete request. +func (client *CertificateObjectGlobalRulestackClient) deleteCreateRequest(ctx context.Context, globalRulestackName string, name string, options *CertificateObjectGlobalRulestackClientBeginDeleteOptions) (*policy.Request, error) { + urlPath := "/providers/PaloAltoNetworks.Cloudngfw/globalRulestacks/{globalRulestackName}/certificates/{name}" + if globalRulestackName == "" { + return nil, errors.New("parameter globalRulestackName cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{globalRulestackName}", url.PathEscape(globalRulestackName)) + if name == "" { + return nil, errors.New("parameter name cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{name}", url.PathEscape(name)) + req, err := runtime.NewRequest(ctx, http.MethodDelete, runtime.JoinPaths(client.internal.Endpoint(), urlPath)) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("api-version", "2022-08-29-preview") + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["Accept"] = []string{"application/json"} + return req, nil +} + +// Get - Get a CertificateObjectGlobalRulestackResource +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2022-08-29-preview +// - globalRulestackName - GlobalRulestack resource name +// - name - certificate name +// - options - CertificateObjectGlobalRulestackClientGetOptions contains the optional parameters for the CertificateObjectGlobalRulestackClient.Get +// method. +func (client *CertificateObjectGlobalRulestackClient) Get(ctx context.Context, globalRulestackName string, name string, options *CertificateObjectGlobalRulestackClientGetOptions) (CertificateObjectGlobalRulestackClientGetResponse, error) { + req, err := client.getCreateRequest(ctx, globalRulestackName, name, options) + if err != nil { + return CertificateObjectGlobalRulestackClientGetResponse{}, err + } + resp, err := client.internal.Pipeline().Do(req) + if err != nil { + return CertificateObjectGlobalRulestackClientGetResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusOK) { + return CertificateObjectGlobalRulestackClientGetResponse{}, runtime.NewResponseError(resp) + } + return client.getHandleResponse(resp) +} + +// getCreateRequest creates the Get request. +func (client *CertificateObjectGlobalRulestackClient) getCreateRequest(ctx context.Context, globalRulestackName string, name string, options *CertificateObjectGlobalRulestackClientGetOptions) (*policy.Request, error) { + urlPath := "/providers/PaloAltoNetworks.Cloudngfw/globalRulestacks/{globalRulestackName}/certificates/{name}" + if globalRulestackName == "" { + return nil, errors.New("parameter globalRulestackName cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{globalRulestackName}", url.PathEscape(globalRulestackName)) + if name == "" { + return nil, errors.New("parameter name cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{name}", url.PathEscape(name)) + req, err := runtime.NewRequest(ctx, http.MethodGet, runtime.JoinPaths(client.internal.Endpoint(), urlPath)) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("api-version", "2022-08-29-preview") + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["Accept"] = []string{"application/json"} + return req, nil +} + +// getHandleResponse handles the Get response. +func (client *CertificateObjectGlobalRulestackClient) getHandleResponse(resp *http.Response) (CertificateObjectGlobalRulestackClientGetResponse, error) { + result := CertificateObjectGlobalRulestackClientGetResponse{} + if err := runtime.UnmarshalAsJSON(resp, &result.CertificateObjectGlobalRulestackResource); err != nil { + return CertificateObjectGlobalRulestackClientGetResponse{}, err + } + return result, nil +} + +// NewListPager - List CertificateObjectGlobalRulestackResource resources by Tenant +// +// Generated from API version 2022-08-29-preview +// - globalRulestackName - GlobalRulestack resource name +// - options - CertificateObjectGlobalRulestackClientListOptions contains the optional parameters for the CertificateObjectGlobalRulestackClient.NewListPager +// method. +func (client *CertificateObjectGlobalRulestackClient) NewListPager(globalRulestackName string, options *CertificateObjectGlobalRulestackClientListOptions) *runtime.Pager[CertificateObjectGlobalRulestackClientListResponse] { + return runtime.NewPager(runtime.PagingHandler[CertificateObjectGlobalRulestackClientListResponse]{ + More: func(page CertificateObjectGlobalRulestackClientListResponse) bool { + return page.NextLink != nil && len(*page.NextLink) > 0 + }, + Fetcher: func(ctx context.Context, page *CertificateObjectGlobalRulestackClientListResponse) (CertificateObjectGlobalRulestackClientListResponse, error) { + var req *policy.Request + var err error + if page == nil { + req, err = client.listCreateRequest(ctx, globalRulestackName, options) + } else { + req, err = runtime.NewRequest(ctx, http.MethodGet, *page.NextLink) + } + if err != nil { + return CertificateObjectGlobalRulestackClientListResponse{}, err + } + resp, err := client.internal.Pipeline().Do(req) + if err != nil { + return CertificateObjectGlobalRulestackClientListResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusOK) { + return CertificateObjectGlobalRulestackClientListResponse{}, runtime.NewResponseError(resp) + } + return client.listHandleResponse(resp) + }, + }) +} + +// listCreateRequest creates the List request. +func (client *CertificateObjectGlobalRulestackClient) listCreateRequest(ctx context.Context, globalRulestackName string, options *CertificateObjectGlobalRulestackClientListOptions) (*policy.Request, error) { + urlPath := "/providers/PaloAltoNetworks.Cloudngfw/globalRulestacks/{globalRulestackName}/certificates" + if globalRulestackName == "" { + return nil, errors.New("parameter globalRulestackName cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{globalRulestackName}", url.PathEscape(globalRulestackName)) + req, err := runtime.NewRequest(ctx, http.MethodGet, runtime.JoinPaths(client.internal.Endpoint(), urlPath)) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("api-version", "2022-08-29-preview") + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["Accept"] = []string{"application/json"} + return req, nil +} + +// listHandleResponse handles the List response. +func (client *CertificateObjectGlobalRulestackClient) listHandleResponse(resp *http.Response) (CertificateObjectGlobalRulestackClientListResponse, error) { + result := CertificateObjectGlobalRulestackClientListResponse{} + if err := runtime.UnmarshalAsJSON(resp, &result.CertificateObjectGlobalRulestackResourceListResult); err != nil { + return CertificateObjectGlobalRulestackClientListResponse{}, err + } + return result, nil +} diff --git a/sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/certificateobjectglobalrulestack_client_example_test.go b/sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/certificateobjectglobalrulestack_client_example_test.go new file mode 100644 index 000000000000..7406b642e34e --- /dev/null +++ b/sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/certificateobjectglobalrulestack_client_example_test.go @@ -0,0 +1,299 @@ +//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. +// Code generated by Microsoft (R) AutoRest Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. +// DO NOT EDIT. + +package armpanngfw_test + +import ( + "context" + "log" + + "github.com/Azure/azure-sdk-for-go/sdk/azcore/to" + "github.com/Azure/azure-sdk-for-go/sdk/azidentity" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/paloaltonetworksngfw/armpanngfw" +) + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/CertificateObjectGlobalRulestack_List_MaximumSet_Gen.json +func ExampleCertificateObjectGlobalRulestackClient_NewListPager_certificateObjectGlobalRulestackListMaximumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + pager := clientFactory.NewCertificateObjectGlobalRulestackClient().NewListPager("praval", nil) + for pager.More() { + page, err := pager.NextPage(ctx) + if err != nil { + log.Fatalf("failed to advance page: %v", err) + } + for _, v := range page.Value { + // You could use page here. We use blank identifier for just demo purposes. + _ = v + } + // If the HTTP response code is 200 as defined in example definition, your page structure would look as follows. Please pay attention that all the values in the output are fake values for just demo purposes. + // page.CertificateObjectGlobalRulestackResourceListResult = armpanngfw.CertificateObjectGlobalRulestackResourceListResult{ + // Value: []*armpanngfw.CertificateObjectGlobalRulestackResource{ + // { + // Name: to.Ptr("armid1"), + // Type: to.Ptr("certificates"), + // ID: to.Ptr("/providers/PaloAltoNetworks.Cloudngfw/globalrulestacks/armid1/certificates/armid1"), + // SystemData: &armpanngfw.SystemData{ + // CreatedAt: to.Ptr(func() time.Time { t, _ := time.Parse(time.RFC3339Nano, "2022-09-09T05:08:24.229Z"); return t}()), + // CreatedBy: to.Ptr("praval"), + // CreatedByType: to.Ptr(armpanngfw.CreatedByTypeUser), + // LastModifiedAt: to.Ptr(func() time.Time { t, _ := time.Parse(time.RFC3339Nano, "2022-09-09T05:08:24.229Z"); return t}()), + // LastModifiedBy: to.Ptr("praval"), + // LastModifiedByType: to.Ptr(armpanngfw.CreatedByTypeUser), + // }, + // Properties: &armpanngfw.CertificateObject{ + // Description: to.Ptr("desc"), + // AuditComment: to.Ptr("comment"), + // CertificateSelfSigned: to.Ptr(armpanngfw.BooleanEnumTRUE), + // CertificateSignerResourceID: to.Ptr(""), + // Etag: to.Ptr("2bf4a339-294d-4c25-b0b2-ef649e9f5c27"), + // ProvisioningState: to.Ptr(armpanngfw.ProvisioningStateSucceeded), + // }, + // }}, + // } + } +} + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/CertificateObjectGlobalRulestack_List_MinimumSet_Gen.json +func ExampleCertificateObjectGlobalRulestackClient_NewListPager_certificateObjectGlobalRulestackListMinimumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + pager := clientFactory.NewCertificateObjectGlobalRulestackClient().NewListPager("praval", nil) + for pager.More() { + page, err := pager.NextPage(ctx) + if err != nil { + log.Fatalf("failed to advance page: %v", err) + } + for _, v := range page.Value { + // You could use page here. We use blank identifier for just demo purposes. + _ = v + } + // If the HTTP response code is 200 as defined in example definition, your page structure would look as follows. Please pay attention that all the values in the output are fake values for just demo purposes. + // page.CertificateObjectGlobalRulestackResourceListResult = armpanngfw.CertificateObjectGlobalRulestackResourceListResult{ + // Value: []*armpanngfw.CertificateObjectGlobalRulestackResource{ + // { + // ID: to.Ptr("/providers/PaloAltoNetworks.Cloudngfw/globalRulestacks/praval/certificates/certificates1"), + // Properties: &armpanngfw.CertificateObject{ + // CertificateSelfSigned: to.Ptr(armpanngfw.BooleanEnumTRUE), + // }, + // }}, + // } + } +} + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/CertificateObjectGlobalRulestack_Get_MaximumSet_Gen.json +func ExampleCertificateObjectGlobalRulestackClient_Get_certificateObjectGlobalRulestackGetMaximumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + res, err := clientFactory.NewCertificateObjectGlobalRulestackClient().Get(ctx, "praval", "armid1", nil) + if err != nil { + log.Fatalf("failed to finish the request: %v", err) + } + // You could use response here. We use blank identifier for just demo purposes. + _ = res + // If the HTTP response code is 200 as defined in example definition, your response structure would look as follows. Please pay attention that all the values in the output are fake values for just demo purposes. + // res.CertificateObjectGlobalRulestackResource = armpanngfw.CertificateObjectGlobalRulestackResource{ + // Name: to.Ptr("armid1"), + // Type: to.Ptr("certificates"), + // ID: to.Ptr("/providers/PaloAltoNetworks.Cloudngfw/globalrulestacks/armid1/certificates/armid1"), + // SystemData: &armpanngfw.SystemData{ + // CreatedAt: to.Ptr(func() time.Time { t, _ := time.Parse(time.RFC3339Nano, "2022-09-09T05:08:24.229Z"); return t}()), + // CreatedBy: to.Ptr("praval"), + // CreatedByType: to.Ptr(armpanngfw.CreatedByTypeUser), + // LastModifiedAt: to.Ptr(func() time.Time { t, _ := time.Parse(time.RFC3339Nano, "2022-09-09T05:08:24.229Z"); return t}()), + // LastModifiedBy: to.Ptr("praval"), + // LastModifiedByType: to.Ptr(armpanngfw.CreatedByTypeUser), + // }, + // Properties: &armpanngfw.CertificateObject{ + // Description: to.Ptr("description"), + // AuditComment: to.Ptr("comment"), + // CertificateSelfSigned: to.Ptr(armpanngfw.BooleanEnumTRUE), + // CertificateSignerResourceID: to.Ptr(""), + // Etag: to.Ptr("2bf4a339-294d-4c25-b0b2-ef649e9f5c27"), + // ProvisioningState: to.Ptr(armpanngfw.ProvisioningStateSucceeded), + // }, + // } +} + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/CertificateObjectGlobalRulestack_Get_MinimumSet_Gen.json +func ExampleCertificateObjectGlobalRulestackClient_Get_certificateObjectGlobalRulestackGetMinimumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + res, err := clientFactory.NewCertificateObjectGlobalRulestackClient().Get(ctx, "praval", "armid1", nil) + if err != nil { + log.Fatalf("failed to finish the request: %v", err) + } + // You could use response here. We use blank identifier for just demo purposes. + _ = res + // If the HTTP response code is 200 as defined in example definition, your response structure would look as follows. Please pay attention that all the values in the output are fake values for just demo purposes. + // res.CertificateObjectGlobalRulestackResource = armpanngfw.CertificateObjectGlobalRulestackResource{ + // ID: to.Ptr("/providers/PaloAltoNetworks.Cloudngfw/globalRulestacks/praval/certificates/armid1"), + // Properties: &armpanngfw.CertificateObject{ + // CertificateSelfSigned: to.Ptr(armpanngfw.BooleanEnumTRUE), + // }, + // } +} + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/CertificateObjectGlobalRulestack_CreateOrUpdate_MaximumSet_Gen.json +func ExampleCertificateObjectGlobalRulestackClient_BeginCreateOrUpdate_certificateObjectGlobalRulestackCreateOrUpdateMaximumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + poller, err := clientFactory.NewCertificateObjectGlobalRulestackClient().BeginCreateOrUpdate(ctx, "praval", "armid1", armpanngfw.CertificateObjectGlobalRulestackResource{ + Properties: &armpanngfw.CertificateObject{ + Description: to.Ptr("description"), + AuditComment: to.Ptr("comment"), + CertificateSelfSigned: to.Ptr(armpanngfw.BooleanEnumTRUE), + CertificateSignerResourceID: to.Ptr(""), + Etag: to.Ptr("2bf4a339-294d-4c25-b0b2-ef649e9f5c27"), + ProvisioningState: to.Ptr(armpanngfw.ProvisioningStateAccepted), + }, + }, nil) + if err != nil { + log.Fatalf("failed to finish the request: %v", err) + } + res, err := poller.PollUntilDone(ctx, nil) + if err != nil { + log.Fatalf("failed to pull the result: %v", err) + } + // You could use response here. We use blank identifier for just demo purposes. + _ = res + // If the HTTP response code is 200 as defined in example definition, your response structure would look as follows. Please pay attention that all the values in the output are fake values for just demo purposes. + // res.CertificateObjectGlobalRulestackResource = armpanngfw.CertificateObjectGlobalRulestackResource{ + // Name: to.Ptr("armid1"), + // Type: to.Ptr("certificates"), + // ID: to.Ptr("/providers/PaloAltoNetworks.Cloudngfw/globalrulestacks/armid1/certificates/armid1"), + // SystemData: &armpanngfw.SystemData{ + // CreatedAt: to.Ptr(func() time.Time { t, _ := time.Parse(time.RFC3339Nano, "2022-09-09T05:08:24.229Z"); return t}()), + // CreatedBy: to.Ptr("praval"), + // CreatedByType: to.Ptr(armpanngfw.CreatedByTypeUser), + // LastModifiedAt: to.Ptr(func() time.Time { t, _ := time.Parse(time.RFC3339Nano, "2022-09-09T05:08:24.229Z"); return t}()), + // LastModifiedBy: to.Ptr("praval"), + // LastModifiedByType: to.Ptr(armpanngfw.CreatedByTypeUser), + // }, + // Properties: &armpanngfw.CertificateObject{ + // Description: to.Ptr("description"), + // AuditComment: to.Ptr("comment"), + // CertificateSelfSigned: to.Ptr(armpanngfw.BooleanEnumTRUE), + // CertificateSignerResourceID: to.Ptr(""), + // Etag: to.Ptr("2bf4a339-294d-4c25-b0b2-ef649e9f5c27"), + // ProvisioningState: to.Ptr(armpanngfw.ProvisioningStateSucceeded), + // }, + // } +} + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/CertificateObjectGlobalRulestack_CreateOrUpdate_MinimumSet_Gen.json +func ExampleCertificateObjectGlobalRulestackClient_BeginCreateOrUpdate_certificateObjectGlobalRulestackCreateOrUpdateMinimumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + poller, err := clientFactory.NewCertificateObjectGlobalRulestackClient().BeginCreateOrUpdate(ctx, "praval", "armid1", armpanngfw.CertificateObjectGlobalRulestackResource{ + Properties: &armpanngfw.CertificateObject{ + CertificateSelfSigned: to.Ptr(armpanngfw.BooleanEnumTRUE), + }, + }, nil) + if err != nil { + log.Fatalf("failed to finish the request: %v", err) + } + res, err := poller.PollUntilDone(ctx, nil) + if err != nil { + log.Fatalf("failed to pull the result: %v", err) + } + // You could use response here. We use blank identifier for just demo purposes. + _ = res + // If the HTTP response code is 200 as defined in example definition, your response structure would look as follows. Please pay attention that all the values in the output are fake values for just demo purposes. + // res.CertificateObjectGlobalRulestackResource = armpanngfw.CertificateObjectGlobalRulestackResource{ + // ID: to.Ptr("/providers/PaloAltoNetworks.Cloudngfw/globalRulestacks/praval/certificates/armid1"), + // Properties: &armpanngfw.CertificateObject{ + // CertificateSelfSigned: to.Ptr(armpanngfw.BooleanEnumTRUE), + // }, + // } +} + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/CertificateObjectGlobalRulestack_Delete_MaximumSet_Gen.json +func ExampleCertificateObjectGlobalRulestackClient_BeginDelete_certificateObjectGlobalRulestackDeleteMaximumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + poller, err := clientFactory.NewCertificateObjectGlobalRulestackClient().BeginDelete(ctx, "praval", "armid1", nil) + if err != nil { + log.Fatalf("failed to finish the request: %v", err) + } + _, err = poller.PollUntilDone(ctx, nil) + if err != nil { + log.Fatalf("failed to pull the result: %v", err) + } +} + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/CertificateObjectGlobalRulestack_Delete_MinimumSet_Gen.json +func ExampleCertificateObjectGlobalRulestackClient_BeginDelete_certificateObjectGlobalRulestackDeleteMinimumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + poller, err := clientFactory.NewCertificateObjectGlobalRulestackClient().BeginDelete(ctx, "praval", "armid1", nil) + if err != nil { + log.Fatalf("failed to finish the request: %v", err) + } + _, err = poller.PollUntilDone(ctx, nil) + if err != nil { + log.Fatalf("failed to pull the result: %v", err) + } +} diff --git a/sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/certificateobjectlocalrulestack_client.go b/sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/certificateobjectlocalrulestack_client.go new file mode 100644 index 000000000000..34b9a4b35dbf --- /dev/null +++ b/sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/certificateobjectlocalrulestack_client.go @@ -0,0 +1,323 @@ +//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. +// Code generated by Microsoft (R) AutoRest Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. +// DO NOT EDIT. + +package armpanngfw + +import ( + "context" + "errors" + "github.com/Azure/azure-sdk-for-go/sdk/azcore" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/arm" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/policy" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime" + "net/http" + "net/url" + "strings" +) + +// CertificateObjectLocalRulestackClient contains the methods for the CertificateObjectLocalRulestack group. +// Don't use this type directly, use NewCertificateObjectLocalRulestackClient() instead. +type CertificateObjectLocalRulestackClient struct { + internal *arm.Client + subscriptionID string +} + +// NewCertificateObjectLocalRulestackClient creates a new instance of CertificateObjectLocalRulestackClient with the specified values. +// - subscriptionID - The ID of the target subscription. +// - credential - used to authorize requests. Usually a credential from azidentity. +// - options - pass nil to accept the default values. +func NewCertificateObjectLocalRulestackClient(subscriptionID string, credential azcore.TokenCredential, options *arm.ClientOptions) (*CertificateObjectLocalRulestackClient, error) { + cl, err := arm.NewClient(moduleName+".CertificateObjectLocalRulestackClient", moduleVersion, credential, options) + if err != nil { + return nil, err + } + client := &CertificateObjectLocalRulestackClient{ + subscriptionID: subscriptionID, + internal: cl, + } + return client, nil +} + +// BeginCreateOrUpdate - Create a CertificateObjectLocalRulestackResource +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2022-08-29-preview +// - resourceGroupName - The name of the resource group. The name is case insensitive. +// - localRulestackName - LocalRulestack resource name +// - name - certificate name +// - resource - Resource create parameters. +// - options - CertificateObjectLocalRulestackClientBeginCreateOrUpdateOptions contains the optional parameters for the CertificateObjectLocalRulestackClient.BeginCreateOrUpdate +// method. +func (client *CertificateObjectLocalRulestackClient) BeginCreateOrUpdate(ctx context.Context, resourceGroupName string, localRulestackName string, name string, resource CertificateObjectLocalRulestackResource, options *CertificateObjectLocalRulestackClientBeginCreateOrUpdateOptions) (*runtime.Poller[CertificateObjectLocalRulestackClientCreateOrUpdateResponse], error) { + if options == nil || options.ResumeToken == "" { + resp, err := client.createOrUpdate(ctx, resourceGroupName, localRulestackName, name, resource, options) + if err != nil { + return nil, err + } + return runtime.NewPoller(resp, client.internal.Pipeline(), &runtime.NewPollerOptions[CertificateObjectLocalRulestackClientCreateOrUpdateResponse]{ + FinalStateVia: runtime.FinalStateViaAzureAsyncOp, + }) + } else { + return runtime.NewPollerFromResumeToken[CertificateObjectLocalRulestackClientCreateOrUpdateResponse](options.ResumeToken, client.internal.Pipeline(), nil) + } +} + +// CreateOrUpdate - Create a CertificateObjectLocalRulestackResource +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2022-08-29-preview +func (client *CertificateObjectLocalRulestackClient) createOrUpdate(ctx context.Context, resourceGroupName string, localRulestackName string, name string, resource CertificateObjectLocalRulestackResource, options *CertificateObjectLocalRulestackClientBeginCreateOrUpdateOptions) (*http.Response, error) { + req, err := client.createOrUpdateCreateRequest(ctx, resourceGroupName, localRulestackName, name, resource, options) + if err != nil { + return nil, err + } + resp, err := client.internal.Pipeline().Do(req) + if err != nil { + return nil, err + } + if !runtime.HasStatusCode(resp, http.StatusOK, http.StatusCreated) { + return nil, runtime.NewResponseError(resp) + } + return resp, nil +} + +// createOrUpdateCreateRequest creates the CreateOrUpdate request. +func (client *CertificateObjectLocalRulestackClient) createOrUpdateCreateRequest(ctx context.Context, resourceGroupName string, localRulestackName string, name string, resource CertificateObjectLocalRulestackResource, options *CertificateObjectLocalRulestackClientBeginCreateOrUpdateOptions) (*policy.Request, error) { + urlPath := "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/PaloAltoNetworks.Cloudngfw/localRulestacks/{localRulestackName}/certificates/{name}" + if client.subscriptionID == "" { + return nil, errors.New("parameter client.subscriptionID cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{subscriptionId}", url.PathEscape(client.subscriptionID)) + if resourceGroupName == "" { + return nil, errors.New("parameter resourceGroupName cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{resourceGroupName}", url.PathEscape(resourceGroupName)) + if localRulestackName == "" { + return nil, errors.New("parameter localRulestackName cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{localRulestackName}", url.PathEscape(localRulestackName)) + if name == "" { + return nil, errors.New("parameter name cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{name}", url.PathEscape(name)) + req, err := runtime.NewRequest(ctx, http.MethodPut, runtime.JoinPaths(client.internal.Endpoint(), urlPath)) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("api-version", "2022-08-29-preview") + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["Accept"] = []string{"application/json"} + return req, runtime.MarshalAsJSON(req, resource) +} + +// BeginDelete - Delete a CertificateObjectLocalRulestackResource +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2022-08-29-preview +// - resourceGroupName - The name of the resource group. The name is case insensitive. +// - localRulestackName - LocalRulestack resource name +// - name - certificate name +// - options - CertificateObjectLocalRulestackClientBeginDeleteOptions contains the optional parameters for the CertificateObjectLocalRulestackClient.BeginDelete +// method. +func (client *CertificateObjectLocalRulestackClient) BeginDelete(ctx context.Context, resourceGroupName string, localRulestackName string, name string, options *CertificateObjectLocalRulestackClientBeginDeleteOptions) (*runtime.Poller[CertificateObjectLocalRulestackClientDeleteResponse], error) { + if options == nil || options.ResumeToken == "" { + resp, err := client.deleteOperation(ctx, resourceGroupName, localRulestackName, name, options) + if err != nil { + return nil, err + } + return runtime.NewPoller(resp, client.internal.Pipeline(), &runtime.NewPollerOptions[CertificateObjectLocalRulestackClientDeleteResponse]{ + FinalStateVia: runtime.FinalStateViaAzureAsyncOp, + }) + } else { + return runtime.NewPollerFromResumeToken[CertificateObjectLocalRulestackClientDeleteResponse](options.ResumeToken, client.internal.Pipeline(), nil) + } +} + +// Delete - Delete a CertificateObjectLocalRulestackResource +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2022-08-29-preview +func (client *CertificateObjectLocalRulestackClient) deleteOperation(ctx context.Context, resourceGroupName string, localRulestackName string, name string, options *CertificateObjectLocalRulestackClientBeginDeleteOptions) (*http.Response, error) { + req, err := client.deleteCreateRequest(ctx, resourceGroupName, localRulestackName, name, options) + if err != nil { + return nil, err + } + resp, err := client.internal.Pipeline().Do(req) + if err != nil { + return nil, err + } + if !runtime.HasStatusCode(resp, http.StatusOK, http.StatusAccepted, http.StatusNoContent) { + return nil, runtime.NewResponseError(resp) + } + return resp, nil +} + +// deleteCreateRequest creates the Delete request. +func (client *CertificateObjectLocalRulestackClient) deleteCreateRequest(ctx context.Context, resourceGroupName string, localRulestackName string, name string, options *CertificateObjectLocalRulestackClientBeginDeleteOptions) (*policy.Request, error) { + urlPath := "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/PaloAltoNetworks.Cloudngfw/localRulestacks/{localRulestackName}/certificates/{name}" + if client.subscriptionID == "" { + return nil, errors.New("parameter client.subscriptionID cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{subscriptionId}", url.PathEscape(client.subscriptionID)) + if resourceGroupName == "" { + return nil, errors.New("parameter resourceGroupName cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{resourceGroupName}", url.PathEscape(resourceGroupName)) + if localRulestackName == "" { + return nil, errors.New("parameter localRulestackName cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{localRulestackName}", url.PathEscape(localRulestackName)) + if name == "" { + return nil, errors.New("parameter name cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{name}", url.PathEscape(name)) + req, err := runtime.NewRequest(ctx, http.MethodDelete, runtime.JoinPaths(client.internal.Endpoint(), urlPath)) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("api-version", "2022-08-29-preview") + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["Accept"] = []string{"application/json"} + return req, nil +} + +// Get - Get a CertificateObjectLocalRulestackResource +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2022-08-29-preview +// - resourceGroupName - The name of the resource group. The name is case insensitive. +// - localRulestackName - LocalRulestack resource name +// - name - certificate name +// - options - CertificateObjectLocalRulestackClientGetOptions contains the optional parameters for the CertificateObjectLocalRulestackClient.Get +// method. +func (client *CertificateObjectLocalRulestackClient) Get(ctx context.Context, resourceGroupName string, localRulestackName string, name string, options *CertificateObjectLocalRulestackClientGetOptions) (CertificateObjectLocalRulestackClientGetResponse, error) { + req, err := client.getCreateRequest(ctx, resourceGroupName, localRulestackName, name, options) + if err != nil { + return CertificateObjectLocalRulestackClientGetResponse{}, err + } + resp, err := client.internal.Pipeline().Do(req) + if err != nil { + return CertificateObjectLocalRulestackClientGetResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusOK) { + return CertificateObjectLocalRulestackClientGetResponse{}, runtime.NewResponseError(resp) + } + return client.getHandleResponse(resp) +} + +// getCreateRequest creates the Get request. +func (client *CertificateObjectLocalRulestackClient) getCreateRequest(ctx context.Context, resourceGroupName string, localRulestackName string, name string, options *CertificateObjectLocalRulestackClientGetOptions) (*policy.Request, error) { + urlPath := "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/PaloAltoNetworks.Cloudngfw/localRulestacks/{localRulestackName}/certificates/{name}" + if client.subscriptionID == "" { + return nil, errors.New("parameter client.subscriptionID cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{subscriptionId}", url.PathEscape(client.subscriptionID)) + if resourceGroupName == "" { + return nil, errors.New("parameter resourceGroupName cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{resourceGroupName}", url.PathEscape(resourceGroupName)) + if localRulestackName == "" { + return nil, errors.New("parameter localRulestackName cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{localRulestackName}", url.PathEscape(localRulestackName)) + if name == "" { + return nil, errors.New("parameter name cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{name}", url.PathEscape(name)) + req, err := runtime.NewRequest(ctx, http.MethodGet, runtime.JoinPaths(client.internal.Endpoint(), urlPath)) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("api-version", "2022-08-29-preview") + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["Accept"] = []string{"application/json"} + return req, nil +} + +// getHandleResponse handles the Get response. +func (client *CertificateObjectLocalRulestackClient) getHandleResponse(resp *http.Response) (CertificateObjectLocalRulestackClientGetResponse, error) { + result := CertificateObjectLocalRulestackClientGetResponse{} + if err := runtime.UnmarshalAsJSON(resp, &result.CertificateObjectLocalRulestackResource); err != nil { + return CertificateObjectLocalRulestackClientGetResponse{}, err + } + return result, nil +} + +// NewListByLocalRulestacksPager - List CertificateObjectLocalRulestackResource resources by LocalRulestacks +// +// Generated from API version 2022-08-29-preview +// - resourceGroupName - The name of the resource group. The name is case insensitive. +// - localRulestackName - LocalRulestack resource name +// - options - CertificateObjectLocalRulestackClientListByLocalRulestacksOptions contains the optional parameters for the CertificateObjectLocalRulestackClient.NewListByLocalRulestacksPager +// method. +func (client *CertificateObjectLocalRulestackClient) NewListByLocalRulestacksPager(resourceGroupName string, localRulestackName string, options *CertificateObjectLocalRulestackClientListByLocalRulestacksOptions) *runtime.Pager[CertificateObjectLocalRulestackClientListByLocalRulestacksResponse] { + return runtime.NewPager(runtime.PagingHandler[CertificateObjectLocalRulestackClientListByLocalRulestacksResponse]{ + More: func(page CertificateObjectLocalRulestackClientListByLocalRulestacksResponse) bool { + return page.NextLink != nil && len(*page.NextLink) > 0 + }, + Fetcher: func(ctx context.Context, page *CertificateObjectLocalRulestackClientListByLocalRulestacksResponse) (CertificateObjectLocalRulestackClientListByLocalRulestacksResponse, error) { + var req *policy.Request + var err error + if page == nil { + req, err = client.listByLocalRulestacksCreateRequest(ctx, resourceGroupName, localRulestackName, options) + } else { + req, err = runtime.NewRequest(ctx, http.MethodGet, *page.NextLink) + } + if err != nil { + return CertificateObjectLocalRulestackClientListByLocalRulestacksResponse{}, err + } + resp, err := client.internal.Pipeline().Do(req) + if err != nil { + return CertificateObjectLocalRulestackClientListByLocalRulestacksResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusOK) { + return CertificateObjectLocalRulestackClientListByLocalRulestacksResponse{}, runtime.NewResponseError(resp) + } + return client.listByLocalRulestacksHandleResponse(resp) + }, + }) +} + +// listByLocalRulestacksCreateRequest creates the ListByLocalRulestacks request. +func (client *CertificateObjectLocalRulestackClient) listByLocalRulestacksCreateRequest(ctx context.Context, resourceGroupName string, localRulestackName string, options *CertificateObjectLocalRulestackClientListByLocalRulestacksOptions) (*policy.Request, error) { + urlPath := "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/PaloAltoNetworks.Cloudngfw/localRulestacks/{localRulestackName}/certificates" + if client.subscriptionID == "" { + return nil, errors.New("parameter client.subscriptionID cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{subscriptionId}", url.PathEscape(client.subscriptionID)) + if resourceGroupName == "" { + return nil, errors.New("parameter resourceGroupName cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{resourceGroupName}", url.PathEscape(resourceGroupName)) + if localRulestackName == "" { + return nil, errors.New("parameter localRulestackName cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{localRulestackName}", url.PathEscape(localRulestackName)) + req, err := runtime.NewRequest(ctx, http.MethodGet, runtime.JoinPaths(client.internal.Endpoint(), urlPath)) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("api-version", "2022-08-29-preview") + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["Accept"] = []string{"application/json"} + return req, nil +} + +// listByLocalRulestacksHandleResponse handles the ListByLocalRulestacks response. +func (client *CertificateObjectLocalRulestackClient) listByLocalRulestacksHandleResponse(resp *http.Response) (CertificateObjectLocalRulestackClientListByLocalRulestacksResponse, error) { + result := CertificateObjectLocalRulestackClientListByLocalRulestacksResponse{} + if err := runtime.UnmarshalAsJSON(resp, &result.CertificateObjectLocalRulestackResourceListResult); err != nil { + return CertificateObjectLocalRulestackClientListByLocalRulestacksResponse{}, err + } + return result, nil +} diff --git a/sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/certificateobjectlocalrulestack_client_example_test.go b/sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/certificateobjectlocalrulestack_client_example_test.go new file mode 100644 index 000000000000..b29605d1fed7 --- /dev/null +++ b/sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/certificateobjectlocalrulestack_client_example_test.go @@ -0,0 +1,299 @@ +//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. +// Code generated by Microsoft (R) AutoRest Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. +// DO NOT EDIT. + +package armpanngfw_test + +import ( + "context" + "log" + + "github.com/Azure/azure-sdk-for-go/sdk/azcore/to" + "github.com/Azure/azure-sdk-for-go/sdk/azidentity" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/paloaltonetworksngfw/armpanngfw" +) + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/CertificateObjectLocalRulestack_ListByLocalRulestacks_MaximumSet_Gen.json +func ExampleCertificateObjectLocalRulestackClient_NewListByLocalRulestacksPager_certificateObjectLocalRulestackListByLocalRulestacksMaximumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + pager := clientFactory.NewCertificateObjectLocalRulestackClient().NewListByLocalRulestacksPager("rgopenapi", "lrs1", nil) + for pager.More() { + page, err := pager.NextPage(ctx) + if err != nil { + log.Fatalf("failed to advance page: %v", err) + } + for _, v := range page.Value { + // You could use page here. We use blank identifier for just demo purposes. + _ = v + } + // If the HTTP response code is 200 as defined in example definition, your page structure would look as follows. Please pay attention that all the values in the output are fake values for just demo purposes. + // page.CertificateObjectLocalRulestackResourceListResult = armpanngfw.CertificateObjectLocalRulestackResourceListResult{ + // Value: []*armpanngfw.CertificateObjectLocalRulestackResource{ + // { + // Name: to.Ptr("armid1"), + // Type: to.Ptr("certificates"), + // ID: to.Ptr("/providers/PaloAltoNetworks.Cloudngfw/globalrulestacks/armid1/certificates/armid1"), + // SystemData: &armpanngfw.SystemData{ + // CreatedAt: to.Ptr(func() time.Time { t, _ := time.Parse(time.RFC3339Nano, "2022-09-09T05:08:24.229Z"); return t}()), + // CreatedBy: to.Ptr("praval"), + // CreatedByType: to.Ptr(armpanngfw.CreatedByTypeUser), + // LastModifiedAt: to.Ptr(func() time.Time { t, _ := time.Parse(time.RFC3339Nano, "2022-09-09T05:08:24.229Z"); return t}()), + // LastModifiedBy: to.Ptr("praval"), + // LastModifiedByType: to.Ptr(armpanngfw.CreatedByTypeUser), + // }, + // Properties: &armpanngfw.CertificateObject{ + // Description: to.Ptr("desc"), + // AuditComment: to.Ptr("comment"), + // CertificateSelfSigned: to.Ptr(armpanngfw.BooleanEnumTRUE), + // CertificateSignerResourceID: to.Ptr(""), + // Etag: to.Ptr("2bf4a339-294d-4c25-b0b2-ef649e9f5c27"), + // ProvisioningState: to.Ptr(armpanngfw.ProvisioningStateSucceeded), + // }, + // }}, + // } + } +} + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/CertificateObjectLocalRulestack_ListByLocalRulestacks_MinimumSet_Gen.json +func ExampleCertificateObjectLocalRulestackClient_NewListByLocalRulestacksPager_certificateObjectLocalRulestackListByLocalRulestacksMinimumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + pager := clientFactory.NewCertificateObjectLocalRulestackClient().NewListByLocalRulestacksPager("rgopenapi", "lrs1", nil) + for pager.More() { + page, err := pager.NextPage(ctx) + if err != nil { + log.Fatalf("failed to advance page: %v", err) + } + for _, v := range page.Value { + // You could use page here. We use blank identifier for just demo purposes. + _ = v + } + // If the HTTP response code is 200 as defined in example definition, your page structure would look as follows. Please pay attention that all the values in the output are fake values for just demo purposes. + // page.CertificateObjectLocalRulestackResourceListResult = armpanngfw.CertificateObjectLocalRulestackResourceListResult{ + // Value: []*armpanngfw.CertificateObjectLocalRulestackResource{ + // { + // ID: to.Ptr("/subscriptions/2bf4a339-294d-4c25-b0b2-ef649e9f5c27/resourcegroups/rgopenapi/providers/PaloAltoNetworks.Cloudngfw/localRulestacks/praval/certificates/certificates1"), + // Properties: &armpanngfw.CertificateObject{ + // CertificateSelfSigned: to.Ptr(armpanngfw.BooleanEnumTRUE), + // }, + // }}, + // } + } +} + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/CertificateObjectLocalRulestack_Get_MaximumSet_Gen.json +func ExampleCertificateObjectLocalRulestackClient_Get_certificateObjectLocalRulestackGetMaximumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + res, err := clientFactory.NewCertificateObjectLocalRulestackClient().Get(ctx, "rgopenapi", "lrs1", "armid1", nil) + if err != nil { + log.Fatalf("failed to finish the request: %v", err) + } + // You could use response here. We use blank identifier for just demo purposes. + _ = res + // If the HTTP response code is 200 as defined in example definition, your response structure would look as follows. Please pay attention that all the values in the output are fake values for just demo purposes. + // res.CertificateObjectLocalRulestackResource = armpanngfw.CertificateObjectLocalRulestackResource{ + // Name: to.Ptr("armid1"), + // Type: to.Ptr("certificates"), + // ID: to.Ptr("/providers/PaloAltoNetworks.Cloudngfw/globalrulestacks/armid1/certificates/armid1"), + // SystemData: &armpanngfw.SystemData{ + // CreatedAt: to.Ptr(func() time.Time { t, _ := time.Parse(time.RFC3339Nano, "2022-09-09T05:08:24.229Z"); return t}()), + // CreatedBy: to.Ptr("praval"), + // CreatedByType: to.Ptr(armpanngfw.CreatedByTypeUser), + // LastModifiedAt: to.Ptr(func() time.Time { t, _ := time.Parse(time.RFC3339Nano, "2022-09-09T05:08:24.229Z"); return t}()), + // LastModifiedBy: to.Ptr("praval"), + // LastModifiedByType: to.Ptr(armpanngfw.CreatedByTypeUser), + // }, + // Properties: &armpanngfw.CertificateObject{ + // Description: to.Ptr("description"), + // AuditComment: to.Ptr("comment"), + // CertificateSelfSigned: to.Ptr(armpanngfw.BooleanEnumTRUE), + // CertificateSignerResourceID: to.Ptr(""), + // Etag: to.Ptr("2bf4a339-294d-4c25-b0b2-ef649e9f5c27"), + // ProvisioningState: to.Ptr(armpanngfw.ProvisioningStateSucceeded), + // }, + // } +} + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/CertificateObjectLocalRulestack_Get_MinimumSet_Gen.json +func ExampleCertificateObjectLocalRulestackClient_Get_certificateObjectLocalRulestackGetMinimumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + res, err := clientFactory.NewCertificateObjectLocalRulestackClient().Get(ctx, "rgopenapi", "lrs1", "armid1", nil) + if err != nil { + log.Fatalf("failed to finish the request: %v", err) + } + // You could use response here. We use blank identifier for just demo purposes. + _ = res + // If the HTTP response code is 200 as defined in example definition, your response structure would look as follows. Please pay attention that all the values in the output are fake values for just demo purposes. + // res.CertificateObjectLocalRulestackResource = armpanngfw.CertificateObjectLocalRulestackResource{ + // ID: to.Ptr("/subscriptions/2bf4a339-294d-4c25-b0b2-ef649e9f5c27/resourcegroups/rgopenapi/providers/PaloAltoNetworks.Cloudngfw/localRulestacks/praval/certificates/armid1"), + // Properties: &armpanngfw.CertificateObject{ + // CertificateSelfSigned: to.Ptr(armpanngfw.BooleanEnumTRUE), + // }, + // } +} + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/CertificateObjectLocalRulestack_CreateOrUpdate_MaximumSet_Gen.json +func ExampleCertificateObjectLocalRulestackClient_BeginCreateOrUpdate_certificateObjectLocalRulestackCreateOrUpdateMaximumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + poller, err := clientFactory.NewCertificateObjectLocalRulestackClient().BeginCreateOrUpdate(ctx, "rgopenapi", "lrs1", "armid1", armpanngfw.CertificateObjectLocalRulestackResource{ + Properties: &armpanngfw.CertificateObject{ + Description: to.Ptr("description"), + AuditComment: to.Ptr("comment"), + CertificateSelfSigned: to.Ptr(armpanngfw.BooleanEnumTRUE), + CertificateSignerResourceID: to.Ptr(""), + Etag: to.Ptr("2bf4a339-294d-4c25-b0b2-ef649e9f5c27"), + ProvisioningState: to.Ptr(armpanngfw.ProvisioningStateAccepted), + }, + }, nil) + if err != nil { + log.Fatalf("failed to finish the request: %v", err) + } + res, err := poller.PollUntilDone(ctx, nil) + if err != nil { + log.Fatalf("failed to pull the result: %v", err) + } + // You could use response here. We use blank identifier for just demo purposes. + _ = res + // If the HTTP response code is 200 as defined in example definition, your response structure would look as follows. Please pay attention that all the values in the output are fake values for just demo purposes. + // res.CertificateObjectLocalRulestackResource = armpanngfw.CertificateObjectLocalRulestackResource{ + // Name: to.Ptr("armid1"), + // Type: to.Ptr("certificates"), + // ID: to.Ptr("/providers/PaloAltoNetworks.Cloudngfw/globalrulestacks/armid1/certificates/armid1"), + // SystemData: &armpanngfw.SystemData{ + // CreatedAt: to.Ptr(func() time.Time { t, _ := time.Parse(time.RFC3339Nano, "2022-09-09T05:08:24.229Z"); return t}()), + // CreatedBy: to.Ptr("praval"), + // CreatedByType: to.Ptr(armpanngfw.CreatedByTypeUser), + // LastModifiedAt: to.Ptr(func() time.Time { t, _ := time.Parse(time.RFC3339Nano, "2022-09-09T05:08:24.229Z"); return t}()), + // LastModifiedBy: to.Ptr("praval"), + // LastModifiedByType: to.Ptr(armpanngfw.CreatedByTypeUser), + // }, + // Properties: &armpanngfw.CertificateObject{ + // Description: to.Ptr("description"), + // AuditComment: to.Ptr("comment"), + // CertificateSelfSigned: to.Ptr(armpanngfw.BooleanEnumTRUE), + // CertificateSignerResourceID: to.Ptr(""), + // Etag: to.Ptr("2bf4a339-294d-4c25-b0b2-ef649e9f5c27"), + // ProvisioningState: to.Ptr(armpanngfw.ProvisioningStateSucceeded), + // }, + // } +} + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/CertificateObjectLocalRulestack_CreateOrUpdate_MinimumSet_Gen.json +func ExampleCertificateObjectLocalRulestackClient_BeginCreateOrUpdate_certificateObjectLocalRulestackCreateOrUpdateMinimumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + poller, err := clientFactory.NewCertificateObjectLocalRulestackClient().BeginCreateOrUpdate(ctx, "rgopenapi", "lrs1", "armid1", armpanngfw.CertificateObjectLocalRulestackResource{ + Properties: &armpanngfw.CertificateObject{ + CertificateSelfSigned: to.Ptr(armpanngfw.BooleanEnumTRUE), + }, + }, nil) + if err != nil { + log.Fatalf("failed to finish the request: %v", err) + } + res, err := poller.PollUntilDone(ctx, nil) + if err != nil { + log.Fatalf("failed to pull the result: %v", err) + } + // You could use response here. We use blank identifier for just demo purposes. + _ = res + // If the HTTP response code is 200 as defined in example definition, your response structure would look as follows. Please pay attention that all the values in the output are fake values for just demo purposes. + // res.CertificateObjectLocalRulestackResource = armpanngfw.CertificateObjectLocalRulestackResource{ + // ID: to.Ptr("/subscriptions/2bf4a339-294d-4c25-b0b2-ef649e9f5c27/resourcegroups/rgopenapi/providers/PaloAltoNetworks.Cloudngfw/localRulestacks/praval/certificates/armid1"), + // Properties: &armpanngfw.CertificateObject{ + // CertificateSelfSigned: to.Ptr(armpanngfw.BooleanEnumTRUE), + // }, + // } +} + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/CertificateObjectLocalRulestack_Delete_MaximumSet_Gen.json +func ExampleCertificateObjectLocalRulestackClient_BeginDelete_certificateObjectLocalRulestackDeleteMaximumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + poller, err := clientFactory.NewCertificateObjectLocalRulestackClient().BeginDelete(ctx, "rgopenapi", "lrs1", "armid1", nil) + if err != nil { + log.Fatalf("failed to finish the request: %v", err) + } + _, err = poller.PollUntilDone(ctx, nil) + if err != nil { + log.Fatalf("failed to pull the result: %v", err) + } +} + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/CertificateObjectLocalRulestack_Delete_MinimumSet_Gen.json +func ExampleCertificateObjectLocalRulestackClient_BeginDelete_certificateObjectLocalRulestackDeleteMinimumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + poller, err := clientFactory.NewCertificateObjectLocalRulestackClient().BeginDelete(ctx, "rgopenapi", "lrs1", "armid1", nil) + if err != nil { + log.Fatalf("failed to finish the request: %v", err) + } + _, err = poller.PollUntilDone(ctx, nil) + if err != nil { + log.Fatalf("failed to pull the result: %v", err) + } +} diff --git a/sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/ci.yml b/sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/ci.yml new file mode 100644 index 000000000000..b997139ea5a5 --- /dev/null +++ b/sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/ci.yml @@ -0,0 +1,28 @@ +# NOTE: Please refer to https://aka.ms/azsdk/engsys/ci-yaml before editing this file. +trigger: + branches: + include: + - main + - feature/* + - hotfix/* + - release/* + paths: + include: + - sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/ + +pr: + branches: + include: + - main + - feature/* + - hotfix/* + - release/* + paths: + include: + - sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/ + +stages: +- template: /eng/pipelines/templates/jobs/archetype-sdk-client.yml + parameters: + IncludeRelease: true + ServiceDirectory: 'resourcemanager/paloaltonetworksngfw/armpanngfw' diff --git a/sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/client_factory.go b/sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/client_factory.go new file mode 100644 index 000000000000..f6fe0e8300d8 --- /dev/null +++ b/sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/client_factory.go @@ -0,0 +1,109 @@ +//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. +// Code generated by Microsoft (R) AutoRest Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. +// DO NOT EDIT. + +package armpanngfw + +import ( + "github.com/Azure/azure-sdk-for-go/sdk/azcore" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/arm" +) + +// ClientFactory is a client factory used to create any client in this module. +// Don't use this type directly, use NewClientFactory instead. +type ClientFactory struct { + subscriptionID string + credential azcore.TokenCredential + options *arm.ClientOptions +} + +// NewClientFactory creates a new instance of ClientFactory with the specified values. +// The parameter values will be propagated to any client created from this factory. +// - subscriptionID - The ID of the target subscription. +// - credential - used to authorize requests. Usually a credential from azidentity. +// - options - pass nil to accept the default values. +func NewClientFactory(subscriptionID string, credential azcore.TokenCredential, options *arm.ClientOptions) (*ClientFactory, error) { + _, err := arm.NewClient(moduleName+".ClientFactory", moduleVersion, credential, options) + if err != nil { + return nil, err + } + return &ClientFactory{ + subscriptionID: subscriptionID, credential: credential, + options: options.Clone(), + }, nil +} + +func (c *ClientFactory) NewGlobalRulestackClient() *GlobalRulestackClient { + subClient, _ := NewGlobalRulestackClient(c.credential, c.options) + return subClient +} + +func (c *ClientFactory) NewCertificateObjectGlobalRulestackClient() *CertificateObjectGlobalRulestackClient { + subClient, _ := NewCertificateObjectGlobalRulestackClient(c.credential, c.options) + return subClient +} + +func (c *ClientFactory) NewFqdnListGlobalRulestackClient() *FqdnListGlobalRulestackClient { + subClient, _ := NewFqdnListGlobalRulestackClient(c.credential, c.options) + return subClient +} + +func (c *ClientFactory) NewPostRulesClient() *PostRulesClient { + subClient, _ := NewPostRulesClient(c.credential, c.options) + return subClient +} + +func (c *ClientFactory) NewPrefixListGlobalRulestackClient() *PrefixListGlobalRulestackClient { + subClient, _ := NewPrefixListGlobalRulestackClient(c.credential, c.options) + return subClient +} + +func (c *ClientFactory) NewPreRulesClient() *PreRulesClient { + subClient, _ := NewPreRulesClient(c.credential, c.options) + return subClient +} + +func (c *ClientFactory) NewOperationsClient() *OperationsClient { + subClient, _ := NewOperationsClient(c.credential, c.options) + return subClient +} + +func (c *ClientFactory) NewFirewallsClient() *FirewallsClient { + subClient, _ := NewFirewallsClient(c.subscriptionID, c.credential, c.options) + return subClient +} + +func (c *ClientFactory) NewLocalRulestacksClient() *LocalRulestacksClient { + subClient, _ := NewLocalRulestacksClient(c.subscriptionID, c.credential, c.options) + return subClient +} + +func (c *ClientFactory) NewFirewallStatusClient() *FirewallStatusClient { + subClient, _ := NewFirewallStatusClient(c.subscriptionID, c.credential, c.options) + return subClient +} + +func (c *ClientFactory) NewCertificateObjectLocalRulestackClient() *CertificateObjectLocalRulestackClient { + subClient, _ := NewCertificateObjectLocalRulestackClient(c.subscriptionID, c.credential, c.options) + return subClient +} + +func (c *ClientFactory) NewFqdnListLocalRulestackClient() *FqdnListLocalRulestackClient { + subClient, _ := NewFqdnListLocalRulestackClient(c.subscriptionID, c.credential, c.options) + return subClient +} + +func (c *ClientFactory) NewLocalRulesClient() *LocalRulesClient { + subClient, _ := NewLocalRulesClient(c.subscriptionID, c.credential, c.options) + return subClient +} + +func (c *ClientFactory) NewPrefixListLocalRulestackClient() *PrefixListLocalRulestackClient { + subClient, _ := NewPrefixListLocalRulestackClient(c.subscriptionID, c.credential, c.options) + return subClient +} diff --git a/sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/constants.go b/sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/constants.go new file mode 100644 index 000000000000..69b6941017ed --- /dev/null +++ b/sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/constants.go @@ -0,0 +1,488 @@ +//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. +// Code generated by Microsoft (R) AutoRest Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. +// DO NOT EDIT. + +package armpanngfw + +const ( + moduleName = "armpanngfw" + moduleVersion = "v0.1.0" +) + +type ActionEnum string + +const ( + ActionEnumAllow ActionEnum = "Allow" + ActionEnumDenyResetBoth ActionEnum = "DenyResetBoth" + ActionEnumDenyResetServer ActionEnum = "DenyResetServer" + ActionEnumDenySilent ActionEnum = "DenySilent" +) + +// PossibleActionEnumValues returns the possible values for the ActionEnum const type. +func PossibleActionEnumValues() []ActionEnum { + return []ActionEnum{ + ActionEnumAllow, + ActionEnumDenyResetBoth, + ActionEnumDenyResetServer, + ActionEnumDenySilent, + } +} + +// ActionType - Enum. Indicates the action type. "Internal" refers to actions that are for internal only APIs. +type ActionType string + +const ( + ActionTypeInternal ActionType = "Internal" +) + +// PossibleActionTypeValues returns the possible values for the ActionType const type. +func PossibleActionTypeValues() []ActionType { + return []ActionType{ + ActionTypeInternal, + } +} + +type AdvSecurityObjectTypeEnum string + +const ( + AdvSecurityObjectTypeEnumFeeds AdvSecurityObjectTypeEnum = "feeds" + AdvSecurityObjectTypeEnumURLCustom AdvSecurityObjectTypeEnum = "urlCustom" +) + +// PossibleAdvSecurityObjectTypeEnumValues returns the possible values for the AdvSecurityObjectTypeEnum const type. +func PossibleAdvSecurityObjectTypeEnumValues() []AdvSecurityObjectTypeEnum { + return []AdvSecurityObjectTypeEnum{ + AdvSecurityObjectTypeEnumFeeds, + AdvSecurityObjectTypeEnumURLCustom, + } +} + +// BillingCycle - Billing cycle +type BillingCycle string + +const ( + BillingCycleMONTHLY BillingCycle = "MONTHLY" + BillingCycleWEEKLY BillingCycle = "WEEKLY" +) + +// PossibleBillingCycleValues returns the possible values for the BillingCycle const type. +func PossibleBillingCycleValues() []BillingCycle { + return []BillingCycle{ + BillingCycleMONTHLY, + BillingCycleWEEKLY, + } +} + +// BooleanEnum - Boolean Enum +type BooleanEnum string + +const ( + BooleanEnumFALSE BooleanEnum = "FALSE" + BooleanEnumTRUE BooleanEnum = "TRUE" +) + +// PossibleBooleanEnumValues returns the possible values for the BooleanEnum const type. +func PossibleBooleanEnumValues() []BooleanEnum { + return []BooleanEnum{ + BooleanEnumFALSE, + BooleanEnumTRUE, + } +} + +// CreatedByType - The type of identity that created the resource. +type CreatedByType string + +const ( + CreatedByTypeApplication CreatedByType = "Application" + CreatedByTypeKey CreatedByType = "Key" + CreatedByTypeManagedIdentity CreatedByType = "ManagedIdentity" + CreatedByTypeUser CreatedByType = "User" +) + +// PossibleCreatedByTypeValues returns the possible values for the CreatedByType const type. +func PossibleCreatedByTypeValues() []CreatedByType { + return []CreatedByType{ + CreatedByTypeApplication, + CreatedByTypeKey, + CreatedByTypeManagedIdentity, + CreatedByTypeUser, + } +} + +// DNSProxy - DNS Proxy +type DNSProxy string + +const ( + DNSProxyDISABLED DNSProxy = "DISABLED" + DNSProxyENABLED DNSProxy = "ENABLED" +) + +// PossibleDNSProxyValues returns the possible values for the DNSProxy const type. +func PossibleDNSProxyValues() []DNSProxy { + return []DNSProxy{ + DNSProxyDISABLED, + DNSProxyENABLED, + } +} + +type DecryptionRuleTypeEnum string + +const ( + DecryptionRuleTypeEnumNone DecryptionRuleTypeEnum = "None" + DecryptionRuleTypeEnumSSLInboundInspection DecryptionRuleTypeEnum = "SSLInboundInspection" + DecryptionRuleTypeEnumSSLOutboundInspection DecryptionRuleTypeEnum = "SSLOutboundInspection" +) + +// PossibleDecryptionRuleTypeEnumValues returns the possible values for the DecryptionRuleTypeEnum const type. +func PossibleDecryptionRuleTypeEnumValues() []DecryptionRuleTypeEnum { + return []DecryptionRuleTypeEnum{ + DecryptionRuleTypeEnumNone, + DecryptionRuleTypeEnumSSLInboundInspection, + DecryptionRuleTypeEnumSSLOutboundInspection, + } +} + +// DefaultMode - Type for Default Mode for rules creation +type DefaultMode string + +const ( + DefaultModeFIREWALL DefaultMode = "FIREWALL" + DefaultModeIPS DefaultMode = "IPS" + DefaultModeNONE DefaultMode = "NONE" +) + +// PossibleDefaultModeValues returns the possible values for the DefaultMode const type. +func PossibleDefaultModeValues() []DefaultMode { + return []DefaultMode{ + DefaultModeFIREWALL, + DefaultModeIPS, + DefaultModeNONE, + } +} + +// EgressNat - Egress NAT +type EgressNat string + +const ( + EgressNatDISABLED EgressNat = "DISABLED" + EgressNatENABLED EgressNat = "ENABLED" +) + +// PossibleEgressNatValues returns the possible values for the EgressNat const type. +func PossibleEgressNatValues() []EgressNat { + return []EgressNat{ + EgressNatDISABLED, + EgressNatENABLED, + } +} + +// EnabledDNSType - Enabled DNS type values +type EnabledDNSType string + +const ( + EnabledDNSTypeAZURE EnabledDNSType = "AZURE" + EnabledDNSTypeCUSTOM EnabledDNSType = "CUSTOM" +) + +// PossibleEnabledDNSTypeValues returns the possible values for the EnabledDNSType const type. +func PossibleEnabledDNSTypeValues() []EnabledDNSType { + return []EnabledDNSType{ + EnabledDNSTypeAZURE, + EnabledDNSTypeCUSTOM, + } +} + +// HealthStatus - Status Codes for the Firewall +type HealthStatus string + +const ( + HealthStatusGREEN HealthStatus = "GREEN" + HealthStatusINITIALIZING HealthStatus = "INITIALIZING" + HealthStatusRED HealthStatus = "RED" + HealthStatusYELLOW HealthStatus = "YELLOW" +) + +// PossibleHealthStatusValues returns the possible values for the HealthStatus const type. +func PossibleHealthStatusValues() []HealthStatus { + return []HealthStatus{ + HealthStatusGREEN, + HealthStatusINITIALIZING, + HealthStatusRED, + HealthStatusYELLOW, + } +} + +// LogOption - Log options possible +type LogOption string + +const ( + LogOptionINDIVIDUALDESTINATION LogOption = "INDIVIDUAL_DESTINATION" + LogOptionSAMEDESTINATION LogOption = "SAME_DESTINATION" +) + +// PossibleLogOptionValues returns the possible values for the LogOption const type. +func PossibleLogOptionValues() []LogOption { + return []LogOption{ + LogOptionINDIVIDUALDESTINATION, + LogOptionSAMEDESTINATION, + } +} + +// LogType - Possible log types +type LogType string + +const ( + LogTypeAUDIT LogType = "AUDIT" + LogTypeDECRYPTION LogType = "DECRYPTION" + LogTypeDLP LogType = "DLP" + LogTypeTHREAT LogType = "THREAT" + LogTypeTRAFFIC LogType = "TRAFFIC" + LogTypeWILDFIRE LogType = "WILDFIRE" +) + +// PossibleLogTypeValues returns the possible values for the LogType const type. +func PossibleLogTypeValues() []LogType { + return []LogType{ + LogTypeAUDIT, + LogTypeDECRYPTION, + LogTypeDLP, + LogTypeTHREAT, + LogTypeTRAFFIC, + LogTypeWILDFIRE, + } +} + +// ManagedIdentityType - The kind of managed identity assigned to this resource. +type ManagedIdentityType string + +const ( + ManagedIdentityTypeNone ManagedIdentityType = "None" + ManagedIdentityTypeSystemAndUserAssigned ManagedIdentityType = "SystemAssigned,UserAssigned" + ManagedIdentityTypeSystemAssigned ManagedIdentityType = "SystemAssigned" + ManagedIdentityTypeUserAssigned ManagedIdentityType = "UserAssigned" +) + +// PossibleManagedIdentityTypeValues returns the possible values for the ManagedIdentityType const type. +func PossibleManagedIdentityTypeValues() []ManagedIdentityType { + return []ManagedIdentityType{ + ManagedIdentityTypeNone, + ManagedIdentityTypeSystemAndUserAssigned, + ManagedIdentityTypeSystemAssigned, + ManagedIdentityTypeUserAssigned, + } +} + +// MarketplaceSubscriptionStatus - Marketplace Subscription Status +type MarketplaceSubscriptionStatus string + +const ( + MarketplaceSubscriptionStatusFulfillmentRequested MarketplaceSubscriptionStatus = "FulfillmentRequested" + MarketplaceSubscriptionStatusNotStarted MarketplaceSubscriptionStatus = "NotStarted" + MarketplaceSubscriptionStatusPendingFulfillmentStart MarketplaceSubscriptionStatus = "PendingFulfillmentStart" + MarketplaceSubscriptionStatusSubscribed MarketplaceSubscriptionStatus = "Subscribed" + MarketplaceSubscriptionStatusSuspended MarketplaceSubscriptionStatus = "Suspended" + MarketplaceSubscriptionStatusUnsubscribed MarketplaceSubscriptionStatus = "Unsubscribed" +) + +// PossibleMarketplaceSubscriptionStatusValues returns the possible values for the MarketplaceSubscriptionStatus const type. +func PossibleMarketplaceSubscriptionStatusValues() []MarketplaceSubscriptionStatus { + return []MarketplaceSubscriptionStatus{ + MarketplaceSubscriptionStatusFulfillmentRequested, + MarketplaceSubscriptionStatusNotStarted, + MarketplaceSubscriptionStatusPendingFulfillmentStart, + MarketplaceSubscriptionStatusSubscribed, + MarketplaceSubscriptionStatusSuspended, + MarketplaceSubscriptionStatusUnsubscribed, + } +} + +// NetworkType - NetworkType Enum +type NetworkType string + +const ( + NetworkTypeVNET NetworkType = "VNET" + NetworkTypeVWAN NetworkType = "VWAN" +) + +// PossibleNetworkTypeValues returns the possible values for the NetworkType const type. +func PossibleNetworkTypeValues() []NetworkType { + return []NetworkType{ + NetworkTypeVNET, + NetworkTypeVWAN, + } +} + +// Origin - The intended executor of the operation; as in Resource Based Access Control (RBAC) and audit logs UX. Default +// value is "user,system" +type Origin string + +const ( + OriginSystem Origin = "system" + OriginUser Origin = "user" + OriginUserSystem Origin = "user,system" +) + +// PossibleOriginValues returns the possible values for the Origin const type. +func PossibleOriginValues() []Origin { + return []Origin{ + OriginSystem, + OriginUser, + OriginUserSystem, + } +} + +// ProtocolType - Protocol Enum +type ProtocolType string + +const ( + ProtocolTypeTCP ProtocolType = "TCP" + ProtocolTypeUDP ProtocolType = "UDP" +) + +// PossibleProtocolTypeValues returns the possible values for the ProtocolType const type. +func PossibleProtocolTypeValues() []ProtocolType { + return []ProtocolType{ + ProtocolTypeTCP, + ProtocolTypeUDP, + } +} + +// ProvisioningState - Provisioning state of the firewall resource. +type ProvisioningState string + +const ( + ProvisioningStateAccepted ProvisioningState = "Accepted" + ProvisioningStateCanceled ProvisioningState = "Canceled" + ProvisioningStateCreating ProvisioningState = "Creating" + ProvisioningStateDeleted ProvisioningState = "Deleted" + ProvisioningStateDeleting ProvisioningState = "Deleting" + ProvisioningStateFailed ProvisioningState = "Failed" + ProvisioningStateNotSpecified ProvisioningState = "NotSpecified" + ProvisioningStateSucceeded ProvisioningState = "Succeeded" + ProvisioningStateUpdating ProvisioningState = "Updating" +) + +// PossibleProvisioningStateValues returns the possible values for the ProvisioningState const type. +func PossibleProvisioningStateValues() []ProvisioningState { + return []ProvisioningState{ + ProvisioningStateAccepted, + ProvisioningStateCanceled, + ProvisioningStateCreating, + ProvisioningStateDeleted, + ProvisioningStateDeleting, + ProvisioningStateFailed, + ProvisioningStateNotSpecified, + ProvisioningStateSucceeded, + ProvisioningStateUpdating, + } +} + +// ReadOnlyProvisioningState - Provisioning state of the firewall resource. +type ReadOnlyProvisioningState string + +const ( + ReadOnlyProvisioningStateDeleted ReadOnlyProvisioningState = "Deleted" + ReadOnlyProvisioningStateFailed ReadOnlyProvisioningState = "Failed" + ReadOnlyProvisioningStateSucceeded ReadOnlyProvisioningState = "Succeeded" +) + +// PossibleReadOnlyProvisioningStateValues returns the possible values for the ReadOnlyProvisioningState const type. +func PossibleReadOnlyProvisioningStateValues() []ReadOnlyProvisioningState { + return []ReadOnlyProvisioningState{ + ReadOnlyProvisioningStateDeleted, + ReadOnlyProvisioningStateFailed, + ReadOnlyProvisioningStateSucceeded, + } +} + +// ScopeType - Rulestack Type +type ScopeType string + +const ( + ScopeTypeGLOBAL ScopeType = "GLOBAL" + ScopeTypeLOCAL ScopeType = "LOCAL" +) + +// PossibleScopeTypeValues returns the possible values for the ScopeType const type. +func PossibleScopeTypeValues() []ScopeType { + return []ScopeType{ + ScopeTypeGLOBAL, + ScopeTypeLOCAL, + } +} + +type SecurityServicesTypeEnum string + +const ( + SecurityServicesTypeEnumAntiSpyware SecurityServicesTypeEnum = "antiSpyware" + SecurityServicesTypeEnumAntiVirus SecurityServicesTypeEnum = "antiVirus" + SecurityServicesTypeEnumDNSSubscription SecurityServicesTypeEnum = "dnsSubscription" + SecurityServicesTypeEnumFileBlocking SecurityServicesTypeEnum = "fileBlocking" + SecurityServicesTypeEnumIPsVulnerability SecurityServicesTypeEnum = "ipsVulnerability" + SecurityServicesTypeEnumURLFiltering SecurityServicesTypeEnum = "urlFiltering" +) + +// PossibleSecurityServicesTypeEnumValues returns the possible values for the SecurityServicesTypeEnum const type. +func PossibleSecurityServicesTypeEnumValues() []SecurityServicesTypeEnum { + return []SecurityServicesTypeEnum{ + SecurityServicesTypeEnumAntiSpyware, + SecurityServicesTypeEnumAntiVirus, + SecurityServicesTypeEnumDNSSubscription, + SecurityServicesTypeEnumFileBlocking, + SecurityServicesTypeEnumIPsVulnerability, + SecurityServicesTypeEnumURLFiltering, + } +} + +// ServerStatus - Connectivity Status for Panorama Server +type ServerStatus string + +const ( + ServerStatusDOWN ServerStatus = "DOWN" + ServerStatusUP ServerStatus = "UP" +) + +// PossibleServerStatusValues returns the possible values for the ServerStatus const type. +func PossibleServerStatusValues() []ServerStatus { + return []ServerStatus{ + ServerStatusDOWN, + ServerStatusUP, + } +} + +// StateEnum - Enabled or Disabled Enum +type StateEnum string + +const ( + StateEnumDISABLED StateEnum = "DISABLED" + StateEnumENABLED StateEnum = "ENABLED" +) + +// PossibleStateEnumValues returns the possible values for the StateEnum const type. +func PossibleStateEnumValues() []StateEnum { + return []StateEnum{ + StateEnumDISABLED, + StateEnumENABLED, + } +} + +// UsageType - Usage Type +type UsageType string + +const ( + UsageTypeCOMMITTED UsageType = "COMMITTED" + UsageTypePAYG UsageType = "PAYG" +) + +// PossibleUsageTypeValues returns the possible values for the UsageType const type. +func PossibleUsageTypeValues() []UsageType { + return []UsageType{ + UsageTypeCOMMITTED, + UsageTypePAYG, + } +} diff --git a/sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/firewalls_client.go b/sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/firewalls_client.go new file mode 100644 index 000000000000..5dacb5f2f900 --- /dev/null +++ b/sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/firewalls_client.go @@ -0,0 +1,647 @@ +//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. +// Code generated by Microsoft (R) AutoRest Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. +// DO NOT EDIT. + +package armpanngfw + +import ( + "context" + "errors" + "github.com/Azure/azure-sdk-for-go/sdk/azcore" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/arm" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/policy" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime" + "net/http" + "net/url" + "strings" +) + +// FirewallsClient contains the methods for the Firewalls group. +// Don't use this type directly, use NewFirewallsClient() instead. +type FirewallsClient struct { + internal *arm.Client + subscriptionID string +} + +// NewFirewallsClient creates a new instance of FirewallsClient with the specified values. +// - subscriptionID - The ID of the target subscription. +// - credential - used to authorize requests. Usually a credential from azidentity. +// - options - pass nil to accept the default values. +func NewFirewallsClient(subscriptionID string, credential azcore.TokenCredential, options *arm.ClientOptions) (*FirewallsClient, error) { + cl, err := arm.NewClient(moduleName+".FirewallsClient", moduleVersion, credential, options) + if err != nil { + return nil, err + } + client := &FirewallsClient{ + subscriptionID: subscriptionID, + internal: cl, + } + return client, nil +} + +// BeginCreateOrUpdate - Create a FirewallResource +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2022-08-29-preview +// - resourceGroupName - The name of the resource group. The name is case insensitive. +// - firewallName - Firewall resource name +// - resource - Resource create parameters. +// - options - FirewallsClientBeginCreateOrUpdateOptions contains the optional parameters for the FirewallsClient.BeginCreateOrUpdate +// method. +func (client *FirewallsClient) BeginCreateOrUpdate(ctx context.Context, resourceGroupName string, firewallName string, resource FirewallResource, options *FirewallsClientBeginCreateOrUpdateOptions) (*runtime.Poller[FirewallsClientCreateOrUpdateResponse], error) { + if options == nil || options.ResumeToken == "" { + resp, err := client.createOrUpdate(ctx, resourceGroupName, firewallName, resource, options) + if err != nil { + return nil, err + } + return runtime.NewPoller(resp, client.internal.Pipeline(), &runtime.NewPollerOptions[FirewallsClientCreateOrUpdateResponse]{ + FinalStateVia: runtime.FinalStateViaAzureAsyncOp, + }) + } else { + return runtime.NewPollerFromResumeToken[FirewallsClientCreateOrUpdateResponse](options.ResumeToken, client.internal.Pipeline(), nil) + } +} + +// CreateOrUpdate - Create a FirewallResource +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2022-08-29-preview +func (client *FirewallsClient) createOrUpdate(ctx context.Context, resourceGroupName string, firewallName string, resource FirewallResource, options *FirewallsClientBeginCreateOrUpdateOptions) (*http.Response, error) { + req, err := client.createOrUpdateCreateRequest(ctx, resourceGroupName, firewallName, resource, options) + if err != nil { + return nil, err + } + resp, err := client.internal.Pipeline().Do(req) + if err != nil { + return nil, err + } + if !runtime.HasStatusCode(resp, http.StatusOK, http.StatusCreated) { + return nil, runtime.NewResponseError(resp) + } + return resp, nil +} + +// createOrUpdateCreateRequest creates the CreateOrUpdate request. +func (client *FirewallsClient) createOrUpdateCreateRequest(ctx context.Context, resourceGroupName string, firewallName string, resource FirewallResource, options *FirewallsClientBeginCreateOrUpdateOptions) (*policy.Request, error) { + urlPath := "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/PaloAltoNetworks.Cloudngfw/firewalls/{firewallName}" + if client.subscriptionID == "" { + return nil, errors.New("parameter client.subscriptionID cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{subscriptionId}", url.PathEscape(client.subscriptionID)) + if resourceGroupName == "" { + return nil, errors.New("parameter resourceGroupName cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{resourceGroupName}", url.PathEscape(resourceGroupName)) + if firewallName == "" { + return nil, errors.New("parameter firewallName cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{firewallName}", url.PathEscape(firewallName)) + req, err := runtime.NewRequest(ctx, http.MethodPut, runtime.JoinPaths(client.internal.Endpoint(), urlPath)) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("api-version", "2022-08-29-preview") + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["Accept"] = []string{"application/json"} + return req, runtime.MarshalAsJSON(req, resource) +} + +// BeginDelete - Delete a FirewallResource +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2022-08-29-preview +// - resourceGroupName - The name of the resource group. The name is case insensitive. +// - firewallName - Firewall resource name +// - options - FirewallsClientBeginDeleteOptions contains the optional parameters for the FirewallsClient.BeginDelete method. +func (client *FirewallsClient) BeginDelete(ctx context.Context, resourceGroupName string, firewallName string, options *FirewallsClientBeginDeleteOptions) (*runtime.Poller[FirewallsClientDeleteResponse], error) { + if options == nil || options.ResumeToken == "" { + resp, err := client.deleteOperation(ctx, resourceGroupName, firewallName, options) + if err != nil { + return nil, err + } + return runtime.NewPoller(resp, client.internal.Pipeline(), &runtime.NewPollerOptions[FirewallsClientDeleteResponse]{ + FinalStateVia: runtime.FinalStateViaAzureAsyncOp, + }) + } else { + return runtime.NewPollerFromResumeToken[FirewallsClientDeleteResponse](options.ResumeToken, client.internal.Pipeline(), nil) + } +} + +// Delete - Delete a FirewallResource +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2022-08-29-preview +func (client *FirewallsClient) deleteOperation(ctx context.Context, resourceGroupName string, firewallName string, options *FirewallsClientBeginDeleteOptions) (*http.Response, error) { + req, err := client.deleteCreateRequest(ctx, resourceGroupName, firewallName, options) + if err != nil { + return nil, err + } + resp, err := client.internal.Pipeline().Do(req) + if err != nil { + return nil, err + } + if !runtime.HasStatusCode(resp, http.StatusOK, http.StatusAccepted, http.StatusNoContent) { + return nil, runtime.NewResponseError(resp) + } + return resp, nil +} + +// deleteCreateRequest creates the Delete request. +func (client *FirewallsClient) deleteCreateRequest(ctx context.Context, resourceGroupName string, firewallName string, options *FirewallsClientBeginDeleteOptions) (*policy.Request, error) { + urlPath := "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/PaloAltoNetworks.Cloudngfw/firewalls/{firewallName}" + if client.subscriptionID == "" { + return nil, errors.New("parameter client.subscriptionID cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{subscriptionId}", url.PathEscape(client.subscriptionID)) + if resourceGroupName == "" { + return nil, errors.New("parameter resourceGroupName cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{resourceGroupName}", url.PathEscape(resourceGroupName)) + if firewallName == "" { + return nil, errors.New("parameter firewallName cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{firewallName}", url.PathEscape(firewallName)) + req, err := runtime.NewRequest(ctx, http.MethodDelete, runtime.JoinPaths(client.internal.Endpoint(), urlPath)) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("api-version", "2022-08-29-preview") + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["Accept"] = []string{"application/json"} + return req, nil +} + +// Get - Get a FirewallResource +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2022-08-29-preview +// - resourceGroupName - The name of the resource group. The name is case insensitive. +// - firewallName - Firewall resource name +// - options - FirewallsClientGetOptions contains the optional parameters for the FirewallsClient.Get method. +func (client *FirewallsClient) Get(ctx context.Context, resourceGroupName string, firewallName string, options *FirewallsClientGetOptions) (FirewallsClientGetResponse, error) { + req, err := client.getCreateRequest(ctx, resourceGroupName, firewallName, options) + if err != nil { + return FirewallsClientGetResponse{}, err + } + resp, err := client.internal.Pipeline().Do(req) + if err != nil { + return FirewallsClientGetResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusOK) { + return FirewallsClientGetResponse{}, runtime.NewResponseError(resp) + } + return client.getHandleResponse(resp) +} + +// getCreateRequest creates the Get request. +func (client *FirewallsClient) getCreateRequest(ctx context.Context, resourceGroupName string, firewallName string, options *FirewallsClientGetOptions) (*policy.Request, error) { + urlPath := "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/PaloAltoNetworks.Cloudngfw/firewalls/{firewallName}" + if client.subscriptionID == "" { + return nil, errors.New("parameter client.subscriptionID cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{subscriptionId}", url.PathEscape(client.subscriptionID)) + if resourceGroupName == "" { + return nil, errors.New("parameter resourceGroupName cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{resourceGroupName}", url.PathEscape(resourceGroupName)) + if firewallName == "" { + return nil, errors.New("parameter firewallName cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{firewallName}", url.PathEscape(firewallName)) + req, err := runtime.NewRequest(ctx, http.MethodGet, runtime.JoinPaths(client.internal.Endpoint(), urlPath)) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("api-version", "2022-08-29-preview") + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["Accept"] = []string{"application/json"} + return req, nil +} + +// getHandleResponse handles the Get response. +func (client *FirewallsClient) getHandleResponse(resp *http.Response) (FirewallsClientGetResponse, error) { + result := FirewallsClientGetResponse{} + if err := runtime.UnmarshalAsJSON(resp, &result.FirewallResource); err != nil { + return FirewallsClientGetResponse{}, err + } + return result, nil +} + +// GetGlobalRulestack - Get Global Rulestack associated with the Firewall +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2022-08-29-preview +// - resourceGroupName - The name of the resource group. The name is case insensitive. +// - firewallName - Firewall resource name +// - options - FirewallsClientGetGlobalRulestackOptions contains the optional parameters for the FirewallsClient.GetGlobalRulestack +// method. +func (client *FirewallsClient) GetGlobalRulestack(ctx context.Context, resourceGroupName string, firewallName string, options *FirewallsClientGetGlobalRulestackOptions) (FirewallsClientGetGlobalRulestackResponse, error) { + req, err := client.getGlobalRulestackCreateRequest(ctx, resourceGroupName, firewallName, options) + if err != nil { + return FirewallsClientGetGlobalRulestackResponse{}, err + } + resp, err := client.internal.Pipeline().Do(req) + if err != nil { + return FirewallsClientGetGlobalRulestackResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusOK) { + return FirewallsClientGetGlobalRulestackResponse{}, runtime.NewResponseError(resp) + } + return client.getGlobalRulestackHandleResponse(resp) +} + +// getGlobalRulestackCreateRequest creates the GetGlobalRulestack request. +func (client *FirewallsClient) getGlobalRulestackCreateRequest(ctx context.Context, resourceGroupName string, firewallName string, options *FirewallsClientGetGlobalRulestackOptions) (*policy.Request, error) { + urlPath := "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/PaloAltoNetworks.Cloudngfw/firewalls/{firewallName}/getGlobalRulestack" + if client.subscriptionID == "" { + return nil, errors.New("parameter client.subscriptionID cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{subscriptionId}", url.PathEscape(client.subscriptionID)) + if resourceGroupName == "" { + return nil, errors.New("parameter resourceGroupName cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{resourceGroupName}", url.PathEscape(resourceGroupName)) + if firewallName == "" { + return nil, errors.New("parameter firewallName cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{firewallName}", url.PathEscape(firewallName)) + req, err := runtime.NewRequest(ctx, http.MethodPost, runtime.JoinPaths(client.internal.Endpoint(), urlPath)) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("api-version", "2022-08-29-preview") + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["Accept"] = []string{"application/json"} + return req, nil +} + +// getGlobalRulestackHandleResponse handles the GetGlobalRulestack response. +func (client *FirewallsClient) getGlobalRulestackHandleResponse(resp *http.Response) (FirewallsClientGetGlobalRulestackResponse, error) { + result := FirewallsClientGetGlobalRulestackResponse{} + if err := runtime.UnmarshalAsJSON(resp, &result.GlobalRulestackInfo); err != nil { + return FirewallsClientGetGlobalRulestackResponse{}, err + } + return result, nil +} + +// GetLogProfile - Log Profile for Firewall +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2022-08-29-preview +// - resourceGroupName - The name of the resource group. The name is case insensitive. +// - firewallName - Firewall resource name +// - options - FirewallsClientGetLogProfileOptions contains the optional parameters for the FirewallsClient.GetLogProfile method. +func (client *FirewallsClient) GetLogProfile(ctx context.Context, resourceGroupName string, firewallName string, options *FirewallsClientGetLogProfileOptions) (FirewallsClientGetLogProfileResponse, error) { + req, err := client.getLogProfileCreateRequest(ctx, resourceGroupName, firewallName, options) + if err != nil { + return FirewallsClientGetLogProfileResponse{}, err + } + resp, err := client.internal.Pipeline().Do(req) + if err != nil { + return FirewallsClientGetLogProfileResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusOK) { + return FirewallsClientGetLogProfileResponse{}, runtime.NewResponseError(resp) + } + return client.getLogProfileHandleResponse(resp) +} + +// getLogProfileCreateRequest creates the GetLogProfile request. +func (client *FirewallsClient) getLogProfileCreateRequest(ctx context.Context, resourceGroupName string, firewallName string, options *FirewallsClientGetLogProfileOptions) (*policy.Request, error) { + urlPath := "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/PaloAltoNetworks.Cloudngfw/firewalls/{firewallName}/getLogProfile" + if client.subscriptionID == "" { + return nil, errors.New("parameter client.subscriptionID cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{subscriptionId}", url.PathEscape(client.subscriptionID)) + if resourceGroupName == "" { + return nil, errors.New("parameter resourceGroupName cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{resourceGroupName}", url.PathEscape(resourceGroupName)) + if firewallName == "" { + return nil, errors.New("parameter firewallName cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{firewallName}", url.PathEscape(firewallName)) + req, err := runtime.NewRequest(ctx, http.MethodPost, runtime.JoinPaths(client.internal.Endpoint(), urlPath)) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("api-version", "2022-08-29-preview") + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["Accept"] = []string{"application/json"} + return req, nil +} + +// getLogProfileHandleResponse handles the GetLogProfile response. +func (client *FirewallsClient) getLogProfileHandleResponse(resp *http.Response) (FirewallsClientGetLogProfileResponse, error) { + result := FirewallsClientGetLogProfileResponse{} + if err := runtime.UnmarshalAsJSON(resp, &result.LogSettings); err != nil { + return FirewallsClientGetLogProfileResponse{}, err + } + return result, nil +} + +// GetSupportInfo - support info for firewall. +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2022-08-29-preview +// - resourceGroupName - The name of the resource group. The name is case insensitive. +// - firewallName - Firewall resource name +// - options - FirewallsClientGetSupportInfoOptions contains the optional parameters for the FirewallsClient.GetSupportInfo +// method. +func (client *FirewallsClient) GetSupportInfo(ctx context.Context, resourceGroupName string, firewallName string, options *FirewallsClientGetSupportInfoOptions) (FirewallsClientGetSupportInfoResponse, error) { + req, err := client.getSupportInfoCreateRequest(ctx, resourceGroupName, firewallName, options) + if err != nil { + return FirewallsClientGetSupportInfoResponse{}, err + } + resp, err := client.internal.Pipeline().Do(req) + if err != nil { + return FirewallsClientGetSupportInfoResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusOK) { + return FirewallsClientGetSupportInfoResponse{}, runtime.NewResponseError(resp) + } + return client.getSupportInfoHandleResponse(resp) +} + +// getSupportInfoCreateRequest creates the GetSupportInfo request. +func (client *FirewallsClient) getSupportInfoCreateRequest(ctx context.Context, resourceGroupName string, firewallName string, options *FirewallsClientGetSupportInfoOptions) (*policy.Request, error) { + urlPath := "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/PaloAltoNetworks.Cloudngfw/firewalls/{firewallName}/getSupportInfo" + if client.subscriptionID == "" { + return nil, errors.New("parameter client.subscriptionID cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{subscriptionId}", url.PathEscape(client.subscriptionID)) + if resourceGroupName == "" { + return nil, errors.New("parameter resourceGroupName cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{resourceGroupName}", url.PathEscape(resourceGroupName)) + if firewallName == "" { + return nil, errors.New("parameter firewallName cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{firewallName}", url.PathEscape(firewallName)) + req, err := runtime.NewRequest(ctx, http.MethodPost, runtime.JoinPaths(client.internal.Endpoint(), urlPath)) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("api-version", "2022-08-29-preview") + if options != nil && options.Email != nil { + reqQP.Set("email", *options.Email) + } + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["Accept"] = []string{"application/json"} + return req, nil +} + +// getSupportInfoHandleResponse handles the GetSupportInfo response. +func (client *FirewallsClient) getSupportInfoHandleResponse(resp *http.Response) (FirewallsClientGetSupportInfoResponse, error) { + result := FirewallsClientGetSupportInfoResponse{} + if err := runtime.UnmarshalAsJSON(resp, &result.SupportInfo); err != nil { + return FirewallsClientGetSupportInfoResponse{}, err + } + return result, nil +} + +// NewListByResourceGroupPager - List FirewallResource resources by resource group +// +// Generated from API version 2022-08-29-preview +// - resourceGroupName - The name of the resource group. The name is case insensitive. +// - options - FirewallsClientListByResourceGroupOptions contains the optional parameters for the FirewallsClient.NewListByResourceGroupPager +// method. +func (client *FirewallsClient) NewListByResourceGroupPager(resourceGroupName string, options *FirewallsClientListByResourceGroupOptions) *runtime.Pager[FirewallsClientListByResourceGroupResponse] { + return runtime.NewPager(runtime.PagingHandler[FirewallsClientListByResourceGroupResponse]{ + More: func(page FirewallsClientListByResourceGroupResponse) bool { + return page.NextLink != nil && len(*page.NextLink) > 0 + }, + Fetcher: func(ctx context.Context, page *FirewallsClientListByResourceGroupResponse) (FirewallsClientListByResourceGroupResponse, error) { + var req *policy.Request + var err error + if page == nil { + req, err = client.listByResourceGroupCreateRequest(ctx, resourceGroupName, options) + } else { + req, err = runtime.NewRequest(ctx, http.MethodGet, *page.NextLink) + } + if err != nil { + return FirewallsClientListByResourceGroupResponse{}, err + } + resp, err := client.internal.Pipeline().Do(req) + if err != nil { + return FirewallsClientListByResourceGroupResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusOK) { + return FirewallsClientListByResourceGroupResponse{}, runtime.NewResponseError(resp) + } + return client.listByResourceGroupHandleResponse(resp) + }, + }) +} + +// listByResourceGroupCreateRequest creates the ListByResourceGroup request. +func (client *FirewallsClient) listByResourceGroupCreateRequest(ctx context.Context, resourceGroupName string, options *FirewallsClientListByResourceGroupOptions) (*policy.Request, error) { + urlPath := "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/PaloAltoNetworks.Cloudngfw/firewalls" + if client.subscriptionID == "" { + return nil, errors.New("parameter client.subscriptionID cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{subscriptionId}", url.PathEscape(client.subscriptionID)) + if resourceGroupName == "" { + return nil, errors.New("parameter resourceGroupName cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{resourceGroupName}", url.PathEscape(resourceGroupName)) + req, err := runtime.NewRequest(ctx, http.MethodGet, runtime.JoinPaths(client.internal.Endpoint(), urlPath)) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("api-version", "2022-08-29-preview") + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["Accept"] = []string{"application/json"} + return req, nil +} + +// listByResourceGroupHandleResponse handles the ListByResourceGroup response. +func (client *FirewallsClient) listByResourceGroupHandleResponse(resp *http.Response) (FirewallsClientListByResourceGroupResponse, error) { + result := FirewallsClientListByResourceGroupResponse{} + if err := runtime.UnmarshalAsJSON(resp, &result.FirewallResourceListResult); err != nil { + return FirewallsClientListByResourceGroupResponse{}, err + } + return result, nil +} + +// NewListBySubscriptionPager - List FirewallResource resources by subscription ID +// +// Generated from API version 2022-08-29-preview +// - options - FirewallsClientListBySubscriptionOptions contains the optional parameters for the FirewallsClient.NewListBySubscriptionPager +// method. +func (client *FirewallsClient) NewListBySubscriptionPager(options *FirewallsClientListBySubscriptionOptions) *runtime.Pager[FirewallsClientListBySubscriptionResponse] { + return runtime.NewPager(runtime.PagingHandler[FirewallsClientListBySubscriptionResponse]{ + More: func(page FirewallsClientListBySubscriptionResponse) bool { + return page.NextLink != nil && len(*page.NextLink) > 0 + }, + Fetcher: func(ctx context.Context, page *FirewallsClientListBySubscriptionResponse) (FirewallsClientListBySubscriptionResponse, error) { + var req *policy.Request + var err error + if page == nil { + req, err = client.listBySubscriptionCreateRequest(ctx, options) + } else { + req, err = runtime.NewRequest(ctx, http.MethodGet, *page.NextLink) + } + if err != nil { + return FirewallsClientListBySubscriptionResponse{}, err + } + resp, err := client.internal.Pipeline().Do(req) + if err != nil { + return FirewallsClientListBySubscriptionResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusOK) { + return FirewallsClientListBySubscriptionResponse{}, runtime.NewResponseError(resp) + } + return client.listBySubscriptionHandleResponse(resp) + }, + }) +} + +// listBySubscriptionCreateRequest creates the ListBySubscription request. +func (client *FirewallsClient) listBySubscriptionCreateRequest(ctx context.Context, options *FirewallsClientListBySubscriptionOptions) (*policy.Request, error) { + urlPath := "/subscriptions/{subscriptionId}/providers/PaloAltoNetworks.Cloudngfw/firewalls" + if client.subscriptionID == "" { + return nil, errors.New("parameter client.subscriptionID cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{subscriptionId}", url.PathEscape(client.subscriptionID)) + req, err := runtime.NewRequest(ctx, http.MethodGet, runtime.JoinPaths(client.internal.Endpoint(), urlPath)) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("api-version", "2022-08-29-preview") + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["Accept"] = []string{"application/json"} + return req, nil +} + +// listBySubscriptionHandleResponse handles the ListBySubscription response. +func (client *FirewallsClient) listBySubscriptionHandleResponse(resp *http.Response) (FirewallsClientListBySubscriptionResponse, error) { + result := FirewallsClientListBySubscriptionResponse{} + if err := runtime.UnmarshalAsJSON(resp, &result.FirewallResourceListResult); err != nil { + return FirewallsClientListBySubscriptionResponse{}, err + } + return result, nil +} + +// SaveLogProfile - Log Profile for Firewall +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2022-08-29-preview +// - resourceGroupName - The name of the resource group. The name is case insensitive. +// - firewallName - Firewall resource name +// - options - FirewallsClientSaveLogProfileOptions contains the optional parameters for the FirewallsClient.SaveLogProfile +// method. +func (client *FirewallsClient) SaveLogProfile(ctx context.Context, resourceGroupName string, firewallName string, options *FirewallsClientSaveLogProfileOptions) (FirewallsClientSaveLogProfileResponse, error) { + req, err := client.saveLogProfileCreateRequest(ctx, resourceGroupName, firewallName, options) + if err != nil { + return FirewallsClientSaveLogProfileResponse{}, err + } + resp, err := client.internal.Pipeline().Do(req) + if err != nil { + return FirewallsClientSaveLogProfileResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusNoContent) { + return FirewallsClientSaveLogProfileResponse{}, runtime.NewResponseError(resp) + } + return FirewallsClientSaveLogProfileResponse{}, nil +} + +// saveLogProfileCreateRequest creates the SaveLogProfile request. +func (client *FirewallsClient) saveLogProfileCreateRequest(ctx context.Context, resourceGroupName string, firewallName string, options *FirewallsClientSaveLogProfileOptions) (*policy.Request, error) { + urlPath := "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/PaloAltoNetworks.Cloudngfw/firewalls/{firewallName}/saveLogProfile" + if client.subscriptionID == "" { + return nil, errors.New("parameter client.subscriptionID cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{subscriptionId}", url.PathEscape(client.subscriptionID)) + if resourceGroupName == "" { + return nil, errors.New("parameter resourceGroupName cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{resourceGroupName}", url.PathEscape(resourceGroupName)) + if firewallName == "" { + return nil, errors.New("parameter firewallName cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{firewallName}", url.PathEscape(firewallName)) + req, err := runtime.NewRequest(ctx, http.MethodPost, runtime.JoinPaths(client.internal.Endpoint(), urlPath)) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("api-version", "2022-08-29-preview") + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["Accept"] = []string{"application/json"} + if options != nil && options.LogSettings != nil { + return req, runtime.MarshalAsJSON(req, *options.LogSettings) + } + return req, nil +} + +// Update - Update a FirewallResource +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2022-08-29-preview +// - resourceGroupName - The name of the resource group. The name is case insensitive. +// - firewallName - Firewall resource name +// - properties - The resource properties to be updated. +// - options - FirewallsClientUpdateOptions contains the optional parameters for the FirewallsClient.Update method. +func (client *FirewallsClient) Update(ctx context.Context, resourceGroupName string, firewallName string, properties FirewallResourceUpdate, options *FirewallsClientUpdateOptions) (FirewallsClientUpdateResponse, error) { + req, err := client.updateCreateRequest(ctx, resourceGroupName, firewallName, properties, options) + if err != nil { + return FirewallsClientUpdateResponse{}, err + } + resp, err := client.internal.Pipeline().Do(req) + if err != nil { + return FirewallsClientUpdateResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusOK) { + return FirewallsClientUpdateResponse{}, runtime.NewResponseError(resp) + } + return client.updateHandleResponse(resp) +} + +// updateCreateRequest creates the Update request. +func (client *FirewallsClient) updateCreateRequest(ctx context.Context, resourceGroupName string, firewallName string, properties FirewallResourceUpdate, options *FirewallsClientUpdateOptions) (*policy.Request, error) { + urlPath := "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/PaloAltoNetworks.Cloudngfw/firewalls/{firewallName}" + if client.subscriptionID == "" { + return nil, errors.New("parameter client.subscriptionID cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{subscriptionId}", url.PathEscape(client.subscriptionID)) + if resourceGroupName == "" { + return nil, errors.New("parameter resourceGroupName cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{resourceGroupName}", url.PathEscape(resourceGroupName)) + if firewallName == "" { + return nil, errors.New("parameter firewallName cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{firewallName}", url.PathEscape(firewallName)) + req, err := runtime.NewRequest(ctx, http.MethodPatch, runtime.JoinPaths(client.internal.Endpoint(), urlPath)) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("api-version", "2022-08-29-preview") + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["Accept"] = []string{"application/json"} + return req, runtime.MarshalAsJSON(req, properties) +} + +// updateHandleResponse handles the Update response. +func (client *FirewallsClient) updateHandleResponse(resp *http.Response) (FirewallsClientUpdateResponse, error) { + result := FirewallsClientUpdateResponse{} + if err := runtime.UnmarshalAsJSON(resp, &result.FirewallResource); err != nil { + return FirewallsClientUpdateResponse{}, err + } + return result, nil +} diff --git a/sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/firewalls_client_example_test.go b/sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/firewalls_client_example_test.go new file mode 100644 index 000000000000..ea7a1961f110 --- /dev/null +++ b/sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/firewalls_client_example_test.go @@ -0,0 +1,1734 @@ +//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. +// Code generated by Microsoft (R) AutoRest Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. +// DO NOT EDIT. + +package armpanngfw_test + +import ( + "context" + "log" + + "github.com/Azure/azure-sdk-for-go/sdk/azcore/to" + "github.com/Azure/azure-sdk-for-go/sdk/azidentity" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/paloaltonetworksngfw/armpanngfw" +) + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/Firewalls_ListBySubscription_MaximumSet_Gen.json +func ExampleFirewallsClient_NewListBySubscriptionPager_firewallsListBySubscriptionMaximumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + pager := clientFactory.NewFirewallsClient().NewListBySubscriptionPager(nil) + for pager.More() { + page, err := pager.NextPage(ctx) + if err != nil { + log.Fatalf("failed to advance page: %v", err) + } + for _, v := range page.Value { + // You could use page here. We use blank identifier for just demo purposes. + _ = v + } + // If the HTTP response code is 200 as defined in example definition, your page structure would look as follows. Please pay attention that all the values in the output are fake values for just demo purposes. + // page.FirewallResourceListResult = armpanngfw.FirewallResourceListResult{ + // Value: []*armpanngfw.FirewallResource{ + // { + // Name: to.Ptr("aaaaaaaaaaaaa"), + // Type: to.Ptr("aaaaaa"), + // ID: to.Ptr("aaaaaaaaaaaaaaaaaaaaaaaa"), + // SystemData: &armpanngfw.SystemData{ + // CreatedAt: to.Ptr(func() time.Time { t, _ := time.Parse(time.RFC3339Nano, "2022-09-09T05:08:24.229Z"); return t}()), + // CreatedBy: to.Ptr("praval"), + // CreatedByType: to.Ptr(armpanngfw.CreatedByTypeUser), + // LastModifiedAt: to.Ptr(func() time.Time { t, _ := time.Parse(time.RFC3339Nano, "2022-09-09T05:08:24.229Z"); return t}()), + // LastModifiedBy: to.Ptr("praval"), + // LastModifiedByType: to.Ptr(armpanngfw.CreatedByTypeUser), + // }, + // Location: to.Ptr("eastus"), + // Tags: map[string]*string{ + // "tagName": to.Ptr("value"), + // }, + // Identity: &armpanngfw.AzureResourceManagerManagedIdentityProperties{ + // Type: to.Ptr(armpanngfw.ManagedIdentityTypeNone), + // PrincipalID: to.Ptr("aaaaaaaaaaaaaaaaaaaaaaaaaa"), + // TenantID: to.Ptr("aaaaaaaaaaaaaaaaaaaaaaaaaaaa"), + // UserAssignedIdentities: map[string]*armpanngfw.AzureResourceManagerUserAssignedIdentity{ + // "key16": &armpanngfw.AzureResourceManagerUserAssignedIdentity{ + // ClientID: to.Ptr("aaaa"), + // PrincipalID: to.Ptr("aaaaaaaaaaaaaaa"), + // }, + // }, + // }, + // Properties: &armpanngfw.FirewallDeploymentProperties{ + // AssociatedRulestack: &armpanngfw.RulestackDetails{ + // Location: to.Ptr("eastus"), + // ResourceID: to.Ptr("aaaaaaaaaa"), + // RulestackID: to.Ptr("aaaaaaaaaaaaaaaa"), + // }, + // DNSSettings: &armpanngfw.DNSSettings{ + // DNSServers: []*armpanngfw.IPAddress{ + // { + // Address: to.Ptr("20.22.92.111"), + // ResourceID: to.Ptr("/subscriptions/01c7d41f-afaf-464e-8a8b-5c6f9f98cee8/resourceGroups/mj-liftr-integration/providers/Microsoft.Network/publicIPAddresses/mj-liftr-integration-egressNatIp1"), + // }}, + // EnableDNSProxy: to.Ptr(armpanngfw.DNSProxyDISABLED), + // EnabledDNSType: to.Ptr(armpanngfw.EnabledDNSTypeCUSTOM), + // }, + // FrontEndSettings: []*armpanngfw.FrontendSetting{ + // { + // Name: to.Ptr("frontendsetting11"), + // BackendConfiguration: &armpanngfw.EndpointConfiguration{ + // Address: &armpanngfw.IPAddress{ + // Address: to.Ptr("20.22.32.136"), + // ResourceID: to.Ptr("/subscriptions/01c7d41f-afaf-464e-8a8b-5c6f9f98cee8/resourceGroups/mj-liftr-integration/providers/Microsoft.Network/publicIPAddresses/mj-liftr-integration-frontendSettingIp2"), + // }, + // Port: to.Ptr("80"), + // }, + // FrontendConfiguration: &armpanngfw.EndpointConfiguration{ + // Address: &armpanngfw.IPAddress{ + // Address: to.Ptr("20.22.91.251"), + // ResourceID: to.Ptr("/subscriptions/01c7d41f-afaf-464e-8a8b-5c6f9f98cee8/resourceGroups/mj-liftr-integration/providers/Microsoft.Network/publicIPAddresses/mj-liftr-integration-frontendSettingIp1"), + // }, + // Port: to.Ptr("80"), + // }, + // Protocol: to.Ptr(armpanngfw.ProtocolTypeTCP), + // }}, + // IsPanoramaManaged: to.Ptr(armpanngfw.BooleanEnumTRUE), + // MarketplaceDetails: &armpanngfw.MarketplaceDetails{ + // MarketplaceSubscriptionID: to.Ptr("aa"), + // MarketplaceSubscriptionStatus: to.Ptr(armpanngfw.MarketplaceSubscriptionStatusPendingFulfillmentStart), + // OfferID: to.Ptr("aaaaaaaaaaaaaaaaaaaaaaaaaaaaa"), + // PublisherID: to.Ptr("aaaa"), + // }, + // NetworkProfile: &armpanngfw.NetworkProfile{ + // EgressNatIP: []*armpanngfw.IPAddress{ + // { + // Address: to.Ptr("20.22.92.111"), + // ResourceID: to.Ptr("/subscriptions/01c7d41f-afaf-464e-8a8b-5c6f9f98cee8/resourceGroups/mj-liftr-integration/providers/Microsoft.Network/publicIPAddresses/mj-liftr-integration-egressNatIp1"), + // }}, + // EnableEgressNat: to.Ptr(armpanngfw.EgressNatENABLED), + // NetworkType: to.Ptr(armpanngfw.NetworkTypeVNET), + // PublicIPs: []*armpanngfw.IPAddress{ + // { + // Address: to.Ptr("20.22.92.11"), + // ResourceID: to.Ptr("/subscriptions/01c7d41f-afaf-464e-8a8b-5c6f9f98cee8/resourceGroups/mj-liftr-integration/providers/Microsoft.Network/publicIPAddresses/mj-liftr-integration-PublicIp1"), + // }}, + // VnetConfiguration: &armpanngfw.VnetConfiguration{ + // IPOfTrustSubnetForUdr: &armpanngfw.IPAddress{ + // Address: to.Ptr("10.1.1.0/24"), + // ResourceID: to.Ptr("/subscriptions/2bf4a339-294d-4c25-b0b2-ef649e9f5c27/resourceGroups/os-liftr-integration/providers/Microsoft.Network/virtualNetworks/os-liftr-integration-vnet/subnets/os-liftr-integration-untrust-subnet"), + // }, + // TrustSubnet: &armpanngfw.IPAddressSpace{ + // AddressSpace: to.Ptr("10.1.1.0/24"), + // ResourceID: to.Ptr("/subscriptions/2bf4a339-294d-4c25-b0b2-ef649e9f5c27/resourceGroups/os-liftr-integration/providers/Microsoft.Network/virtualNetworks/os-liftr-integration-vnet/subnets/os-liftr-integration-trust-subnet"), + // }, + // UnTrustSubnet: &armpanngfw.IPAddressSpace{ + // AddressSpace: to.Ptr("10.1.1.0/24"), + // ResourceID: to.Ptr("/subscriptions/2bf4a339-294d-4c25-b0b2-ef649e9f5c27/resourceGroups/os-liftr-integration/providers/Microsoft.Network/virtualNetworks/os-liftr-integration-vnet/subnets/os-liftr-integration-untrust-subnet"), + // }, + // Vnet: &armpanngfw.IPAddressSpace{ + // AddressSpace: to.Ptr("10.1.0.0/16"), + // ResourceID: to.Ptr("/subscriptions/2bf4a339-294d-4c25-b0b2-ef649e9f5c27/resourceGroups/os-liftr-integration/providers/Microsoft.Network/virtualNetworks/os-liftr-integration-vnet"), + // }, + // }, + // VwanConfiguration: &armpanngfw.VwanConfiguration{ + // IPOfTrustSubnetForUdr: &armpanngfw.IPAddress{ + // Address: to.Ptr("10.1.1.0/24"), + // ResourceID: to.Ptr("/subscriptions/2bf4a339-294d-4c25-b0b2-ef649e9f5c27/resourceGroups/os-liftr-integration/providers/Microsoft.Network/virtualNetworks/os-liftr-integration-vnet/subnets/os-liftr-integration-untrust-subnet"), + // }, + // NetworkVirtualApplianceID: to.Ptr("2bf4a339-294d-4c25-b0b2-ef649e9f5c12"), + // TrustSubnet: &armpanngfw.IPAddressSpace{ + // AddressSpace: to.Ptr("10.1.1.0/24"), + // ResourceID: to.Ptr("/subscriptions/2bf4a339-294d-4c25-b0b2-ef649e9f5c27/resourceGroups/os-liftr-integration/providers/Microsoft.Network/virtualNetworks/os-liftr-integration-vnet/subnets/os-liftr-integration-trust-subnet"), + // }, + // UnTrustSubnet: &armpanngfw.IPAddressSpace{ + // AddressSpace: to.Ptr("10.1.1.0/24"), + // ResourceID: to.Ptr("/subscriptions/2bf4a339-294d-4c25-b0b2-ef649e9f5c27/resourceGroups/os-liftr-integration/providers/Microsoft.Network/virtualNetworks/os-liftr-integration-vnet/subnets/os-liftr-integration-untrust-subnet"), + // }, + // VHub: &armpanngfw.IPAddressSpace{ + // AddressSpace: to.Ptr("10.1.1.0/24"), + // ResourceID: to.Ptr("/subscriptions/2bf4a339-294d-4c25-b0b2-ef649e9f5c27/resourceGroups/os-liftr-integration/providers/Microsoft.Network/virtualNetworks/os-liftr-integration-vnet/subnets/os-liftr-integration-untrust-subnet"), + // }, + // }, + // }, + // PanEtag: to.Ptr("2bf4a339-294d-4c25-b0b2-ef649e9f5c12"), + // PanoramaConfig: &armpanngfw.PanoramaConfig{ + // CgName: to.Ptr("PanoramaCollectorGroup"), + // ConfigString: to.Ptr("bas64EncodedString"), + // DgName: to.Ptr("PanoramaDeviceGroup"), + // HostName: to.Ptr("hostname"), + // PanoramaServer: to.Ptr("10.25.1.1"), + // PanoramaServer2: to.Ptr("10.20.1.1"), + // TplName: to.Ptr("PanoramaTemplateStack"), + // VMAuthKey: to.Ptr("SSH_AUTH_KEY"), + // }, + // PlanData: &armpanngfw.PlanData{ + // BillingCycle: to.Ptr(armpanngfw.BillingCycleWEEKLY), + // EffectiveDate: to.Ptr(func() time.Time { t, _ := time.Parse(time.RFC3339Nano, "2022-09-13T00:46:05.283Z"); return t}()), + // PlanID: to.Ptr("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"), + // UsageType: to.Ptr(armpanngfw.UsageTypePAYG), + // }, + // ProvisioningState: to.Ptr(armpanngfw.ProvisioningStateSucceeded), + // }, + // }}, + // } + } +} + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/Firewalls_ListBySubscription_MinimumSet_Gen.json +func ExampleFirewallsClient_NewListBySubscriptionPager_firewallsListBySubscriptionMinimumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + pager := clientFactory.NewFirewallsClient().NewListBySubscriptionPager(nil) + for pager.More() { + page, err := pager.NextPage(ctx) + if err != nil { + log.Fatalf("failed to advance page: %v", err) + } + for _, v := range page.Value { + // You could use page here. We use blank identifier for just demo purposes. + _ = v + } + // If the HTTP response code is 200 as defined in example definition, your page structure would look as follows. Please pay attention that all the values in the output are fake values for just demo purposes. + // page.FirewallResourceListResult = armpanngfw.FirewallResourceListResult{ + // Value: []*armpanngfw.FirewallResource{ + // { + // ID: to.Ptr("/subscriptions/2bf4a339-294d-4c25-b0b2-ef649e9f5c27/providers/PaloAltoNetworks.Cloudngfw/firewalls/firewall"), + // Location: to.Ptr("eastus"), + // Properties: &armpanngfw.FirewallDeploymentProperties{ + // DNSSettings: &armpanngfw.DNSSettings{ + // }, + // MarketplaceDetails: &armpanngfw.MarketplaceDetails{ + // OfferID: to.Ptr("aaaaaaaaaaaaaaaaaaaaaaaaaaaaa"), + // PublisherID: to.Ptr("aaaa"), + // }, + // NetworkProfile: &armpanngfw.NetworkProfile{ + // EnableEgressNat: to.Ptr(armpanngfw.EgressNatENABLED), + // NetworkType: to.Ptr(armpanngfw.NetworkTypeVNET), + // PublicIPs: []*armpanngfw.IPAddress{ + // { + // Address: to.Ptr("20.22.92.11"), + // ResourceID: to.Ptr("/subscriptions/01c7d41f-afaf-464e-8a8b-5c6f9f98cee8/resourceGroups/mj-liftr-integration/providers/Microsoft.Network/publicIPAddresses/mj-liftr-integration-PublicIp1"), + // }}, + // }, + // PlanData: &armpanngfw.PlanData{ + // BillingCycle: to.Ptr(armpanngfw.BillingCycleWEEKLY), + // PlanID: to.Ptr("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"), + // }, + // }, + // }}, + // } + } +} + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/Firewalls_ListByResourceGroup_MaximumSet_Gen.json +func ExampleFirewallsClient_NewListByResourceGroupPager_firewallsListByResourceGroupMaximumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + pager := clientFactory.NewFirewallsClient().NewListByResourceGroupPager("firewall-rg", nil) + for pager.More() { + page, err := pager.NextPage(ctx) + if err != nil { + log.Fatalf("failed to advance page: %v", err) + } + for _, v := range page.Value { + // You could use page here. We use blank identifier for just demo purposes. + _ = v + } + // If the HTTP response code is 200 as defined in example definition, your page structure would look as follows. Please pay attention that all the values in the output are fake values for just demo purposes. + // page.FirewallResourceListResult = armpanngfw.FirewallResourceListResult{ + // Value: []*armpanngfw.FirewallResource{ + // { + // Name: to.Ptr("aaaaaaaaaaaaa"), + // Type: to.Ptr("aaaaaa"), + // ID: to.Ptr("aaaaaaaaaaaaaaaaaaaaaaaa"), + // SystemData: &armpanngfw.SystemData{ + // CreatedAt: to.Ptr(func() time.Time { t, _ := time.Parse(time.RFC3339Nano, "2022-09-09T05:08:24.229Z"); return t}()), + // CreatedBy: to.Ptr("praval"), + // CreatedByType: to.Ptr(armpanngfw.CreatedByTypeUser), + // LastModifiedAt: to.Ptr(func() time.Time { t, _ := time.Parse(time.RFC3339Nano, "2022-09-09T05:08:24.229Z"); return t}()), + // LastModifiedBy: to.Ptr("praval"), + // LastModifiedByType: to.Ptr(armpanngfw.CreatedByTypeUser), + // }, + // Location: to.Ptr("eastus"), + // Tags: map[string]*string{ + // "tagName": to.Ptr("value"), + // }, + // Identity: &armpanngfw.AzureResourceManagerManagedIdentityProperties{ + // Type: to.Ptr(armpanngfw.ManagedIdentityTypeNone), + // PrincipalID: to.Ptr("aaaaaaaaaaaaaaaaaaaaaaaaaa"), + // TenantID: to.Ptr("aaaaaaaaaaaaaaaaaaaaaaaaaaaa"), + // UserAssignedIdentities: map[string]*armpanngfw.AzureResourceManagerUserAssignedIdentity{ + // "key16": &armpanngfw.AzureResourceManagerUserAssignedIdentity{ + // ClientID: to.Ptr("aaaa"), + // PrincipalID: to.Ptr("aaaaaaaaaaaaaaa"), + // }, + // }, + // }, + // Properties: &armpanngfw.FirewallDeploymentProperties{ + // AssociatedRulestack: &armpanngfw.RulestackDetails{ + // Location: to.Ptr("eastus"), + // ResourceID: to.Ptr("aaaaaaaaaa"), + // RulestackID: to.Ptr("aaaaaaaaaaaaaaaa"), + // }, + // DNSSettings: &armpanngfw.DNSSettings{ + // DNSServers: []*armpanngfw.IPAddress{ + // { + // Address: to.Ptr("20.22.92.111"), + // ResourceID: to.Ptr("/subscriptions/01c7d41f-afaf-464e-8a8b-5c6f9f98cee8/resourceGroups/mj-liftr-integration/providers/Microsoft.Network/publicIPAddresses/mj-liftr-integration-egressNatIp1"), + // }}, + // EnableDNSProxy: to.Ptr(armpanngfw.DNSProxyDISABLED), + // EnabledDNSType: to.Ptr(armpanngfw.EnabledDNSTypeCUSTOM), + // }, + // FrontEndSettings: []*armpanngfw.FrontendSetting{ + // { + // Name: to.Ptr("frontendsetting11"), + // BackendConfiguration: &armpanngfw.EndpointConfiguration{ + // Address: &armpanngfw.IPAddress{ + // Address: to.Ptr("20.22.32.136"), + // ResourceID: to.Ptr("/subscriptions/01c7d41f-afaf-464e-8a8b-5c6f9f98cee8/resourceGroups/mj-liftr-integration/providers/Microsoft.Network/publicIPAddresses/mj-liftr-integration-frontendSettingIp2"), + // }, + // Port: to.Ptr("80"), + // }, + // FrontendConfiguration: &armpanngfw.EndpointConfiguration{ + // Address: &armpanngfw.IPAddress{ + // Address: to.Ptr("20.22.91.251"), + // ResourceID: to.Ptr("/subscriptions/01c7d41f-afaf-464e-8a8b-5c6f9f98cee8/resourceGroups/mj-liftr-integration/providers/Microsoft.Network/publicIPAddresses/mj-liftr-integration-frontendSettingIp1"), + // }, + // Port: to.Ptr("80"), + // }, + // Protocol: to.Ptr(armpanngfw.ProtocolTypeTCP), + // }}, + // IsPanoramaManaged: to.Ptr(armpanngfw.BooleanEnumTRUE), + // MarketplaceDetails: &armpanngfw.MarketplaceDetails{ + // MarketplaceSubscriptionID: to.Ptr("aa"), + // MarketplaceSubscriptionStatus: to.Ptr(armpanngfw.MarketplaceSubscriptionStatusPendingFulfillmentStart), + // OfferID: to.Ptr("aaaaaaaaaaaaaaaaaaaaaaaaaaaaa"), + // PublisherID: to.Ptr("aaaa"), + // }, + // NetworkProfile: &armpanngfw.NetworkProfile{ + // EgressNatIP: []*armpanngfw.IPAddress{ + // { + // Address: to.Ptr("20.22.92.111"), + // ResourceID: to.Ptr("/subscriptions/01c7d41f-afaf-464e-8a8b-5c6f9f98cee8/resourceGroups/mj-liftr-integration/providers/Microsoft.Network/publicIPAddresses/mj-liftr-integration-egressNatIp1"), + // }}, + // EnableEgressNat: to.Ptr(armpanngfw.EgressNatENABLED), + // NetworkType: to.Ptr(armpanngfw.NetworkTypeVNET), + // PublicIPs: []*armpanngfw.IPAddress{ + // { + // Address: to.Ptr("20.22.92.11"), + // ResourceID: to.Ptr("/subscriptions/01c7d41f-afaf-464e-8a8b-5c6f9f98cee8/resourceGroups/mj-liftr-integration/providers/Microsoft.Network/publicIPAddresses/mj-liftr-integration-PublicIp1"), + // }}, + // VnetConfiguration: &armpanngfw.VnetConfiguration{ + // IPOfTrustSubnetForUdr: &armpanngfw.IPAddress{ + // Address: to.Ptr("10.1.1.0/24"), + // ResourceID: to.Ptr("/subscriptions/2bf4a339-294d-4c25-b0b2-ef649e9f5c27/resourceGroups/os-liftr-integration/providers/Microsoft.Network/virtualNetworks/os-liftr-integration-vnet/subnets/os-liftr-integration-untrust-subnet"), + // }, + // TrustSubnet: &armpanngfw.IPAddressSpace{ + // AddressSpace: to.Ptr("10.1.1.0/24"), + // ResourceID: to.Ptr("/subscriptions/2bf4a339-294d-4c25-b0b2-ef649e9f5c27/resourceGroups/os-liftr-integration/providers/Microsoft.Network/virtualNetworks/os-liftr-integration-vnet/subnets/os-liftr-integration-trust-subnet"), + // }, + // UnTrustSubnet: &armpanngfw.IPAddressSpace{ + // AddressSpace: to.Ptr("10.1.1.0/24"), + // ResourceID: to.Ptr("/subscriptions/2bf4a339-294d-4c25-b0b2-ef649e9f5c27/resourceGroups/os-liftr-integration/providers/Microsoft.Network/virtualNetworks/os-liftr-integration-vnet/subnets/os-liftr-integration-untrust-subnet"), + // }, + // Vnet: &armpanngfw.IPAddressSpace{ + // AddressSpace: to.Ptr("10.1.0.0/16"), + // ResourceID: to.Ptr("/subscriptions/2bf4a339-294d-4c25-b0b2-ef649e9f5c27/resourceGroups/os-liftr-integration/providers/Microsoft.Network/virtualNetworks/os-liftr-integration-vnet"), + // }, + // }, + // VwanConfiguration: &armpanngfw.VwanConfiguration{ + // IPOfTrustSubnetForUdr: &armpanngfw.IPAddress{ + // Address: to.Ptr("10.1.1.0/24"), + // ResourceID: to.Ptr("/subscriptions/2bf4a339-294d-4c25-b0b2-ef649e9f5c27/resourceGroups/os-liftr-integration/providers/Microsoft.Network/virtualNetworks/os-liftr-integration-vnet/subnets/os-liftr-integration-untrust-subnet"), + // }, + // NetworkVirtualApplianceID: to.Ptr("2bf4a339-294d-4c25-b0b2-ef649e9f5c12"), + // TrustSubnet: &armpanngfw.IPAddressSpace{ + // AddressSpace: to.Ptr("10.1.1.0/24"), + // ResourceID: to.Ptr("/subscriptions/2bf4a339-294d-4c25-b0b2-ef649e9f5c27/resourceGroups/os-liftr-integration/providers/Microsoft.Network/virtualNetworks/os-liftr-integration-vnet/subnets/os-liftr-integration-trust-subnet"), + // }, + // UnTrustSubnet: &armpanngfw.IPAddressSpace{ + // AddressSpace: to.Ptr("10.1.1.0/24"), + // ResourceID: to.Ptr("/subscriptions/2bf4a339-294d-4c25-b0b2-ef649e9f5c27/resourceGroups/os-liftr-integration/providers/Microsoft.Network/virtualNetworks/os-liftr-integration-vnet/subnets/os-liftr-integration-untrust-subnet"), + // }, + // VHub: &armpanngfw.IPAddressSpace{ + // AddressSpace: to.Ptr("10.1.1.0/24"), + // ResourceID: to.Ptr("/subscriptions/2bf4a339-294d-4c25-b0b2-ef649e9f5c27/resourceGroups/os-liftr-integration/providers/Microsoft.Network/virtualNetworks/os-liftr-integration-vnet/subnets/os-liftr-integration-untrust-subnet"), + // }, + // }, + // }, + // PanEtag: to.Ptr("2bf4a339-294d-4c25-b0b2-ef649e9f5c12"), + // PanoramaConfig: &armpanngfw.PanoramaConfig{ + // CgName: to.Ptr("PanoramaCollectorGroup"), + // ConfigString: to.Ptr("bas64EncodedString"), + // DgName: to.Ptr("PanoramaDeviceGroup"), + // HostName: to.Ptr("hostname"), + // PanoramaServer: to.Ptr("10.25.1.1"), + // PanoramaServer2: to.Ptr("10.20.1.1"), + // TplName: to.Ptr("PanoramaTemplateStack"), + // VMAuthKey: to.Ptr("SSH_AUTH_KEY"), + // }, + // PlanData: &armpanngfw.PlanData{ + // BillingCycle: to.Ptr(armpanngfw.BillingCycleWEEKLY), + // EffectiveDate: to.Ptr(func() time.Time { t, _ := time.Parse(time.RFC3339Nano, "2022-09-13T00:46:05.283Z"); return t}()), + // PlanID: to.Ptr("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"), + // UsageType: to.Ptr(armpanngfw.UsageTypePAYG), + // }, + // ProvisioningState: to.Ptr(armpanngfw.ProvisioningStateSucceeded), + // }, + // }}, + // } + } +} + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/Firewalls_ListByResourceGroup_MinimumSet_Gen.json +func ExampleFirewallsClient_NewListByResourceGroupPager_firewallsListByResourceGroupMinimumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + pager := clientFactory.NewFirewallsClient().NewListByResourceGroupPager("firewall-rg", nil) + for pager.More() { + page, err := pager.NextPage(ctx) + if err != nil { + log.Fatalf("failed to advance page: %v", err) + } + for _, v := range page.Value { + // You could use page here. We use blank identifier for just demo purposes. + _ = v + } + // If the HTTP response code is 200 as defined in example definition, your page structure would look as follows. Please pay attention that all the values in the output are fake values for just demo purposes. + // page.FirewallResourceListResult = armpanngfw.FirewallResourceListResult{ + // Value: []*armpanngfw.FirewallResource{ + // { + // ID: to.Ptr("/subscriptions/2bf4a339-294d-4c25-b0b2-ef649e9f5c27/resourcegroups/firewall-rg/providers/PaloAltoNetworks.Cloudngfw/firewalls/firewall"), + // Location: to.Ptr("eastus"), + // Properties: &armpanngfw.FirewallDeploymentProperties{ + // DNSSettings: &armpanngfw.DNSSettings{ + // }, + // MarketplaceDetails: &armpanngfw.MarketplaceDetails{ + // OfferID: to.Ptr("aaaaaaaaaaaaaaaaaaaaaaaaaaaaa"), + // PublisherID: to.Ptr("aaaa"), + // }, + // NetworkProfile: &armpanngfw.NetworkProfile{ + // EnableEgressNat: to.Ptr(armpanngfw.EgressNatENABLED), + // NetworkType: to.Ptr(armpanngfw.NetworkTypeVNET), + // PublicIPs: []*armpanngfw.IPAddress{ + // { + // Address: to.Ptr("20.22.92.11"), + // ResourceID: to.Ptr("/subscriptions/01c7d41f-afaf-464e-8a8b-5c6f9f98cee8/resourceGroups/mj-liftr-integration/providers/Microsoft.Network/publicIPAddresses/mj-liftr-integration-PublicIp1"), + // }}, + // }, + // PlanData: &armpanngfw.PlanData{ + // BillingCycle: to.Ptr(armpanngfw.BillingCycleWEEKLY), + // PlanID: to.Ptr("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"), + // }, + // }, + // }}, + // } + } +} + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/Firewalls_Get_MaximumSet_Gen.json +func ExampleFirewallsClient_Get_firewallsGetMaximumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + res, err := clientFactory.NewFirewallsClient().Get(ctx, "firewall-rg", "firewall1", nil) + if err != nil { + log.Fatalf("failed to finish the request: %v", err) + } + // You could use response here. We use blank identifier for just demo purposes. + _ = res + // If the HTTP response code is 200 as defined in example definition, your response structure would look as follows. Please pay attention that all the values in the output are fake values for just demo purposes. + // res.FirewallResource = armpanngfw.FirewallResource{ + // Name: to.Ptr("aaaaaaaaaaaaa"), + // Type: to.Ptr("aaaaaa"), + // ID: to.Ptr("aaaaaaaaaaaaaaaaaaaaaaaa"), + // SystemData: &armpanngfw.SystemData{ + // CreatedAt: to.Ptr(func() time.Time { t, _ := time.Parse(time.RFC3339Nano, "2022-09-09T05:08:24.229Z"); return t}()), + // CreatedBy: to.Ptr("praval"), + // CreatedByType: to.Ptr(armpanngfw.CreatedByTypeUser), + // LastModifiedAt: to.Ptr(func() time.Time { t, _ := time.Parse(time.RFC3339Nano, "2022-09-09T05:08:24.229Z"); return t}()), + // LastModifiedBy: to.Ptr("praval"), + // LastModifiedByType: to.Ptr(armpanngfw.CreatedByTypeUser), + // }, + // Location: to.Ptr("eastus"), + // Tags: map[string]*string{ + // "tagName": to.Ptr("value"), + // }, + // Identity: &armpanngfw.AzureResourceManagerManagedIdentityProperties{ + // Type: to.Ptr(armpanngfw.ManagedIdentityTypeNone), + // PrincipalID: to.Ptr("aaaaaaaaaaaaaaaaaaaaaaaaaa"), + // TenantID: to.Ptr("aaaaaaaaaaaaaaaaaaaaaaaaaaaa"), + // UserAssignedIdentities: map[string]*armpanngfw.AzureResourceManagerUserAssignedIdentity{ + // "key16": &armpanngfw.AzureResourceManagerUserAssignedIdentity{ + // ClientID: to.Ptr("aaaa"), + // PrincipalID: to.Ptr("aaaaaaaaaaaaaaa"), + // }, + // }, + // }, + // Properties: &armpanngfw.FirewallDeploymentProperties{ + // AssociatedRulestack: &armpanngfw.RulestackDetails{ + // Location: to.Ptr("eastus"), + // ResourceID: to.Ptr("aaaaaaaaaa"), + // RulestackID: to.Ptr("aaaaaaaaaaaaaaaa"), + // }, + // DNSSettings: &armpanngfw.DNSSettings{ + // DNSServers: []*armpanngfw.IPAddress{ + // { + // Address: to.Ptr("20.22.92.111"), + // ResourceID: to.Ptr("/subscriptions/01c7d41f-afaf-464e-8a8b-5c6f9f98cee8/resourceGroups/mj-liftr-integration/providers/Microsoft.Network/publicIPAddresses/mj-liftr-integration-egressNatIp1"), + // }}, + // EnableDNSProxy: to.Ptr(armpanngfw.DNSProxyDISABLED), + // EnabledDNSType: to.Ptr(armpanngfw.EnabledDNSTypeCUSTOM), + // }, + // FrontEndSettings: []*armpanngfw.FrontendSetting{ + // { + // Name: to.Ptr("frontendsetting11"), + // BackendConfiguration: &armpanngfw.EndpointConfiguration{ + // Address: &armpanngfw.IPAddress{ + // Address: to.Ptr("20.22.32.136"), + // ResourceID: to.Ptr("/subscriptions/01c7d41f-afaf-464e-8a8b-5c6f9f98cee8/resourceGroups/mj-liftr-integration/providers/Microsoft.Network/publicIPAddresses/mj-liftr-integration-frontendSettingIp2"), + // }, + // Port: to.Ptr("80"), + // }, + // FrontendConfiguration: &armpanngfw.EndpointConfiguration{ + // Address: &armpanngfw.IPAddress{ + // Address: to.Ptr("20.22.91.251"), + // ResourceID: to.Ptr("/subscriptions/01c7d41f-afaf-464e-8a8b-5c6f9f98cee8/resourceGroups/mj-liftr-integration/providers/Microsoft.Network/publicIPAddresses/mj-liftr-integration-frontendSettingIp1"), + // }, + // Port: to.Ptr("80"), + // }, + // Protocol: to.Ptr(armpanngfw.ProtocolTypeTCP), + // }}, + // IsPanoramaManaged: to.Ptr(armpanngfw.BooleanEnumTRUE), + // MarketplaceDetails: &armpanngfw.MarketplaceDetails{ + // MarketplaceSubscriptionID: to.Ptr("aa"), + // MarketplaceSubscriptionStatus: to.Ptr(armpanngfw.MarketplaceSubscriptionStatusPendingFulfillmentStart), + // OfferID: to.Ptr("aaaaaaaaaaaaaaaaaaaaaaaaaaaaa"), + // PublisherID: to.Ptr("aaaa"), + // }, + // NetworkProfile: &armpanngfw.NetworkProfile{ + // EgressNatIP: []*armpanngfw.IPAddress{ + // { + // Address: to.Ptr("20.22.92.111"), + // ResourceID: to.Ptr("/subscriptions/01c7d41f-afaf-464e-8a8b-5c6f9f98cee8/resourceGroups/mj-liftr-integration/providers/Microsoft.Network/publicIPAddresses/mj-liftr-integration-egressNatIp1"), + // }}, + // EnableEgressNat: to.Ptr(armpanngfw.EgressNatENABLED), + // NetworkType: to.Ptr(armpanngfw.NetworkTypeVNET), + // PublicIPs: []*armpanngfw.IPAddress{ + // { + // Address: to.Ptr("20.22.92.11"), + // ResourceID: to.Ptr("/subscriptions/01c7d41f-afaf-464e-8a8b-5c6f9f98cee8/resourceGroups/mj-liftr-integration/providers/Microsoft.Network/publicIPAddresses/mj-liftr-integration-PublicIp1"), + // }}, + // VnetConfiguration: &armpanngfw.VnetConfiguration{ + // IPOfTrustSubnetForUdr: &armpanngfw.IPAddress{ + // Address: to.Ptr("10.1.1.0/24"), + // ResourceID: to.Ptr("/subscriptions/2bf4a339-294d-4c25-b0b2-ef649e9f5c27/resourceGroups/os-liftr-integration/providers/Microsoft.Network/virtualNetworks/os-liftr-integration-vnet/subnets/os-liftr-integration-untrust-subnet"), + // }, + // TrustSubnet: &armpanngfw.IPAddressSpace{ + // AddressSpace: to.Ptr("10.1.1.0/24"), + // ResourceID: to.Ptr("/subscriptions/2bf4a339-294d-4c25-b0b2-ef649e9f5c27/resourceGroups/os-liftr-integration/providers/Microsoft.Network/virtualNetworks/os-liftr-integration-vnet/subnets/os-liftr-integration-trust-subnet"), + // }, + // UnTrustSubnet: &armpanngfw.IPAddressSpace{ + // AddressSpace: to.Ptr("10.1.1.0/24"), + // ResourceID: to.Ptr("/subscriptions/2bf4a339-294d-4c25-b0b2-ef649e9f5c27/resourceGroups/os-liftr-integration/providers/Microsoft.Network/virtualNetworks/os-liftr-integration-vnet/subnets/os-liftr-integration-untrust-subnet"), + // }, + // Vnet: &armpanngfw.IPAddressSpace{ + // AddressSpace: to.Ptr("10.1.0.0/16"), + // ResourceID: to.Ptr("/subscriptions/2bf4a339-294d-4c25-b0b2-ef649e9f5c27/resourceGroups/os-liftr-integration/providers/Microsoft.Network/virtualNetworks/os-liftr-integration-vnet"), + // }, + // }, + // VwanConfiguration: &armpanngfw.VwanConfiguration{ + // IPOfTrustSubnetForUdr: &armpanngfw.IPAddress{ + // Address: to.Ptr("10.1.1.0/24"), + // ResourceID: to.Ptr("/subscriptions/2bf4a339-294d-4c25-b0b2-ef649e9f5c27/resourceGroups/os-liftr-integration/providers/Microsoft.Network/virtualNetworks/os-liftr-integration-vnet/subnets/os-liftr-integration-untrust-subnet"), + // }, + // NetworkVirtualApplianceID: to.Ptr("2bf4a339-294d-4c25-b0b2-ef649e9f5c12"), + // TrustSubnet: &armpanngfw.IPAddressSpace{ + // AddressSpace: to.Ptr("10.1.1.0/24"), + // ResourceID: to.Ptr("/subscriptions/2bf4a339-294d-4c25-b0b2-ef649e9f5c27/resourceGroups/os-liftr-integration/providers/Microsoft.Network/virtualNetworks/os-liftr-integration-vnet/subnets/os-liftr-integration-trust-subnet"), + // }, + // UnTrustSubnet: &armpanngfw.IPAddressSpace{ + // AddressSpace: to.Ptr("10.1.1.0/24"), + // ResourceID: to.Ptr("/subscriptions/2bf4a339-294d-4c25-b0b2-ef649e9f5c27/resourceGroups/os-liftr-integration/providers/Microsoft.Network/virtualNetworks/os-liftr-integration-vnet/subnets/os-liftr-integration-untrust-subnet"), + // }, + // VHub: &armpanngfw.IPAddressSpace{ + // AddressSpace: to.Ptr("10.1.1.0/24"), + // ResourceID: to.Ptr("/subscriptions/2bf4a339-294d-4c25-b0b2-ef649e9f5c27/resourceGroups/os-liftr-integration/providers/Microsoft.Network/virtualNetworks/os-liftr-integration-vnet/subnets/os-liftr-integration-untrust-subnet"), + // }, + // }, + // }, + // PanEtag: to.Ptr("2bf4a339-294d-4c25-b0b2-ef649e9f5c12"), + // PanoramaConfig: &armpanngfw.PanoramaConfig{ + // CgName: to.Ptr("PanoramaCollectorGroup"), + // ConfigString: to.Ptr("bas64EncodedString"), + // DgName: to.Ptr("PanoramaDeviceGroup"), + // HostName: to.Ptr("hostname"), + // PanoramaServer: to.Ptr("10.25.1.1"), + // PanoramaServer2: to.Ptr("10.20.1.1"), + // TplName: to.Ptr("PanoramaTemplateStack"), + // VMAuthKey: to.Ptr("SSH_AUTH_KEY"), + // }, + // PlanData: &armpanngfw.PlanData{ + // BillingCycle: to.Ptr(armpanngfw.BillingCycleWEEKLY), + // EffectiveDate: to.Ptr(func() time.Time { t, _ := time.Parse(time.RFC3339Nano, "2022-09-13T00:46:05.283Z"); return t}()), + // PlanID: to.Ptr("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"), + // UsageType: to.Ptr(armpanngfw.UsageTypePAYG), + // }, + // ProvisioningState: to.Ptr(armpanngfw.ProvisioningStateSucceeded), + // }, + // } +} + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/Firewalls_Get_MinimumSet_Gen.json +func ExampleFirewallsClient_Get_firewallsGetMinimumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + res, err := clientFactory.NewFirewallsClient().Get(ctx, "firewall-rg", "firewall1", nil) + if err != nil { + log.Fatalf("failed to finish the request: %v", err) + } + // You could use response here. We use blank identifier for just demo purposes. + _ = res + // If the HTTP response code is 200 as defined in example definition, your response structure would look as follows. Please pay attention that all the values in the output are fake values for just demo purposes. + // res.FirewallResource = armpanngfw.FirewallResource{ + // ID: to.Ptr("/subscriptions/2bf4a339-294d-4c25-b0b2-ef649e9f5c27/resourcegroups/firewall-rg/providers/PaloAltoNetworks.Cloudngfw/firewalls/firewall1"), + // Location: to.Ptr("eastus"), + // Properties: &armpanngfw.FirewallDeploymentProperties{ + // DNSSettings: &armpanngfw.DNSSettings{ + // }, + // MarketplaceDetails: &armpanngfw.MarketplaceDetails{ + // OfferID: to.Ptr("aaaaaaaaaaaaaaaaaaaaaaaaaaaaa"), + // PublisherID: to.Ptr("aaaa"), + // }, + // NetworkProfile: &armpanngfw.NetworkProfile{ + // EnableEgressNat: to.Ptr(armpanngfw.EgressNatENABLED), + // NetworkType: to.Ptr(armpanngfw.NetworkTypeVNET), + // PublicIPs: []*armpanngfw.IPAddress{ + // { + // Address: to.Ptr("20.22.92.11"), + // ResourceID: to.Ptr("/subscriptions/01c7d41f-afaf-464e-8a8b-5c6f9f98cee8/resourceGroups/mj-liftr-integration/providers/Microsoft.Network/publicIPAddresses/mj-liftr-integration-PublicIp1"), + // }}, + // }, + // PlanData: &armpanngfw.PlanData{ + // BillingCycle: to.Ptr(armpanngfw.BillingCycleWEEKLY), + // PlanID: to.Ptr("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"), + // }, + // }, + // } +} + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/Firewalls_CreateOrUpdate_MaximumSet_Gen.json +func ExampleFirewallsClient_BeginCreateOrUpdate_firewallsCreateOrUpdateMaximumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + poller, err := clientFactory.NewFirewallsClient().BeginCreateOrUpdate(ctx, "firewall-rg", "firewall1", armpanngfw.FirewallResource{ + Location: to.Ptr("eastus"), + Tags: map[string]*string{ + "tagName": to.Ptr("value"), + }, + Identity: &armpanngfw.AzureResourceManagerManagedIdentityProperties{ + Type: to.Ptr(armpanngfw.ManagedIdentityTypeNone), + UserAssignedIdentities: map[string]*armpanngfw.AzureResourceManagerUserAssignedIdentity{ + "key16": { + ClientID: to.Ptr("aaaa"), + PrincipalID: to.Ptr("aaaaaaaaaaaaaaa"), + }, + }, + }, + Properties: &armpanngfw.FirewallDeploymentProperties{ + AssociatedRulestack: &armpanngfw.RulestackDetails{ + Location: to.Ptr("eastus"), + ResourceID: to.Ptr("lrs1"), + RulestackID: to.Ptr("PANRSID"), + }, + DNSSettings: &armpanngfw.DNSSettings{ + DNSServers: []*armpanngfw.IPAddress{ + { + Address: to.Ptr("20.22.92.111"), + ResourceID: to.Ptr("/subscriptions/01c7d41f-afaf-464e-8a8b-5c6f9f98cee8/resourceGroups/mj-liftr-integration/providers/Microsoft.Network/publicIPAddresses/mj-liftr-integration-egressNatIp1"), + }}, + EnableDNSProxy: to.Ptr(armpanngfw.DNSProxyDISABLED), + EnabledDNSType: to.Ptr(armpanngfw.EnabledDNSTypeCUSTOM), + }, + FrontEndSettings: []*armpanngfw.FrontendSetting{ + { + Name: to.Ptr("frontendsetting11"), + BackendConfiguration: &armpanngfw.EndpointConfiguration{ + Address: &armpanngfw.IPAddress{ + Address: to.Ptr("20.22.32.136"), + ResourceID: to.Ptr("/subscriptions/01c7d41f-afaf-464e-8a8b-5c6f9f98cee8/resourceGroups/mj-liftr-integration/providers/Microsoft.Network/publicIPAddresses/mj-liftr-integration-frontendSettingIp2"), + }, + Port: to.Ptr("80"), + }, + FrontendConfiguration: &armpanngfw.EndpointConfiguration{ + Address: &armpanngfw.IPAddress{ + Address: to.Ptr("20.22.91.251"), + ResourceID: to.Ptr("/subscriptions/01c7d41f-afaf-464e-8a8b-5c6f9f98cee8/resourceGroups/mj-liftr-integration/providers/Microsoft.Network/publicIPAddresses/mj-liftr-integration-frontendSettingIp1"), + }, + Port: to.Ptr("80"), + }, + Protocol: to.Ptr(armpanngfw.ProtocolTypeTCP), + }}, + IsPanoramaManaged: to.Ptr(armpanngfw.BooleanEnumTRUE), + MarketplaceDetails: &armpanngfw.MarketplaceDetails{ + MarketplaceSubscriptionStatus: to.Ptr(armpanngfw.MarketplaceSubscriptionStatusPendingFulfillmentStart), + OfferID: to.Ptr("liftr-pan-ame-test"), + PublisherID: to.Ptr("isvtestuklegacy"), + }, + NetworkProfile: &armpanngfw.NetworkProfile{ + EgressNatIP: []*armpanngfw.IPAddress{ + { + Address: to.Ptr("20.22.92.111"), + ResourceID: to.Ptr("/subscriptions/01c7d41f-afaf-464e-8a8b-5c6f9f98cee8/resourceGroups/mj-liftr-integration/providers/Microsoft.Network/publicIPAddresses/mj-liftr-integration-egressNatIp1"), + }}, + EnableEgressNat: to.Ptr(armpanngfw.EgressNatENABLED), + NetworkType: to.Ptr(armpanngfw.NetworkTypeVNET), + PublicIPs: []*armpanngfw.IPAddress{ + { + Address: to.Ptr("20.22.92.11"), + ResourceID: to.Ptr("/subscriptions/01c7d41f-afaf-464e-8a8b-5c6f9f98cee8/resourceGroups/mj-liftr-integration/providers/Microsoft.Network/publicIPAddresses/mj-liftr-integration-PublicIp1"), + }}, + VnetConfiguration: &armpanngfw.VnetConfiguration{ + IPOfTrustSubnetForUdr: &armpanngfw.IPAddress{ + Address: to.Ptr("10.1.1.0/24"), + ResourceID: to.Ptr("/subscriptions/2bf4a339-294d-4c25-b0b2-ef649e9f5c27/resourceGroups/os-liftr-integration/providers/Microsoft.Network/virtualNetworks/os-liftr-integration-vnet/subnets/os-liftr-integration-untrust-subnet"), + }, + TrustSubnet: &armpanngfw.IPAddressSpace{ + AddressSpace: to.Ptr("10.1.1.0/24"), + ResourceID: to.Ptr("/subscriptions/2bf4a339-294d-4c25-b0b2-ef649e9f5c27/resourceGroups/os-liftr-integration/providers/Microsoft.Network/virtualNetworks/os-liftr-integration-vnet/subnets/os-liftr-integration-trust-subnet"), + }, + UnTrustSubnet: &armpanngfw.IPAddressSpace{ + AddressSpace: to.Ptr("10.1.1.0/24"), + ResourceID: to.Ptr("/subscriptions/2bf4a339-294d-4c25-b0b2-ef649e9f5c27/resourceGroups/os-liftr-integration/providers/Microsoft.Network/virtualNetworks/os-liftr-integration-vnet/subnets/os-liftr-integration-untrust-subnet"), + }, + Vnet: &armpanngfw.IPAddressSpace{ + AddressSpace: to.Ptr("10.1.0.0/16"), + ResourceID: to.Ptr("/subscriptions/2bf4a339-294d-4c25-b0b2-ef649e9f5c27/resourceGroups/os-liftr-integration/providers/Microsoft.Network/virtualNetworks/os-liftr-integration-vnet"), + }, + }, + VwanConfiguration: &armpanngfw.VwanConfiguration{ + IPOfTrustSubnetForUdr: &armpanngfw.IPAddress{ + Address: to.Ptr("10.1.1.0/24"), + ResourceID: to.Ptr("/subscriptions/2bf4a339-294d-4c25-b0b2-ef649e9f5c27/resourceGroups/os-liftr-integration/providers/Microsoft.Network/virtualNetworks/os-liftr-integration-vnet/subnets/os-liftr-integration-untrust-subnet"), + }, + NetworkVirtualApplianceID: to.Ptr("2bf4a339-294d-4c25-b0b2-ef649e9f5c12"), + TrustSubnet: &armpanngfw.IPAddressSpace{ + AddressSpace: to.Ptr("10.1.1.0/24"), + ResourceID: to.Ptr("/subscriptions/2bf4a339-294d-4c25-b0b2-ef649e9f5c27/resourceGroups/os-liftr-integration/providers/Microsoft.Network/virtualNetworks/os-liftr-integration-vnet/subnets/os-liftr-integration-trust-subnet"), + }, + UnTrustSubnet: &armpanngfw.IPAddressSpace{ + AddressSpace: to.Ptr("10.1.1.0/24"), + ResourceID: to.Ptr("/subscriptions/2bf4a339-294d-4c25-b0b2-ef649e9f5c27/resourceGroups/os-liftr-integration/providers/Microsoft.Network/virtualNetworks/os-liftr-integration-vnet/subnets/os-liftr-integration-untrust-subnet"), + }, + VHub: &armpanngfw.IPAddressSpace{ + AddressSpace: to.Ptr("10.1.1.0/24"), + ResourceID: to.Ptr("/subscriptions/2bf4a339-294d-4c25-b0b2-ef649e9f5c27/resourceGroups/os-liftr-integration/providers/Microsoft.Network/virtualNetworks/os-liftr-integration-vnet/subnets/os-liftr-integration-untrust-subnet"), + }, + }, + }, + PanEtag: to.Ptr("2bf4a339-294d-4c25-b0b2-ef649e9f5c12"), + PanoramaConfig: &armpanngfw.PanoramaConfig{ + ConfigString: to.Ptr("bas64EncodedString"), + }, + PlanData: &armpanngfw.PlanData{ + BillingCycle: to.Ptr(armpanngfw.BillingCycleMONTHLY), + PlanID: to.Ptr("liftrpantestplan"), + UsageType: to.Ptr(armpanngfw.UsageTypePAYG), + }, + ProvisioningState: to.Ptr(armpanngfw.ProvisioningStateAccepted), + }, + }, nil) + if err != nil { + log.Fatalf("failed to finish the request: %v", err) + } + res, err := poller.PollUntilDone(ctx, nil) + if err != nil { + log.Fatalf("failed to pull the result: %v", err) + } + // You could use response here. We use blank identifier for just demo purposes. + _ = res + // If the HTTP response code is 200 as defined in example definition, your response structure would look as follows. Please pay attention that all the values in the output are fake values for just demo purposes. + // res.FirewallResource = armpanngfw.FirewallResource{ + // Name: to.Ptr("armid1"), + // Type: to.Ptr("firewalls"), + // ID: to.Ptr("/providers/PaloAltoNetworks.Cloudngfw/globalrulestacks/armid1/firewalls/armid1"), + // SystemData: &armpanngfw.SystemData{ + // CreatedAt: to.Ptr(func() time.Time { t, _ := time.Parse(time.RFC3339Nano, "2022-09-09T05:08:24.229Z"); return t}()), + // CreatedBy: to.Ptr("praval"), + // CreatedByType: to.Ptr(armpanngfw.CreatedByTypeUser), + // LastModifiedAt: to.Ptr(func() time.Time { t, _ := time.Parse(time.RFC3339Nano, "2022-09-09T05:08:24.229Z"); return t}()), + // LastModifiedBy: to.Ptr("praval"), + // LastModifiedByType: to.Ptr(armpanngfw.CreatedByTypeUser), + // }, + // Location: to.Ptr("eastus"), + // Tags: map[string]*string{ + // "tagName": to.Ptr("value"), + // }, + // Identity: &armpanngfw.AzureResourceManagerManagedIdentityProperties{ + // Type: to.Ptr(armpanngfw.ManagedIdentityTypeNone), + // PrincipalID: to.Ptr("aaaaaaaaaaaaaaaaaaaaaaaaaa"), + // TenantID: to.Ptr("aaaaaaaaaaaaaaaaaaaaaaaaaaaa"), + // UserAssignedIdentities: map[string]*armpanngfw.AzureResourceManagerUserAssignedIdentity{ + // "key16": &armpanngfw.AzureResourceManagerUserAssignedIdentity{ + // ClientID: to.Ptr("aaaa"), + // PrincipalID: to.Ptr("aaaaaaaaaaaaaaa"), + // }, + // }, + // }, + // Properties: &armpanngfw.FirewallDeploymentProperties{ + // AssociatedRulestack: &armpanngfw.RulestackDetails{ + // Location: to.Ptr("eastus"), + // ResourceID: to.Ptr("aaaaaaaaaa"), + // RulestackID: to.Ptr("aaaaaaaaaaaaaaaa"), + // }, + // DNSSettings: &armpanngfw.DNSSettings{ + // DNSServers: []*armpanngfw.IPAddress{ + // { + // Address: to.Ptr("20.22.92.111"), + // ResourceID: to.Ptr("/subscriptions/01c7d41f-afaf-464e-8a8b-5c6f9f98cee8/resourceGroups/mj-liftr-integration/providers/Microsoft.Network/publicIPAddresses/mj-liftr-integration-egressNatIp1"), + // }}, + // EnableDNSProxy: to.Ptr(armpanngfw.DNSProxyDISABLED), + // EnabledDNSType: to.Ptr(armpanngfw.EnabledDNSTypeCUSTOM), + // }, + // FrontEndSettings: []*armpanngfw.FrontendSetting{ + // { + // Name: to.Ptr("frontendsetting11"), + // BackendConfiguration: &armpanngfw.EndpointConfiguration{ + // Address: &armpanngfw.IPAddress{ + // Address: to.Ptr("20.22.32.136"), + // ResourceID: to.Ptr("/subscriptions/01c7d41f-afaf-464e-8a8b-5c6f9f98cee8/resourceGroups/mj-liftr-integration/providers/Microsoft.Network/publicIPAddresses/mj-liftr-integration-frontendSettingIp2"), + // }, + // Port: to.Ptr("80"), + // }, + // FrontendConfiguration: &armpanngfw.EndpointConfiguration{ + // Address: &armpanngfw.IPAddress{ + // Address: to.Ptr("20.22.91.251"), + // ResourceID: to.Ptr("/subscriptions/01c7d41f-afaf-464e-8a8b-5c6f9f98cee8/resourceGroups/mj-liftr-integration/providers/Microsoft.Network/publicIPAddresses/mj-liftr-integration-frontendSettingIp1"), + // }, + // Port: to.Ptr("80"), + // }, + // Protocol: to.Ptr(armpanngfw.ProtocolTypeTCP), + // }}, + // IsPanoramaManaged: to.Ptr(armpanngfw.BooleanEnumTRUE), + // MarketplaceDetails: &armpanngfw.MarketplaceDetails{ + // MarketplaceSubscriptionID: to.Ptr("aa"), + // MarketplaceSubscriptionStatus: to.Ptr(armpanngfw.MarketplaceSubscriptionStatusPendingFulfillmentStart), + // OfferID: to.Ptr("aaaaaaaaaaaaaaaaaaaaaaaaaaaaa"), + // PublisherID: to.Ptr("aaaa"), + // }, + // NetworkProfile: &armpanngfw.NetworkProfile{ + // EgressNatIP: []*armpanngfw.IPAddress{ + // { + // Address: to.Ptr("20.22.92.111"), + // ResourceID: to.Ptr("/subscriptions/01c7d41f-afaf-464e-8a8b-5c6f9f98cee8/resourceGroups/mj-liftr-integration/providers/Microsoft.Network/publicIPAddresses/mj-liftr-integration-egressNatIp1"), + // }}, + // EnableEgressNat: to.Ptr(armpanngfw.EgressNatENABLED), + // NetworkType: to.Ptr(armpanngfw.NetworkTypeVNET), + // PublicIPs: []*armpanngfw.IPAddress{ + // { + // Address: to.Ptr("20.22.92.11"), + // ResourceID: to.Ptr("/subscriptions/01c7d41f-afaf-464e-8a8b-5c6f9f98cee8/resourceGroups/mj-liftr-integration/providers/Microsoft.Network/publicIPAddresses/mj-liftr-integration-PublicIp1"), + // }}, + // VnetConfiguration: &armpanngfw.VnetConfiguration{ + // IPOfTrustSubnetForUdr: &armpanngfw.IPAddress{ + // Address: to.Ptr("10.1.1.0/24"), + // ResourceID: to.Ptr("/subscriptions/2bf4a339-294d-4c25-b0b2-ef649e9f5c27/resourceGroups/os-liftr-integration/providers/Microsoft.Network/virtualNetworks/os-liftr-integration-vnet/subnets/os-liftr-integration-untrust-subnet"), + // }, + // TrustSubnet: &armpanngfw.IPAddressSpace{ + // AddressSpace: to.Ptr("10.1.1.0/24"), + // ResourceID: to.Ptr("/subscriptions/2bf4a339-294d-4c25-b0b2-ef649e9f5c27/resourceGroups/os-liftr-integration/providers/Microsoft.Network/virtualNetworks/os-liftr-integration-vnet/subnets/os-liftr-integration-trust-subnet"), + // }, + // UnTrustSubnet: &armpanngfw.IPAddressSpace{ + // AddressSpace: to.Ptr("10.1.1.0/24"), + // ResourceID: to.Ptr("/subscriptions/2bf4a339-294d-4c25-b0b2-ef649e9f5c27/resourceGroups/os-liftr-integration/providers/Microsoft.Network/virtualNetworks/os-liftr-integration-vnet/subnets/os-liftr-integration-untrust-subnet"), + // }, + // Vnet: &armpanngfw.IPAddressSpace{ + // AddressSpace: to.Ptr("10.1.0.0/16"), + // ResourceID: to.Ptr("/subscriptions/2bf4a339-294d-4c25-b0b2-ef649e9f5c27/resourceGroups/os-liftr-integration/providers/Microsoft.Network/virtualNetworks/os-liftr-integration-vnet"), + // }, + // }, + // VwanConfiguration: &armpanngfw.VwanConfiguration{ + // IPOfTrustSubnetForUdr: &armpanngfw.IPAddress{ + // Address: to.Ptr("10.1.1.0/24"), + // ResourceID: to.Ptr("/subscriptions/2bf4a339-294d-4c25-b0b2-ef649e9f5c27/resourceGroups/os-liftr-integration/providers/Microsoft.Network/virtualNetworks/os-liftr-integration-vnet/subnets/os-liftr-integration-untrust-subnet"), + // }, + // NetworkVirtualApplianceID: to.Ptr("2bf4a339-294d-4c25-b0b2-ef649e9f5c12"), + // TrustSubnet: &armpanngfw.IPAddressSpace{ + // AddressSpace: to.Ptr("10.1.1.0/24"), + // ResourceID: to.Ptr("/subscriptions/2bf4a339-294d-4c25-b0b2-ef649e9f5c27/resourceGroups/os-liftr-integration/providers/Microsoft.Network/virtualNetworks/os-liftr-integration-vnet/subnets/os-liftr-integration-trust-subnet"), + // }, + // UnTrustSubnet: &armpanngfw.IPAddressSpace{ + // AddressSpace: to.Ptr("10.1.1.0/24"), + // ResourceID: to.Ptr("/subscriptions/2bf4a339-294d-4c25-b0b2-ef649e9f5c27/resourceGroups/os-liftr-integration/providers/Microsoft.Network/virtualNetworks/os-liftr-integration-vnet/subnets/os-liftr-integration-untrust-subnet"), + // }, + // VHub: &armpanngfw.IPAddressSpace{ + // AddressSpace: to.Ptr("10.1.1.0/24"), + // ResourceID: to.Ptr("/subscriptions/2bf4a339-294d-4c25-b0b2-ef649e9f5c27/resourceGroups/os-liftr-integration/providers/Microsoft.Network/virtualNetworks/os-liftr-integration-vnet/subnets/os-liftr-integration-untrust-subnet"), + // }, + // }, + // }, + // PanEtag: to.Ptr("2bf4a339-294d-4c25-b0b2-ef649e9f5c12"), + // PanoramaConfig: &armpanngfw.PanoramaConfig{ + // CgName: to.Ptr("PanoramaCollectorGroup"), + // ConfigString: to.Ptr("bas64EncodedString"), + // DgName: to.Ptr("PanoramaDeviceGroup"), + // HostName: to.Ptr("hostname"), + // PanoramaServer: to.Ptr("10.25.1.1"), + // PanoramaServer2: to.Ptr("10.20.1.1"), + // TplName: to.Ptr("PanoramaTemplateStack"), + // VMAuthKey: to.Ptr("SSH_AUTH_KEY"), + // }, + // PlanData: &armpanngfw.PlanData{ + // BillingCycle: to.Ptr(armpanngfw.BillingCycleWEEKLY), + // EffectiveDate: to.Ptr(func() time.Time { t, _ := time.Parse(time.RFC3339Nano, "2022-09-13T00:46:05.283Z"); return t}()), + // PlanID: to.Ptr("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"), + // UsageType: to.Ptr(armpanngfw.UsageTypePAYG), + // }, + // ProvisioningState: to.Ptr(armpanngfw.ProvisioningStateSucceeded), + // }, + // } +} + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/Firewalls_CreateOrUpdate_MinimumSet_Gen.json +func ExampleFirewallsClient_BeginCreateOrUpdate_firewallsCreateOrUpdateMinimumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + poller, err := clientFactory.NewFirewallsClient().BeginCreateOrUpdate(ctx, "firewall-rg", "firewall1", armpanngfw.FirewallResource{ + Location: to.Ptr("eastus"), + Properties: &armpanngfw.FirewallDeploymentProperties{ + DNSSettings: &armpanngfw.DNSSettings{}, + MarketplaceDetails: &armpanngfw.MarketplaceDetails{ + OfferID: to.Ptr("liftr-pan-ame-test"), + PublisherID: to.Ptr("isvtestuklegacy"), + }, + NetworkProfile: &armpanngfw.NetworkProfile{ + EnableEgressNat: to.Ptr(armpanngfw.EgressNatENABLED), + NetworkType: to.Ptr(armpanngfw.NetworkTypeVNET), + PublicIPs: []*armpanngfw.IPAddress{ + { + Address: to.Ptr("20.22.92.11"), + ResourceID: to.Ptr("/subscriptions/01c7d41f-afaf-464e-8a8b-5c6f9f98cee8/resourceGroups/mj-liftr-integration/providers/Microsoft.Network/publicIPAddresses/mj-liftr-integration-PublicIp1"), + }}, + }, + PlanData: &armpanngfw.PlanData{ + BillingCycle: to.Ptr(armpanngfw.BillingCycleMONTHLY), + PlanID: to.Ptr("liftrpantestplan"), + }, + }, + }, nil) + if err != nil { + log.Fatalf("failed to finish the request: %v", err) + } + res, err := poller.PollUntilDone(ctx, nil) + if err != nil { + log.Fatalf("failed to pull the result: %v", err) + } + // You could use response here. We use blank identifier for just demo purposes. + _ = res + // If the HTTP response code is 200 as defined in example definition, your response structure would look as follows. Please pay attention that all the values in the output are fake values for just demo purposes. + // res.FirewallResource = armpanngfw.FirewallResource{ + // ID: to.Ptr("/subscriptions/2bf4a339-294d-4c25-b0b2-ef649e9f5c27/resourcegroups/firewall-rg/providers/PaloAltoNetworks.Cloudngfw/firewalls/firewall1"), + // Location: to.Ptr("eastus"), + // Properties: &armpanngfw.FirewallDeploymentProperties{ + // DNSSettings: &armpanngfw.DNSSettings{ + // }, + // MarketplaceDetails: &armpanngfw.MarketplaceDetails{ + // OfferID: to.Ptr("aaaaaaaaaaaaaaaaaaaaaaaaaaaaa"), + // PublisherID: to.Ptr("aaaa"), + // }, + // NetworkProfile: &armpanngfw.NetworkProfile{ + // EnableEgressNat: to.Ptr(armpanngfw.EgressNatENABLED), + // NetworkType: to.Ptr(armpanngfw.NetworkTypeVNET), + // PublicIPs: []*armpanngfw.IPAddress{ + // { + // Address: to.Ptr("20.22.92.11"), + // ResourceID: to.Ptr("/subscriptions/01c7d41f-afaf-464e-8a8b-5c6f9f98cee8/resourceGroups/mj-liftr-integration/providers/Microsoft.Network/publicIPAddresses/mj-liftr-integration-PublicIp1"), + // }}, + // }, + // PlanData: &armpanngfw.PlanData{ + // BillingCycle: to.Ptr(armpanngfw.BillingCycleWEEKLY), + // PlanID: to.Ptr("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"), + // }, + // }, + // } +} + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/Firewalls_Update_MaximumSet_Gen.json +func ExampleFirewallsClient_Update_firewallsUpdateMaximumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + res, err := clientFactory.NewFirewallsClient().Update(ctx, "firewall-rg", "firewall1", armpanngfw.FirewallResourceUpdate{ + Identity: &armpanngfw.AzureResourceManagerManagedIdentityProperties{ + Type: to.Ptr(armpanngfw.ManagedIdentityTypeNone), + UserAssignedIdentities: map[string]*armpanngfw.AzureResourceManagerUserAssignedIdentity{ + "key16": { + ClientID: to.Ptr("aaaa"), + PrincipalID: to.Ptr("aaaaaaaaaaaaaaa"), + }, + }, + }, + Properties: &armpanngfw.FirewallResourceUpdateProperties{ + AssociatedRulestack: &armpanngfw.RulestackDetails{ + Location: to.Ptr("eastus"), + ResourceID: to.Ptr("aaaaaaaaaa"), + RulestackID: to.Ptr("aaaaaaaaaaaaaaaa"), + }, + DNSSettings: &armpanngfw.DNSSettings{ + DNSServers: []*armpanngfw.IPAddress{ + { + Address: to.Ptr("20.22.92.111"), + ResourceID: to.Ptr("/subscriptions/01c7d41f-afaf-464e-8a8b-5c6f9f98cee8/resourceGroups/mj-liftr-integration/providers/Microsoft.Network/publicIPAddresses/mj-liftr-integration-egressNatIp1"), + }}, + EnableDNSProxy: to.Ptr(armpanngfw.DNSProxyDISABLED), + EnabledDNSType: to.Ptr(armpanngfw.EnabledDNSTypeCUSTOM), + }, + FrontEndSettings: []*armpanngfw.FrontendSetting{ + { + Name: to.Ptr("frontendsetting11"), + BackendConfiguration: &armpanngfw.EndpointConfiguration{ + Address: &armpanngfw.IPAddress{ + Address: to.Ptr("20.22.32.136"), + ResourceID: to.Ptr("/subscriptions/01c7d41f-afaf-464e-8a8b-5c6f9f98cee8/resourceGroups/mj-liftr-integration/providers/Microsoft.Network/publicIPAddresses/mj-liftr-integration-frontendSettingIp2"), + }, + Port: to.Ptr("80"), + }, + FrontendConfiguration: &armpanngfw.EndpointConfiguration{ + Address: &armpanngfw.IPAddress{ + Address: to.Ptr("20.22.91.251"), + ResourceID: to.Ptr("/subscriptions/01c7d41f-afaf-464e-8a8b-5c6f9f98cee8/resourceGroups/mj-liftr-integration/providers/Microsoft.Network/publicIPAddresses/mj-liftr-integration-frontendSettingIp1"), + }, + Port: to.Ptr("80"), + }, + Protocol: to.Ptr(armpanngfw.ProtocolTypeTCP), + }}, + IsPanoramaManaged: to.Ptr(armpanngfw.BooleanEnumTRUE), + MarketplaceDetails: &armpanngfw.MarketplaceDetails{ + MarketplaceSubscriptionStatus: to.Ptr(armpanngfw.MarketplaceSubscriptionStatusPendingFulfillmentStart), + OfferID: to.Ptr("aaaaaaaaaaaaaaaaaaaaaaaaaaaaa"), + PublisherID: to.Ptr("aaaa"), + }, + NetworkProfile: &armpanngfw.NetworkProfile{ + EgressNatIP: []*armpanngfw.IPAddress{ + { + Address: to.Ptr("20.22.92.111"), + ResourceID: to.Ptr("/subscriptions/01c7d41f-afaf-464e-8a8b-5c6f9f98cee8/resourceGroups/mj-liftr-integration/providers/Microsoft.Network/publicIPAddresses/mj-liftr-integration-egressNatIp1"), + }}, + EnableEgressNat: to.Ptr(armpanngfw.EgressNatENABLED), + NetworkType: to.Ptr(armpanngfw.NetworkTypeVNET), + PublicIPs: []*armpanngfw.IPAddress{ + { + Address: to.Ptr("20.22.92.11"), + ResourceID: to.Ptr("/subscriptions/01c7d41f-afaf-464e-8a8b-5c6f9f98cee8/resourceGroups/mj-liftr-integration/providers/Microsoft.Network/publicIPAddresses/mj-liftr-integration-PublicIp1"), + }}, + VnetConfiguration: &armpanngfw.VnetConfiguration{ + IPOfTrustSubnetForUdr: &armpanngfw.IPAddress{ + Address: to.Ptr("10.1.1.0/24"), + ResourceID: to.Ptr("/subscriptions/2bf4a339-294d-4c25-b0b2-ef649e9f5c27/resourceGroups/os-liftr-integration/providers/Microsoft.Network/virtualNetworks/os-liftr-integration-vnet/subnets/os-liftr-integration-untrust-subnet"), + }, + TrustSubnet: &armpanngfw.IPAddressSpace{ + AddressSpace: to.Ptr("10.1.1.0/24"), + ResourceID: to.Ptr("/subscriptions/2bf4a339-294d-4c25-b0b2-ef649e9f5c27/resourceGroups/os-liftr-integration/providers/Microsoft.Network/virtualNetworks/os-liftr-integration-vnet/subnets/os-liftr-integration-trust-subnet"), + }, + UnTrustSubnet: &armpanngfw.IPAddressSpace{ + AddressSpace: to.Ptr("10.1.1.0/24"), + ResourceID: to.Ptr("/subscriptions/2bf4a339-294d-4c25-b0b2-ef649e9f5c27/resourceGroups/os-liftr-integration/providers/Microsoft.Network/virtualNetworks/os-liftr-integration-vnet/subnets/os-liftr-integration-untrust-subnet"), + }, + Vnet: &armpanngfw.IPAddressSpace{ + AddressSpace: to.Ptr("10.1.0.0/16"), + ResourceID: to.Ptr("/subscriptions/2bf4a339-294d-4c25-b0b2-ef649e9f5c27/resourceGroups/os-liftr-integration/providers/Microsoft.Network/virtualNetworks/os-liftr-integration-vnet"), + }, + }, + VwanConfiguration: &armpanngfw.VwanConfiguration{ + IPOfTrustSubnetForUdr: &armpanngfw.IPAddress{ + Address: to.Ptr("10.1.1.0/24"), + ResourceID: to.Ptr("/subscriptions/2bf4a339-294d-4c25-b0b2-ef649e9f5c27/resourceGroups/os-liftr-integration/providers/Microsoft.Network/virtualNetworks/os-liftr-integration-vnet/subnets/os-liftr-integration-untrust-subnet"), + }, + NetworkVirtualApplianceID: to.Ptr("2bf4a339-294d-4c25-b0b2-ef649e9f5c12"), + TrustSubnet: &armpanngfw.IPAddressSpace{ + AddressSpace: to.Ptr("10.1.1.0/24"), + ResourceID: to.Ptr("/subscriptions/2bf4a339-294d-4c25-b0b2-ef649e9f5c27/resourceGroups/os-liftr-integration/providers/Microsoft.Network/virtualNetworks/os-liftr-integration-vnet/subnets/os-liftr-integration-trust-subnet"), + }, + UnTrustSubnet: &armpanngfw.IPAddressSpace{ + AddressSpace: to.Ptr("10.1.1.0/24"), + ResourceID: to.Ptr("/subscriptions/2bf4a339-294d-4c25-b0b2-ef649e9f5c27/resourceGroups/os-liftr-integration/providers/Microsoft.Network/virtualNetworks/os-liftr-integration-vnet/subnets/os-liftr-integration-untrust-subnet"), + }, + VHub: &armpanngfw.IPAddressSpace{ + AddressSpace: to.Ptr("10.1.1.0/24"), + ResourceID: to.Ptr("/subscriptions/2bf4a339-294d-4c25-b0b2-ef649e9f5c27/resourceGroups/os-liftr-integration/providers/Microsoft.Network/virtualNetworks/os-liftr-integration-vnet/subnets/os-liftr-integration-untrust-subnet"), + }, + }, + }, + PanEtag: to.Ptr("2bf4a339-294d-4c25-b0b2-ef649e9f5c12"), + PanoramaConfig: &armpanngfw.PanoramaConfig{ + ConfigString: to.Ptr("bas64EncodedString"), + }, + PlanData: &armpanngfw.PlanData{ + BillingCycle: to.Ptr(armpanngfw.BillingCycleWEEKLY), + PlanID: to.Ptr("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"), + UsageType: to.Ptr(armpanngfw.UsageTypePAYG), + }, + }, + Tags: map[string]*string{ + "tagName": to.Ptr("value"), + }, + }, nil) + if err != nil { + log.Fatalf("failed to finish the request: %v", err) + } + // You could use response here. We use blank identifier for just demo purposes. + _ = res + // If the HTTP response code is 200 as defined in example definition, your response structure would look as follows. Please pay attention that all the values in the output are fake values for just demo purposes. + // res.FirewallResource = armpanngfw.FirewallResource{ + // Name: to.Ptr("aaaaaaaaaaaaa"), + // Type: to.Ptr("aaaaaa"), + // ID: to.Ptr("aaaaaaaaaaaaaaaaaaaaaaaa"), + // SystemData: &armpanngfw.SystemData{ + // CreatedAt: to.Ptr(func() time.Time { t, _ := time.Parse(time.RFC3339Nano, "2022-09-09T05:08:24.229Z"); return t}()), + // CreatedBy: to.Ptr("praval"), + // CreatedByType: to.Ptr(armpanngfw.CreatedByTypeUser), + // LastModifiedAt: to.Ptr(func() time.Time { t, _ := time.Parse(time.RFC3339Nano, "2022-09-09T05:08:24.229Z"); return t}()), + // LastModifiedBy: to.Ptr("praval"), + // LastModifiedByType: to.Ptr(armpanngfw.CreatedByTypeUser), + // }, + // Location: to.Ptr("eastus"), + // Tags: map[string]*string{ + // "tagName": to.Ptr("value"), + // }, + // Identity: &armpanngfw.AzureResourceManagerManagedIdentityProperties{ + // Type: to.Ptr(armpanngfw.ManagedIdentityTypeNone), + // PrincipalID: to.Ptr("aaaaaaaaaaaaaaaaaaaaaaaaaa"), + // TenantID: to.Ptr("aaaaaaaaaaaaaaaaaaaaaaaaaaaa"), + // UserAssignedIdentities: map[string]*armpanngfw.AzureResourceManagerUserAssignedIdentity{ + // "key16": &armpanngfw.AzureResourceManagerUserAssignedIdentity{ + // ClientID: to.Ptr("aaaa"), + // PrincipalID: to.Ptr("aaaaaaaaaaaaaaa"), + // }, + // }, + // }, + // Properties: &armpanngfw.FirewallDeploymentProperties{ + // AssociatedRulestack: &armpanngfw.RulestackDetails{ + // Location: to.Ptr("eastus"), + // ResourceID: to.Ptr("aaaaaaaaaa"), + // RulestackID: to.Ptr("aaaaaaaaaaaaaaaa"), + // }, + // DNSSettings: &armpanngfw.DNSSettings{ + // DNSServers: []*armpanngfw.IPAddress{ + // { + // Address: to.Ptr("20.22.92.111"), + // ResourceID: to.Ptr("/subscriptions/01c7d41f-afaf-464e-8a8b-5c6f9f98cee8/resourceGroups/mj-liftr-integration/providers/Microsoft.Network/publicIPAddresses/mj-liftr-integration-egressNatIp1"), + // }}, + // EnableDNSProxy: to.Ptr(armpanngfw.DNSProxyDISABLED), + // EnabledDNSType: to.Ptr(armpanngfw.EnabledDNSTypeCUSTOM), + // }, + // FrontEndSettings: []*armpanngfw.FrontendSetting{ + // { + // Name: to.Ptr("frontendsetting11"), + // BackendConfiguration: &armpanngfw.EndpointConfiguration{ + // Address: &armpanngfw.IPAddress{ + // Address: to.Ptr("20.22.32.136"), + // ResourceID: to.Ptr("/subscriptions/01c7d41f-afaf-464e-8a8b-5c6f9f98cee8/resourceGroups/mj-liftr-integration/providers/Microsoft.Network/publicIPAddresses/mj-liftr-integration-frontendSettingIp2"), + // }, + // Port: to.Ptr("80"), + // }, + // FrontendConfiguration: &armpanngfw.EndpointConfiguration{ + // Address: &armpanngfw.IPAddress{ + // Address: to.Ptr("20.22.91.251"), + // ResourceID: to.Ptr("/subscriptions/01c7d41f-afaf-464e-8a8b-5c6f9f98cee8/resourceGroups/mj-liftr-integration/providers/Microsoft.Network/publicIPAddresses/mj-liftr-integration-frontendSettingIp1"), + // }, + // Port: to.Ptr("80"), + // }, + // Protocol: to.Ptr(armpanngfw.ProtocolTypeTCP), + // }}, + // IsPanoramaManaged: to.Ptr(armpanngfw.BooleanEnumTRUE), + // MarketplaceDetails: &armpanngfw.MarketplaceDetails{ + // MarketplaceSubscriptionID: to.Ptr("aa"), + // MarketplaceSubscriptionStatus: to.Ptr(armpanngfw.MarketplaceSubscriptionStatusPendingFulfillmentStart), + // OfferID: to.Ptr("aaaaaaaaaaaaaaaaaaaaaaaaaaaaa"), + // PublisherID: to.Ptr("aaaa"), + // }, + // NetworkProfile: &armpanngfw.NetworkProfile{ + // EgressNatIP: []*armpanngfw.IPAddress{ + // { + // Address: to.Ptr("20.22.92.111"), + // ResourceID: to.Ptr("/subscriptions/01c7d41f-afaf-464e-8a8b-5c6f9f98cee8/resourceGroups/mj-liftr-integration/providers/Microsoft.Network/publicIPAddresses/mj-liftr-integration-egressNatIp1"), + // }}, + // EnableEgressNat: to.Ptr(armpanngfw.EgressNatENABLED), + // NetworkType: to.Ptr(armpanngfw.NetworkTypeVNET), + // PublicIPs: []*armpanngfw.IPAddress{ + // { + // Address: to.Ptr("20.22.92.11"), + // ResourceID: to.Ptr("/subscriptions/01c7d41f-afaf-464e-8a8b-5c6f9f98cee8/resourceGroups/mj-liftr-integration/providers/Microsoft.Network/publicIPAddresses/mj-liftr-integration-PublicIp1"), + // }}, + // VnetConfiguration: &armpanngfw.VnetConfiguration{ + // IPOfTrustSubnetForUdr: &armpanngfw.IPAddress{ + // Address: to.Ptr("10.1.1.0/24"), + // ResourceID: to.Ptr("/subscriptions/2bf4a339-294d-4c25-b0b2-ef649e9f5c27/resourceGroups/os-liftr-integration/providers/Microsoft.Network/virtualNetworks/os-liftr-integration-vnet/subnets/os-liftr-integration-untrust-subnet"), + // }, + // TrustSubnet: &armpanngfw.IPAddressSpace{ + // AddressSpace: to.Ptr("10.1.1.0/24"), + // ResourceID: to.Ptr("/subscriptions/2bf4a339-294d-4c25-b0b2-ef649e9f5c27/resourceGroups/os-liftr-integration/providers/Microsoft.Network/virtualNetworks/os-liftr-integration-vnet/subnets/os-liftr-integration-trust-subnet"), + // }, + // UnTrustSubnet: &armpanngfw.IPAddressSpace{ + // AddressSpace: to.Ptr("10.1.1.0/24"), + // ResourceID: to.Ptr("/subscriptions/2bf4a339-294d-4c25-b0b2-ef649e9f5c27/resourceGroups/os-liftr-integration/providers/Microsoft.Network/virtualNetworks/os-liftr-integration-vnet/subnets/os-liftr-integration-untrust-subnet"), + // }, + // Vnet: &armpanngfw.IPAddressSpace{ + // AddressSpace: to.Ptr("10.1.0.0/16"), + // ResourceID: to.Ptr("/subscriptions/2bf4a339-294d-4c25-b0b2-ef649e9f5c27/resourceGroups/os-liftr-integration/providers/Microsoft.Network/virtualNetworks/os-liftr-integration-vnet"), + // }, + // }, + // VwanConfiguration: &armpanngfw.VwanConfiguration{ + // IPOfTrustSubnetForUdr: &armpanngfw.IPAddress{ + // Address: to.Ptr("10.1.1.0/24"), + // ResourceID: to.Ptr("/subscriptions/2bf4a339-294d-4c25-b0b2-ef649e9f5c27/resourceGroups/os-liftr-integration/providers/Microsoft.Network/virtualNetworks/os-liftr-integration-vnet/subnets/os-liftr-integration-untrust-subnet"), + // }, + // NetworkVirtualApplianceID: to.Ptr("2bf4a339-294d-4c25-b0b2-ef649e9f5c12"), + // TrustSubnet: &armpanngfw.IPAddressSpace{ + // AddressSpace: to.Ptr("10.1.1.0/24"), + // ResourceID: to.Ptr("/subscriptions/2bf4a339-294d-4c25-b0b2-ef649e9f5c27/resourceGroups/os-liftr-integration/providers/Microsoft.Network/virtualNetworks/os-liftr-integration-vnet/subnets/os-liftr-integration-trust-subnet"), + // }, + // UnTrustSubnet: &armpanngfw.IPAddressSpace{ + // AddressSpace: to.Ptr("10.1.1.0/24"), + // ResourceID: to.Ptr("/subscriptions/2bf4a339-294d-4c25-b0b2-ef649e9f5c27/resourceGroups/os-liftr-integration/providers/Microsoft.Network/virtualNetworks/os-liftr-integration-vnet/subnets/os-liftr-integration-untrust-subnet"), + // }, + // VHub: &armpanngfw.IPAddressSpace{ + // AddressSpace: to.Ptr("10.1.1.0/24"), + // ResourceID: to.Ptr("/subscriptions/2bf4a339-294d-4c25-b0b2-ef649e9f5c27/resourceGroups/os-liftr-integration/providers/Microsoft.Network/virtualNetworks/os-liftr-integration-vnet/subnets/os-liftr-integration-untrust-subnet"), + // }, + // }, + // }, + // PanEtag: to.Ptr("2bf4a339-294d-4c25-b0b2-ef649e9f5c12"), + // PanoramaConfig: &armpanngfw.PanoramaConfig{ + // CgName: to.Ptr("PanoramaCollectorGroup"), + // ConfigString: to.Ptr("bas64EncodedString"), + // DgName: to.Ptr("PanoramaDeviceGroup"), + // HostName: to.Ptr("hostname"), + // PanoramaServer: to.Ptr("10.25.1.1"), + // PanoramaServer2: to.Ptr("10.20.1.1"), + // TplName: to.Ptr("PanoramaTemplateStack"), + // VMAuthKey: to.Ptr("SSH_AUTH_KEY"), + // }, + // PlanData: &armpanngfw.PlanData{ + // BillingCycle: to.Ptr(armpanngfw.BillingCycleWEEKLY), + // EffectiveDate: to.Ptr(func() time.Time { t, _ := time.Parse(time.RFC3339Nano, "2022-09-13T00:46:05.283Z"); return t}()), + // PlanID: to.Ptr("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"), + // UsageType: to.Ptr(armpanngfw.UsageTypePAYG), + // }, + // ProvisioningState: to.Ptr(armpanngfw.ProvisioningStateSucceeded), + // }, + // } +} + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/Firewalls_Update_MinimumSet_Gen.json +func ExampleFirewallsClient_Update_firewallsUpdateMinimumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + res, err := clientFactory.NewFirewallsClient().Update(ctx, "firewall-rg", "firewall1", armpanngfw.FirewallResourceUpdate{}, nil) + if err != nil { + log.Fatalf("failed to finish the request: %v", err) + } + // You could use response here. We use blank identifier for just demo purposes. + _ = res + // If the HTTP response code is 200 as defined in example definition, your response structure would look as follows. Please pay attention that all the values in the output are fake values for just demo purposes. + // res.FirewallResource = armpanngfw.FirewallResource{ + // Location: to.Ptr("eastus"), + // Properties: &armpanngfw.FirewallDeploymentProperties{ + // DNSSettings: &armpanngfw.DNSSettings{ + // }, + // MarketplaceDetails: &armpanngfw.MarketplaceDetails{ + // OfferID: to.Ptr("aaaaaaaaaaaaaaaaaaaaaaaaaaaaa"), + // PublisherID: to.Ptr("aaaa"), + // }, + // NetworkProfile: &armpanngfw.NetworkProfile{ + // EnableEgressNat: to.Ptr(armpanngfw.EgressNatENABLED), + // NetworkType: to.Ptr(armpanngfw.NetworkTypeVNET), + // PublicIPs: []*armpanngfw.IPAddress{ + // { + // Address: to.Ptr("20.22.92.11"), + // ResourceID: to.Ptr("/subscriptions/01c7d41f-afaf-464e-8a8b-5c6f9f98cee8/resourceGroups/mj-liftr-integration/providers/Microsoft.Network/publicIPAddresses/mj-liftr-integration-PublicIp1"), + // }}, + // }, + // PlanData: &armpanngfw.PlanData{ + // BillingCycle: to.Ptr(armpanngfw.BillingCycleWEEKLY), + // PlanID: to.Ptr("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"), + // }, + // }, + // } +} + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/Firewalls_Delete_MaximumSet_Gen.json +func ExampleFirewallsClient_BeginDelete_firewallsDeleteMaximumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + poller, err := clientFactory.NewFirewallsClient().BeginDelete(ctx, "firewall-rg", "firewall1", nil) + if err != nil { + log.Fatalf("failed to finish the request: %v", err) + } + _, err = poller.PollUntilDone(ctx, nil) + if err != nil { + log.Fatalf("failed to pull the result: %v", err) + } +} + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/Firewalls_Delete_MinimumSet_Gen.json +func ExampleFirewallsClient_BeginDelete_firewallsDeleteMinimumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + poller, err := clientFactory.NewFirewallsClient().BeginDelete(ctx, "firewall-rg", "firewall1", nil) + if err != nil { + log.Fatalf("failed to finish the request: %v", err) + } + _, err = poller.PollUntilDone(ctx, nil) + if err != nil { + log.Fatalf("failed to pull the result: %v", err) + } +} + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/Firewalls_getGlobalRulestack_MaximumSet_Gen.json +func ExampleFirewallsClient_GetGlobalRulestack_firewallsGetGlobalRulestackMaximumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + res, err := clientFactory.NewFirewallsClient().GetGlobalRulestack(ctx, "firewall-rg", "firewall1", nil) + if err != nil { + log.Fatalf("failed to finish the request: %v", err) + } + // You could use response here. We use blank identifier for just demo purposes. + _ = res + // If the HTTP response code is 200 as defined in example definition, your response structure would look as follows. Please pay attention that all the values in the output are fake values for just demo purposes. + // res.GlobalRulestackInfo = armpanngfw.GlobalRulestackInfo{ + // AzureID: to.Ptr("aaaaaaaaaa"), + // } +} + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/Firewalls_getGlobalRulestack_MinimumSet_Gen.json +func ExampleFirewallsClient_GetGlobalRulestack_firewallsGetGlobalRulestackMinimumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + res, err := clientFactory.NewFirewallsClient().GetGlobalRulestack(ctx, "firewall-rg", "firewall1", nil) + if err != nil { + log.Fatalf("failed to finish the request: %v", err) + } + // You could use response here. We use blank identifier for just demo purposes. + _ = res + // If the HTTP response code is 200 as defined in example definition, your response structure would look as follows. Please pay attention that all the values in the output are fake values for just demo purposes. + // res.GlobalRulestackInfo = armpanngfw.GlobalRulestackInfo{ + // AzureID: to.Ptr("aaaaaaaaaa"), + // } +} + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/Firewalls_getLogProfile_MaximumSet_Gen.json +func ExampleFirewallsClient_GetLogProfile_firewallsGetLogProfileMaximumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + res, err := clientFactory.NewFirewallsClient().GetLogProfile(ctx, "firewall-rg", "firewall1", nil) + if err != nil { + log.Fatalf("failed to finish the request: %v", err) + } + // You could use response here. We use blank identifier for just demo purposes. + _ = res + // If the HTTP response code is 200 as defined in example definition, your response structure would look as follows. Please pay attention that all the values in the output are fake values for just demo purposes. + // res.LogSettings = armpanngfw.LogSettings{ + // ApplicationInsights: &armpanngfw.ApplicationInsights{ + // ID: to.Ptr("aaaaaaaaaaaaaaaa"), + // Key: to.Ptr("aaaaaaaaaaaaa"), + // }, + // CommonDestination: &armpanngfw.LogDestination{ + // EventHubConfigurations: &armpanngfw.EventHub{ + // Name: to.Ptr("aaaaaaaa"), + // ID: to.Ptr("aaaaaaaaaa"), + // NameSpace: to.Ptr("aaaaaaaaaaaaaaaaaaaaa"), + // PolicyName: to.Ptr("aaaaaaaaaaaa"), + // SubscriptionID: to.Ptr("aaaaaaaaaa"), + // }, + // MonitorConfigurations: &armpanngfw.MonitorLog{ + // ID: to.Ptr("aaaaaaaaaaaaaaaaaaa"), + // PrimaryKey: to.Ptr("aaaaaaaaaaaaa"), + // SecondaryKey: to.Ptr("a"), + // SubscriptionID: to.Ptr("aaaaaaaaaaaaa"), + // Workspace: to.Ptr("aaaaaaaaaaa"), + // }, + // StorageConfigurations: &armpanngfw.StorageAccount{ + // AccountName: to.Ptr("aaaaaaaaaaaaaaaaaaaaaaa"), + // ID: to.Ptr("aaaaaaaaaaaaaaa"), + // SubscriptionID: to.Ptr("aaaaaaaaa"), + // }, + // }, + // DecryptLogDestination: &armpanngfw.LogDestination{ + // EventHubConfigurations: &armpanngfw.EventHub{ + // Name: to.Ptr("aaaaaaaa"), + // ID: to.Ptr("aaaaaaaaaa"), + // NameSpace: to.Ptr("aaaaaaaaaaaaaaaaaaaaa"), + // PolicyName: to.Ptr("aaaaaaaaaaaa"), + // SubscriptionID: to.Ptr("aaaaaaaaaa"), + // }, + // MonitorConfigurations: &armpanngfw.MonitorLog{ + // ID: to.Ptr("aaaaaaaaaaaaaaaaaaa"), + // PrimaryKey: to.Ptr("aaaaaaaaaaaaa"), + // SecondaryKey: to.Ptr("a"), + // SubscriptionID: to.Ptr("aaaaaaaaaaaaa"), + // Workspace: to.Ptr("aaaaaaaaaaa"), + // }, + // StorageConfigurations: &armpanngfw.StorageAccount{ + // AccountName: to.Ptr("aaaaaaaaaaaaaaaaaaaaaaa"), + // ID: to.Ptr("aaaaaaaaaaaaaaa"), + // SubscriptionID: to.Ptr("aaaaaaaaa"), + // }, + // }, + // LogOption: to.Ptr(armpanngfw.LogOptionSAMEDESTINATION), + // LogType: to.Ptr(armpanngfw.LogTypeTRAFFIC), + // ThreatLogDestination: &armpanngfw.LogDestination{ + // EventHubConfigurations: &armpanngfw.EventHub{ + // Name: to.Ptr("aaaaaaaa"), + // ID: to.Ptr("aaaaaaaaaa"), + // NameSpace: to.Ptr("aaaaaaaaaaaaaaaaaaaaa"), + // PolicyName: to.Ptr("aaaaaaaaaaaa"), + // SubscriptionID: to.Ptr("aaaaaaaaaa"), + // }, + // MonitorConfigurations: &armpanngfw.MonitorLog{ + // ID: to.Ptr("aaaaaaaaaaaaaaaaaaa"), + // PrimaryKey: to.Ptr("aaaaaaaaaaaaa"), + // SecondaryKey: to.Ptr("a"), + // SubscriptionID: to.Ptr("aaaaaaaaaaaaa"), + // Workspace: to.Ptr("aaaaaaaaaaa"), + // }, + // StorageConfigurations: &armpanngfw.StorageAccount{ + // AccountName: to.Ptr("aaaaaaaaaaaaaaaaaaaaaaa"), + // ID: to.Ptr("aaaaaaaaaaaaaaa"), + // SubscriptionID: to.Ptr("aaaaaaaaa"), + // }, + // }, + // TrafficLogDestination: &armpanngfw.LogDestination{ + // EventHubConfigurations: &armpanngfw.EventHub{ + // Name: to.Ptr("aaaaaaaa"), + // ID: to.Ptr("aaaaaaaaaa"), + // NameSpace: to.Ptr("aaaaaaaaaaaaaaaaaaaaa"), + // PolicyName: to.Ptr("aaaaaaaaaaaa"), + // SubscriptionID: to.Ptr("aaaaaaaaaa"), + // }, + // MonitorConfigurations: &armpanngfw.MonitorLog{ + // ID: to.Ptr("aaaaaaaaaaaaaaaaaaa"), + // PrimaryKey: to.Ptr("aaaaaaaaaaaaa"), + // SecondaryKey: to.Ptr("a"), + // SubscriptionID: to.Ptr("aaaaaaaaaaaaa"), + // Workspace: to.Ptr("aaaaaaaaaaa"), + // }, + // StorageConfigurations: &armpanngfw.StorageAccount{ + // AccountName: to.Ptr("aaaaaaaaaaaaaaaaaaaaaaa"), + // ID: to.Ptr("aaaaaaaaaaaaaaa"), + // SubscriptionID: to.Ptr("aaaaaaaaa"), + // }, + // }, + // } +} + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/Firewalls_getLogProfile_MinimumSet_Gen.json +func ExampleFirewallsClient_GetLogProfile_firewallsGetLogProfileMinimumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + res, err := clientFactory.NewFirewallsClient().GetLogProfile(ctx, "firewall-rg", "firewall1", nil) + if err != nil { + log.Fatalf("failed to finish the request: %v", err) + } + // You could use response here. We use blank identifier for just demo purposes. + _ = res + // If the HTTP response code is 200 as defined in example definition, your response structure would look as follows. Please pay attention that all the values in the output are fake values for just demo purposes. + // res.LogSettings = armpanngfw.LogSettings{ + // } +} + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/Firewalls_getSupportInfo_MaximumSet_Gen.json +func ExampleFirewallsClient_GetSupportInfo_firewallsGetSupportInfoMaximumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + res, err := clientFactory.NewFirewallsClient().GetSupportInfo(ctx, "rgopenapi", "firewall1", &armpanngfw.FirewallsClientGetSupportInfoOptions{Email: to.Ptr("user1@domain.com")}) + if err != nil { + log.Fatalf("failed to finish the request: %v", err) + } + // You could use response here. We use blank identifier for just demo purposes. + _ = res + // If the HTTP response code is 200 as defined in example definition, your response structure would look as follows. Please pay attention that all the values in the output are fake values for just demo purposes. + // res.SupportInfo = armpanngfw.SupportInfo{ + // AccountID: to.Ptr("3cg5b439-294d-4c25-b0b2-ef649e0g6d38"), + // AccountRegistered: to.Ptr(armpanngfw.BooleanEnumTRUE), + // FreeTrial: to.Ptr(armpanngfw.BooleanEnumTRUE), + // FreeTrialCreditLeft: to.Ptr[int32](10), + // FreeTrialDaysLeft: to.Ptr[int32](1), + // HelpURL: to.Ptr("https://ssopreview.paloaltonetworks.com/home/bookmark/0oa4ao61shG4rd3Ub1d7/2557"), + // ProductSerial: to.Ptr("e22715cb-7e4e-4814-ad4f-ccd1417755d7"), + // ProductSKU: to.Ptr("62f63e3c-bc5a-4d68-a8a1-fcba9f526c90"), + // RegisterURL: to.Ptr("https://ssopreview.paloaltonetworks.com/home/bookmark/0oa4ao61shG4rd3Ub1d7/2557"), + // SupportURL: to.Ptr("https://ssopreview.paloaltonetworks.com/home/bookmark/0oa4ao61shG4rd3Ub1d7/2557"), + // UserDomainSupported: to.Ptr(armpanngfw.BooleanEnumTRUE), + // UserRegistered: to.Ptr(armpanngfw.BooleanEnumTRUE), + // } +} + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/Firewalls_getSupportInfo_MinimumSet_Gen.json +func ExampleFirewallsClient_GetSupportInfo_firewallsGetSupportInfoMinimumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + res, err := clientFactory.NewFirewallsClient().GetSupportInfo(ctx, "rgopenapi", "firewall1", &armpanngfw.FirewallsClientGetSupportInfoOptions{Email: nil}) + if err != nil { + log.Fatalf("failed to finish the request: %v", err) + } + // You could use response here. We use blank identifier for just demo purposes. + _ = res + // If the HTTP response code is 200 as defined in example definition, your response structure would look as follows. Please pay attention that all the values in the output are fake values for just demo purposes. + // res.SupportInfo = armpanngfw.SupportInfo{ + // } +} + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/Firewalls_saveLogProfile_MaximumSet_Gen.json +func ExampleFirewallsClient_SaveLogProfile_firewallsSaveLogProfileMaximumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + _, err = clientFactory.NewFirewallsClient().SaveLogProfile(ctx, "firewall-rg", "firewall1", &armpanngfw.FirewallsClientSaveLogProfileOptions{LogSettings: &armpanngfw.LogSettings{ + ApplicationInsights: &armpanngfw.ApplicationInsights{ + ID: to.Ptr("aaaaaaaaaaaaaaaa"), + Key: to.Ptr("aaaaaaaaaaaaa"), + }, + CommonDestination: &armpanngfw.LogDestination{ + EventHubConfigurations: &armpanngfw.EventHub{ + Name: to.Ptr("aaaaaaaa"), + ID: to.Ptr("aaaaaaaaaa"), + NameSpace: to.Ptr("aaaaaaaaaaaaaaaaaaaaa"), + PolicyName: to.Ptr("aaaaaaaaaaaa"), + SubscriptionID: to.Ptr("aaaaaaaaaa"), + }, + MonitorConfigurations: &armpanngfw.MonitorLog{ + ID: to.Ptr("aaaaaaaaaaaaaaaaaaa"), + PrimaryKey: to.Ptr("aaaaaaaaaaaaa"), + SecondaryKey: to.Ptr("a"), + SubscriptionID: to.Ptr("aaaaaaaaaaaaa"), + Workspace: to.Ptr("aaaaaaaaaaa"), + }, + StorageConfigurations: &armpanngfw.StorageAccount{ + AccountName: to.Ptr("aaaaaaaaaaaaaaaaaaaaaaa"), + ID: to.Ptr("aaaaaaaaaaaaaaa"), + SubscriptionID: to.Ptr("aaaaaaaaa"), + }, + }, + DecryptLogDestination: &armpanngfw.LogDestination{ + EventHubConfigurations: &armpanngfw.EventHub{ + Name: to.Ptr("aaaaaaaa"), + ID: to.Ptr("aaaaaaaaaa"), + NameSpace: to.Ptr("aaaaaaaaaaaaaaaaaaaaa"), + PolicyName: to.Ptr("aaaaaaaaaaaa"), + SubscriptionID: to.Ptr("aaaaaaaaaa"), + }, + MonitorConfigurations: &armpanngfw.MonitorLog{ + ID: to.Ptr("aaaaaaaaaaaaaaaaaaa"), + PrimaryKey: to.Ptr("aaaaaaaaaaaaa"), + SecondaryKey: to.Ptr("a"), + SubscriptionID: to.Ptr("aaaaaaaaaaaaa"), + Workspace: to.Ptr("aaaaaaaaaaa"), + }, + StorageConfigurations: &armpanngfw.StorageAccount{ + AccountName: to.Ptr("aaaaaaaaaaaaaaaaaaaaaaa"), + ID: to.Ptr("aaaaaaaaaaaaaaa"), + SubscriptionID: to.Ptr("aaaaaaaaa"), + }, + }, + LogOption: to.Ptr(armpanngfw.LogOptionSAMEDESTINATION), + LogType: to.Ptr(armpanngfw.LogTypeTRAFFIC), + ThreatLogDestination: &armpanngfw.LogDestination{ + EventHubConfigurations: &armpanngfw.EventHub{ + Name: to.Ptr("aaaaaaaa"), + ID: to.Ptr("aaaaaaaaaa"), + NameSpace: to.Ptr("aaaaaaaaaaaaaaaaaaaaa"), + PolicyName: to.Ptr("aaaaaaaaaaaa"), + SubscriptionID: to.Ptr("aaaaaaaaaa"), + }, + MonitorConfigurations: &armpanngfw.MonitorLog{ + ID: to.Ptr("aaaaaaaaaaaaaaaaaaa"), + PrimaryKey: to.Ptr("aaaaaaaaaaaaa"), + SecondaryKey: to.Ptr("a"), + SubscriptionID: to.Ptr("aaaaaaaaaaaaa"), + Workspace: to.Ptr("aaaaaaaaaaa"), + }, + StorageConfigurations: &armpanngfw.StorageAccount{ + AccountName: to.Ptr("aaaaaaaaaaaaaaaaaaaaaaa"), + ID: to.Ptr("aaaaaaaaaaaaaaa"), + SubscriptionID: to.Ptr("aaaaaaaaa"), + }, + }, + TrafficLogDestination: &armpanngfw.LogDestination{ + EventHubConfigurations: &armpanngfw.EventHub{ + Name: to.Ptr("aaaaaaaa"), + ID: to.Ptr("aaaaaaaaaa"), + NameSpace: to.Ptr("aaaaaaaaaaaaaaaaaaaaa"), + PolicyName: to.Ptr("aaaaaaaaaaaa"), + SubscriptionID: to.Ptr("aaaaaaaaaa"), + }, + MonitorConfigurations: &armpanngfw.MonitorLog{ + ID: to.Ptr("aaaaaaaaaaaaaaaaaaa"), + PrimaryKey: to.Ptr("aaaaaaaaaaaaa"), + SecondaryKey: to.Ptr("a"), + SubscriptionID: to.Ptr("aaaaaaaaaaaaa"), + Workspace: to.Ptr("aaaaaaaaaaa"), + }, + StorageConfigurations: &armpanngfw.StorageAccount{ + AccountName: to.Ptr("aaaaaaaaaaaaaaaaaaaaaaa"), + ID: to.Ptr("aaaaaaaaaaaaaaa"), + SubscriptionID: to.Ptr("aaaaaaaaa"), + }, + }, + }, + }) + if err != nil { + log.Fatalf("failed to finish the request: %v", err) + } +} + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/Firewalls_saveLogProfile_MinimumSet_Gen.json +func ExampleFirewallsClient_SaveLogProfile_firewallsSaveLogProfileMinimumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + _, err = clientFactory.NewFirewallsClient().SaveLogProfile(ctx, "firewall-rg", "firewall1", &armpanngfw.FirewallsClientSaveLogProfileOptions{LogSettings: nil}) + if err != nil { + log.Fatalf("failed to finish the request: %v", err) + } +} diff --git a/sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/firewallstatus_client.go b/sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/firewallstatus_client.go new file mode 100644 index 000000000000..a0ec2d96d03f --- /dev/null +++ b/sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/firewallstatus_client.go @@ -0,0 +1,172 @@ +//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. +// Code generated by Microsoft (R) AutoRest Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. +// DO NOT EDIT. + +package armpanngfw + +import ( + "context" + "errors" + "github.com/Azure/azure-sdk-for-go/sdk/azcore" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/arm" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/policy" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime" + "net/http" + "net/url" + "strings" +) + +// FirewallStatusClient contains the methods for the FirewallStatus group. +// Don't use this type directly, use NewFirewallStatusClient() instead. +type FirewallStatusClient struct { + internal *arm.Client + subscriptionID string +} + +// NewFirewallStatusClient creates a new instance of FirewallStatusClient with the specified values. +// - subscriptionID - The ID of the target subscription. +// - credential - used to authorize requests. Usually a credential from azidentity. +// - options - pass nil to accept the default values. +func NewFirewallStatusClient(subscriptionID string, credential azcore.TokenCredential, options *arm.ClientOptions) (*FirewallStatusClient, error) { + cl, err := arm.NewClient(moduleName+".FirewallStatusClient", moduleVersion, credential, options) + if err != nil { + return nil, err + } + client := &FirewallStatusClient{ + subscriptionID: subscriptionID, + internal: cl, + } + return client, nil +} + +// Get - Get a FirewallStatusResource +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2022-08-29-preview +// - resourceGroupName - The name of the resource group. The name is case insensitive. +// - firewallName - Firewall resource name +// - options - FirewallStatusClientGetOptions contains the optional parameters for the FirewallStatusClient.Get method. +func (client *FirewallStatusClient) Get(ctx context.Context, resourceGroupName string, firewallName string, options *FirewallStatusClientGetOptions) (FirewallStatusClientGetResponse, error) { + req, err := client.getCreateRequest(ctx, resourceGroupName, firewallName, options) + if err != nil { + return FirewallStatusClientGetResponse{}, err + } + resp, err := client.internal.Pipeline().Do(req) + if err != nil { + return FirewallStatusClientGetResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusOK) { + return FirewallStatusClientGetResponse{}, runtime.NewResponseError(resp) + } + return client.getHandleResponse(resp) +} + +// getCreateRequest creates the Get request. +func (client *FirewallStatusClient) getCreateRequest(ctx context.Context, resourceGroupName string, firewallName string, options *FirewallStatusClientGetOptions) (*policy.Request, error) { + urlPath := "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/PaloAltoNetworks.Cloudngfw/firewalls/{firewallName}/statuses/default" + if client.subscriptionID == "" { + return nil, errors.New("parameter client.subscriptionID cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{subscriptionId}", url.PathEscape(client.subscriptionID)) + if resourceGroupName == "" { + return nil, errors.New("parameter resourceGroupName cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{resourceGroupName}", url.PathEscape(resourceGroupName)) + if firewallName == "" { + return nil, errors.New("parameter firewallName cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{firewallName}", url.PathEscape(firewallName)) + req, err := runtime.NewRequest(ctx, http.MethodGet, runtime.JoinPaths(client.internal.Endpoint(), urlPath)) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("api-version", "2022-08-29-preview") + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["Accept"] = []string{"application/json"} + return req, nil +} + +// getHandleResponse handles the Get response. +func (client *FirewallStatusClient) getHandleResponse(resp *http.Response) (FirewallStatusClientGetResponse, error) { + result := FirewallStatusClientGetResponse{} + if err := runtime.UnmarshalAsJSON(resp, &result.FirewallStatusResource); err != nil { + return FirewallStatusClientGetResponse{}, err + } + return result, nil +} + +// NewListByFirewallsPager - List FirewallStatusResource resources by Firewalls +// +// Generated from API version 2022-08-29-preview +// - resourceGroupName - The name of the resource group. The name is case insensitive. +// - firewallName - Firewall resource name +// - options - FirewallStatusClientListByFirewallsOptions contains the optional parameters for the FirewallStatusClient.NewListByFirewallsPager +// method. +func (client *FirewallStatusClient) NewListByFirewallsPager(resourceGroupName string, firewallName string, options *FirewallStatusClientListByFirewallsOptions) *runtime.Pager[FirewallStatusClientListByFirewallsResponse] { + return runtime.NewPager(runtime.PagingHandler[FirewallStatusClientListByFirewallsResponse]{ + More: func(page FirewallStatusClientListByFirewallsResponse) bool { + return page.NextLink != nil && len(*page.NextLink) > 0 + }, + Fetcher: func(ctx context.Context, page *FirewallStatusClientListByFirewallsResponse) (FirewallStatusClientListByFirewallsResponse, error) { + var req *policy.Request + var err error + if page == nil { + req, err = client.listByFirewallsCreateRequest(ctx, resourceGroupName, firewallName, options) + } else { + req, err = runtime.NewRequest(ctx, http.MethodGet, *page.NextLink) + } + if err != nil { + return FirewallStatusClientListByFirewallsResponse{}, err + } + resp, err := client.internal.Pipeline().Do(req) + if err != nil { + return FirewallStatusClientListByFirewallsResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusOK) { + return FirewallStatusClientListByFirewallsResponse{}, runtime.NewResponseError(resp) + } + return client.listByFirewallsHandleResponse(resp) + }, + }) +} + +// listByFirewallsCreateRequest creates the ListByFirewalls request. +func (client *FirewallStatusClient) listByFirewallsCreateRequest(ctx context.Context, resourceGroupName string, firewallName string, options *FirewallStatusClientListByFirewallsOptions) (*policy.Request, error) { + urlPath := "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/PaloAltoNetworks.Cloudngfw/firewalls/{firewallName}/statuses" + if client.subscriptionID == "" { + return nil, errors.New("parameter client.subscriptionID cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{subscriptionId}", url.PathEscape(client.subscriptionID)) + if resourceGroupName == "" { + return nil, errors.New("parameter resourceGroupName cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{resourceGroupName}", url.PathEscape(resourceGroupName)) + if firewallName == "" { + return nil, errors.New("parameter firewallName cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{firewallName}", url.PathEscape(firewallName)) + req, err := runtime.NewRequest(ctx, http.MethodGet, runtime.JoinPaths(client.internal.Endpoint(), urlPath)) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("api-version", "2022-08-29-preview") + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["Accept"] = []string{"application/json"} + return req, nil +} + +// listByFirewallsHandleResponse handles the ListByFirewalls response. +func (client *FirewallStatusClient) listByFirewallsHandleResponse(resp *http.Response) (FirewallStatusClientListByFirewallsResponse, error) { + result := FirewallStatusClientListByFirewallsResponse{} + if err := runtime.UnmarshalAsJSON(resp, &result.FirewallStatusResourceListResult); err != nil { + return FirewallStatusClientListByFirewallsResponse{}, err + } + return result, nil +} diff --git a/sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/firewallstatus_client_example_test.go b/sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/firewallstatus_client_example_test.go new file mode 100644 index 000000000000..160373e157f3 --- /dev/null +++ b/sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/firewallstatus_client_example_test.go @@ -0,0 +1,170 @@ +//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. +// Code generated by Microsoft (R) AutoRest Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. +// DO NOT EDIT. + +package armpanngfw_test + +import ( + "context" + "log" + + "github.com/Azure/azure-sdk-for-go/sdk/azidentity" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/paloaltonetworksngfw/armpanngfw" +) + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/FirewallStatus_ListByFirewalls_MaximumSet_Gen.json +func ExampleFirewallStatusClient_NewListByFirewallsPager_firewallStatusListByFirewallsMaximumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + pager := clientFactory.NewFirewallStatusClient().NewListByFirewallsPager("rgopenapi", "firewall1", nil) + for pager.More() { + page, err := pager.NextPage(ctx) + if err != nil { + log.Fatalf("failed to advance page: %v", err) + } + for _, v := range page.Value { + // You could use page here. We use blank identifier for just demo purposes. + _ = v + } + // If the HTTP response code is 200 as defined in example definition, your page structure would look as follows. Please pay attention that all the values in the output are fake values for just demo purposes. + // page.FirewallStatusResourceListResult = armpanngfw.FirewallStatusResourceListResult{ + // Value: []*armpanngfw.FirewallStatusResource{ + // { + // Name: to.Ptr("default"), + // Type: to.Ptr("aaaaaaa"), + // ID: to.Ptr("/subscriptions/2bf4a339-294d-4c25-b0b2-ef649e9f5c27/resourcegroups/firewall-rg/providers/PaloAltoNetworks.Cloudngfw/firewalls/firewall1/statuses/default"), + // SystemData: &armpanngfw.SystemData{ + // CreatedAt: to.Ptr(func() time.Time { t, _ := time.Parse(time.RFC3339Nano, "2022-09-09T05:08:24.229Z"); return t}()), + // CreatedBy: to.Ptr("praval"), + // CreatedByType: to.Ptr(armpanngfw.CreatedByTypeUser), + // LastModifiedAt: to.Ptr(func() time.Time { t, _ := time.Parse(time.RFC3339Nano, "2022-09-09T05:08:24.229Z"); return t}()), + // LastModifiedBy: to.Ptr("praval"), + // LastModifiedByType: to.Ptr(armpanngfw.CreatedByTypeUser), + // }, + // Properties: &armpanngfw.FirewallStatusProperty{ + // HealthReason: to.Ptr("aaaaaaaaaaaaaaaaaaaaaaaaaaa"), + // HealthStatus: to.Ptr(armpanngfw.HealthStatusGREEN), + // IsPanoramaManaged: to.Ptr(armpanngfw.BooleanEnumTRUE), + // PanoramaStatus: &armpanngfw.PanoramaStatus{ + // PanoramaServer2Status: to.Ptr(armpanngfw.ServerStatusUP), + // PanoramaServerStatus: to.Ptr(armpanngfw.ServerStatusUP), + // }, + // ProvisioningState: to.Ptr(armpanngfw.ReadOnlyProvisioningStateSucceeded), + // }, + // }}, + // } + } +} + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/FirewallStatus_ListByFirewalls_MinimumSet_Gen.json +func ExampleFirewallStatusClient_NewListByFirewallsPager_firewallStatusListByFirewallsMinimumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + pager := clientFactory.NewFirewallStatusClient().NewListByFirewallsPager("rgopenapi", "firewall1", nil) + for pager.More() { + page, err := pager.NextPage(ctx) + if err != nil { + log.Fatalf("failed to advance page: %v", err) + } + for _, v := range page.Value { + // You could use page here. We use blank identifier for just demo purposes. + _ = v + } + // If the HTTP response code is 200 as defined in example definition, your page structure would look as follows. Please pay attention that all the values in the output are fake values for just demo purposes. + // page.FirewallStatusResourceListResult = armpanngfw.FirewallStatusResourceListResult{ + // Value: []*armpanngfw.FirewallStatusResource{ + // { + // ID: to.Ptr("/subscriptions/2bf4a339-294d-4c25-b0b2-ef649e9f5c27/resourcegroups/firewall-rg/providers/PaloAltoNetworks.Cloudngfw/firewalls/firewall1/statuses/default"), + // Properties: &armpanngfw.FirewallStatusProperty{ + // }, + // }}, + // } + } +} + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/FirewallStatus_Get_MaximumSet_Gen.json +func ExampleFirewallStatusClient_Get_firewallStatusGetMaximumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + res, err := clientFactory.NewFirewallStatusClient().Get(ctx, "rgopenapi", "firewall1", nil) + if err != nil { + log.Fatalf("failed to finish the request: %v", err) + } + // You could use response here. We use blank identifier for just demo purposes. + _ = res + // If the HTTP response code is 200 as defined in example definition, your response structure would look as follows. Please pay attention that all the values in the output are fake values for just demo purposes. + // res.FirewallStatusResource = armpanngfw.FirewallStatusResource{ + // Name: to.Ptr("default"), + // Type: to.Ptr("aaaa"), + // ID: to.Ptr("/subscriptions/2bf4a339-294d-4c25-b0b2-ef649e9f5c27/resourcegroups/firewall-rg/providers/PaloAltoNetworks.Cloudngfw/firewalls/firewall1/statuses/default"), + // SystemData: &armpanngfw.SystemData{ + // CreatedAt: to.Ptr(func() time.Time { t, _ := time.Parse(time.RFC3339Nano, "2022-09-09T05:08:24.229Z"); return t}()), + // CreatedBy: to.Ptr("praval"), + // CreatedByType: to.Ptr(armpanngfw.CreatedByTypeUser), + // LastModifiedAt: to.Ptr(func() time.Time { t, _ := time.Parse(time.RFC3339Nano, "2022-09-09T05:08:24.229Z"); return t}()), + // LastModifiedBy: to.Ptr("praval"), + // LastModifiedByType: to.Ptr(armpanngfw.CreatedByTypeUser), + // }, + // Properties: &armpanngfw.FirewallStatusProperty{ + // HealthReason: to.Ptr("aaaaaaaaaaaa"), + // HealthStatus: to.Ptr(armpanngfw.HealthStatusGREEN), + // IsPanoramaManaged: to.Ptr(armpanngfw.BooleanEnumTRUE), + // PanoramaStatus: &armpanngfw.PanoramaStatus{ + // PanoramaServer2Status: to.Ptr(armpanngfw.ServerStatusUP), + // PanoramaServerStatus: to.Ptr(armpanngfw.ServerStatusUP), + // }, + // ProvisioningState: to.Ptr(armpanngfw.ReadOnlyProvisioningStateSucceeded), + // }, + // } +} + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/FirewallStatus_Get_MinimumSet_Gen.json +func ExampleFirewallStatusClient_Get_firewallStatusGetMinimumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + res, err := clientFactory.NewFirewallStatusClient().Get(ctx, "rgopenapi", "firewall1", nil) + if err != nil { + log.Fatalf("failed to finish the request: %v", err) + } + // You could use response here. We use blank identifier for just demo purposes. + _ = res + // If the HTTP response code is 200 as defined in example definition, your response structure would look as follows. Please pay attention that all the values in the output are fake values for just demo purposes. + // res.FirewallStatusResource = armpanngfw.FirewallStatusResource{ + // ID: to.Ptr("/subscriptions/2bf4a339-294d-4c25-b0b2-ef649e9f5c27/resourcegroups/firewall-rg/providers/PaloAltoNetworks.Cloudngfw/firewalls/firewall1/statuses/default"), + // Properties: &armpanngfw.FirewallStatusProperty{ + // }, + // } +} diff --git a/sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/fqdnlistglobalrulestack_client.go b/sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/fqdnlistglobalrulestack_client.go new file mode 100644 index 000000000000..f9fb5d648650 --- /dev/null +++ b/sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/fqdnlistglobalrulestack_client.go @@ -0,0 +1,284 @@ +//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. +// Code generated by Microsoft (R) AutoRest Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. +// DO NOT EDIT. + +package armpanngfw + +import ( + "context" + "errors" + "github.com/Azure/azure-sdk-for-go/sdk/azcore" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/arm" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/policy" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime" + "net/http" + "net/url" + "strings" +) + +// FqdnListGlobalRulestackClient contains the methods for the FqdnListGlobalRulestack group. +// Don't use this type directly, use NewFqdnListGlobalRulestackClient() instead. +type FqdnListGlobalRulestackClient struct { + internal *arm.Client +} + +// NewFqdnListGlobalRulestackClient creates a new instance of FqdnListGlobalRulestackClient with the specified values. +// - credential - used to authorize requests. Usually a credential from azidentity. +// - options - pass nil to accept the default values. +func NewFqdnListGlobalRulestackClient(credential azcore.TokenCredential, options *arm.ClientOptions) (*FqdnListGlobalRulestackClient, error) { + cl, err := arm.NewClient(moduleName+".FqdnListGlobalRulestackClient", moduleVersion, credential, options) + if err != nil { + return nil, err + } + client := &FqdnListGlobalRulestackClient{ + internal: cl, + } + return client, nil +} + +// BeginCreateOrUpdate - Create a FqdnListGlobalRulestackResource +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2022-08-29-preview +// - globalRulestackName - GlobalRulestack resource name +// - name - fqdn list name +// - resource - Resource create parameters. +// - options - FqdnListGlobalRulestackClientBeginCreateOrUpdateOptions contains the optional parameters for the FqdnListGlobalRulestackClient.BeginCreateOrUpdate +// method. +func (client *FqdnListGlobalRulestackClient) BeginCreateOrUpdate(ctx context.Context, globalRulestackName string, name string, resource FqdnListGlobalRulestackResource, options *FqdnListGlobalRulestackClientBeginCreateOrUpdateOptions) (*runtime.Poller[FqdnListGlobalRulestackClientCreateOrUpdateResponse], error) { + if options == nil || options.ResumeToken == "" { + resp, err := client.createOrUpdate(ctx, globalRulestackName, name, resource, options) + if err != nil { + return nil, err + } + return runtime.NewPoller(resp, client.internal.Pipeline(), &runtime.NewPollerOptions[FqdnListGlobalRulestackClientCreateOrUpdateResponse]{ + FinalStateVia: runtime.FinalStateViaAzureAsyncOp, + }) + } else { + return runtime.NewPollerFromResumeToken[FqdnListGlobalRulestackClientCreateOrUpdateResponse](options.ResumeToken, client.internal.Pipeline(), nil) + } +} + +// CreateOrUpdate - Create a FqdnListGlobalRulestackResource +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2022-08-29-preview +func (client *FqdnListGlobalRulestackClient) createOrUpdate(ctx context.Context, globalRulestackName string, name string, resource FqdnListGlobalRulestackResource, options *FqdnListGlobalRulestackClientBeginCreateOrUpdateOptions) (*http.Response, error) { + req, err := client.createOrUpdateCreateRequest(ctx, globalRulestackName, name, resource, options) + if err != nil { + return nil, err + } + resp, err := client.internal.Pipeline().Do(req) + if err != nil { + return nil, err + } + if !runtime.HasStatusCode(resp, http.StatusOK, http.StatusCreated) { + return nil, runtime.NewResponseError(resp) + } + return resp, nil +} + +// createOrUpdateCreateRequest creates the CreateOrUpdate request. +func (client *FqdnListGlobalRulestackClient) createOrUpdateCreateRequest(ctx context.Context, globalRulestackName string, name string, resource FqdnListGlobalRulestackResource, options *FqdnListGlobalRulestackClientBeginCreateOrUpdateOptions) (*policy.Request, error) { + urlPath := "/providers/PaloAltoNetworks.Cloudngfw/globalRulestacks/{globalRulestackName}/fqdnlists/{name}" + if globalRulestackName == "" { + return nil, errors.New("parameter globalRulestackName cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{globalRulestackName}", url.PathEscape(globalRulestackName)) + if name == "" { + return nil, errors.New("parameter name cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{name}", url.PathEscape(name)) + req, err := runtime.NewRequest(ctx, http.MethodPut, runtime.JoinPaths(client.internal.Endpoint(), urlPath)) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("api-version", "2022-08-29-preview") + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["Accept"] = []string{"application/json"} + return req, runtime.MarshalAsJSON(req, resource) +} + +// BeginDelete - Delete a FqdnListGlobalRulestackResource +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2022-08-29-preview +// - globalRulestackName - GlobalRulestack resource name +// - name - fqdn list name +// - options - FqdnListGlobalRulestackClientBeginDeleteOptions contains the optional parameters for the FqdnListGlobalRulestackClient.BeginDelete +// method. +func (client *FqdnListGlobalRulestackClient) BeginDelete(ctx context.Context, globalRulestackName string, name string, options *FqdnListGlobalRulestackClientBeginDeleteOptions) (*runtime.Poller[FqdnListGlobalRulestackClientDeleteResponse], error) { + if options == nil || options.ResumeToken == "" { + resp, err := client.deleteOperation(ctx, globalRulestackName, name, options) + if err != nil { + return nil, err + } + return runtime.NewPoller(resp, client.internal.Pipeline(), &runtime.NewPollerOptions[FqdnListGlobalRulestackClientDeleteResponse]{ + FinalStateVia: runtime.FinalStateViaAzureAsyncOp, + }) + } else { + return runtime.NewPollerFromResumeToken[FqdnListGlobalRulestackClientDeleteResponse](options.ResumeToken, client.internal.Pipeline(), nil) + } +} + +// Delete - Delete a FqdnListGlobalRulestackResource +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2022-08-29-preview +func (client *FqdnListGlobalRulestackClient) deleteOperation(ctx context.Context, globalRulestackName string, name string, options *FqdnListGlobalRulestackClientBeginDeleteOptions) (*http.Response, error) { + req, err := client.deleteCreateRequest(ctx, globalRulestackName, name, options) + if err != nil { + return nil, err + } + resp, err := client.internal.Pipeline().Do(req) + if err != nil { + return nil, err + } + if !runtime.HasStatusCode(resp, http.StatusOK, http.StatusAccepted, http.StatusNoContent) { + return nil, runtime.NewResponseError(resp) + } + return resp, nil +} + +// deleteCreateRequest creates the Delete request. +func (client *FqdnListGlobalRulestackClient) deleteCreateRequest(ctx context.Context, globalRulestackName string, name string, options *FqdnListGlobalRulestackClientBeginDeleteOptions) (*policy.Request, error) { + urlPath := "/providers/PaloAltoNetworks.Cloudngfw/globalRulestacks/{globalRulestackName}/fqdnlists/{name}" + if globalRulestackName == "" { + return nil, errors.New("parameter globalRulestackName cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{globalRulestackName}", url.PathEscape(globalRulestackName)) + if name == "" { + return nil, errors.New("parameter name cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{name}", url.PathEscape(name)) + req, err := runtime.NewRequest(ctx, http.MethodDelete, runtime.JoinPaths(client.internal.Endpoint(), urlPath)) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("api-version", "2022-08-29-preview") + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["Accept"] = []string{"application/json"} + return req, nil +} + +// Get - Get a FqdnListGlobalRulestackResource +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2022-08-29-preview +// - globalRulestackName - GlobalRulestack resource name +// - name - fqdn list name +// - options - FqdnListGlobalRulestackClientGetOptions contains the optional parameters for the FqdnListGlobalRulestackClient.Get +// method. +func (client *FqdnListGlobalRulestackClient) Get(ctx context.Context, globalRulestackName string, name string, options *FqdnListGlobalRulestackClientGetOptions) (FqdnListGlobalRulestackClientGetResponse, error) { + req, err := client.getCreateRequest(ctx, globalRulestackName, name, options) + if err != nil { + return FqdnListGlobalRulestackClientGetResponse{}, err + } + resp, err := client.internal.Pipeline().Do(req) + if err != nil { + return FqdnListGlobalRulestackClientGetResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusOK) { + return FqdnListGlobalRulestackClientGetResponse{}, runtime.NewResponseError(resp) + } + return client.getHandleResponse(resp) +} + +// getCreateRequest creates the Get request. +func (client *FqdnListGlobalRulestackClient) getCreateRequest(ctx context.Context, globalRulestackName string, name string, options *FqdnListGlobalRulestackClientGetOptions) (*policy.Request, error) { + urlPath := "/providers/PaloAltoNetworks.Cloudngfw/globalRulestacks/{globalRulestackName}/fqdnlists/{name}" + if globalRulestackName == "" { + return nil, errors.New("parameter globalRulestackName cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{globalRulestackName}", url.PathEscape(globalRulestackName)) + if name == "" { + return nil, errors.New("parameter name cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{name}", url.PathEscape(name)) + req, err := runtime.NewRequest(ctx, http.MethodGet, runtime.JoinPaths(client.internal.Endpoint(), urlPath)) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("api-version", "2022-08-29-preview") + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["Accept"] = []string{"application/json"} + return req, nil +} + +// getHandleResponse handles the Get response. +func (client *FqdnListGlobalRulestackClient) getHandleResponse(resp *http.Response) (FqdnListGlobalRulestackClientGetResponse, error) { + result := FqdnListGlobalRulestackClientGetResponse{} + if err := runtime.UnmarshalAsJSON(resp, &result.FqdnListGlobalRulestackResource); err != nil { + return FqdnListGlobalRulestackClientGetResponse{}, err + } + return result, nil +} + +// NewListPager - List FqdnListGlobalRulestackResource resources by Tenant +// +// Generated from API version 2022-08-29-preview +// - globalRulestackName - GlobalRulestack resource name +// - options - FqdnListGlobalRulestackClientListOptions contains the optional parameters for the FqdnListGlobalRulestackClient.NewListPager +// method. +func (client *FqdnListGlobalRulestackClient) NewListPager(globalRulestackName string, options *FqdnListGlobalRulestackClientListOptions) *runtime.Pager[FqdnListGlobalRulestackClientListResponse] { + return runtime.NewPager(runtime.PagingHandler[FqdnListGlobalRulestackClientListResponse]{ + More: func(page FqdnListGlobalRulestackClientListResponse) bool { + return page.NextLink != nil && len(*page.NextLink) > 0 + }, + Fetcher: func(ctx context.Context, page *FqdnListGlobalRulestackClientListResponse) (FqdnListGlobalRulestackClientListResponse, error) { + var req *policy.Request + var err error + if page == nil { + req, err = client.listCreateRequest(ctx, globalRulestackName, options) + } else { + req, err = runtime.NewRequest(ctx, http.MethodGet, *page.NextLink) + } + if err != nil { + return FqdnListGlobalRulestackClientListResponse{}, err + } + resp, err := client.internal.Pipeline().Do(req) + if err != nil { + return FqdnListGlobalRulestackClientListResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusOK) { + return FqdnListGlobalRulestackClientListResponse{}, runtime.NewResponseError(resp) + } + return client.listHandleResponse(resp) + }, + }) +} + +// listCreateRequest creates the List request. +func (client *FqdnListGlobalRulestackClient) listCreateRequest(ctx context.Context, globalRulestackName string, options *FqdnListGlobalRulestackClientListOptions) (*policy.Request, error) { + urlPath := "/providers/PaloAltoNetworks.Cloudngfw/globalRulestacks/{globalRulestackName}/fqdnlists" + if globalRulestackName == "" { + return nil, errors.New("parameter globalRulestackName cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{globalRulestackName}", url.PathEscape(globalRulestackName)) + req, err := runtime.NewRequest(ctx, http.MethodGet, runtime.JoinPaths(client.internal.Endpoint(), urlPath)) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("api-version", "2022-08-29-preview") + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["Accept"] = []string{"application/json"} + return req, nil +} + +// listHandleResponse handles the List response. +func (client *FqdnListGlobalRulestackClient) listHandleResponse(resp *http.Response) (FqdnListGlobalRulestackClientListResponse, error) { + result := FqdnListGlobalRulestackClientListResponse{} + if err := runtime.UnmarshalAsJSON(resp, &result.FqdnListGlobalRulestackResourceListResult); err != nil { + return FqdnListGlobalRulestackClientListResponse{}, err + } + return result, nil +} diff --git a/sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/fqdnlistglobalrulestack_client_example_test.go b/sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/fqdnlistglobalrulestack_client_example_test.go new file mode 100644 index 000000000000..dc9f95dc39a1 --- /dev/null +++ b/sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/fqdnlistglobalrulestack_client_example_test.go @@ -0,0 +1,311 @@ +//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. +// Code generated by Microsoft (R) AutoRest Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. +// DO NOT EDIT. + +package armpanngfw_test + +import ( + "context" + "log" + + "github.com/Azure/azure-sdk-for-go/sdk/azcore/to" + "github.com/Azure/azure-sdk-for-go/sdk/azidentity" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/paloaltonetworksngfw/armpanngfw" +) + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/FqdnListGlobalRulestack_List_MaximumSet_Gen.json +func ExampleFqdnListGlobalRulestackClient_NewListPager_fqdnListGlobalRulestackListMaximumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + pager := clientFactory.NewFqdnListGlobalRulestackClient().NewListPager("praval", nil) + for pager.More() { + page, err := pager.NextPage(ctx) + if err != nil { + log.Fatalf("failed to advance page: %v", err) + } + for _, v := range page.Value { + // You could use page here. We use blank identifier for just demo purposes. + _ = v + } + // If the HTTP response code is 200 as defined in example definition, your page structure would look as follows. Please pay attention that all the values in the output are fake values for just demo purposes. + // page.FqdnListGlobalRulestackResourceListResult = armpanngfw.FqdnListGlobalRulestackResourceListResult{ + // Value: []*armpanngfw.FqdnListGlobalRulestackResource{ + // { + // Name: to.Ptr("aaaaaaaaaaaaaaaaaaaaaaaaaa"), + // Type: to.Ptr("aaaaa"), + // ID: to.Ptr("aaaaaaaaaaaaaaaaaaaaaa"), + // SystemData: &armpanngfw.SystemData{ + // CreatedAt: to.Ptr(func() time.Time { t, _ := time.Parse(time.RFC3339Nano, "2022-09-09T05:08:24.229Z"); return t}()), + // CreatedBy: to.Ptr("praval"), + // CreatedByType: to.Ptr(armpanngfw.CreatedByTypeUser), + // LastModifiedAt: to.Ptr(func() time.Time { t, _ := time.Parse(time.RFC3339Nano, "2022-09-09T05:08:24.229Z"); return t}()), + // LastModifiedBy: to.Ptr("praval"), + // LastModifiedByType: to.Ptr(armpanngfw.CreatedByTypeUser), + // }, + // Properties: &armpanngfw.FqdnObject{ + // Description: to.Ptr("aaaaaaaaaaaaaaaaaaaaaaa"), + // AuditComment: to.Ptr("aaaaaaaaaaaaaaaaaaaaaaaaa"), + // Etag: to.Ptr("aaaaaaaaaaaaaaaaaa"), + // FqdnList: []*string{ + // to.Ptr("string1"), + // to.Ptr("string2")}, + // ProvisioningState: to.Ptr(armpanngfw.ProvisioningStateSucceeded), + // }, + // }}, + // } + } +} + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/FqdnListGlobalRulestack_List_MinimumSet_Gen.json +func ExampleFqdnListGlobalRulestackClient_NewListPager_fqdnListGlobalRulestackListMinimumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + pager := clientFactory.NewFqdnListGlobalRulestackClient().NewListPager("praval", nil) + for pager.More() { + page, err := pager.NextPage(ctx) + if err != nil { + log.Fatalf("failed to advance page: %v", err) + } + for _, v := range page.Value { + // You could use page here. We use blank identifier for just demo purposes. + _ = v + } + // If the HTTP response code is 200 as defined in example definition, your page structure would look as follows. Please pay attention that all the values in the output are fake values for just demo purposes. + // page.FqdnListGlobalRulestackResourceListResult = armpanngfw.FqdnListGlobalRulestackResourceListResult{ + // Value: []*armpanngfw.FqdnListGlobalRulestackResource{ + // { + // ID: to.Ptr("/providers/PaloAltoNetworks.Cloudngfw/globalRulestacks/praval/fqdnlists/fqdnlists1"), + // Properties: &armpanngfw.FqdnObject{ + // FqdnList: []*string{ + // to.Ptr("string1"), + // to.Ptr("string2")}, + // }, + // }}, + // } + } +} + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/FqdnListGlobalRulestack_Get_MaximumSet_Gen.json +func ExampleFqdnListGlobalRulestackClient_Get_fqdnListGlobalRulestackGetMaximumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + res, err := clientFactory.NewFqdnListGlobalRulestackClient().Get(ctx, "praval", "armid1", nil) + if err != nil { + log.Fatalf("failed to finish the request: %v", err) + } + // You could use response here. We use blank identifier for just demo purposes. + _ = res + // If the HTTP response code is 200 as defined in example definition, your response structure would look as follows. Please pay attention that all the values in the output are fake values for just demo purposes. + // res.FqdnListGlobalRulestackResource = armpanngfw.FqdnListGlobalRulestackResource{ + // Name: to.Ptr("armid1"), + // Type: to.Ptr("certificates"), + // ID: to.Ptr("/providers/PaloAltoNetworks.Cloudngfw/globalrulestacks/armid1/certificates/armid1"), + // SystemData: &armpanngfw.SystemData{ + // CreatedAt: to.Ptr(func() time.Time { t, _ := time.Parse(time.RFC3339Nano, "2022-09-09T05:08:24.229Z"); return t}()), + // CreatedBy: to.Ptr("praval"), + // CreatedByType: to.Ptr(armpanngfw.CreatedByTypeUser), + // LastModifiedAt: to.Ptr(func() time.Time { t, _ := time.Parse(time.RFC3339Nano, "2022-09-09T05:08:24.229Z"); return t}()), + // LastModifiedBy: to.Ptr("praval"), + // LastModifiedByType: to.Ptr(armpanngfw.CreatedByTypeUser), + // }, + // Properties: &armpanngfw.FqdnObject{ + // Description: to.Ptr("string"), + // AuditComment: to.Ptr("string"), + // Etag: to.Ptr("aaaaaaaaaaaaaaaaaa"), + // FqdnList: []*string{ + // to.Ptr("string1"), + // to.Ptr("string2")}, + // ProvisioningState: to.Ptr(armpanngfw.ProvisioningStateSucceeded), + // }, + // } +} + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/FqdnListGlobalRulestack_Get_MinimumSet_Gen.json +func ExampleFqdnListGlobalRulestackClient_Get_fqdnListGlobalRulestackGetMinimumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + res, err := clientFactory.NewFqdnListGlobalRulestackClient().Get(ctx, "praval", "armid1", nil) + if err != nil { + log.Fatalf("failed to finish the request: %v", err) + } + // You could use response here. We use blank identifier for just demo purposes. + _ = res + // If the HTTP response code is 200 as defined in example definition, your response structure would look as follows. Please pay attention that all the values in the output are fake values for just demo purposes. + // res.FqdnListGlobalRulestackResource = armpanngfw.FqdnListGlobalRulestackResource{ + // ID: to.Ptr("/providers/PaloAltoNetworks.Cloudngfw/globalRulestacks/praval/fqdnlists/armid1"), + // Properties: &armpanngfw.FqdnObject{ + // FqdnList: []*string{ + // to.Ptr("string1"), + // to.Ptr("string2")}, + // }, + // } +} + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/FqdnListGlobalRulestack_CreateOrUpdate_MaximumSet_Gen.json +func ExampleFqdnListGlobalRulestackClient_BeginCreateOrUpdate_fqdnListGlobalRulestackCreateOrUpdateMaximumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + poller, err := clientFactory.NewFqdnListGlobalRulestackClient().BeginCreateOrUpdate(ctx, "praval", "armid1", armpanngfw.FqdnListGlobalRulestackResource{ + Properties: &armpanngfw.FqdnObject{ + Description: to.Ptr("string"), + AuditComment: to.Ptr("string"), + Etag: to.Ptr("aaaaaaaaaaaaaaaaaa"), + FqdnList: []*string{ + to.Ptr("string1"), + to.Ptr("string2")}, + ProvisioningState: to.Ptr(armpanngfw.ProvisioningStateAccepted), + }, + }, nil) + if err != nil { + log.Fatalf("failed to finish the request: %v", err) + } + res, err := poller.PollUntilDone(ctx, nil) + if err != nil { + log.Fatalf("failed to pull the result: %v", err) + } + // You could use response here. We use blank identifier for just demo purposes. + _ = res + // If the HTTP response code is 200 as defined in example definition, your response structure would look as follows. Please pay attention that all the values in the output are fake values for just demo purposes. + // res.FqdnListGlobalRulestackResource = armpanngfw.FqdnListGlobalRulestackResource{ + // Name: to.Ptr("armid1"), + // Type: to.Ptr("certificates"), + // ID: to.Ptr("/providers/PaloAltoNetworks.Cloudngfw/globalrulestacks/armid1/certificates/armid1"), + // SystemData: &armpanngfw.SystemData{ + // CreatedAt: to.Ptr(func() time.Time { t, _ := time.Parse(time.RFC3339Nano, "2022-09-09T05:08:24.229Z"); return t}()), + // CreatedBy: to.Ptr("praval"), + // CreatedByType: to.Ptr(armpanngfw.CreatedByTypeUser), + // LastModifiedAt: to.Ptr(func() time.Time { t, _ := time.Parse(time.RFC3339Nano, "2022-09-09T05:08:24.229Z"); return t}()), + // LastModifiedBy: to.Ptr("praval"), + // LastModifiedByType: to.Ptr(armpanngfw.CreatedByTypeUser), + // }, + // Properties: &armpanngfw.FqdnObject{ + // Description: to.Ptr("string"), + // AuditComment: to.Ptr("string"), + // Etag: to.Ptr("aaaaaaaaaaaaaaaaaa"), + // FqdnList: []*string{ + // to.Ptr("string1"), + // to.Ptr("string2")}, + // ProvisioningState: to.Ptr(armpanngfw.ProvisioningStateSucceeded), + // }, + // } +} + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/FqdnListGlobalRulestack_CreateOrUpdate_MinimumSet_Gen.json +func ExampleFqdnListGlobalRulestackClient_BeginCreateOrUpdate_fqdnListGlobalRulestackCreateOrUpdateMinimumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + poller, err := clientFactory.NewFqdnListGlobalRulestackClient().BeginCreateOrUpdate(ctx, "praval", "armid1", armpanngfw.FqdnListGlobalRulestackResource{ + Properties: &armpanngfw.FqdnObject{ + FqdnList: []*string{ + to.Ptr("string1"), + to.Ptr("string2")}, + }, + }, nil) + if err != nil { + log.Fatalf("failed to finish the request: %v", err) + } + res, err := poller.PollUntilDone(ctx, nil) + if err != nil { + log.Fatalf("failed to pull the result: %v", err) + } + // You could use response here. We use blank identifier for just demo purposes. + _ = res + // If the HTTP response code is 200 as defined in example definition, your response structure would look as follows. Please pay attention that all the values in the output are fake values for just demo purposes. + // res.FqdnListGlobalRulestackResource = armpanngfw.FqdnListGlobalRulestackResource{ + // ID: to.Ptr("/providers/PaloAltoNetworks.Cloudngfw/globalRulestacks/praval/fqdnlists/armid1"), + // Properties: &armpanngfw.FqdnObject{ + // FqdnList: []*string{ + // to.Ptr("string1"), + // to.Ptr("string2")}, + // }, + // } +} + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/FqdnListGlobalRulestack_Delete_MaximumSet_Gen.json +func ExampleFqdnListGlobalRulestackClient_BeginDelete_fqdnListGlobalRulestackDeleteMaximumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + poller, err := clientFactory.NewFqdnListGlobalRulestackClient().BeginDelete(ctx, "praval", "armid1", nil) + if err != nil { + log.Fatalf("failed to finish the request: %v", err) + } + _, err = poller.PollUntilDone(ctx, nil) + if err != nil { + log.Fatalf("failed to pull the result: %v", err) + } +} + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/FqdnListGlobalRulestack_Delete_MinimumSet_Gen.json +func ExampleFqdnListGlobalRulestackClient_BeginDelete_fqdnListGlobalRulestackDeleteMinimumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + poller, err := clientFactory.NewFqdnListGlobalRulestackClient().BeginDelete(ctx, "praval", "armid1", nil) + if err != nil { + log.Fatalf("failed to finish the request: %v", err) + } + _, err = poller.PollUntilDone(ctx, nil) + if err != nil { + log.Fatalf("failed to pull the result: %v", err) + } +} diff --git a/sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/fqdnlistlocalrulestack_client.go b/sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/fqdnlistlocalrulestack_client.go new file mode 100644 index 000000000000..bdd9267c4ea0 --- /dev/null +++ b/sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/fqdnlistlocalrulestack_client.go @@ -0,0 +1,323 @@ +//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. +// Code generated by Microsoft (R) AutoRest Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. +// DO NOT EDIT. + +package armpanngfw + +import ( + "context" + "errors" + "github.com/Azure/azure-sdk-for-go/sdk/azcore" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/arm" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/policy" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime" + "net/http" + "net/url" + "strings" +) + +// FqdnListLocalRulestackClient contains the methods for the FqdnListLocalRulestack group. +// Don't use this type directly, use NewFqdnListLocalRulestackClient() instead. +type FqdnListLocalRulestackClient struct { + internal *arm.Client + subscriptionID string +} + +// NewFqdnListLocalRulestackClient creates a new instance of FqdnListLocalRulestackClient with the specified values. +// - subscriptionID - The ID of the target subscription. +// - credential - used to authorize requests. Usually a credential from azidentity. +// - options - pass nil to accept the default values. +func NewFqdnListLocalRulestackClient(subscriptionID string, credential azcore.TokenCredential, options *arm.ClientOptions) (*FqdnListLocalRulestackClient, error) { + cl, err := arm.NewClient(moduleName+".FqdnListLocalRulestackClient", moduleVersion, credential, options) + if err != nil { + return nil, err + } + client := &FqdnListLocalRulestackClient{ + subscriptionID: subscriptionID, + internal: cl, + } + return client, nil +} + +// BeginCreateOrUpdate - Create a FqdnListLocalRulestackResource +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2022-08-29-preview +// - resourceGroupName - The name of the resource group. The name is case insensitive. +// - localRulestackName - LocalRulestack resource name +// - name - fqdn list name +// - resource - Resource create parameters. +// - options - FqdnListLocalRulestackClientBeginCreateOrUpdateOptions contains the optional parameters for the FqdnListLocalRulestackClient.BeginCreateOrUpdate +// method. +func (client *FqdnListLocalRulestackClient) BeginCreateOrUpdate(ctx context.Context, resourceGroupName string, localRulestackName string, name string, resource FqdnListLocalRulestackResource, options *FqdnListLocalRulestackClientBeginCreateOrUpdateOptions) (*runtime.Poller[FqdnListLocalRulestackClientCreateOrUpdateResponse], error) { + if options == nil || options.ResumeToken == "" { + resp, err := client.createOrUpdate(ctx, resourceGroupName, localRulestackName, name, resource, options) + if err != nil { + return nil, err + } + return runtime.NewPoller(resp, client.internal.Pipeline(), &runtime.NewPollerOptions[FqdnListLocalRulestackClientCreateOrUpdateResponse]{ + FinalStateVia: runtime.FinalStateViaAzureAsyncOp, + }) + } else { + return runtime.NewPollerFromResumeToken[FqdnListLocalRulestackClientCreateOrUpdateResponse](options.ResumeToken, client.internal.Pipeline(), nil) + } +} + +// CreateOrUpdate - Create a FqdnListLocalRulestackResource +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2022-08-29-preview +func (client *FqdnListLocalRulestackClient) createOrUpdate(ctx context.Context, resourceGroupName string, localRulestackName string, name string, resource FqdnListLocalRulestackResource, options *FqdnListLocalRulestackClientBeginCreateOrUpdateOptions) (*http.Response, error) { + req, err := client.createOrUpdateCreateRequest(ctx, resourceGroupName, localRulestackName, name, resource, options) + if err != nil { + return nil, err + } + resp, err := client.internal.Pipeline().Do(req) + if err != nil { + return nil, err + } + if !runtime.HasStatusCode(resp, http.StatusOK, http.StatusCreated) { + return nil, runtime.NewResponseError(resp) + } + return resp, nil +} + +// createOrUpdateCreateRequest creates the CreateOrUpdate request. +func (client *FqdnListLocalRulestackClient) createOrUpdateCreateRequest(ctx context.Context, resourceGroupName string, localRulestackName string, name string, resource FqdnListLocalRulestackResource, options *FqdnListLocalRulestackClientBeginCreateOrUpdateOptions) (*policy.Request, error) { + urlPath := "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/PaloAltoNetworks.Cloudngfw/localRulestacks/{localRulestackName}/fqdnlists/{name}" + if client.subscriptionID == "" { + return nil, errors.New("parameter client.subscriptionID cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{subscriptionId}", url.PathEscape(client.subscriptionID)) + if resourceGroupName == "" { + return nil, errors.New("parameter resourceGroupName cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{resourceGroupName}", url.PathEscape(resourceGroupName)) + if localRulestackName == "" { + return nil, errors.New("parameter localRulestackName cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{localRulestackName}", url.PathEscape(localRulestackName)) + if name == "" { + return nil, errors.New("parameter name cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{name}", url.PathEscape(name)) + req, err := runtime.NewRequest(ctx, http.MethodPut, runtime.JoinPaths(client.internal.Endpoint(), urlPath)) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("api-version", "2022-08-29-preview") + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["Accept"] = []string{"application/json"} + return req, runtime.MarshalAsJSON(req, resource) +} + +// BeginDelete - Delete a FqdnListLocalRulestackResource +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2022-08-29-preview +// - resourceGroupName - The name of the resource group. The name is case insensitive. +// - localRulestackName - LocalRulestack resource name +// - name - fqdn list name +// - options - FqdnListLocalRulestackClientBeginDeleteOptions contains the optional parameters for the FqdnListLocalRulestackClient.BeginDelete +// method. +func (client *FqdnListLocalRulestackClient) BeginDelete(ctx context.Context, resourceGroupName string, localRulestackName string, name string, options *FqdnListLocalRulestackClientBeginDeleteOptions) (*runtime.Poller[FqdnListLocalRulestackClientDeleteResponse], error) { + if options == nil || options.ResumeToken == "" { + resp, err := client.deleteOperation(ctx, resourceGroupName, localRulestackName, name, options) + if err != nil { + return nil, err + } + return runtime.NewPoller(resp, client.internal.Pipeline(), &runtime.NewPollerOptions[FqdnListLocalRulestackClientDeleteResponse]{ + FinalStateVia: runtime.FinalStateViaAzureAsyncOp, + }) + } else { + return runtime.NewPollerFromResumeToken[FqdnListLocalRulestackClientDeleteResponse](options.ResumeToken, client.internal.Pipeline(), nil) + } +} + +// Delete - Delete a FqdnListLocalRulestackResource +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2022-08-29-preview +func (client *FqdnListLocalRulestackClient) deleteOperation(ctx context.Context, resourceGroupName string, localRulestackName string, name string, options *FqdnListLocalRulestackClientBeginDeleteOptions) (*http.Response, error) { + req, err := client.deleteCreateRequest(ctx, resourceGroupName, localRulestackName, name, options) + if err != nil { + return nil, err + } + resp, err := client.internal.Pipeline().Do(req) + if err != nil { + return nil, err + } + if !runtime.HasStatusCode(resp, http.StatusOK, http.StatusAccepted, http.StatusNoContent) { + return nil, runtime.NewResponseError(resp) + } + return resp, nil +} + +// deleteCreateRequest creates the Delete request. +func (client *FqdnListLocalRulestackClient) deleteCreateRequest(ctx context.Context, resourceGroupName string, localRulestackName string, name string, options *FqdnListLocalRulestackClientBeginDeleteOptions) (*policy.Request, error) { + urlPath := "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/PaloAltoNetworks.Cloudngfw/localRulestacks/{localRulestackName}/fqdnlists/{name}" + if client.subscriptionID == "" { + return nil, errors.New("parameter client.subscriptionID cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{subscriptionId}", url.PathEscape(client.subscriptionID)) + if resourceGroupName == "" { + return nil, errors.New("parameter resourceGroupName cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{resourceGroupName}", url.PathEscape(resourceGroupName)) + if localRulestackName == "" { + return nil, errors.New("parameter localRulestackName cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{localRulestackName}", url.PathEscape(localRulestackName)) + if name == "" { + return nil, errors.New("parameter name cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{name}", url.PathEscape(name)) + req, err := runtime.NewRequest(ctx, http.MethodDelete, runtime.JoinPaths(client.internal.Endpoint(), urlPath)) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("api-version", "2022-08-29-preview") + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["Accept"] = []string{"application/json"} + return req, nil +} + +// Get - Get a FqdnListLocalRulestackResource +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2022-08-29-preview +// - resourceGroupName - The name of the resource group. The name is case insensitive. +// - localRulestackName - LocalRulestack resource name +// - name - fqdn list name +// - options - FqdnListLocalRulestackClientGetOptions contains the optional parameters for the FqdnListLocalRulestackClient.Get +// method. +func (client *FqdnListLocalRulestackClient) Get(ctx context.Context, resourceGroupName string, localRulestackName string, name string, options *FqdnListLocalRulestackClientGetOptions) (FqdnListLocalRulestackClientGetResponse, error) { + req, err := client.getCreateRequest(ctx, resourceGroupName, localRulestackName, name, options) + if err != nil { + return FqdnListLocalRulestackClientGetResponse{}, err + } + resp, err := client.internal.Pipeline().Do(req) + if err != nil { + return FqdnListLocalRulestackClientGetResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusOK) { + return FqdnListLocalRulestackClientGetResponse{}, runtime.NewResponseError(resp) + } + return client.getHandleResponse(resp) +} + +// getCreateRequest creates the Get request. +func (client *FqdnListLocalRulestackClient) getCreateRequest(ctx context.Context, resourceGroupName string, localRulestackName string, name string, options *FqdnListLocalRulestackClientGetOptions) (*policy.Request, error) { + urlPath := "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/PaloAltoNetworks.Cloudngfw/localRulestacks/{localRulestackName}/fqdnlists/{name}" + if client.subscriptionID == "" { + return nil, errors.New("parameter client.subscriptionID cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{subscriptionId}", url.PathEscape(client.subscriptionID)) + if resourceGroupName == "" { + return nil, errors.New("parameter resourceGroupName cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{resourceGroupName}", url.PathEscape(resourceGroupName)) + if localRulestackName == "" { + return nil, errors.New("parameter localRulestackName cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{localRulestackName}", url.PathEscape(localRulestackName)) + if name == "" { + return nil, errors.New("parameter name cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{name}", url.PathEscape(name)) + req, err := runtime.NewRequest(ctx, http.MethodGet, runtime.JoinPaths(client.internal.Endpoint(), urlPath)) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("api-version", "2022-08-29-preview") + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["Accept"] = []string{"application/json"} + return req, nil +} + +// getHandleResponse handles the Get response. +func (client *FqdnListLocalRulestackClient) getHandleResponse(resp *http.Response) (FqdnListLocalRulestackClientGetResponse, error) { + result := FqdnListLocalRulestackClientGetResponse{} + if err := runtime.UnmarshalAsJSON(resp, &result.FqdnListLocalRulestackResource); err != nil { + return FqdnListLocalRulestackClientGetResponse{}, err + } + return result, nil +} + +// NewListByLocalRulestacksPager - List FqdnListLocalRulestackResource resources by LocalRulestacks +// +// Generated from API version 2022-08-29-preview +// - resourceGroupName - The name of the resource group. The name is case insensitive. +// - localRulestackName - LocalRulestack resource name +// - options - FqdnListLocalRulestackClientListByLocalRulestacksOptions contains the optional parameters for the FqdnListLocalRulestackClient.NewListByLocalRulestacksPager +// method. +func (client *FqdnListLocalRulestackClient) NewListByLocalRulestacksPager(resourceGroupName string, localRulestackName string, options *FqdnListLocalRulestackClientListByLocalRulestacksOptions) *runtime.Pager[FqdnListLocalRulestackClientListByLocalRulestacksResponse] { + return runtime.NewPager(runtime.PagingHandler[FqdnListLocalRulestackClientListByLocalRulestacksResponse]{ + More: func(page FqdnListLocalRulestackClientListByLocalRulestacksResponse) bool { + return page.NextLink != nil && len(*page.NextLink) > 0 + }, + Fetcher: func(ctx context.Context, page *FqdnListLocalRulestackClientListByLocalRulestacksResponse) (FqdnListLocalRulestackClientListByLocalRulestacksResponse, error) { + var req *policy.Request + var err error + if page == nil { + req, err = client.listByLocalRulestacksCreateRequest(ctx, resourceGroupName, localRulestackName, options) + } else { + req, err = runtime.NewRequest(ctx, http.MethodGet, *page.NextLink) + } + if err != nil { + return FqdnListLocalRulestackClientListByLocalRulestacksResponse{}, err + } + resp, err := client.internal.Pipeline().Do(req) + if err != nil { + return FqdnListLocalRulestackClientListByLocalRulestacksResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusOK) { + return FqdnListLocalRulestackClientListByLocalRulestacksResponse{}, runtime.NewResponseError(resp) + } + return client.listByLocalRulestacksHandleResponse(resp) + }, + }) +} + +// listByLocalRulestacksCreateRequest creates the ListByLocalRulestacks request. +func (client *FqdnListLocalRulestackClient) listByLocalRulestacksCreateRequest(ctx context.Context, resourceGroupName string, localRulestackName string, options *FqdnListLocalRulestackClientListByLocalRulestacksOptions) (*policy.Request, error) { + urlPath := "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/PaloAltoNetworks.Cloudngfw/localRulestacks/{localRulestackName}/fqdnlists" + if client.subscriptionID == "" { + return nil, errors.New("parameter client.subscriptionID cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{subscriptionId}", url.PathEscape(client.subscriptionID)) + if resourceGroupName == "" { + return nil, errors.New("parameter resourceGroupName cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{resourceGroupName}", url.PathEscape(resourceGroupName)) + if localRulestackName == "" { + return nil, errors.New("parameter localRulestackName cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{localRulestackName}", url.PathEscape(localRulestackName)) + req, err := runtime.NewRequest(ctx, http.MethodGet, runtime.JoinPaths(client.internal.Endpoint(), urlPath)) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("api-version", "2022-08-29-preview") + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["Accept"] = []string{"application/json"} + return req, nil +} + +// listByLocalRulestacksHandleResponse handles the ListByLocalRulestacks response. +func (client *FqdnListLocalRulestackClient) listByLocalRulestacksHandleResponse(resp *http.Response) (FqdnListLocalRulestackClientListByLocalRulestacksResponse, error) { + result := FqdnListLocalRulestackClientListByLocalRulestacksResponse{} + if err := runtime.UnmarshalAsJSON(resp, &result.FqdnListLocalRulestackResourceListResult); err != nil { + return FqdnListLocalRulestackClientListByLocalRulestacksResponse{}, err + } + return result, nil +} diff --git a/sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/fqdnlistlocalrulestack_client_example_test.go b/sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/fqdnlistlocalrulestack_client_example_test.go new file mode 100644 index 000000000000..593aa6d5568e --- /dev/null +++ b/sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/fqdnlistlocalrulestack_client_example_test.go @@ -0,0 +1,311 @@ +//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. +// Code generated by Microsoft (R) AutoRest Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. +// DO NOT EDIT. + +package armpanngfw_test + +import ( + "context" + "log" + + "github.com/Azure/azure-sdk-for-go/sdk/azcore/to" + "github.com/Azure/azure-sdk-for-go/sdk/azidentity" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/paloaltonetworksngfw/armpanngfw" +) + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/FqdnListLocalRulestack_ListByLocalRulestacks_MaximumSet_Gen.json +func ExampleFqdnListLocalRulestackClient_NewListByLocalRulestacksPager_fqdnListLocalRulestackListByLocalRulestacksMaximumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + pager := clientFactory.NewFqdnListLocalRulestackClient().NewListByLocalRulestacksPager("rgopenapi", "lrs1", nil) + for pager.More() { + page, err := pager.NextPage(ctx) + if err != nil { + log.Fatalf("failed to advance page: %v", err) + } + for _, v := range page.Value { + // You could use page here. We use blank identifier for just demo purposes. + _ = v + } + // If the HTTP response code is 200 as defined in example definition, your page structure would look as follows. Please pay attention that all the values in the output are fake values for just demo purposes. + // page.FqdnListLocalRulestackResourceListResult = armpanngfw.FqdnListLocalRulestackResourceListResult{ + // Value: []*armpanngfw.FqdnListLocalRulestackResource{ + // { + // Name: to.Ptr("aaaaaaaaaaaaaa"), + // Type: to.Ptr("aaaaaaaaaaaaaaaaaaaaaaaaaaa"), + // ID: to.Ptr("aaaaaaaaa"), + // SystemData: &armpanngfw.SystemData{ + // CreatedAt: to.Ptr(func() time.Time { t, _ := time.Parse(time.RFC3339Nano, "2022-09-09T05:08:24.229Z"); return t}()), + // CreatedBy: to.Ptr("praval"), + // CreatedByType: to.Ptr(armpanngfw.CreatedByTypeUser), + // LastModifiedAt: to.Ptr(func() time.Time { t, _ := time.Parse(time.RFC3339Nano, "2022-09-09T05:08:24.229Z"); return t}()), + // LastModifiedBy: to.Ptr("praval"), + // LastModifiedByType: to.Ptr(armpanngfw.CreatedByTypeUser), + // }, + // Properties: &armpanngfw.FqdnObject{ + // Description: to.Ptr("aaaaaaaaaaaaaaaaaaaaaaa"), + // AuditComment: to.Ptr("aaaaaaaaaaaaaaaaaaaaaaaaa"), + // Etag: to.Ptr("aaaaaaaaaaaaaaaaaa"), + // FqdnList: []*string{ + // to.Ptr("string1"), + // to.Ptr("string2")}, + // ProvisioningState: to.Ptr(armpanngfw.ProvisioningStateSucceeded), + // }, + // }}, + // } + } +} + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/FqdnListLocalRulestack_ListByLocalRulestacks_MinimumSet_Gen.json +func ExampleFqdnListLocalRulestackClient_NewListByLocalRulestacksPager_fqdnListLocalRulestackListByLocalRulestacksMinimumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + pager := clientFactory.NewFqdnListLocalRulestackClient().NewListByLocalRulestacksPager("rgopenapi", "lrs1", nil) + for pager.More() { + page, err := pager.NextPage(ctx) + if err != nil { + log.Fatalf("failed to advance page: %v", err) + } + for _, v := range page.Value { + // You could use page here. We use blank identifier for just demo purposes. + _ = v + } + // If the HTTP response code is 200 as defined in example definition, your page structure would look as follows. Please pay attention that all the values in the output are fake values for just demo purposes. + // page.FqdnListLocalRulestackResourceListResult = armpanngfw.FqdnListLocalRulestackResourceListResult{ + // Value: []*armpanngfw.FqdnListLocalRulestackResource{ + // { + // ID: to.Ptr("/subscriptions/2bf4a339-294d-4c25-b0b2-ef649e9f5c27/resourcegroups/rgopenapi/providers/PaloAltoNetworks.Cloudngfw/localRulestacks/praval/fqdnlists/fqdnlists1"), + // Properties: &armpanngfw.FqdnObject{ + // FqdnList: []*string{ + // to.Ptr("string1"), + // to.Ptr("string2")}, + // }, + // }}, + // } + } +} + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/FqdnListLocalRulestack_Get_MaximumSet_Gen.json +func ExampleFqdnListLocalRulestackClient_Get_fqdnListLocalRulestackGetMaximumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + res, err := clientFactory.NewFqdnListLocalRulestackClient().Get(ctx, "rgopenapi", "lrs1", "armid1", nil) + if err != nil { + log.Fatalf("failed to finish the request: %v", err) + } + // You could use response here. We use blank identifier for just demo purposes. + _ = res + // If the HTTP response code is 200 as defined in example definition, your response structure would look as follows. Please pay attention that all the values in the output are fake values for just demo purposes. + // res.FqdnListLocalRulestackResource = armpanngfw.FqdnListLocalRulestackResource{ + // Name: to.Ptr("armid1"), + // Type: to.Ptr("certificates"), + // ID: to.Ptr("/providers/PaloAltoNetworks.Cloudngfw/globalrulestacks/armid1/certificates/armid1"), + // SystemData: &armpanngfw.SystemData{ + // CreatedAt: to.Ptr(func() time.Time { t, _ := time.Parse(time.RFC3339Nano, "2022-09-09T05:08:24.229Z"); return t}()), + // CreatedBy: to.Ptr("praval"), + // CreatedByType: to.Ptr(armpanngfw.CreatedByTypeUser), + // LastModifiedAt: to.Ptr(func() time.Time { t, _ := time.Parse(time.RFC3339Nano, "2022-09-09T05:08:24.229Z"); return t}()), + // LastModifiedBy: to.Ptr("praval"), + // LastModifiedByType: to.Ptr(armpanngfw.CreatedByTypeUser), + // }, + // Properties: &armpanngfw.FqdnObject{ + // Description: to.Ptr("string"), + // AuditComment: to.Ptr("string"), + // Etag: to.Ptr("aaaaaaaaaaaaaaaaaa"), + // FqdnList: []*string{ + // to.Ptr("string1"), + // to.Ptr("string2")}, + // ProvisioningState: to.Ptr(armpanngfw.ProvisioningStateSucceeded), + // }, + // } +} + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/FqdnListLocalRulestack_Get_MinimumSet_Gen.json +func ExampleFqdnListLocalRulestackClient_Get_fqdnListLocalRulestackGetMinimumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + res, err := clientFactory.NewFqdnListLocalRulestackClient().Get(ctx, "rgopenapi", "lrs1", "armid1", nil) + if err != nil { + log.Fatalf("failed to finish the request: %v", err) + } + // You could use response here. We use blank identifier for just demo purposes. + _ = res + // If the HTTP response code is 200 as defined in example definition, your response structure would look as follows. Please pay attention that all the values in the output are fake values for just demo purposes. + // res.FqdnListLocalRulestackResource = armpanngfw.FqdnListLocalRulestackResource{ + // ID: to.Ptr("/subscriptions/2bf4a339-294d-4c25-b0b2-ef649e9f5c27/resourcegroups/rgopenapi/providers/PaloAltoNetworks.Cloudngfw/localRulestacks/praval/fqdnlists/armid1"), + // Properties: &armpanngfw.FqdnObject{ + // FqdnList: []*string{ + // to.Ptr("string1"), + // to.Ptr("string2")}, + // }, + // } +} + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/FqdnListLocalRulestack_CreateOrUpdate_MaximumSet_Gen.json +func ExampleFqdnListLocalRulestackClient_BeginCreateOrUpdate_fqdnListLocalRulestackCreateOrUpdateMaximumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + poller, err := clientFactory.NewFqdnListLocalRulestackClient().BeginCreateOrUpdate(ctx, "rgopenapi", "lrs1", "armid1", armpanngfw.FqdnListLocalRulestackResource{ + Properties: &armpanngfw.FqdnObject{ + Description: to.Ptr("string"), + AuditComment: to.Ptr("string"), + Etag: to.Ptr("aaaaaaaaaaaaaaaaaa"), + FqdnList: []*string{ + to.Ptr("string1"), + to.Ptr("string2")}, + ProvisioningState: to.Ptr(armpanngfw.ProvisioningStateAccepted), + }, + }, nil) + if err != nil { + log.Fatalf("failed to finish the request: %v", err) + } + res, err := poller.PollUntilDone(ctx, nil) + if err != nil { + log.Fatalf("failed to pull the result: %v", err) + } + // You could use response here. We use blank identifier for just demo purposes. + _ = res + // If the HTTP response code is 200 as defined in example definition, your response structure would look as follows. Please pay attention that all the values in the output are fake values for just demo purposes. + // res.FqdnListLocalRulestackResource = armpanngfw.FqdnListLocalRulestackResource{ + // Name: to.Ptr("armid1"), + // Type: to.Ptr("certificates"), + // ID: to.Ptr("/providers/PaloAltoNetworks.Cloudngfw/globalrulestacks/armid1/certificates/armid1"), + // SystemData: &armpanngfw.SystemData{ + // CreatedAt: to.Ptr(func() time.Time { t, _ := time.Parse(time.RFC3339Nano, "2022-09-09T05:08:24.229Z"); return t}()), + // CreatedBy: to.Ptr("praval"), + // CreatedByType: to.Ptr(armpanngfw.CreatedByTypeUser), + // LastModifiedAt: to.Ptr(func() time.Time { t, _ := time.Parse(time.RFC3339Nano, "2022-09-09T05:08:24.229Z"); return t}()), + // LastModifiedBy: to.Ptr("praval"), + // LastModifiedByType: to.Ptr(armpanngfw.CreatedByTypeUser), + // }, + // Properties: &armpanngfw.FqdnObject{ + // Description: to.Ptr("string"), + // AuditComment: to.Ptr("string"), + // Etag: to.Ptr("aaaaaaaaaaaaaaaaaa"), + // FqdnList: []*string{ + // to.Ptr("string1"), + // to.Ptr("string2")}, + // ProvisioningState: to.Ptr(armpanngfw.ProvisioningStateSucceeded), + // }, + // } +} + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/FqdnListLocalRulestack_CreateOrUpdate_MinimumSet_Gen.json +func ExampleFqdnListLocalRulestackClient_BeginCreateOrUpdate_fqdnListLocalRulestackCreateOrUpdateMinimumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + poller, err := clientFactory.NewFqdnListLocalRulestackClient().BeginCreateOrUpdate(ctx, "rgopenapi", "lrs1", "armid1", armpanngfw.FqdnListLocalRulestackResource{ + Properties: &armpanngfw.FqdnObject{ + FqdnList: []*string{ + to.Ptr("string1"), + to.Ptr("string2")}, + }, + }, nil) + if err != nil { + log.Fatalf("failed to finish the request: %v", err) + } + res, err := poller.PollUntilDone(ctx, nil) + if err != nil { + log.Fatalf("failed to pull the result: %v", err) + } + // You could use response here. We use blank identifier for just demo purposes. + _ = res + // If the HTTP response code is 200 as defined in example definition, your response structure would look as follows. Please pay attention that all the values in the output are fake values for just demo purposes. + // res.FqdnListLocalRulestackResource = armpanngfw.FqdnListLocalRulestackResource{ + // ID: to.Ptr("/subscriptions/2bf4a339-294d-4c25-b0b2-ef649e9f5c27/resourcegroups/rgopenapi/providers/PaloAltoNetworks.Cloudngfw/localRulestacks/praval/fqdnlists/armid1"), + // Properties: &armpanngfw.FqdnObject{ + // FqdnList: []*string{ + // to.Ptr("string1"), + // to.Ptr("string2")}, + // }, + // } +} + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/FqdnListLocalRulestack_Delete_MaximumSet_Gen.json +func ExampleFqdnListLocalRulestackClient_BeginDelete_fqdnListLocalRulestackDeleteMaximumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + poller, err := clientFactory.NewFqdnListLocalRulestackClient().BeginDelete(ctx, "rgopenapi", "lrs1", "armid1", nil) + if err != nil { + log.Fatalf("failed to finish the request: %v", err) + } + _, err = poller.PollUntilDone(ctx, nil) + if err != nil { + log.Fatalf("failed to pull the result: %v", err) + } +} + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/FqdnListLocalRulestack_Delete_MinimumSet_Gen.json +func ExampleFqdnListLocalRulestackClient_BeginDelete_fqdnListLocalRulestackDeleteMinimumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + poller, err := clientFactory.NewFqdnListLocalRulestackClient().BeginDelete(ctx, "rgopenapi", "lrs1", "armid1", nil) + if err != nil { + log.Fatalf("failed to finish the request: %v", err) + } + _, err = poller.PollUntilDone(ctx, nil) + if err != nil { + log.Fatalf("failed to pull the result: %v", err) + } +} diff --git a/sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/globalrulestack_client.go b/sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/globalrulestack_client.go new file mode 100644 index 000000000000..37bb85ed24b0 --- /dev/null +++ b/sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/globalrulestack_client.go @@ -0,0 +1,791 @@ +//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. +// Code generated by Microsoft (R) AutoRest Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. +// DO NOT EDIT. + +package armpanngfw + +import ( + "context" + "errors" + "github.com/Azure/azure-sdk-for-go/sdk/azcore" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/arm" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/policy" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime" + "net/http" + "net/url" + "strconv" + "strings" +) + +// GlobalRulestackClient contains the methods for the GlobalRulestack group. +// Don't use this type directly, use NewGlobalRulestackClient() instead. +type GlobalRulestackClient struct { + internal *arm.Client +} + +// NewGlobalRulestackClient creates a new instance of GlobalRulestackClient with the specified values. +// - credential - used to authorize requests. Usually a credential from azidentity. +// - options - pass nil to accept the default values. +func NewGlobalRulestackClient(credential azcore.TokenCredential, options *arm.ClientOptions) (*GlobalRulestackClient, error) { + cl, err := arm.NewClient(moduleName+".GlobalRulestackClient", moduleVersion, credential, options) + if err != nil { + return nil, err + } + client := &GlobalRulestackClient{ + internal: cl, + } + return client, nil +} + +// BeginCommit - Commit rulestack configuration +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2022-08-29-preview +// - globalRulestackName - GlobalRulestack resource name +// - options - GlobalRulestackClientBeginCommitOptions contains the optional parameters for the GlobalRulestackClient.BeginCommit +// method. +func (client *GlobalRulestackClient) BeginCommit(ctx context.Context, globalRulestackName string, options *GlobalRulestackClientBeginCommitOptions) (*runtime.Poller[GlobalRulestackClientCommitResponse], error) { + if options == nil || options.ResumeToken == "" { + resp, err := client.commit(ctx, globalRulestackName, options) + if err != nil { + return nil, err + } + return runtime.NewPoller(resp, client.internal.Pipeline(), &runtime.NewPollerOptions[GlobalRulestackClientCommitResponse]{ + FinalStateVia: runtime.FinalStateViaLocation, + }) + } else { + return runtime.NewPollerFromResumeToken[GlobalRulestackClientCommitResponse](options.ResumeToken, client.internal.Pipeline(), nil) + } +} + +// Commit - Commit rulestack configuration +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2022-08-29-preview +func (client *GlobalRulestackClient) commit(ctx context.Context, globalRulestackName string, options *GlobalRulestackClientBeginCommitOptions) (*http.Response, error) { + req, err := client.commitCreateRequest(ctx, globalRulestackName, options) + if err != nil { + return nil, err + } + resp, err := client.internal.Pipeline().Do(req) + if err != nil { + return nil, err + } + if !runtime.HasStatusCode(resp, http.StatusAccepted) { + return nil, runtime.NewResponseError(resp) + } + return resp, nil +} + +// commitCreateRequest creates the Commit request. +func (client *GlobalRulestackClient) commitCreateRequest(ctx context.Context, globalRulestackName string, options *GlobalRulestackClientBeginCommitOptions) (*policy.Request, error) { + urlPath := "/providers/PaloAltoNetworks.Cloudngfw/globalRulestacks/{globalRulestackName}/commit" + if globalRulestackName == "" { + return nil, errors.New("parameter globalRulestackName cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{globalRulestackName}", url.PathEscape(globalRulestackName)) + req, err := runtime.NewRequest(ctx, http.MethodPost, runtime.JoinPaths(client.internal.Endpoint(), urlPath)) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("api-version", "2022-08-29-preview") + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["Accept"] = []string{"application/json"} + return req, nil +} + +// BeginCreateOrUpdate - Create a GlobalRulestackResource +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2022-08-29-preview +// - globalRulestackName - GlobalRulestack resource name +// - resource - Resource create parameters. +// - options - GlobalRulestackClientBeginCreateOrUpdateOptions contains the optional parameters for the GlobalRulestackClient.BeginCreateOrUpdate +// method. +func (client *GlobalRulestackClient) BeginCreateOrUpdate(ctx context.Context, globalRulestackName string, resource GlobalRulestackResource, options *GlobalRulestackClientBeginCreateOrUpdateOptions) (*runtime.Poller[GlobalRulestackClientCreateOrUpdateResponse], error) { + if options == nil || options.ResumeToken == "" { + resp, err := client.createOrUpdate(ctx, globalRulestackName, resource, options) + if err != nil { + return nil, err + } + return runtime.NewPoller(resp, client.internal.Pipeline(), &runtime.NewPollerOptions[GlobalRulestackClientCreateOrUpdateResponse]{ + FinalStateVia: runtime.FinalStateViaAzureAsyncOp, + }) + } else { + return runtime.NewPollerFromResumeToken[GlobalRulestackClientCreateOrUpdateResponse](options.ResumeToken, client.internal.Pipeline(), nil) + } +} + +// CreateOrUpdate - Create a GlobalRulestackResource +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2022-08-29-preview +func (client *GlobalRulestackClient) createOrUpdate(ctx context.Context, globalRulestackName string, resource GlobalRulestackResource, options *GlobalRulestackClientBeginCreateOrUpdateOptions) (*http.Response, error) { + req, err := client.createOrUpdateCreateRequest(ctx, globalRulestackName, resource, options) + if err != nil { + return nil, err + } + resp, err := client.internal.Pipeline().Do(req) + if err != nil { + return nil, err + } + if !runtime.HasStatusCode(resp, http.StatusOK, http.StatusCreated) { + return nil, runtime.NewResponseError(resp) + } + return resp, nil +} + +// createOrUpdateCreateRequest creates the CreateOrUpdate request. +func (client *GlobalRulestackClient) createOrUpdateCreateRequest(ctx context.Context, globalRulestackName string, resource GlobalRulestackResource, options *GlobalRulestackClientBeginCreateOrUpdateOptions) (*policy.Request, error) { + urlPath := "/providers/PaloAltoNetworks.Cloudngfw/globalRulestacks/{globalRulestackName}" + if globalRulestackName == "" { + return nil, errors.New("parameter globalRulestackName cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{globalRulestackName}", url.PathEscape(globalRulestackName)) + req, err := runtime.NewRequest(ctx, http.MethodPut, runtime.JoinPaths(client.internal.Endpoint(), urlPath)) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("api-version", "2022-08-29-preview") + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["Accept"] = []string{"application/json"} + return req, runtime.MarshalAsJSON(req, resource) +} + +// BeginDelete - Delete a GlobalRulestackResource +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2022-08-29-preview +// - globalRulestackName - GlobalRulestack resource name +// - options - GlobalRulestackClientBeginDeleteOptions contains the optional parameters for the GlobalRulestackClient.BeginDelete +// method. +func (client *GlobalRulestackClient) BeginDelete(ctx context.Context, globalRulestackName string, options *GlobalRulestackClientBeginDeleteOptions) (*runtime.Poller[GlobalRulestackClientDeleteResponse], error) { + if options == nil || options.ResumeToken == "" { + resp, err := client.deleteOperation(ctx, globalRulestackName, options) + if err != nil { + return nil, err + } + return runtime.NewPoller(resp, client.internal.Pipeline(), &runtime.NewPollerOptions[GlobalRulestackClientDeleteResponse]{ + FinalStateVia: runtime.FinalStateViaAzureAsyncOp, + }) + } else { + return runtime.NewPollerFromResumeToken[GlobalRulestackClientDeleteResponse](options.ResumeToken, client.internal.Pipeline(), nil) + } +} + +// Delete - Delete a GlobalRulestackResource +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2022-08-29-preview +func (client *GlobalRulestackClient) deleteOperation(ctx context.Context, globalRulestackName string, options *GlobalRulestackClientBeginDeleteOptions) (*http.Response, error) { + req, err := client.deleteCreateRequest(ctx, globalRulestackName, options) + if err != nil { + return nil, err + } + resp, err := client.internal.Pipeline().Do(req) + if err != nil { + return nil, err + } + if !runtime.HasStatusCode(resp, http.StatusOK, http.StatusAccepted, http.StatusNoContent) { + return nil, runtime.NewResponseError(resp) + } + return resp, nil +} + +// deleteCreateRequest creates the Delete request. +func (client *GlobalRulestackClient) deleteCreateRequest(ctx context.Context, globalRulestackName string, options *GlobalRulestackClientBeginDeleteOptions) (*policy.Request, error) { + urlPath := "/providers/PaloAltoNetworks.Cloudngfw/globalRulestacks/{globalRulestackName}" + if globalRulestackName == "" { + return nil, errors.New("parameter globalRulestackName cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{globalRulestackName}", url.PathEscape(globalRulestackName)) + req, err := runtime.NewRequest(ctx, http.MethodDelete, runtime.JoinPaths(client.internal.Endpoint(), urlPath)) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("api-version", "2022-08-29-preview") + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["Accept"] = []string{"application/json"} + return req, nil +} + +// Get - Get a GlobalRulestackResource +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2022-08-29-preview +// - globalRulestackName - GlobalRulestack resource name +// - options - GlobalRulestackClientGetOptions contains the optional parameters for the GlobalRulestackClient.Get method. +func (client *GlobalRulestackClient) Get(ctx context.Context, globalRulestackName string, options *GlobalRulestackClientGetOptions) (GlobalRulestackClientGetResponse, error) { + req, err := client.getCreateRequest(ctx, globalRulestackName, options) + if err != nil { + return GlobalRulestackClientGetResponse{}, err + } + resp, err := client.internal.Pipeline().Do(req) + if err != nil { + return GlobalRulestackClientGetResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusOK) { + return GlobalRulestackClientGetResponse{}, runtime.NewResponseError(resp) + } + return client.getHandleResponse(resp) +} + +// getCreateRequest creates the Get request. +func (client *GlobalRulestackClient) getCreateRequest(ctx context.Context, globalRulestackName string, options *GlobalRulestackClientGetOptions) (*policy.Request, error) { + urlPath := "/providers/PaloAltoNetworks.Cloudngfw/globalRulestacks/{globalRulestackName}" + if globalRulestackName == "" { + return nil, errors.New("parameter globalRulestackName cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{globalRulestackName}", url.PathEscape(globalRulestackName)) + req, err := runtime.NewRequest(ctx, http.MethodGet, runtime.JoinPaths(client.internal.Endpoint(), urlPath)) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("api-version", "2022-08-29-preview") + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["Accept"] = []string{"application/json"} + return req, nil +} + +// getHandleResponse handles the Get response. +func (client *GlobalRulestackClient) getHandleResponse(resp *http.Response) (GlobalRulestackClientGetResponse, error) { + result := GlobalRulestackClientGetResponse{} + if err := runtime.UnmarshalAsJSON(resp, &result.GlobalRulestackResource); err != nil { + return GlobalRulestackClientGetResponse{}, err + } + return result, nil +} + +// GetChangeLog - Get changelog +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2022-08-29-preview +// - globalRulestackName - GlobalRulestack resource name +// - options - GlobalRulestackClientGetChangeLogOptions contains the optional parameters for the GlobalRulestackClient.GetChangeLog +// method. +func (client *GlobalRulestackClient) GetChangeLog(ctx context.Context, globalRulestackName string, options *GlobalRulestackClientGetChangeLogOptions) (GlobalRulestackClientGetChangeLogResponse, error) { + req, err := client.getChangeLogCreateRequest(ctx, globalRulestackName, options) + if err != nil { + return GlobalRulestackClientGetChangeLogResponse{}, err + } + resp, err := client.internal.Pipeline().Do(req) + if err != nil { + return GlobalRulestackClientGetChangeLogResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusOK) { + return GlobalRulestackClientGetChangeLogResponse{}, runtime.NewResponseError(resp) + } + return client.getChangeLogHandleResponse(resp) +} + +// getChangeLogCreateRequest creates the GetChangeLog request. +func (client *GlobalRulestackClient) getChangeLogCreateRequest(ctx context.Context, globalRulestackName string, options *GlobalRulestackClientGetChangeLogOptions) (*policy.Request, error) { + urlPath := "/providers/PaloAltoNetworks.Cloudngfw/globalRulestacks/{globalRulestackName}/getChangeLog" + if globalRulestackName == "" { + return nil, errors.New("parameter globalRulestackName cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{globalRulestackName}", url.PathEscape(globalRulestackName)) + req, err := runtime.NewRequest(ctx, http.MethodPost, runtime.JoinPaths(client.internal.Endpoint(), urlPath)) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("api-version", "2022-08-29-preview") + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["Accept"] = []string{"application/json"} + return req, nil +} + +// getChangeLogHandleResponse handles the GetChangeLog response. +func (client *GlobalRulestackClient) getChangeLogHandleResponse(resp *http.Response) (GlobalRulestackClientGetChangeLogResponse, error) { + result := GlobalRulestackClientGetChangeLogResponse{} + if err := runtime.UnmarshalAsJSON(resp, &result.Changelog); err != nil { + return GlobalRulestackClientGetChangeLogResponse{}, err + } + return result, nil +} + +// NewListPager - List GlobalRulestackResource resources by Tenant +// +// Generated from API version 2022-08-29-preview +// - options - GlobalRulestackClientListOptions contains the optional parameters for the GlobalRulestackClient.NewListPager +// method. +func (client *GlobalRulestackClient) NewListPager(options *GlobalRulestackClientListOptions) *runtime.Pager[GlobalRulestackClientListResponse] { + return runtime.NewPager(runtime.PagingHandler[GlobalRulestackClientListResponse]{ + More: func(page GlobalRulestackClientListResponse) bool { + return page.NextLink != nil && len(*page.NextLink) > 0 + }, + Fetcher: func(ctx context.Context, page *GlobalRulestackClientListResponse) (GlobalRulestackClientListResponse, error) { + var req *policy.Request + var err error + if page == nil { + req, err = client.listCreateRequest(ctx, options) + } else { + req, err = runtime.NewRequest(ctx, http.MethodGet, *page.NextLink) + } + if err != nil { + return GlobalRulestackClientListResponse{}, err + } + resp, err := client.internal.Pipeline().Do(req) + if err != nil { + return GlobalRulestackClientListResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusOK) { + return GlobalRulestackClientListResponse{}, runtime.NewResponseError(resp) + } + return client.listHandleResponse(resp) + }, + }) +} + +// listCreateRequest creates the List request. +func (client *GlobalRulestackClient) listCreateRequest(ctx context.Context, options *GlobalRulestackClientListOptions) (*policy.Request, error) { + urlPath := "/providers/PaloAltoNetworks.Cloudngfw/globalRulestacks" + req, err := runtime.NewRequest(ctx, http.MethodGet, runtime.JoinPaths(client.internal.Endpoint(), urlPath)) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("api-version", "2022-08-29-preview") + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["Accept"] = []string{"application/json"} + return req, nil +} + +// listHandleResponse handles the List response. +func (client *GlobalRulestackClient) listHandleResponse(resp *http.Response) (GlobalRulestackClientListResponse, error) { + result := GlobalRulestackClientListResponse{} + if err := runtime.UnmarshalAsJSON(resp, &result.GlobalRulestackResourceListResult); err != nil { + return GlobalRulestackClientListResponse{}, err + } + return result, nil +} + +// ListAdvancedSecurityObjects - Get the list of advanced security objects +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2022-08-29-preview +// - globalRulestackName - GlobalRulestack resource name +// - options - GlobalRulestackClientListAdvancedSecurityObjectsOptions contains the optional parameters for the GlobalRulestackClient.ListAdvancedSecurityObjects +// method. +func (client *GlobalRulestackClient) ListAdvancedSecurityObjects(ctx context.Context, globalRulestackName string, typeParam AdvSecurityObjectTypeEnum, options *GlobalRulestackClientListAdvancedSecurityObjectsOptions) (GlobalRulestackClientListAdvancedSecurityObjectsResponse, error) { + req, err := client.listAdvancedSecurityObjectsCreateRequest(ctx, globalRulestackName, typeParam, options) + if err != nil { + return GlobalRulestackClientListAdvancedSecurityObjectsResponse{}, err + } + resp, err := client.internal.Pipeline().Do(req) + if err != nil { + return GlobalRulestackClientListAdvancedSecurityObjectsResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusOK) { + return GlobalRulestackClientListAdvancedSecurityObjectsResponse{}, runtime.NewResponseError(resp) + } + return client.listAdvancedSecurityObjectsHandleResponse(resp) +} + +// listAdvancedSecurityObjectsCreateRequest creates the ListAdvancedSecurityObjects request. +func (client *GlobalRulestackClient) listAdvancedSecurityObjectsCreateRequest(ctx context.Context, globalRulestackName string, typeParam AdvSecurityObjectTypeEnum, options *GlobalRulestackClientListAdvancedSecurityObjectsOptions) (*policy.Request, error) { + urlPath := "/providers/PaloAltoNetworks.Cloudngfw/globalRulestacks/{globalRulestackName}/listAdvancedSecurityObjects" + if globalRulestackName == "" { + return nil, errors.New("parameter globalRulestackName cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{globalRulestackName}", url.PathEscape(globalRulestackName)) + req, err := runtime.NewRequest(ctx, http.MethodPost, runtime.JoinPaths(client.internal.Endpoint(), urlPath)) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("api-version", "2022-08-29-preview") + if options != nil && options.Skip != nil { + reqQP.Set("skip", *options.Skip) + } + if options != nil && options.Top != nil { + reqQP.Set("top", strconv.FormatInt(int64(*options.Top), 10)) + } + reqQP.Set("type", string(typeParam)) + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["Accept"] = []string{"application/json"} + return req, nil +} + +// listAdvancedSecurityObjectsHandleResponse handles the ListAdvancedSecurityObjects response. +func (client *GlobalRulestackClient) listAdvancedSecurityObjectsHandleResponse(resp *http.Response) (GlobalRulestackClientListAdvancedSecurityObjectsResponse, error) { + result := GlobalRulestackClientListAdvancedSecurityObjectsResponse{} + if err := runtime.UnmarshalAsJSON(resp, &result.AdvSecurityObjectListResponse); err != nil { + return GlobalRulestackClientListAdvancedSecurityObjectsResponse{}, err + } + return result, nil +} + +// ListAppIDs - List of AppIds for GlobalRulestack ApiVersion +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2022-08-29-preview +// - globalRulestackName - GlobalRulestack resource name +// - options - GlobalRulestackClientListAppIDsOptions contains the optional parameters for the GlobalRulestackClient.ListAppIDs +// method. +func (client *GlobalRulestackClient) ListAppIDs(ctx context.Context, globalRulestackName string, options *GlobalRulestackClientListAppIDsOptions) (GlobalRulestackClientListAppIDsResponse, error) { + req, err := client.listAppIDsCreateRequest(ctx, globalRulestackName, options) + if err != nil { + return GlobalRulestackClientListAppIDsResponse{}, err + } + resp, err := client.internal.Pipeline().Do(req) + if err != nil { + return GlobalRulestackClientListAppIDsResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusOK) { + return GlobalRulestackClientListAppIDsResponse{}, runtime.NewResponseError(resp) + } + return client.listAppIDsHandleResponse(resp) +} + +// listAppIDsCreateRequest creates the ListAppIDs request. +func (client *GlobalRulestackClient) listAppIDsCreateRequest(ctx context.Context, globalRulestackName string, options *GlobalRulestackClientListAppIDsOptions) (*policy.Request, error) { + urlPath := "/providers/PaloAltoNetworks.Cloudngfw/globalRulestacks/{globalRulestackName}/listAppIds" + if globalRulestackName == "" { + return nil, errors.New("parameter globalRulestackName cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{globalRulestackName}", url.PathEscape(globalRulestackName)) + req, err := runtime.NewRequest(ctx, http.MethodPost, runtime.JoinPaths(client.internal.Endpoint(), urlPath)) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("api-version", "2022-08-29-preview") + if options != nil && options.AppIDVersion != nil { + reqQP.Set("appIdVersion", *options.AppIDVersion) + } + if options != nil && options.AppPrefix != nil { + reqQP.Set("appPrefix", *options.AppPrefix) + } + if options != nil && options.Skip != nil { + reqQP.Set("skip", *options.Skip) + } + if options != nil && options.Top != nil { + reqQP.Set("top", strconv.FormatInt(int64(*options.Top), 10)) + } + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["Accept"] = []string{"application/json"} + return req, nil +} + +// listAppIDsHandleResponse handles the ListAppIDs response. +func (client *GlobalRulestackClient) listAppIDsHandleResponse(resp *http.Response) (GlobalRulestackClientListAppIDsResponse, error) { + result := GlobalRulestackClientListAppIDsResponse{} + if err := runtime.UnmarshalAsJSON(resp, &result.ListAppIDResponse); err != nil { + return GlobalRulestackClientListAppIDsResponse{}, err + } + return result, nil +} + +// ListCountries - List of countries for Rulestack +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2022-08-29-preview +// - globalRulestackName - GlobalRulestack resource name +// - options - GlobalRulestackClientListCountriesOptions contains the optional parameters for the GlobalRulestackClient.ListCountries +// method. +func (client *GlobalRulestackClient) ListCountries(ctx context.Context, globalRulestackName string, options *GlobalRulestackClientListCountriesOptions) (GlobalRulestackClientListCountriesResponse, error) { + req, err := client.listCountriesCreateRequest(ctx, globalRulestackName, options) + if err != nil { + return GlobalRulestackClientListCountriesResponse{}, err + } + resp, err := client.internal.Pipeline().Do(req) + if err != nil { + return GlobalRulestackClientListCountriesResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusOK) { + return GlobalRulestackClientListCountriesResponse{}, runtime.NewResponseError(resp) + } + return client.listCountriesHandleResponse(resp) +} + +// listCountriesCreateRequest creates the ListCountries request. +func (client *GlobalRulestackClient) listCountriesCreateRequest(ctx context.Context, globalRulestackName string, options *GlobalRulestackClientListCountriesOptions) (*policy.Request, error) { + urlPath := "/providers/PaloAltoNetworks.Cloudngfw/globalRulestacks/{globalRulestackName}/listCountries" + if globalRulestackName == "" { + return nil, errors.New("parameter globalRulestackName cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{globalRulestackName}", url.PathEscape(globalRulestackName)) + req, err := runtime.NewRequest(ctx, http.MethodPost, runtime.JoinPaths(client.internal.Endpoint(), urlPath)) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("api-version", "2022-08-29-preview") + if options != nil && options.Skip != nil { + reqQP.Set("skip", *options.Skip) + } + if options != nil && options.Top != nil { + reqQP.Set("top", strconv.FormatInt(int64(*options.Top), 10)) + } + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["Accept"] = []string{"application/json"} + return req, nil +} + +// listCountriesHandleResponse handles the ListCountries response. +func (client *GlobalRulestackClient) listCountriesHandleResponse(resp *http.Response) (GlobalRulestackClientListCountriesResponse, error) { + result := GlobalRulestackClientListCountriesResponse{} + if err := runtime.UnmarshalAsJSON(resp, &result.CountriesResponse); err != nil { + return GlobalRulestackClientListCountriesResponse{}, err + } + return result, nil +} + +// ListFirewalls - List of Firewalls associated with Rulestack +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2022-08-29-preview +// - globalRulestackName - GlobalRulestack resource name +// - options - GlobalRulestackClientListFirewallsOptions contains the optional parameters for the GlobalRulestackClient.ListFirewalls +// method. +func (client *GlobalRulestackClient) ListFirewalls(ctx context.Context, globalRulestackName string, options *GlobalRulestackClientListFirewallsOptions) (GlobalRulestackClientListFirewallsResponse, error) { + req, err := client.listFirewallsCreateRequest(ctx, globalRulestackName, options) + if err != nil { + return GlobalRulestackClientListFirewallsResponse{}, err + } + resp, err := client.internal.Pipeline().Do(req) + if err != nil { + return GlobalRulestackClientListFirewallsResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusOK) { + return GlobalRulestackClientListFirewallsResponse{}, runtime.NewResponseError(resp) + } + return client.listFirewallsHandleResponse(resp) +} + +// listFirewallsCreateRequest creates the ListFirewalls request. +func (client *GlobalRulestackClient) listFirewallsCreateRequest(ctx context.Context, globalRulestackName string, options *GlobalRulestackClientListFirewallsOptions) (*policy.Request, error) { + urlPath := "/providers/PaloAltoNetworks.Cloudngfw/globalRulestacks/{globalRulestackName}/listFirewalls" + if globalRulestackName == "" { + return nil, errors.New("parameter globalRulestackName cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{globalRulestackName}", url.PathEscape(globalRulestackName)) + req, err := runtime.NewRequest(ctx, http.MethodPost, runtime.JoinPaths(client.internal.Endpoint(), urlPath)) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("api-version", "2022-08-29-preview") + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["Accept"] = []string{"application/json"} + return req, nil +} + +// listFirewallsHandleResponse handles the ListFirewalls response. +func (client *GlobalRulestackClient) listFirewallsHandleResponse(resp *http.Response) (GlobalRulestackClientListFirewallsResponse, error) { + result := GlobalRulestackClientListFirewallsResponse{} + if err := runtime.UnmarshalAsJSON(resp, &result.ListFirewallsResponse); err != nil { + return GlobalRulestackClientListFirewallsResponse{}, err + } + return result, nil +} + +// ListPredefinedURLCategories - List predefined URL categories for rulestack +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2022-08-29-preview +// - globalRulestackName - GlobalRulestack resource name +// - options - GlobalRulestackClientListPredefinedURLCategoriesOptions contains the optional parameters for the GlobalRulestackClient.ListPredefinedURLCategories +// method. +func (client *GlobalRulestackClient) ListPredefinedURLCategories(ctx context.Context, globalRulestackName string, options *GlobalRulestackClientListPredefinedURLCategoriesOptions) (GlobalRulestackClientListPredefinedURLCategoriesResponse, error) { + req, err := client.listPredefinedURLCategoriesCreateRequest(ctx, globalRulestackName, options) + if err != nil { + return GlobalRulestackClientListPredefinedURLCategoriesResponse{}, err + } + resp, err := client.internal.Pipeline().Do(req) + if err != nil { + return GlobalRulestackClientListPredefinedURLCategoriesResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusOK) { + return GlobalRulestackClientListPredefinedURLCategoriesResponse{}, runtime.NewResponseError(resp) + } + return client.listPredefinedURLCategoriesHandleResponse(resp) +} + +// listPredefinedURLCategoriesCreateRequest creates the ListPredefinedURLCategories request. +func (client *GlobalRulestackClient) listPredefinedURLCategoriesCreateRequest(ctx context.Context, globalRulestackName string, options *GlobalRulestackClientListPredefinedURLCategoriesOptions) (*policy.Request, error) { + urlPath := "/providers/PaloAltoNetworks.Cloudngfw/globalRulestacks/{globalRulestackName}/listPredefinedUrlCategories" + if globalRulestackName == "" { + return nil, errors.New("parameter globalRulestackName cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{globalRulestackName}", url.PathEscape(globalRulestackName)) + req, err := runtime.NewRequest(ctx, http.MethodPost, runtime.JoinPaths(client.internal.Endpoint(), urlPath)) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("api-version", "2022-08-29-preview") + if options != nil && options.Skip != nil { + reqQP.Set("skip", *options.Skip) + } + if options != nil && options.Top != nil { + reqQP.Set("top", strconv.FormatInt(int64(*options.Top), 10)) + } + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["Accept"] = []string{"application/json"} + return req, nil +} + +// listPredefinedURLCategoriesHandleResponse handles the ListPredefinedURLCategories response. +func (client *GlobalRulestackClient) listPredefinedURLCategoriesHandleResponse(resp *http.Response) (GlobalRulestackClientListPredefinedURLCategoriesResponse, error) { + result := GlobalRulestackClientListPredefinedURLCategoriesResponse{} + if err := runtime.UnmarshalAsJSON(resp, &result.PredefinedURLCategoriesResponse); err != nil { + return GlobalRulestackClientListPredefinedURLCategoriesResponse{}, err + } + return result, nil +} + +// ListSecurityServices - List the security services for rulestack +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2022-08-29-preview +// - globalRulestackName - GlobalRulestack resource name +// - options - GlobalRulestackClientListSecurityServicesOptions contains the optional parameters for the GlobalRulestackClient.ListSecurityServices +// method. +func (client *GlobalRulestackClient) ListSecurityServices(ctx context.Context, globalRulestackName string, typeParam SecurityServicesTypeEnum, options *GlobalRulestackClientListSecurityServicesOptions) (GlobalRulestackClientListSecurityServicesResponse, error) { + req, err := client.listSecurityServicesCreateRequest(ctx, globalRulestackName, typeParam, options) + if err != nil { + return GlobalRulestackClientListSecurityServicesResponse{}, err + } + resp, err := client.internal.Pipeline().Do(req) + if err != nil { + return GlobalRulestackClientListSecurityServicesResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusOK) { + return GlobalRulestackClientListSecurityServicesResponse{}, runtime.NewResponseError(resp) + } + return client.listSecurityServicesHandleResponse(resp) +} + +// listSecurityServicesCreateRequest creates the ListSecurityServices request. +func (client *GlobalRulestackClient) listSecurityServicesCreateRequest(ctx context.Context, globalRulestackName string, typeParam SecurityServicesTypeEnum, options *GlobalRulestackClientListSecurityServicesOptions) (*policy.Request, error) { + urlPath := "/providers/PaloAltoNetworks.Cloudngfw/globalRulestacks/{globalRulestackName}/listSecurityServices" + if globalRulestackName == "" { + return nil, errors.New("parameter globalRulestackName cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{globalRulestackName}", url.PathEscape(globalRulestackName)) + req, err := runtime.NewRequest(ctx, http.MethodPost, runtime.JoinPaths(client.internal.Endpoint(), urlPath)) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("api-version", "2022-08-29-preview") + if options != nil && options.Skip != nil { + reqQP.Set("skip", *options.Skip) + } + if options != nil && options.Top != nil { + reqQP.Set("top", strconv.FormatInt(int64(*options.Top), 10)) + } + reqQP.Set("type", string(typeParam)) + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["Accept"] = []string{"application/json"} + return req, nil +} + +// listSecurityServicesHandleResponse handles the ListSecurityServices response. +func (client *GlobalRulestackClient) listSecurityServicesHandleResponse(resp *http.Response) (GlobalRulestackClientListSecurityServicesResponse, error) { + result := GlobalRulestackClientListSecurityServicesResponse{} + if err := runtime.UnmarshalAsJSON(resp, &result.SecurityServicesResponse); err != nil { + return GlobalRulestackClientListSecurityServicesResponse{}, err + } + return result, nil +} + +// Revert - Revert rulestack configuration +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2022-08-29-preview +// - globalRulestackName - GlobalRulestack resource name +// - options - GlobalRulestackClientRevertOptions contains the optional parameters for the GlobalRulestackClient.Revert method. +func (client *GlobalRulestackClient) Revert(ctx context.Context, globalRulestackName string, options *GlobalRulestackClientRevertOptions) (GlobalRulestackClientRevertResponse, error) { + req, err := client.revertCreateRequest(ctx, globalRulestackName, options) + if err != nil { + return GlobalRulestackClientRevertResponse{}, err + } + resp, err := client.internal.Pipeline().Do(req) + if err != nil { + return GlobalRulestackClientRevertResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusNoContent) { + return GlobalRulestackClientRevertResponse{}, runtime.NewResponseError(resp) + } + return GlobalRulestackClientRevertResponse{}, nil +} + +// revertCreateRequest creates the Revert request. +func (client *GlobalRulestackClient) revertCreateRequest(ctx context.Context, globalRulestackName string, options *GlobalRulestackClientRevertOptions) (*policy.Request, error) { + urlPath := "/providers/PaloAltoNetworks.Cloudngfw/globalRulestacks/{globalRulestackName}/revert" + if globalRulestackName == "" { + return nil, errors.New("parameter globalRulestackName cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{globalRulestackName}", url.PathEscape(globalRulestackName)) + req, err := runtime.NewRequest(ctx, http.MethodPost, runtime.JoinPaths(client.internal.Endpoint(), urlPath)) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("api-version", "2022-08-29-preview") + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["Accept"] = []string{"application/json"} + return req, nil +} + +// Update - Update a GlobalRulestackResource +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2022-08-29-preview +// - globalRulestackName - GlobalRulestack resource name +// - properties - The resource properties to be updated. +// - options - GlobalRulestackClientUpdateOptions contains the optional parameters for the GlobalRulestackClient.Update method. +func (client *GlobalRulestackClient) Update(ctx context.Context, globalRulestackName string, properties GlobalRulestackResourceUpdate, options *GlobalRulestackClientUpdateOptions) (GlobalRulestackClientUpdateResponse, error) { + req, err := client.updateCreateRequest(ctx, globalRulestackName, properties, options) + if err != nil { + return GlobalRulestackClientUpdateResponse{}, err + } + resp, err := client.internal.Pipeline().Do(req) + if err != nil { + return GlobalRulestackClientUpdateResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusOK) { + return GlobalRulestackClientUpdateResponse{}, runtime.NewResponseError(resp) + } + return client.updateHandleResponse(resp) +} + +// updateCreateRequest creates the Update request. +func (client *GlobalRulestackClient) updateCreateRequest(ctx context.Context, globalRulestackName string, properties GlobalRulestackResourceUpdate, options *GlobalRulestackClientUpdateOptions) (*policy.Request, error) { + urlPath := "/providers/PaloAltoNetworks.Cloudngfw/globalRulestacks/{globalRulestackName}" + if globalRulestackName == "" { + return nil, errors.New("parameter globalRulestackName cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{globalRulestackName}", url.PathEscape(globalRulestackName)) + req, err := runtime.NewRequest(ctx, http.MethodPatch, runtime.JoinPaths(client.internal.Endpoint(), urlPath)) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("api-version", "2022-08-29-preview") + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["Accept"] = []string{"application/json"} + return req, runtime.MarshalAsJSON(req, properties) +} + +// updateHandleResponse handles the Update response. +func (client *GlobalRulestackClient) updateHandleResponse(resp *http.Response) (GlobalRulestackClientUpdateResponse, error) { + result := GlobalRulestackClientUpdateResponse{} + if err := runtime.UnmarshalAsJSON(resp, &result.GlobalRulestackResource); err != nil { + return GlobalRulestackClientUpdateResponse{}, err + } + return result, nil +} diff --git a/sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/globalrulestack_client_example_test.go b/sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/globalrulestack_client_example_test.go new file mode 100644 index 000000000000..b7cbad9ced12 --- /dev/null +++ b/sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/globalrulestack_client_example_test.go @@ -0,0 +1,987 @@ +//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. +// Code generated by Microsoft (R) AutoRest Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. +// DO NOT EDIT. + +package armpanngfw_test + +import ( + "context" + "log" + + "github.com/Azure/azure-sdk-for-go/sdk/azcore/to" + "github.com/Azure/azure-sdk-for-go/sdk/azidentity" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/paloaltonetworksngfw/armpanngfw" +) + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/GlobalRulestack_List_MaximumSet_Gen.json +func ExampleGlobalRulestackClient_NewListPager_globalRulestackListMaximumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + pager := clientFactory.NewGlobalRulestackClient().NewListPager(nil) + for pager.More() { + page, err := pager.NextPage(ctx) + if err != nil { + log.Fatalf("failed to advance page: %v", err) + } + for _, v := range page.Value { + // You could use page here. We use blank identifier for just demo purposes. + _ = v + } + // If the HTTP response code is 200 as defined in example definition, your page structure would look as follows. Please pay attention that all the values in the output are fake values for just demo purposes. + // page.GlobalRulestackResourceListResult = armpanngfw.GlobalRulestackResourceListResult{ + // Value: []*armpanngfw.GlobalRulestackResource{ + // { + // Name: to.Ptr("aaaaaaaaaaaaaaaaaaaaaaaa"), + // Type: to.Ptr("aaaaaaaaaaaaaaaaaa"), + // ID: to.Ptr("aaaaaaaaaa"), + // SystemData: &armpanngfw.SystemData{ + // CreatedAt: to.Ptr(func() time.Time { t, _ := time.Parse(time.RFC3339Nano, "2022-09-09T05:08:24.229Z"); return t}()), + // CreatedBy: to.Ptr("praval"), + // CreatedByType: to.Ptr(armpanngfw.CreatedByTypeUser), + // LastModifiedAt: to.Ptr(func() time.Time { t, _ := time.Parse(time.RFC3339Nano, "2022-09-09T05:08:24.229Z"); return t}()), + // LastModifiedBy: to.Ptr("praval"), + // LastModifiedByType: to.Ptr(armpanngfw.CreatedByTypeUser), + // }, + // Identity: &armpanngfw.AzureResourceManagerManagedIdentityProperties{ + // Type: to.Ptr(armpanngfw.ManagedIdentityTypeNone), + // PrincipalID: to.Ptr("aaaaaaaaaaaaaaaaaaaaaaaaaa"), + // TenantID: to.Ptr("aaaaaaaaaaaaaaaaaaaaaaaaaaaa"), + // UserAssignedIdentities: map[string]*armpanngfw.AzureResourceManagerUserAssignedIdentity{ + // "key16": &armpanngfw.AzureResourceManagerUserAssignedIdentity{ + // ClientID: to.Ptr("aaaa"), + // PrincipalID: to.Ptr("aaaaaaaaaaaaaaa"), + // }, + // }, + // }, + // Location: to.Ptr("eastus"), + // Properties: &armpanngfw.RulestackProperties{ + // Description: to.Ptr("aaaaaaaaaaaaaaaaaaaaa"), + // AssociatedSubscriptions: []*string{ + // to.Ptr("aaaaaaaaaaaaaaaaaaaaaaaaa")}, + // DefaultMode: to.Ptr(armpanngfw.DefaultModeIPS), + // MinAppIDVersion: to.Ptr("aaaaaaaaaaaaaaaaaaaaa"), + // PanEtag: to.Ptr("2bf4a339-294d-4c25-b0b2-ef649e9f5c12"), + // PanLocation: to.Ptr("eastus"), + // ProvisioningState: to.Ptr(armpanngfw.ProvisioningStateSucceeded), + // Scope: to.Ptr(armpanngfw.ScopeTypeLOCAL), + // SecurityServices: &armpanngfw.SecurityServices{ + // AntiSpywareProfile: to.Ptr("aaaaaaaaaa"), + // AntiVirusProfile: to.Ptr("aaaaaaaaaaaaaaaaaaaaaa"), + // DNSSubscription: to.Ptr("aaaaaaaaaaaaaaaaaaaaaaaaaaaa"), + // FileBlockingProfile: to.Ptr("aaaaa"), + // OutboundTrustCertificate: to.Ptr("aaaaaa"), + // OutboundUnTrustCertificate: to.Ptr("aaaaaaaa"), + // URLFilteringProfile: to.Ptr("aaaaaaaaaaaaaaaaaaaaaaaaaaa"), + // VulnerabilityProfile: to.Ptr("aaaaaaaaaa"), + // }, + // }, + // }}, + // } + } +} + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/GlobalRulestack_List_MinimumSet_Gen.json +func ExampleGlobalRulestackClient_NewListPager_globalRulestackListMinimumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + pager := clientFactory.NewGlobalRulestackClient().NewListPager(nil) + for pager.More() { + page, err := pager.NextPage(ctx) + if err != nil { + log.Fatalf("failed to advance page: %v", err) + } + for _, v := range page.Value { + // You could use page here. We use blank identifier for just demo purposes. + _ = v + } + // If the HTTP response code is 200 as defined in example definition, your page structure would look as follows. Please pay attention that all the values in the output are fake values for just demo purposes. + // page.GlobalRulestackResourceListResult = armpanngfw.GlobalRulestackResourceListResult{ + // Value: []*armpanngfw.GlobalRulestackResource{ + // { + // ID: to.Ptr("/providers/PaloAltoNetworks.Cloudngfw/globalRulestacks/grs1"), + // Location: to.Ptr("eastus"), + // Properties: &armpanngfw.RulestackProperties{ + // }, + // }}, + // } + } +} + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/GlobalRulestack_Get_MaximumSet_Gen.json +func ExampleGlobalRulestackClient_Get_globalRulestackGetMaximumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + res, err := clientFactory.NewGlobalRulestackClient().Get(ctx, "praval", nil) + if err != nil { + log.Fatalf("failed to finish the request: %v", err) + } + // You could use response here. We use blank identifier for just demo purposes. + _ = res + // If the HTTP response code is 200 as defined in example definition, your response structure would look as follows. Please pay attention that all the values in the output are fake values for just demo purposes. + // res.GlobalRulestackResource = armpanngfw.GlobalRulestackResource{ + // Name: to.Ptr("armid1"), + // Type: to.Ptr("globalRulestacks"), + // ID: to.Ptr("/providers/PaloAltoNetworks.Cloudngfw/globalrulestacks/armid1"), + // SystemData: &armpanngfw.SystemData{ + // CreatedAt: to.Ptr(func() time.Time { t, _ := time.Parse(time.RFC3339Nano, "2022-09-09T05:08:24.229Z"); return t}()), + // CreatedBy: to.Ptr("praval"), + // CreatedByType: to.Ptr(armpanngfw.CreatedByTypeUser), + // LastModifiedAt: to.Ptr(func() time.Time { t, _ := time.Parse(time.RFC3339Nano, "2022-09-09T05:08:24.229Z"); return t}()), + // LastModifiedBy: to.Ptr("praval"), + // LastModifiedByType: to.Ptr(armpanngfw.CreatedByTypeUser), + // }, + // Identity: &armpanngfw.AzureResourceManagerManagedIdentityProperties{ + // Type: to.Ptr(armpanngfw.ManagedIdentityTypeNone), + // PrincipalID: to.Ptr("2bf4a339-294d-4c25-b0b2-ef649e9f5c27"), + // TenantID: to.Ptr("2bf4a339-294d-4c25-b0b2-ef649e9f5c27"), + // UserAssignedIdentities: map[string]*armpanngfw.AzureResourceManagerUserAssignedIdentity{ + // "key16": &armpanngfw.AzureResourceManagerUserAssignedIdentity{ + // ClientID: to.Ptr("aaaa"), + // PrincipalID: to.Ptr("aaaaaaaaaaaaaaa"), + // }, + // }, + // }, + // Location: to.Ptr("eastus"), + // Properties: &armpanngfw.RulestackProperties{ + // Description: to.Ptr("global rulestacks"), + // AssociatedSubscriptions: []*string{ + // to.Ptr("2bf4a339-294d-4c25-b0b2-ef649e9f5c27")}, + // DefaultMode: to.Ptr(armpanngfw.DefaultModeIPS), + // MinAppIDVersion: to.Ptr("8.5.3"), + // PanEtag: to.Ptr("2bf4a339-294d-4c25-b0b2-ef649e9f5c12"), + // PanLocation: to.Ptr("eastus"), + // ProvisioningState: to.Ptr(armpanngfw.ProvisioningStateSucceeded), + // Scope: to.Ptr(armpanngfw.ScopeTypeGLOBAL), + // SecurityServices: &armpanngfw.SecurityServices{ + // AntiSpywareProfile: to.Ptr("default"), + // AntiVirusProfile: to.Ptr("default"), + // DNSSubscription: to.Ptr("default"), + // FileBlockingProfile: to.Ptr("default"), + // OutboundTrustCertificate: to.Ptr("default"), + // OutboundUnTrustCertificate: to.Ptr("default"), + // URLFilteringProfile: to.Ptr("default"), + // VulnerabilityProfile: to.Ptr("default"), + // }, + // }, + // } +} + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/GlobalRulestack_Get_MinimumSet_Gen.json +func ExampleGlobalRulestackClient_Get_globalRulestackGetMinimumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + res, err := clientFactory.NewGlobalRulestackClient().Get(ctx, "praval", nil) + if err != nil { + log.Fatalf("failed to finish the request: %v", err) + } + // You could use response here. We use blank identifier for just demo purposes. + _ = res + // If the HTTP response code is 200 as defined in example definition, your response structure would look as follows. Please pay attention that all the values in the output are fake values for just demo purposes. + // res.GlobalRulestackResource = armpanngfw.GlobalRulestackResource{ + // ID: to.Ptr("/providers/PaloAltoNetworks.Cloudngfw/globalRulestacks/praval"), + // Location: to.Ptr("eastus"), + // Properties: &armpanngfw.RulestackProperties{ + // }, + // } +} + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/GlobalRulestack_CreateOrUpdate_MaximumSet_Gen.json +func ExampleGlobalRulestackClient_BeginCreateOrUpdate_globalRulestackCreateOrUpdateMaximumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + poller, err := clientFactory.NewGlobalRulestackClient().BeginCreateOrUpdate(ctx, "praval", armpanngfw.GlobalRulestackResource{ + Identity: &armpanngfw.AzureResourceManagerManagedIdentityProperties{ + Type: to.Ptr(armpanngfw.ManagedIdentityTypeNone), + UserAssignedIdentities: map[string]*armpanngfw.AzureResourceManagerUserAssignedIdentity{ + "key16": { + ClientID: to.Ptr("aaaa"), + PrincipalID: to.Ptr("aaaaaaaaaaaaaaa"), + }, + }, + }, + Location: to.Ptr("eastus"), + Properties: &armpanngfw.RulestackProperties{ + Description: to.Ptr("global rulestacks"), + AssociatedSubscriptions: []*string{ + to.Ptr("2bf4a339-294d-4c25-b0b2-ef649e9f5c27")}, + DefaultMode: to.Ptr(armpanngfw.DefaultModeIPS), + MinAppIDVersion: to.Ptr("8.5.3"), + PanEtag: to.Ptr("2bf4a339-294d-4c25-b0b2-ef649e9f5c12"), + PanLocation: to.Ptr("eastus"), + ProvisioningState: to.Ptr(armpanngfw.ProvisioningStateAccepted), + Scope: to.Ptr(armpanngfw.ScopeTypeGLOBAL), + SecurityServices: &armpanngfw.SecurityServices{ + AntiSpywareProfile: to.Ptr("default"), + AntiVirusProfile: to.Ptr("default"), + DNSSubscription: to.Ptr("default"), + FileBlockingProfile: to.Ptr("default"), + OutboundTrustCertificate: to.Ptr("default"), + OutboundUnTrustCertificate: to.Ptr("default"), + URLFilteringProfile: to.Ptr("default"), + VulnerabilityProfile: to.Ptr("default"), + }, + }, + }, nil) + if err != nil { + log.Fatalf("failed to finish the request: %v", err) + } + res, err := poller.PollUntilDone(ctx, nil) + if err != nil { + log.Fatalf("failed to pull the result: %v", err) + } + // You could use response here. We use blank identifier for just demo purposes. + _ = res + // If the HTTP response code is 200 as defined in example definition, your response structure would look as follows. Please pay attention that all the values in the output are fake values for just demo purposes. + // res.GlobalRulestackResource = armpanngfw.GlobalRulestackResource{ + // Name: to.Ptr("armid1"), + // Type: to.Ptr("globalRulestacks"), + // ID: to.Ptr("/providers/PaloAltoNetworks.Cloudngfw/globalrulestacks/armid1"), + // SystemData: &armpanngfw.SystemData{ + // CreatedAt: to.Ptr(func() time.Time { t, _ := time.Parse(time.RFC3339Nano, "2022-09-09T05:08:24.229Z"); return t}()), + // CreatedBy: to.Ptr("praval"), + // CreatedByType: to.Ptr(armpanngfw.CreatedByTypeUser), + // LastModifiedAt: to.Ptr(func() time.Time { t, _ := time.Parse(time.RFC3339Nano, "2022-09-09T05:08:24.229Z"); return t}()), + // LastModifiedBy: to.Ptr("praval"), + // LastModifiedByType: to.Ptr(armpanngfw.CreatedByTypeUser), + // }, + // Identity: &armpanngfw.AzureResourceManagerManagedIdentityProperties{ + // Type: to.Ptr(armpanngfw.ManagedIdentityTypeNone), + // PrincipalID: to.Ptr("2bf4a339-294d-4c25-b0b2-ef649e9f5c27"), + // TenantID: to.Ptr("2bf4a339-294d-4c25-b0b2-ef649e9f5c27"), + // UserAssignedIdentities: map[string]*armpanngfw.AzureResourceManagerUserAssignedIdentity{ + // "key16": &armpanngfw.AzureResourceManagerUserAssignedIdentity{ + // ClientID: to.Ptr("aaaa"), + // PrincipalID: to.Ptr("aaaaaaaaaaaaaaa"), + // }, + // }, + // }, + // Location: to.Ptr("eastus"), + // Properties: &armpanngfw.RulestackProperties{ + // Description: to.Ptr("global rulestacks"), + // AssociatedSubscriptions: []*string{ + // to.Ptr("2bf4a339-294d-4c25-b0b2-ef649e9f5c27")}, + // DefaultMode: to.Ptr(armpanngfw.DefaultModeIPS), + // MinAppIDVersion: to.Ptr("8.5.3"), + // PanEtag: to.Ptr("2bf4a339-294d-4c25-b0b2-ef649e9f5c12"), + // PanLocation: to.Ptr("eastus"), + // ProvisioningState: to.Ptr(armpanngfw.ProvisioningStateSucceeded), + // Scope: to.Ptr(armpanngfw.ScopeTypeGLOBAL), + // SecurityServices: &armpanngfw.SecurityServices{ + // AntiSpywareProfile: to.Ptr("default"), + // AntiVirusProfile: to.Ptr("default"), + // DNSSubscription: to.Ptr("default"), + // FileBlockingProfile: to.Ptr("default"), + // OutboundTrustCertificate: to.Ptr("default"), + // OutboundUnTrustCertificate: to.Ptr("default"), + // URLFilteringProfile: to.Ptr("default"), + // VulnerabilityProfile: to.Ptr("default"), + // }, + // }, + // } +} + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/GlobalRulestack_CreateOrUpdate_MinimumSet_Gen.json +func ExampleGlobalRulestackClient_BeginCreateOrUpdate_globalRulestackCreateOrUpdateMinimumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + poller, err := clientFactory.NewGlobalRulestackClient().BeginCreateOrUpdate(ctx, "praval", armpanngfw.GlobalRulestackResource{ + Location: to.Ptr("eastus"), + Properties: &armpanngfw.RulestackProperties{}, + }, nil) + if err != nil { + log.Fatalf("failed to finish the request: %v", err) + } + res, err := poller.PollUntilDone(ctx, nil) + if err != nil { + log.Fatalf("failed to pull the result: %v", err) + } + // You could use response here. We use blank identifier for just demo purposes. + _ = res + // If the HTTP response code is 200 as defined in example definition, your response structure would look as follows. Please pay attention that all the values in the output are fake values for just demo purposes. + // res.GlobalRulestackResource = armpanngfw.GlobalRulestackResource{ + // ID: to.Ptr("/providers/PaloAltoNetworks.Cloudngfw/globalRulestacks/praval"), + // Location: to.Ptr("eastus"), + // Properties: &armpanngfw.RulestackProperties{ + // }, + // } +} + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/GlobalRulestack_Update_MaximumSet_Gen.json +func ExampleGlobalRulestackClient_Update_globalRulestackUpdateMaximumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + res, err := clientFactory.NewGlobalRulestackClient().Update(ctx, "praval", armpanngfw.GlobalRulestackResourceUpdate{ + Identity: &armpanngfw.AzureResourceManagerManagedIdentityProperties{ + Type: to.Ptr(armpanngfw.ManagedIdentityTypeNone), + UserAssignedIdentities: map[string]*armpanngfw.AzureResourceManagerUserAssignedIdentity{ + "key16": { + ClientID: to.Ptr("aaaa"), + PrincipalID: to.Ptr("aaaaaaaaaaaaaaa"), + }, + }, + }, + Location: to.Ptr("eastus"), + Properties: &armpanngfw.GlobalRulestackResourceUpdateProperties{ + Description: to.Ptr("global rulestacks"), + AssociatedSubscriptions: []*string{ + to.Ptr("2bf4a339-294d-4c25-b0b2-ef649e9f5c27")}, + DefaultMode: to.Ptr(armpanngfw.DefaultModeIPS), + MinAppIDVersion: to.Ptr("8.5.3"), + PanEtag: to.Ptr("2bf4a339-294d-4c25-b0b2-ef649e9f5c12"), + PanLocation: to.Ptr("eastus"), + Scope: to.Ptr(armpanngfw.ScopeTypeGLOBAL), + SecurityServices: &armpanngfw.SecurityServices{ + AntiSpywareProfile: to.Ptr("default"), + AntiVirusProfile: to.Ptr("default"), + DNSSubscription: to.Ptr("default"), + FileBlockingProfile: to.Ptr("default"), + OutboundTrustCertificate: to.Ptr("default"), + OutboundUnTrustCertificate: to.Ptr("default"), + URLFilteringProfile: to.Ptr("default"), + VulnerabilityProfile: to.Ptr("default"), + }, + }, + }, nil) + if err != nil { + log.Fatalf("failed to finish the request: %v", err) + } + // You could use response here. We use blank identifier for just demo purposes. + _ = res + // If the HTTP response code is 200 as defined in example definition, your response structure would look as follows. Please pay attention that all the values in the output are fake values for just demo purposes. + // res.GlobalRulestackResource = armpanngfw.GlobalRulestackResource{ + // Name: to.Ptr("armid1"), + // Type: to.Ptr("globalRulestacks"), + // ID: to.Ptr("/providers/PaloAltoNetworks.Cloudngfw/globalrulestacks/armid1"), + // SystemData: &armpanngfw.SystemData{ + // CreatedAt: to.Ptr(func() time.Time { t, _ := time.Parse(time.RFC3339Nano, "2022-09-09T05:08:24.229Z"); return t}()), + // CreatedBy: to.Ptr("praval"), + // CreatedByType: to.Ptr(armpanngfw.CreatedByTypeUser), + // LastModifiedAt: to.Ptr(func() time.Time { t, _ := time.Parse(time.RFC3339Nano, "2022-09-09T05:08:24.229Z"); return t}()), + // LastModifiedBy: to.Ptr("praval"), + // LastModifiedByType: to.Ptr(armpanngfw.CreatedByTypeUser), + // }, + // Identity: &armpanngfw.AzureResourceManagerManagedIdentityProperties{ + // Type: to.Ptr(armpanngfw.ManagedIdentityTypeNone), + // PrincipalID: to.Ptr("2bf4a339-294d-4c25-b0b2-ef649e9f5c27"), + // TenantID: to.Ptr("2bf4a339-294d-4c25-b0b2-ef649e9f5c27"), + // UserAssignedIdentities: map[string]*armpanngfw.AzureResourceManagerUserAssignedIdentity{ + // "key16": &armpanngfw.AzureResourceManagerUserAssignedIdentity{ + // ClientID: to.Ptr("aaaa"), + // PrincipalID: to.Ptr("aaaaaaaaaaaaaaa"), + // }, + // }, + // }, + // Location: to.Ptr("eastus"), + // Properties: &armpanngfw.RulestackProperties{ + // Description: to.Ptr("global rulestacks"), + // AssociatedSubscriptions: []*string{ + // to.Ptr("2bf4a339-294d-4c25-b0b2-ef649e9f5c27")}, + // DefaultMode: to.Ptr(armpanngfw.DefaultModeIPS), + // MinAppIDVersion: to.Ptr("8.5.3"), + // PanEtag: to.Ptr("2bf4a339-294d-4c25-b0b2-ef649e9f5c12"), + // PanLocation: to.Ptr("eastus"), + // ProvisioningState: to.Ptr(armpanngfw.ProvisioningStateSucceeded), + // Scope: to.Ptr(armpanngfw.ScopeTypeGLOBAL), + // SecurityServices: &armpanngfw.SecurityServices{ + // AntiSpywareProfile: to.Ptr("default"), + // AntiVirusProfile: to.Ptr("default"), + // DNSSubscription: to.Ptr("default"), + // FileBlockingProfile: to.Ptr("default"), + // OutboundTrustCertificate: to.Ptr("default"), + // OutboundUnTrustCertificate: to.Ptr("default"), + // URLFilteringProfile: to.Ptr("default"), + // VulnerabilityProfile: to.Ptr("default"), + // }, + // }, + // } +} + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/GlobalRulestack_Update_MinimumSet_Gen.json +func ExampleGlobalRulestackClient_Update_globalRulestackUpdateMinimumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + res, err := clientFactory.NewGlobalRulestackClient().Update(ctx, "praval", armpanngfw.GlobalRulestackResourceUpdate{}, nil) + if err != nil { + log.Fatalf("failed to finish the request: %v", err) + } + // You could use response here. We use blank identifier for just demo purposes. + _ = res + // If the HTTP response code is 200 as defined in example definition, your response structure would look as follows. Please pay attention that all the values in the output are fake values for just demo purposes. + // res.GlobalRulestackResource = armpanngfw.GlobalRulestackResource{ + // Location: to.Ptr("eastus"), + // Properties: &armpanngfw.RulestackProperties{ + // }, + // } +} + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/GlobalRulestack_Delete_MaximumSet_Gen.json +func ExampleGlobalRulestackClient_BeginDelete_globalRulestackDeleteMaximumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + poller, err := clientFactory.NewGlobalRulestackClient().BeginDelete(ctx, "praval", nil) + if err != nil { + log.Fatalf("failed to finish the request: %v", err) + } + _, err = poller.PollUntilDone(ctx, nil) + if err != nil { + log.Fatalf("failed to pull the result: %v", err) + } +} + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/GlobalRulestack_Delete_MinimumSet_Gen.json +func ExampleGlobalRulestackClient_BeginDelete_globalRulestackDeleteMinimumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + poller, err := clientFactory.NewGlobalRulestackClient().BeginDelete(ctx, "praval", nil) + if err != nil { + log.Fatalf("failed to finish the request: %v", err) + } + _, err = poller.PollUntilDone(ctx, nil) + if err != nil { + log.Fatalf("failed to pull the result: %v", err) + } +} + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/GlobalRulestack_commit_MaximumSet_Gen.json +func ExampleGlobalRulestackClient_BeginCommit_globalRulestackCommitMaximumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + poller, err := clientFactory.NewGlobalRulestackClient().BeginCommit(ctx, "praval", nil) + if err != nil { + log.Fatalf("failed to finish the request: %v", err) + } + _, err = poller.PollUntilDone(ctx, nil) + if err != nil { + log.Fatalf("failed to pull the result: %v", err) + } +} + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/GlobalRulestack_commit_MinimumSet_Gen.json +func ExampleGlobalRulestackClient_BeginCommit_globalRulestackCommitMinimumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + poller, err := clientFactory.NewGlobalRulestackClient().BeginCommit(ctx, "praval", nil) + if err != nil { + log.Fatalf("failed to finish the request: %v", err) + } + _, err = poller.PollUntilDone(ctx, nil) + if err != nil { + log.Fatalf("failed to pull the result: %v", err) + } +} + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/GlobalRulestack_getChangeLog_MaximumSet_Gen.json +func ExampleGlobalRulestackClient_GetChangeLog_globalRulestackGetChangeLogMaximumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + res, err := clientFactory.NewGlobalRulestackClient().GetChangeLog(ctx, "praval", nil) + if err != nil { + log.Fatalf("failed to finish the request: %v", err) + } + // You could use response here. We use blank identifier for just demo purposes. + _ = res + // If the HTTP response code is 200 as defined in example definition, your response structure would look as follows. Please pay attention that all the values in the output are fake values for just demo purposes. + // res.Changelog = armpanngfw.Changelog{ + // Changes: []*string{ + // to.Ptr("aaaa")}, + // LastCommitted: to.Ptr(func() time.Time { t, _ := time.Parse(time.RFC3339Nano, "2022-09-09T05:08:24.229Z"); return t}()), + // LastModified: to.Ptr(func() time.Time { t, _ := time.Parse(time.RFC3339Nano, "2022-09-09T05:08:24.229Z"); return t}()), + // } +} + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/GlobalRulestack_getChangeLog_MinimumSet_Gen.json +func ExampleGlobalRulestackClient_GetChangeLog_globalRulestackGetChangeLogMinimumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + res, err := clientFactory.NewGlobalRulestackClient().GetChangeLog(ctx, "praval", nil) + if err != nil { + log.Fatalf("failed to finish the request: %v", err) + } + // You could use response here. We use blank identifier for just demo purposes. + _ = res + // If the HTTP response code is 200 as defined in example definition, your response structure would look as follows. Please pay attention that all the values in the output are fake values for just demo purposes. + // res.Changelog = armpanngfw.Changelog{ + // Changes: []*string{ + // to.Ptr("aaaa")}, + // } +} + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/GlobalRulestack_listAdvancedSecurityObjects_MaximumSet_Gen.json +func ExampleGlobalRulestackClient_ListAdvancedSecurityObjects_globalRulestackListAdvancedSecurityObjectsMaximumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + res, err := clientFactory.NewGlobalRulestackClient().ListAdvancedSecurityObjects(ctx, "praval", armpanngfw.AdvSecurityObjectTypeEnum("globalRulestacks"), &armpanngfw.GlobalRulestackClientListAdvancedSecurityObjectsOptions{Skip: to.Ptr("a6a321"), + Top: to.Ptr[int32](20), + }) + if err != nil { + log.Fatalf("failed to finish the request: %v", err) + } + // You could use response here. We use blank identifier for just demo purposes. + _ = res + // If the HTTP response code is 200 as defined in example definition, your response structure would look as follows. Please pay attention that all the values in the output are fake values for just demo purposes. + // res.AdvSecurityObjectListResponse = armpanngfw.AdvSecurityObjectListResponse{ + // Value: &armpanngfw.AdvSecurityObjectModel{ + // Type: to.Ptr("globalRulestacks"), + // Entry: []*armpanngfw.NameDescriptionObject{ + // { + // Name: to.Ptr("aaaaaaaaaa"), + // Description: to.Ptr("aaaaaaaaaaaa"), + // }}, + // }, + // } +} + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/GlobalRulestack_listAdvancedSecurityObjects_MinimumSet_Gen.json +func ExampleGlobalRulestackClient_ListAdvancedSecurityObjects_globalRulestackListAdvancedSecurityObjectsMinimumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + res, err := clientFactory.NewGlobalRulestackClient().ListAdvancedSecurityObjects(ctx, "praval", armpanngfw.AdvSecurityObjectTypeEnum("globalRulestacks"), &armpanngfw.GlobalRulestackClientListAdvancedSecurityObjectsOptions{Skip: nil, + Top: nil, + }) + if err != nil { + log.Fatalf("failed to finish the request: %v", err) + } + // You could use response here. We use blank identifier for just demo purposes. + _ = res + // If the HTTP response code is 200 as defined in example definition, your response structure would look as follows. Please pay attention that all the values in the output are fake values for just demo purposes. + // res.AdvSecurityObjectListResponse = armpanngfw.AdvSecurityObjectListResponse{ + // Value: &armpanngfw.AdvSecurityObjectModel{ + // Entry: []*armpanngfw.NameDescriptionObject{ + // { + // Name: to.Ptr("aaaaaaaaaa"), + // }}, + // }, + // } +} + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/GlobalRulestack_listAppIds_MaximumSet_Gen.json +func ExampleGlobalRulestackClient_ListAppIDs_globalRulestackListAppIdsMaximumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + res, err := clientFactory.NewGlobalRulestackClient().ListAppIDs(ctx, "praval", &armpanngfw.GlobalRulestackClientListAppIDsOptions{AppIDVersion: to.Ptr("8543"), + AppPrefix: to.Ptr("pref"), + Skip: to.Ptr("a6a321"), + Top: to.Ptr[int32](20), + }) + if err != nil { + log.Fatalf("failed to finish the request: %v", err) + } + // You could use response here. We use blank identifier for just demo purposes. + _ = res + // If the HTTP response code is 200 as defined in example definition, your response structure would look as follows. Please pay attention that all the values in the output are fake values for just demo purposes. + // res.ListAppIDResponse = armpanngfw.ListAppIDResponse{ + // Value: []*string{ + // to.Ptr("aaaaaaaaaaaaaaaaaaaaaaa")}, + // } +} + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/GlobalRulestack_listAppIds_MinimumSet_Gen.json +func ExampleGlobalRulestackClient_ListAppIDs_globalRulestackListAppIdsMinimumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + res, err := clientFactory.NewGlobalRulestackClient().ListAppIDs(ctx, "praval", &armpanngfw.GlobalRulestackClientListAppIDsOptions{AppIDVersion: nil, + AppPrefix: nil, + Skip: nil, + Top: nil, + }) + if err != nil { + log.Fatalf("failed to finish the request: %v", err) + } + // You could use response here. We use blank identifier for just demo purposes. + _ = res + // If the HTTP response code is 200 as defined in example definition, your response structure would look as follows. Please pay attention that all the values in the output are fake values for just demo purposes. + // res.ListAppIDResponse = armpanngfw.ListAppIDResponse{ + // Value: []*string{ + // to.Ptr("aaaaaaaaaaaaaaaaaaaaaaa")}, + // } +} + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/GlobalRulestack_listCountries_MaximumSet_Gen.json +func ExampleGlobalRulestackClient_ListCountries_globalRulestackListCountriesMaximumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + res, err := clientFactory.NewGlobalRulestackClient().ListCountries(ctx, "praval", &armpanngfw.GlobalRulestackClientListCountriesOptions{Skip: to.Ptr("a6a321"), + Top: to.Ptr[int32](20), + }) + if err != nil { + log.Fatalf("failed to finish the request: %v", err) + } + // You could use response here. We use blank identifier for just demo purposes. + _ = res + // If the HTTP response code is 200 as defined in example definition, your response structure would look as follows. Please pay attention that all the values in the output are fake values for just demo purposes. + // res.CountriesResponse = armpanngfw.CountriesResponse{ + // Value: []*armpanngfw.Country{ + // { + // Description: to.Ptr("aaaaa"), + // Code: to.Ptr("aaaaaaaaaaaaaaaaaaaaaaaaa"), + // }}, + // } +} + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/GlobalRulestack_listCountries_MinimumSet_Gen.json +func ExampleGlobalRulestackClient_ListCountries_globalRulestackListCountriesMinimumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + res, err := clientFactory.NewGlobalRulestackClient().ListCountries(ctx, "praval", &armpanngfw.GlobalRulestackClientListCountriesOptions{Skip: nil, + Top: nil, + }) + if err != nil { + log.Fatalf("failed to finish the request: %v", err) + } + // You could use response here. We use blank identifier for just demo purposes. + _ = res + // If the HTTP response code is 200 as defined in example definition, your response structure would look as follows. Please pay attention that all the values in the output are fake values for just demo purposes. + // res.CountriesResponse = armpanngfw.CountriesResponse{ + // Value: []*armpanngfw.Country{ + // { + // Code: to.Ptr("aaaaaaaaaaaaaaaaaaaaaaaaa"), + // }}, + // } +} + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/GlobalRulestack_listFirewalls_MaximumSet_Gen.json +func ExampleGlobalRulestackClient_ListFirewalls_globalRulestackListFirewallsMaximumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + res, err := clientFactory.NewGlobalRulestackClient().ListFirewalls(ctx, "praval", nil) + if err != nil { + log.Fatalf("failed to finish the request: %v", err) + } + // You could use response here. We use blank identifier for just demo purposes. + _ = res + // If the HTTP response code is 200 as defined in example definition, your response structure would look as follows. Please pay attention that all the values in the output are fake values for just demo purposes. + // res.ListFirewallsResponse = armpanngfw.ListFirewallsResponse{ + // Value: []*string{ + // to.Ptr("aaaaaaaaaaaaaaaaaaaaaaaaa")}, + // } +} + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/GlobalRulestack_listFirewalls_MinimumSet_Gen.json +func ExampleGlobalRulestackClient_ListFirewalls_globalRulestackListFirewallsMinimumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + res, err := clientFactory.NewGlobalRulestackClient().ListFirewalls(ctx, "praval", nil) + if err != nil { + log.Fatalf("failed to finish the request: %v", err) + } + // You could use response here. We use blank identifier for just demo purposes. + _ = res + // If the HTTP response code is 200 as defined in example definition, your response structure would look as follows. Please pay attention that all the values in the output are fake values for just demo purposes. + // res.ListFirewallsResponse = armpanngfw.ListFirewallsResponse{ + // Value: []*string{ + // to.Ptr("aaaaaaaaaaaaaaaaaaaaaaaaa")}, + // } +} + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/GlobalRulestack_listPredefinedUrlCategories_MaximumSet_Gen.json +func ExampleGlobalRulestackClient_ListPredefinedURLCategories_globalRulestackListPredefinedUrlCategoriesMaximumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + res, err := clientFactory.NewGlobalRulestackClient().ListPredefinedURLCategories(ctx, "praval", &armpanngfw.GlobalRulestackClientListPredefinedURLCategoriesOptions{Skip: to.Ptr("a6a321"), + Top: to.Ptr[int32](20), + }) + if err != nil { + log.Fatalf("failed to finish the request: %v", err) + } + // You could use response here. We use blank identifier for just demo purposes. + _ = res + // If the HTTP response code is 200 as defined in example definition, your response structure would look as follows. Please pay attention that all the values in the output are fake values for just demo purposes. + // res.PredefinedURLCategoriesResponse = armpanngfw.PredefinedURLCategoriesResponse{ + // Value: []*armpanngfw.PredefinedURLCategory{ + // { + // Name: to.Ptr("aaaaaaaaaaaaaaaaaaaaaaaaa"), + // Action: to.Ptr("aaaaaaa"), + // }}, + // } +} + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/GlobalRulestack_listPredefinedUrlCategories_MinimumSet_Gen.json +func ExampleGlobalRulestackClient_ListPredefinedURLCategories_globalRulestackListPredefinedUrlCategoriesMinimumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + res, err := clientFactory.NewGlobalRulestackClient().ListPredefinedURLCategories(ctx, "praval", &armpanngfw.GlobalRulestackClientListPredefinedURLCategoriesOptions{Skip: nil, + Top: nil, + }) + if err != nil { + log.Fatalf("failed to finish the request: %v", err) + } + // You could use response here. We use blank identifier for just demo purposes. + _ = res + // If the HTTP response code is 200 as defined in example definition, your response structure would look as follows. Please pay attention that all the values in the output are fake values for just demo purposes. + // res.PredefinedURLCategoriesResponse = armpanngfw.PredefinedURLCategoriesResponse{ + // Value: []*armpanngfw.PredefinedURLCategory{ + // { + // Name: to.Ptr("aaaaaaaaaaaaaaaaaaaaaaaaa"), + // Action: to.Ptr("aaaaaaa"), + // }}, + // } +} + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/GlobalRulestack_listSecurityServices_MaximumSet_Gen.json +func ExampleGlobalRulestackClient_ListSecurityServices_globalRulestackListSecurityServicesMaximumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + res, err := clientFactory.NewGlobalRulestackClient().ListSecurityServices(ctx, "praval", armpanngfw.SecurityServicesTypeEnum("globalRulestacks"), &armpanngfw.GlobalRulestackClientListSecurityServicesOptions{Skip: to.Ptr("a6a321"), + Top: to.Ptr[int32](20), + }) + if err != nil { + log.Fatalf("failed to finish the request: %v", err) + } + // You could use response here. We use blank identifier for just demo purposes. + _ = res + // If the HTTP response code is 200 as defined in example definition, your response structure would look as follows. Please pay attention that all the values in the output are fake values for just demo purposes. + // res.SecurityServicesResponse = armpanngfw.SecurityServicesResponse{ + // Value: &armpanngfw.SecurityServicesTypeList{ + // Type: to.Ptr("globalRulestacks"), + // Entry: []*armpanngfw.NameDescriptionObject{ + // { + // Name: to.Ptr("aaaaaaaaaa"), + // Description: to.Ptr("aaaaaaaaaaaa"), + // }}, + // }, + // } +} + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/GlobalRulestack_listSecurityServices_MinimumSet_Gen.json +func ExampleGlobalRulestackClient_ListSecurityServices_globalRulestackListSecurityServicesMinimumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + res, err := clientFactory.NewGlobalRulestackClient().ListSecurityServices(ctx, "praval", armpanngfw.SecurityServicesTypeEnum("globalRulestacks"), &armpanngfw.GlobalRulestackClientListSecurityServicesOptions{Skip: nil, + Top: nil, + }) + if err != nil { + log.Fatalf("failed to finish the request: %v", err) + } + // You could use response here. We use blank identifier for just demo purposes. + _ = res + // If the HTTP response code is 200 as defined in example definition, your response structure would look as follows. Please pay attention that all the values in the output are fake values for just demo purposes. + // res.SecurityServicesResponse = armpanngfw.SecurityServicesResponse{ + // Value: &armpanngfw.SecurityServicesTypeList{ + // Entry: []*armpanngfw.NameDescriptionObject{ + // { + // Name: to.Ptr("aaaaaaaaaa"), + // }}, + // }, + // } +} + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/GlobalRulestack_revert_MaximumSet_Gen.json +func ExampleGlobalRulestackClient_Revert_globalRulestackRevertMaximumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + _, err = clientFactory.NewGlobalRulestackClient().Revert(ctx, "praval", nil) + if err != nil { + log.Fatalf("failed to finish the request: %v", err) + } +} + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/GlobalRulestack_revert_MinimumSet_Gen.json +func ExampleGlobalRulestackClient_Revert_globalRulestackRevertMinimumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + _, err = clientFactory.NewGlobalRulestackClient().Revert(ctx, "praval", nil) + if err != nil { + log.Fatalf("failed to finish the request: %v", err) + } +} diff --git a/sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/go.mod b/sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/go.mod new file mode 100644 index 000000000000..f6f7fce5bdff --- /dev/null +++ b/sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/go.mod @@ -0,0 +1,21 @@ +module github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/paloaltonetworksngfw/armpanngfw + +go 1.18 + +require ( + github.com/Azure/azure-sdk-for-go/sdk/azcore v1.4.0 + github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.2.2 +) + +require ( + github.com/Azure/azure-sdk-for-go/sdk/internal v1.2.0 // indirect + github.com/AzureAD/microsoft-authentication-library-for-go v0.9.0 // indirect + github.com/golang-jwt/jwt/v4 v4.5.0 // indirect + github.com/google/uuid v1.3.0 // indirect + github.com/kylelemons/godebug v1.1.0 // indirect + github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 // indirect + golang.org/x/crypto v0.6.0 // indirect + golang.org/x/net v0.7.0 // indirect + golang.org/x/sys v0.5.0 // indirect + golang.org/x/text v0.7.0 // indirect +) diff --git a/sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/go.sum b/sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/go.sum new file mode 100644 index 000000000000..8ba445a8c4da --- /dev/null +++ b/sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/go.sum @@ -0,0 +1,31 @@ +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.4.0 h1:rTnT/Jrcm+figWlYz4Ixzt0SJVR2cMC8lvZcimipiEY= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.4.0/go.mod h1:ON4tFdPTwRcgWEaVDrN3584Ef+b7GgSJaXxe5fW9t4M= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.2.2 h1:uqM+VoHjVH6zdlkLF2b6O0ZANcHoj3rO0PoQ3jglUJA= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.2.2/go.mod h1:twTKAa1E6hLmSDjLhaCkbTMQKc7p/rNLU40rLxGEOCI= +github.com/Azure/azure-sdk-for-go/sdk/internal v1.2.0 h1:leh5DwKv6Ihwi+h60uHtn6UWAxBbZ0q8DwQVMzf61zw= +github.com/Azure/azure-sdk-for-go/sdk/internal v1.2.0/go.mod h1:eWRD7oawr1Mu1sLCawqVc0CUiF43ia3qQMxLscsKQ9w= +github.com/AzureAD/microsoft-authentication-library-for-go v0.9.0 h1:UE9n9rkJF62ArLb1F3DEjRt8O3jLwMWdSoypKV4f3MU= +github.com/AzureAD/microsoft-authentication-library-for-go v0.9.0/go.mod h1:kgDmCTgBzIEPFElEF+FK0SdjAor06dRq2Go927dnQ6o= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/dnaeon/go-vcr v1.1.0 h1:ReYa/UBrRyQdant9B4fNHGoCNKw6qh6P0fsdGmZpR7c= +github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg= +github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= +github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= +github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= +github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= +github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 h1:KoWmjvw+nsYOo29YJK9vDA65RGE3NrOnUtO7a+RF9HU= +github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8/go.mod h1:HKlIX3XHQyzLZPlr7++PzdhaXEj94dEiJgZDTsxEqUI= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= +golang.org/x/crypto v0.6.0 h1:qfktjS5LUO+fFKeJXZ+ikTRijMmljikvG68fpMMruSc= +golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58= +golang.org/x/net v0.7.0 h1:rJrUqqhjsgNp7KqAIc25s9pZnjU7TUcSY7HcVZjdn1g= +golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/sys v0.0.0-20210616045830-e2b7044e8c71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/text v0.7.0 h1:4BRB4x83lYWy72KwLD/qYDuTu7q9PjSagHvijDw7cLo= +golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo= diff --git a/sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/localrules_client.go b/sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/localrules_client.go new file mode 100644 index 000000000000..e8f6b6dd7edd --- /dev/null +++ b/sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/localrules_client.go @@ -0,0 +1,509 @@ +//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. +// Code generated by Microsoft (R) AutoRest Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. +// DO NOT EDIT. + +package armpanngfw + +import ( + "context" + "errors" + "github.com/Azure/azure-sdk-for-go/sdk/azcore" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/arm" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/policy" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime" + "net/http" + "net/url" + "strings" +) + +// LocalRulesClient contains the methods for the LocalRules group. +// Don't use this type directly, use NewLocalRulesClient() instead. +type LocalRulesClient struct { + internal *arm.Client + subscriptionID string +} + +// NewLocalRulesClient creates a new instance of LocalRulesClient with the specified values. +// - subscriptionID - The ID of the target subscription. +// - credential - used to authorize requests. Usually a credential from azidentity. +// - options - pass nil to accept the default values. +func NewLocalRulesClient(subscriptionID string, credential azcore.TokenCredential, options *arm.ClientOptions) (*LocalRulesClient, error) { + cl, err := arm.NewClient(moduleName+".LocalRulesClient", moduleVersion, credential, options) + if err != nil { + return nil, err + } + client := &LocalRulesClient{ + subscriptionID: subscriptionID, + internal: cl, + } + return client, nil +} + +// BeginCreateOrUpdate - Create a LocalRulesResource +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2022-08-29-preview +// - resourceGroupName - The name of the resource group. The name is case insensitive. +// - localRulestackName - LocalRulestack resource name +// - priority - Local Rule priority +// - resource - Resource create parameters. +// - options - LocalRulesClientBeginCreateOrUpdateOptions contains the optional parameters for the LocalRulesClient.BeginCreateOrUpdate +// method. +func (client *LocalRulesClient) BeginCreateOrUpdate(ctx context.Context, resourceGroupName string, localRulestackName string, priority string, resource LocalRulesResource, options *LocalRulesClientBeginCreateOrUpdateOptions) (*runtime.Poller[LocalRulesClientCreateOrUpdateResponse], error) { + if options == nil || options.ResumeToken == "" { + resp, err := client.createOrUpdate(ctx, resourceGroupName, localRulestackName, priority, resource, options) + if err != nil { + return nil, err + } + return runtime.NewPoller(resp, client.internal.Pipeline(), &runtime.NewPollerOptions[LocalRulesClientCreateOrUpdateResponse]{ + FinalStateVia: runtime.FinalStateViaAzureAsyncOp, + }) + } else { + return runtime.NewPollerFromResumeToken[LocalRulesClientCreateOrUpdateResponse](options.ResumeToken, client.internal.Pipeline(), nil) + } +} + +// CreateOrUpdate - Create a LocalRulesResource +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2022-08-29-preview +func (client *LocalRulesClient) createOrUpdate(ctx context.Context, resourceGroupName string, localRulestackName string, priority string, resource LocalRulesResource, options *LocalRulesClientBeginCreateOrUpdateOptions) (*http.Response, error) { + req, err := client.createOrUpdateCreateRequest(ctx, resourceGroupName, localRulestackName, priority, resource, options) + if err != nil { + return nil, err + } + resp, err := client.internal.Pipeline().Do(req) + if err != nil { + return nil, err + } + if !runtime.HasStatusCode(resp, http.StatusOK, http.StatusCreated) { + return nil, runtime.NewResponseError(resp) + } + return resp, nil +} + +// createOrUpdateCreateRequest creates the CreateOrUpdate request. +func (client *LocalRulesClient) createOrUpdateCreateRequest(ctx context.Context, resourceGroupName string, localRulestackName string, priority string, resource LocalRulesResource, options *LocalRulesClientBeginCreateOrUpdateOptions) (*policy.Request, error) { + urlPath := "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/PaloAltoNetworks.Cloudngfw/localRulestacks/{localRulestackName}/localRules/{priority}" + if client.subscriptionID == "" { + return nil, errors.New("parameter client.subscriptionID cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{subscriptionId}", url.PathEscape(client.subscriptionID)) + if resourceGroupName == "" { + return nil, errors.New("parameter resourceGroupName cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{resourceGroupName}", url.PathEscape(resourceGroupName)) + if localRulestackName == "" { + return nil, errors.New("parameter localRulestackName cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{localRulestackName}", url.PathEscape(localRulestackName)) + if priority == "" { + return nil, errors.New("parameter priority cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{priority}", url.PathEscape(priority)) + req, err := runtime.NewRequest(ctx, http.MethodPut, runtime.JoinPaths(client.internal.Endpoint(), urlPath)) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("api-version", "2022-08-29-preview") + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["Accept"] = []string{"application/json"} + return req, runtime.MarshalAsJSON(req, resource) +} + +// BeginDelete - Delete a LocalRulesResource +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2022-08-29-preview +// - resourceGroupName - The name of the resource group. The name is case insensitive. +// - localRulestackName - LocalRulestack resource name +// - priority - Local Rule priority +// - options - LocalRulesClientBeginDeleteOptions contains the optional parameters for the LocalRulesClient.BeginDelete method. +func (client *LocalRulesClient) BeginDelete(ctx context.Context, resourceGroupName string, localRulestackName string, priority string, options *LocalRulesClientBeginDeleteOptions) (*runtime.Poller[LocalRulesClientDeleteResponse], error) { + if options == nil || options.ResumeToken == "" { + resp, err := client.deleteOperation(ctx, resourceGroupName, localRulestackName, priority, options) + if err != nil { + return nil, err + } + return runtime.NewPoller(resp, client.internal.Pipeline(), &runtime.NewPollerOptions[LocalRulesClientDeleteResponse]{ + FinalStateVia: runtime.FinalStateViaAzureAsyncOp, + }) + } else { + return runtime.NewPollerFromResumeToken[LocalRulesClientDeleteResponse](options.ResumeToken, client.internal.Pipeline(), nil) + } +} + +// Delete - Delete a LocalRulesResource +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2022-08-29-preview +func (client *LocalRulesClient) deleteOperation(ctx context.Context, resourceGroupName string, localRulestackName string, priority string, options *LocalRulesClientBeginDeleteOptions) (*http.Response, error) { + req, err := client.deleteCreateRequest(ctx, resourceGroupName, localRulestackName, priority, options) + if err != nil { + return nil, err + } + resp, err := client.internal.Pipeline().Do(req) + if err != nil { + return nil, err + } + if !runtime.HasStatusCode(resp, http.StatusOK, http.StatusAccepted, http.StatusNoContent) { + return nil, runtime.NewResponseError(resp) + } + return resp, nil +} + +// deleteCreateRequest creates the Delete request. +func (client *LocalRulesClient) deleteCreateRequest(ctx context.Context, resourceGroupName string, localRulestackName string, priority string, options *LocalRulesClientBeginDeleteOptions) (*policy.Request, error) { + urlPath := "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/PaloAltoNetworks.Cloudngfw/localRulestacks/{localRulestackName}/localRules/{priority}" + if client.subscriptionID == "" { + return nil, errors.New("parameter client.subscriptionID cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{subscriptionId}", url.PathEscape(client.subscriptionID)) + if resourceGroupName == "" { + return nil, errors.New("parameter resourceGroupName cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{resourceGroupName}", url.PathEscape(resourceGroupName)) + if localRulestackName == "" { + return nil, errors.New("parameter localRulestackName cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{localRulestackName}", url.PathEscape(localRulestackName)) + if priority == "" { + return nil, errors.New("parameter priority cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{priority}", url.PathEscape(priority)) + req, err := runtime.NewRequest(ctx, http.MethodDelete, runtime.JoinPaths(client.internal.Endpoint(), urlPath)) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("api-version", "2022-08-29-preview") + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["Accept"] = []string{"application/json"} + return req, nil +} + +// Get - Get a LocalRulesResource +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2022-08-29-preview +// - resourceGroupName - The name of the resource group. The name is case insensitive. +// - localRulestackName - LocalRulestack resource name +// - priority - Local Rule priority +// - options - LocalRulesClientGetOptions contains the optional parameters for the LocalRulesClient.Get method. +func (client *LocalRulesClient) Get(ctx context.Context, resourceGroupName string, localRulestackName string, priority string, options *LocalRulesClientGetOptions) (LocalRulesClientGetResponse, error) { + req, err := client.getCreateRequest(ctx, resourceGroupName, localRulestackName, priority, options) + if err != nil { + return LocalRulesClientGetResponse{}, err + } + resp, err := client.internal.Pipeline().Do(req) + if err != nil { + return LocalRulesClientGetResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusOK) { + return LocalRulesClientGetResponse{}, runtime.NewResponseError(resp) + } + return client.getHandleResponse(resp) +} + +// getCreateRequest creates the Get request. +func (client *LocalRulesClient) getCreateRequest(ctx context.Context, resourceGroupName string, localRulestackName string, priority string, options *LocalRulesClientGetOptions) (*policy.Request, error) { + urlPath := "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/PaloAltoNetworks.Cloudngfw/localRulestacks/{localRulestackName}/localRules/{priority}" + if client.subscriptionID == "" { + return nil, errors.New("parameter client.subscriptionID cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{subscriptionId}", url.PathEscape(client.subscriptionID)) + if resourceGroupName == "" { + return nil, errors.New("parameter resourceGroupName cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{resourceGroupName}", url.PathEscape(resourceGroupName)) + if localRulestackName == "" { + return nil, errors.New("parameter localRulestackName cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{localRulestackName}", url.PathEscape(localRulestackName)) + if priority == "" { + return nil, errors.New("parameter priority cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{priority}", url.PathEscape(priority)) + req, err := runtime.NewRequest(ctx, http.MethodGet, runtime.JoinPaths(client.internal.Endpoint(), urlPath)) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("api-version", "2022-08-29-preview") + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["Accept"] = []string{"application/json"} + return req, nil +} + +// getHandleResponse handles the Get response. +func (client *LocalRulesClient) getHandleResponse(resp *http.Response) (LocalRulesClientGetResponse, error) { + result := LocalRulesClientGetResponse{} + if err := runtime.UnmarshalAsJSON(resp, &result.LocalRulesResource); err != nil { + return LocalRulesClientGetResponse{}, err + } + return result, nil +} + +// GetCounters - Get counters +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2022-08-29-preview +// - resourceGroupName - The name of the resource group. The name is case insensitive. +// - localRulestackName - LocalRulestack resource name +// - priority - Local Rule priority +// - options - LocalRulesClientGetCountersOptions contains the optional parameters for the LocalRulesClient.GetCounters method. +func (client *LocalRulesClient) GetCounters(ctx context.Context, resourceGroupName string, localRulestackName string, priority string, options *LocalRulesClientGetCountersOptions) (LocalRulesClientGetCountersResponse, error) { + req, err := client.getCountersCreateRequest(ctx, resourceGroupName, localRulestackName, priority, options) + if err != nil { + return LocalRulesClientGetCountersResponse{}, err + } + resp, err := client.internal.Pipeline().Do(req) + if err != nil { + return LocalRulesClientGetCountersResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusOK) { + return LocalRulesClientGetCountersResponse{}, runtime.NewResponseError(resp) + } + return client.getCountersHandleResponse(resp) +} + +// getCountersCreateRequest creates the GetCounters request. +func (client *LocalRulesClient) getCountersCreateRequest(ctx context.Context, resourceGroupName string, localRulestackName string, priority string, options *LocalRulesClientGetCountersOptions) (*policy.Request, error) { + urlPath := "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/PaloAltoNetworks.Cloudngfw/localRulestacks/{localRulestackName}/localRules/{priority}/getCounters" + if client.subscriptionID == "" { + return nil, errors.New("parameter client.subscriptionID cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{subscriptionId}", url.PathEscape(client.subscriptionID)) + if resourceGroupName == "" { + return nil, errors.New("parameter resourceGroupName cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{resourceGroupName}", url.PathEscape(resourceGroupName)) + if localRulestackName == "" { + return nil, errors.New("parameter localRulestackName cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{localRulestackName}", url.PathEscape(localRulestackName)) + if priority == "" { + return nil, errors.New("parameter priority cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{priority}", url.PathEscape(priority)) + req, err := runtime.NewRequest(ctx, http.MethodPost, runtime.JoinPaths(client.internal.Endpoint(), urlPath)) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("api-version", "2022-08-29-preview") + if options != nil && options.FirewallName != nil { + reqQP.Set("firewallName", *options.FirewallName) + } + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["Accept"] = []string{"application/json"} + return req, nil +} + +// getCountersHandleResponse handles the GetCounters response. +func (client *LocalRulesClient) getCountersHandleResponse(resp *http.Response) (LocalRulesClientGetCountersResponse, error) { + result := LocalRulesClientGetCountersResponse{} + if err := runtime.UnmarshalAsJSON(resp, &result.RuleCounter); err != nil { + return LocalRulesClientGetCountersResponse{}, err + } + return result, nil +} + +// NewListByLocalRulestacksPager - List LocalRulesResource resources by LocalRulestacks +// +// Generated from API version 2022-08-29-preview +// - resourceGroupName - The name of the resource group. The name is case insensitive. +// - localRulestackName - LocalRulestack resource name +// - options - LocalRulesClientListByLocalRulestacksOptions contains the optional parameters for the LocalRulesClient.NewListByLocalRulestacksPager +// method. +func (client *LocalRulesClient) NewListByLocalRulestacksPager(resourceGroupName string, localRulestackName string, options *LocalRulesClientListByLocalRulestacksOptions) *runtime.Pager[LocalRulesClientListByLocalRulestacksResponse] { + return runtime.NewPager(runtime.PagingHandler[LocalRulesClientListByLocalRulestacksResponse]{ + More: func(page LocalRulesClientListByLocalRulestacksResponse) bool { + return page.NextLink != nil && len(*page.NextLink) > 0 + }, + Fetcher: func(ctx context.Context, page *LocalRulesClientListByLocalRulestacksResponse) (LocalRulesClientListByLocalRulestacksResponse, error) { + var req *policy.Request + var err error + if page == nil { + req, err = client.listByLocalRulestacksCreateRequest(ctx, resourceGroupName, localRulestackName, options) + } else { + req, err = runtime.NewRequest(ctx, http.MethodGet, *page.NextLink) + } + if err != nil { + return LocalRulesClientListByLocalRulestacksResponse{}, err + } + resp, err := client.internal.Pipeline().Do(req) + if err != nil { + return LocalRulesClientListByLocalRulestacksResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusOK) { + return LocalRulesClientListByLocalRulestacksResponse{}, runtime.NewResponseError(resp) + } + return client.listByLocalRulestacksHandleResponse(resp) + }, + }) +} + +// listByLocalRulestacksCreateRequest creates the ListByLocalRulestacks request. +func (client *LocalRulesClient) listByLocalRulestacksCreateRequest(ctx context.Context, resourceGroupName string, localRulestackName string, options *LocalRulesClientListByLocalRulestacksOptions) (*policy.Request, error) { + urlPath := "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/PaloAltoNetworks.Cloudngfw/localRulestacks/{localRulestackName}/localRules" + if client.subscriptionID == "" { + return nil, errors.New("parameter client.subscriptionID cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{subscriptionId}", url.PathEscape(client.subscriptionID)) + if resourceGroupName == "" { + return nil, errors.New("parameter resourceGroupName cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{resourceGroupName}", url.PathEscape(resourceGroupName)) + if localRulestackName == "" { + return nil, errors.New("parameter localRulestackName cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{localRulestackName}", url.PathEscape(localRulestackName)) + req, err := runtime.NewRequest(ctx, http.MethodGet, runtime.JoinPaths(client.internal.Endpoint(), urlPath)) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("api-version", "2022-08-29-preview") + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["Accept"] = []string{"application/json"} + return req, nil +} + +// listByLocalRulestacksHandleResponse handles the ListByLocalRulestacks response. +func (client *LocalRulesClient) listByLocalRulestacksHandleResponse(resp *http.Response) (LocalRulesClientListByLocalRulestacksResponse, error) { + result := LocalRulesClientListByLocalRulestacksResponse{} + if err := runtime.UnmarshalAsJSON(resp, &result.LocalRulesResourceListResult); err != nil { + return LocalRulesClientListByLocalRulestacksResponse{}, err + } + return result, nil +} + +// RefreshCounters - Refresh counters +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2022-08-29-preview +// - resourceGroupName - The name of the resource group. The name is case insensitive. +// - localRulestackName - LocalRulestack resource name +// - priority - Local Rule priority +// - options - LocalRulesClientRefreshCountersOptions contains the optional parameters for the LocalRulesClient.RefreshCounters +// method. +func (client *LocalRulesClient) RefreshCounters(ctx context.Context, resourceGroupName string, localRulestackName string, priority string, options *LocalRulesClientRefreshCountersOptions) (LocalRulesClientRefreshCountersResponse, error) { + req, err := client.refreshCountersCreateRequest(ctx, resourceGroupName, localRulestackName, priority, options) + if err != nil { + return LocalRulesClientRefreshCountersResponse{}, err + } + resp, err := client.internal.Pipeline().Do(req) + if err != nil { + return LocalRulesClientRefreshCountersResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusNoContent) { + return LocalRulesClientRefreshCountersResponse{}, runtime.NewResponseError(resp) + } + return LocalRulesClientRefreshCountersResponse{}, nil +} + +// refreshCountersCreateRequest creates the RefreshCounters request. +func (client *LocalRulesClient) refreshCountersCreateRequest(ctx context.Context, resourceGroupName string, localRulestackName string, priority string, options *LocalRulesClientRefreshCountersOptions) (*policy.Request, error) { + urlPath := "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/PaloAltoNetworks.Cloudngfw/localRulestacks/{localRulestackName}/localRules/{priority}/refreshCounters" + if client.subscriptionID == "" { + return nil, errors.New("parameter client.subscriptionID cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{subscriptionId}", url.PathEscape(client.subscriptionID)) + if resourceGroupName == "" { + return nil, errors.New("parameter resourceGroupName cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{resourceGroupName}", url.PathEscape(resourceGroupName)) + if localRulestackName == "" { + return nil, errors.New("parameter localRulestackName cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{localRulestackName}", url.PathEscape(localRulestackName)) + if priority == "" { + return nil, errors.New("parameter priority cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{priority}", url.PathEscape(priority)) + req, err := runtime.NewRequest(ctx, http.MethodPost, runtime.JoinPaths(client.internal.Endpoint(), urlPath)) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("api-version", "2022-08-29-preview") + if options != nil && options.FirewallName != nil { + reqQP.Set("firewallName", *options.FirewallName) + } + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["Accept"] = []string{"application/json"} + return req, nil +} + +// ResetCounters - Reset counters +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2022-08-29-preview +// - resourceGroupName - The name of the resource group. The name is case insensitive. +// - localRulestackName - LocalRulestack resource name +// - priority - Local Rule priority +// - options - LocalRulesClientResetCountersOptions contains the optional parameters for the LocalRulesClient.ResetCounters +// method. +func (client *LocalRulesClient) ResetCounters(ctx context.Context, resourceGroupName string, localRulestackName string, priority string, options *LocalRulesClientResetCountersOptions) (LocalRulesClientResetCountersResponse, error) { + req, err := client.resetCountersCreateRequest(ctx, resourceGroupName, localRulestackName, priority, options) + if err != nil { + return LocalRulesClientResetCountersResponse{}, err + } + resp, err := client.internal.Pipeline().Do(req) + if err != nil { + return LocalRulesClientResetCountersResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusOK) { + return LocalRulesClientResetCountersResponse{}, runtime.NewResponseError(resp) + } + return client.resetCountersHandleResponse(resp) +} + +// resetCountersCreateRequest creates the ResetCounters request. +func (client *LocalRulesClient) resetCountersCreateRequest(ctx context.Context, resourceGroupName string, localRulestackName string, priority string, options *LocalRulesClientResetCountersOptions) (*policy.Request, error) { + urlPath := "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/PaloAltoNetworks.Cloudngfw/localRulestacks/{localRulestackName}/localRules/{priority}/resetCounters" + if client.subscriptionID == "" { + return nil, errors.New("parameter client.subscriptionID cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{subscriptionId}", url.PathEscape(client.subscriptionID)) + if resourceGroupName == "" { + return nil, errors.New("parameter resourceGroupName cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{resourceGroupName}", url.PathEscape(resourceGroupName)) + if localRulestackName == "" { + return nil, errors.New("parameter localRulestackName cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{localRulestackName}", url.PathEscape(localRulestackName)) + if priority == "" { + return nil, errors.New("parameter priority cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{priority}", url.PathEscape(priority)) + req, err := runtime.NewRequest(ctx, http.MethodPost, runtime.JoinPaths(client.internal.Endpoint(), urlPath)) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("api-version", "2022-08-29-preview") + if options != nil && options.FirewallName != nil { + reqQP.Set("firewallName", *options.FirewallName) + } + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["Accept"] = []string{"application/json"} + return req, nil +} + +// resetCountersHandleResponse handles the ResetCounters response. +func (client *LocalRulesClient) resetCountersHandleResponse(resp *http.Response) (LocalRulesClientResetCountersResponse, error) { + result := LocalRulesClientResetCountersResponse{} + if err := runtime.UnmarshalAsJSON(resp, &result.RuleCounterReset); err != nil { + return LocalRulesClientResetCountersResponse{}, err + } + return result, nil +} diff --git a/sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/localrules_client_example_test.go b/sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/localrules_client_example_test.go new file mode 100644 index 000000000000..a27d8a63a149 --- /dev/null +++ b/sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/localrules_client_example_test.go @@ -0,0 +1,629 @@ +//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. +// Code generated by Microsoft (R) AutoRest Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. +// DO NOT EDIT. + +package armpanngfw_test + +import ( + "context" + "log" + + "github.com/Azure/azure-sdk-for-go/sdk/azcore/to" + "github.com/Azure/azure-sdk-for-go/sdk/azidentity" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/paloaltonetworksngfw/armpanngfw" +) + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/LocalRules_ListByLocalRulestacks_MaximumSet_Gen.json +func ExampleLocalRulesClient_NewListByLocalRulestacksPager_localRulesListByLocalRulestacksMaximumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + pager := clientFactory.NewLocalRulesClient().NewListByLocalRulestacksPager("firewall-rg", "lrs1", nil) + for pager.More() { + page, err := pager.NextPage(ctx) + if err != nil { + log.Fatalf("failed to advance page: %v", err) + } + for _, v := range page.Value { + // You could use page here. We use blank identifier for just demo purposes. + _ = v + } + // If the HTTP response code is 200 as defined in example definition, your page structure would look as follows. Please pay attention that all the values in the output are fake values for just demo purposes. + // page.LocalRulesResourceListResult = armpanngfw.LocalRulesResourceListResult{ + // Value: []*armpanngfw.LocalRulesResource{ + // { + // Name: to.Ptr("aaaaaaaaaaaaaaaaaaaaaa"), + // Type: to.Ptr("a"), + // ID: to.Ptr("aaaaaaaaaaaaaaaaaaaaaaaaa"), + // SystemData: &armpanngfw.SystemData{ + // CreatedAt: to.Ptr(func() time.Time { t, _ := time.Parse(time.RFC3339Nano, "2022-09-09T05:08:24.229Z"); return t}()), + // CreatedBy: to.Ptr("praval"), + // CreatedByType: to.Ptr(armpanngfw.CreatedByTypeUser), + // LastModifiedAt: to.Ptr(func() time.Time { t, _ := time.Parse(time.RFC3339Nano, "2022-09-09T05:08:24.229Z"); return t}()), + // LastModifiedBy: to.Ptr("praval"), + // LastModifiedByType: to.Ptr(armpanngfw.CreatedByTypeUser), + // }, + // Properties: &armpanngfw.RuleEntry{ + // Description: to.Ptr("aaaaaaaaaaaaaaaaaaaaaaaaaaaa"), + // ActionType: to.Ptr(armpanngfw.ActionEnumAllow), + // Applications: []*string{ + // to.Ptr("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")}, + // AuditComment: to.Ptr("aaa"), + // Category: &armpanngfw.Category{ + // Feeds: []*string{ + // to.Ptr("aaaaaaaaaaaa")}, + // URLCustom: []*string{ + // to.Ptr("aaaaa")}, + // }, + // DecryptionRuleType: to.Ptr(armpanngfw.DecryptionRuleTypeEnumSSLOutboundInspection), + // Destination: &armpanngfw.DestinationAddr{ + // Cidrs: []*string{ + // to.Ptr("aaaaaaa")}, + // Countries: []*string{ + // to.Ptr("aaaaaaaaaaaaaa")}, + // Feeds: []*string{ + // to.Ptr("aaaaaaaaaaaaaaaaaaaaaaaaaa")}, + // FqdnLists: []*string{ + // to.Ptr("aaaaaaaaaaaaa")}, + // PrefixLists: []*string{ + // to.Ptr("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")}, + // }, + // EnableLogging: to.Ptr(armpanngfw.StateEnumDISABLED), + // Etag: to.Ptr("aaaaaaaaaaaaaaaaaaaa"), + // InboundInspectionCertificate: to.Ptr("aaaaaaaaaaaaaaaaaaaaaaaaaaa"), + // NegateDestination: to.Ptr(armpanngfw.BooleanEnumTRUE), + // NegateSource: to.Ptr(armpanngfw.BooleanEnumTRUE), + // Priority: to.Ptr[int32](24), + // ProtocolPortList: []*string{ + // to.Ptr("aaaaaaaaaaaa")}, + // ProvisioningState: to.Ptr(armpanngfw.ProvisioningStateSucceeded), + // RuleName: to.Ptr("aaaaaaaaaaaaaaaaaaaaaaaaa"), + // RuleState: to.Ptr(armpanngfw.StateEnumDISABLED), + // Source: &armpanngfw.SourceAddr{ + // Cidrs: []*string{ + // to.Ptr("aaa")}, + // Countries: []*string{ + // to.Ptr("aaaaa")}, + // Feeds: []*string{ + // to.Ptr("aaaaaaaaaaaaaaaaaaa")}, + // PrefixLists: []*string{ + // to.Ptr("aaaaaaaaaaaaaaaaaaaa")}, + // }, + // Tags: []*armpanngfw.TagInfo{ + // { + // Key: to.Ptr("keyName"), + // Value: to.Ptr("value"), + // }}, + // Protocol: to.Ptr("aaaa"), + // }, + // }}, + // } + } +} + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/LocalRules_ListByLocalRulestacks_MinimumSet_Gen.json +func ExampleLocalRulesClient_NewListByLocalRulestacksPager_localRulesListByLocalRulestacksMinimumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + pager := clientFactory.NewLocalRulesClient().NewListByLocalRulestacksPager("firewall-rg", "lrs1", nil) + for pager.More() { + page, err := pager.NextPage(ctx) + if err != nil { + log.Fatalf("failed to advance page: %v", err) + } + for _, v := range page.Value { + // You could use page here. We use blank identifier for just demo purposes. + _ = v + } + // If the HTTP response code is 200 as defined in example definition, your page structure would look as follows. Please pay attention that all the values in the output are fake values for just demo purposes. + // page.LocalRulesResourceListResult = armpanngfw.LocalRulesResourceListResult{ + // Value: []*armpanngfw.LocalRulesResource{ + // { + // ID: to.Ptr("/subscriptions/2bf4a339-294d-4c25-b0b2-ef649e9f5c27/resourcegroups/firewall-rg/providers/PaloAltoNetworks.Cloudngfw/localRulestacks/lrs1/localrules/1"), + // Properties: &armpanngfw.RuleEntry{ + // RuleName: to.Ptr("aaaaaaaaaaaaaaaaaaaaaaaaa"), + // }, + // }}, + // } + } +} + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/LocalRules_Get_MaximumSet_Gen.json +func ExampleLocalRulesClient_Get_localRulesGetMaximumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + res, err := clientFactory.NewLocalRulesClient().Get(ctx, "firewall-rg", "lrs1", "1", nil) + if err != nil { + log.Fatalf("failed to finish the request: %v", err) + } + // You could use response here. We use blank identifier for just demo purposes. + _ = res + // If the HTTP response code is 200 as defined in example definition, your response structure would look as follows. Please pay attention that all the values in the output are fake values for just demo purposes. + // res.LocalRulesResource = armpanngfw.LocalRulesResource{ + // Name: to.Ptr("aaaaaaaaa"), + // Type: to.Ptr("aaaaaaaaa"), + // ID: to.Ptr("aaaaaaaaaaaaaaaaaaa"), + // SystemData: &armpanngfw.SystemData{ + // CreatedAt: to.Ptr(func() time.Time { t, _ := time.Parse(time.RFC3339Nano, "2022-09-09T05:08:24.229Z"); return t}()), + // CreatedBy: to.Ptr("praval"), + // CreatedByType: to.Ptr(armpanngfw.CreatedByTypeUser), + // LastModifiedAt: to.Ptr(func() time.Time { t, _ := time.Parse(time.RFC3339Nano, "2022-09-09T05:08:24.229Z"); return t}()), + // LastModifiedBy: to.Ptr("praval"), + // LastModifiedByType: to.Ptr(armpanngfw.CreatedByTypeUser), + // }, + // Properties: &armpanngfw.RuleEntry{ + // Description: to.Ptr("aaaaaaa"), + // ActionType: to.Ptr(armpanngfw.ActionEnumAllow), + // Applications: []*string{ + // to.Ptr("aaaaaaaaaaaaaaaaaaa")}, + // AuditComment: to.Ptr("aaaaaaaaaaaaaaaaaaaaaaa"), + // Category: &armpanngfw.Category{ + // Feeds: []*string{ + // to.Ptr("aaaaaaaaaaaaaaaaaaaaaaaa")}, + // URLCustom: []*string{ + // to.Ptr("aa")}, + // }, + // DecryptionRuleType: to.Ptr(armpanngfw.DecryptionRuleTypeEnumSSLOutboundInspection), + // Destination: &armpanngfw.DestinationAddr{ + // Cidrs: []*string{ + // to.Ptr("aaaaaaaaaaaa")}, + // Countries: []*string{ + // to.Ptr("aaaaa")}, + // Feeds: []*string{ + // to.Ptr("aaaaaaa")}, + // FqdnLists: []*string{ + // to.Ptr("aaaaaaaaaaaaaaaaaaaaaaaaaaaa")}, + // PrefixLists: []*string{ + // to.Ptr("aaaaaaaaaaaaa")}, + // }, + // EnableLogging: to.Ptr(armpanngfw.StateEnumDISABLED), + // Etag: to.Ptr("aaaaaaaaaaaaaaaaaaaaaaaaa"), + // InboundInspectionCertificate: to.Ptr("aaaaaaaaaaaaaaaa"), + // NegateDestination: to.Ptr(armpanngfw.BooleanEnumTRUE), + // NegateSource: to.Ptr(armpanngfw.BooleanEnumTRUE), + // Priority: to.Ptr[int32](13), + // ProtocolPortList: []*string{ + // to.Ptr("aaaaaaaaaaaaaaaaaaaaaa")}, + // ProvisioningState: to.Ptr(armpanngfw.ProvisioningStateSucceeded), + // RuleName: to.Ptr("aaaaaa"), + // RuleState: to.Ptr(armpanngfw.StateEnumDISABLED), + // Source: &armpanngfw.SourceAddr{ + // Cidrs: []*string{ + // to.Ptr("aaaaaaaaaaaaaaaaaaaaaaaaa")}, + // Countries: []*string{ + // to.Ptr("aaaaaaa")}, + // Feeds: []*string{ + // to.Ptr("aaaaaaaaaaaaaaaaaaa")}, + // PrefixLists: []*string{ + // to.Ptr("aaaaaaaaaaaaaaaaaaaa")}, + // }, + // Tags: []*armpanngfw.TagInfo{ + // { + // Key: to.Ptr("keyName"), + // Value: to.Ptr("value"), + // }}, + // Protocol: to.Ptr("aaaaaaaaaaaa"), + // }, + // } +} + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/LocalRules_Get_MinimumSet_Gen.json +func ExampleLocalRulesClient_Get_localRulesGetMinimumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + res, err := clientFactory.NewLocalRulesClient().Get(ctx, "firewall-rg", "lrs1", "1", nil) + if err != nil { + log.Fatalf("failed to finish the request: %v", err) + } + // You could use response here. We use blank identifier for just demo purposes. + _ = res + // If the HTTP response code is 200 as defined in example definition, your response structure would look as follows. Please pay attention that all the values in the output are fake values for just demo purposes. + // res.LocalRulesResource = armpanngfw.LocalRulesResource{ + // ID: to.Ptr("/subscriptions/2bf4a339-294d-4c25-b0b2-ef649e9f5c27/resourcegroups/firewall-rg/providers/PaloAltoNetworks.Cloudngfw/globalRulestacks/grs1/localrules/1"), + // Properties: &armpanngfw.RuleEntry{ + // RuleName: to.Ptr("aaaaaa"), + // }, + // } +} + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/LocalRules_CreateOrUpdate_MaximumSet_Gen.json +func ExampleLocalRulesClient_BeginCreateOrUpdate_localRulesCreateOrUpdateMaximumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + poller, err := clientFactory.NewLocalRulesClient().BeginCreateOrUpdate(ctx, "firewall-rg", "lrs1", "1", armpanngfw.LocalRulesResource{ + Properties: &armpanngfw.RuleEntry{ + Description: to.Ptr("description of local rule"), + ActionType: to.Ptr(armpanngfw.ActionEnumAllow), + Applications: []*string{ + to.Ptr("app1")}, + AuditComment: to.Ptr("example comment"), + Category: &armpanngfw.Category{ + Feeds: []*string{ + to.Ptr("feed")}, + URLCustom: []*string{ + to.Ptr("https://microsoft.com")}, + }, + DecryptionRuleType: to.Ptr(armpanngfw.DecryptionRuleTypeEnumSSLOutboundInspection), + Destination: &armpanngfw.DestinationAddr{ + Cidrs: []*string{ + to.Ptr("1.0.0.1/10")}, + Countries: []*string{ + to.Ptr("India")}, + Feeds: []*string{ + to.Ptr("feed")}, + FqdnLists: []*string{ + to.Ptr("FQDN1")}, + PrefixLists: []*string{ + to.Ptr("PL1")}, + }, + EnableLogging: to.Ptr(armpanngfw.StateEnumDISABLED), + Etag: to.Ptr("c18e6eef-ba3e-49ee-8a85-2b36c863a9d0"), + InboundInspectionCertificate: to.Ptr("cert1"), + NegateDestination: to.Ptr(armpanngfw.BooleanEnumTRUE), + NegateSource: to.Ptr(armpanngfw.BooleanEnumTRUE), + ProtocolPortList: []*string{ + to.Ptr("80")}, + ProvisioningState: to.Ptr(armpanngfw.ProvisioningStateAccepted), + RuleName: to.Ptr("localRule1"), + RuleState: to.Ptr(armpanngfw.StateEnumDISABLED), + Source: &armpanngfw.SourceAddr{ + Cidrs: []*string{ + to.Ptr("1.0.0.1/10")}, + Countries: []*string{ + to.Ptr("India")}, + Feeds: []*string{ + to.Ptr("feed")}, + PrefixLists: []*string{ + to.Ptr("PL1")}, + }, + Tags: []*armpanngfw.TagInfo{ + { + Key: to.Ptr("keyName"), + Value: to.Ptr("value"), + }}, + Protocol: to.Ptr("HTTP"), + }, + }, nil) + if err != nil { + log.Fatalf("failed to finish the request: %v", err) + } + res, err := poller.PollUntilDone(ctx, nil) + if err != nil { + log.Fatalf("failed to pull the result: %v", err) + } + // You could use response here. We use blank identifier for just demo purposes. + _ = res + // If the HTTP response code is 200 as defined in example definition, your response structure would look as follows. Please pay attention that all the values in the output are fake values for just demo purposes. + // res.LocalRulesResource = armpanngfw.LocalRulesResource{ + // Name: to.Ptr("aaaaaaaaa"), + // Type: to.Ptr("aaaaaaaaa"), + // ID: to.Ptr("aaaaaaaaaaaaaaaaaaa"), + // SystemData: &armpanngfw.SystemData{ + // CreatedAt: to.Ptr(func() time.Time { t, _ := time.Parse(time.RFC3339Nano, "2022-09-09T05:08:24.229Z"); return t}()), + // CreatedBy: to.Ptr("praval"), + // CreatedByType: to.Ptr(armpanngfw.CreatedByTypeUser), + // LastModifiedAt: to.Ptr(func() time.Time { t, _ := time.Parse(time.RFC3339Nano, "2022-09-09T05:08:24.229Z"); return t}()), + // LastModifiedBy: to.Ptr("praval"), + // LastModifiedByType: to.Ptr(armpanngfw.CreatedByTypeUser), + // }, + // Properties: &armpanngfw.RuleEntry{ + // Description: to.Ptr("aaaaaaa"), + // ActionType: to.Ptr(armpanngfw.ActionEnumAllow), + // Applications: []*string{ + // to.Ptr("aaaaaaaaaaaaaaaaaaa")}, + // AuditComment: to.Ptr("aaaaaaaaaaaaaaaaaaaaaaa"), + // Category: &armpanngfw.Category{ + // Feeds: []*string{ + // to.Ptr("aaaaaaaaaaaaaaaaaaaaaaaa")}, + // URLCustom: []*string{ + // to.Ptr("aa")}, + // }, + // DecryptionRuleType: to.Ptr(armpanngfw.DecryptionRuleTypeEnumSSLOutboundInspection), + // Destination: &armpanngfw.DestinationAddr{ + // Cidrs: []*string{ + // to.Ptr("aaaaaaaaaaaa")}, + // Countries: []*string{ + // to.Ptr("aaaaa")}, + // Feeds: []*string{ + // to.Ptr("aaaaaaa")}, + // FqdnLists: []*string{ + // to.Ptr("aaaaaaaaaaaaaaaaaaaaaaaaaaaa")}, + // PrefixLists: []*string{ + // to.Ptr("aaaaaaaaaaaaa")}, + // }, + // EnableLogging: to.Ptr(armpanngfw.StateEnumDISABLED), + // Etag: to.Ptr("aaaaaaaaaaaaaaaaaaaaaaaaa"), + // InboundInspectionCertificate: to.Ptr("aaaaaaaaaaaaaaaa"), + // NegateDestination: to.Ptr(armpanngfw.BooleanEnumTRUE), + // NegateSource: to.Ptr(armpanngfw.BooleanEnumTRUE), + // Priority: to.Ptr[int32](13), + // ProtocolPortList: []*string{ + // to.Ptr("aaaaaaaaaaaaaaaaaaaaaa")}, + // ProvisioningState: to.Ptr(armpanngfw.ProvisioningStateSucceeded), + // RuleName: to.Ptr("aaaaaa"), + // RuleState: to.Ptr(armpanngfw.StateEnumDISABLED), + // Source: &armpanngfw.SourceAddr{ + // Cidrs: []*string{ + // to.Ptr("aaaaaaaaaaaaaaaaaaaaaaaaa")}, + // Countries: []*string{ + // to.Ptr("aaaaaaa")}, + // Feeds: []*string{ + // to.Ptr("aaaaaaaaaaaaaaaaaaa")}, + // PrefixLists: []*string{ + // to.Ptr("aaaaaaaaaaaaaaaaaaaa")}, + // }, + // Tags: []*armpanngfw.TagInfo{ + // { + // Key: to.Ptr("keyName"), + // Value: to.Ptr("value"), + // }}, + // Protocol: to.Ptr("aaaaaaaaaaaa"), + // }, + // } +} + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/LocalRules_CreateOrUpdate_MinimumSet_Gen.json +func ExampleLocalRulesClient_BeginCreateOrUpdate_localRulesCreateOrUpdateMinimumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + poller, err := clientFactory.NewLocalRulesClient().BeginCreateOrUpdate(ctx, "firewall-rg", "lrs1", "1", armpanngfw.LocalRulesResource{ + Properties: &armpanngfw.RuleEntry{ + RuleName: to.Ptr("localRule1"), + }, + }, nil) + if err != nil { + log.Fatalf("failed to finish the request: %v", err) + } + res, err := poller.PollUntilDone(ctx, nil) + if err != nil { + log.Fatalf("failed to pull the result: %v", err) + } + // You could use response here. We use blank identifier for just demo purposes. + _ = res + // If the HTTP response code is 200 as defined in example definition, your response structure would look as follows. Please pay attention that all the values in the output are fake values for just demo purposes. + // res.LocalRulesResource = armpanngfw.LocalRulesResource{ + // ID: to.Ptr("/subscriptions/2bf4a339-294d-4c25-b0b2-ef649e9f5c27/resourcegroups/firewall-rg/providers/PaloAltoNetworks.Cloudngfw/globalRulestacks/grs1/localrules/1"), + // Properties: &armpanngfw.RuleEntry{ + // RuleName: to.Ptr("aaaaaa"), + // }, + // } +} + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/LocalRules_Delete_MaximumSet_Gen.json +func ExampleLocalRulesClient_BeginDelete_localRulesDeleteMaximumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + poller, err := clientFactory.NewLocalRulesClient().BeginDelete(ctx, "firewall-rg", "lrs1", "1", nil) + if err != nil { + log.Fatalf("failed to finish the request: %v", err) + } + _, err = poller.PollUntilDone(ctx, nil) + if err != nil { + log.Fatalf("failed to pull the result: %v", err) + } +} + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/LocalRules_Delete_MinimumSet_Gen.json +func ExampleLocalRulesClient_BeginDelete_localRulesDeleteMinimumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + poller, err := clientFactory.NewLocalRulesClient().BeginDelete(ctx, "firewall-rg", "lrs1", "1", nil) + if err != nil { + log.Fatalf("failed to finish the request: %v", err) + } + _, err = poller.PollUntilDone(ctx, nil) + if err != nil { + log.Fatalf("failed to pull the result: %v", err) + } +} + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/LocalRules_getCounters_MaximumSet_Gen.json +func ExampleLocalRulesClient_GetCounters_localRulesGetCountersMaximumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + res, err := clientFactory.NewLocalRulesClient().GetCounters(ctx, "firewall-rg", "lrs1", "1", &armpanngfw.LocalRulesClientGetCountersOptions{FirewallName: to.Ptr("firewall1")}) + if err != nil { + log.Fatalf("failed to finish the request: %v", err) + } + // You could use response here. We use blank identifier for just demo purposes. + _ = res + // If the HTTP response code is 200 as defined in example definition, your response structure would look as follows. Please pay attention that all the values in the output are fake values for just demo purposes. + // res.RuleCounter = armpanngfw.RuleCounter{ + // AppSeen: &armpanngfw.AppSeenData{ + // AppSeenList: []*armpanngfw.AppSeenInfo{ + // { + // Category: to.Ptr("aaaaaaaaaaaaaaaaaaa"), + // Risk: to.Ptr("aaaaaaaaaaaaaaaaaaaaaaaaaa"), + // StandardPorts: to.Ptr("aaaaaaaaaaaaaaaaaa"), + // SubCategory: to.Ptr("aaaaaaaaaaaaaaaaa"), + // Tag: to.Ptr("aaaaaaaaaa"), + // Technology: to.Ptr("aaaaaaaaaaaaaaaaaaaa"), + // Title: to.Ptr("aaaaaaaaaaaaaaaaaaaaaaaaaaaa"), + // }}, + // Count: to.Ptr[int32](13), + // }, + // FirewallName: to.Ptr("aaaaaaaaaaaaaaaaaa"), + // HitCount: to.Ptr[int32](20), + // LastUpdatedTimestamp: to.Ptr(func() time.Time { t, _ := time.Parse(time.RFC3339Nano, "2022-09-09T05:08:24.229Z"); return t}()), + // Priority: to.Ptr("aaaaaaaaaaaaaaaaaaaa"), + // RequestTimestamp: to.Ptr(func() time.Time { t, _ := time.Parse(time.RFC3339Nano, "2022-09-09T05:08:24.229Z"); return t}()), + // RuleListName: to.Ptr("aaaaaaaaaaaaaaaaaaa"), + // RuleName: to.Ptr("aaaa"), + // RuleStackName: to.Ptr("aaaaaaaaaaaaaaaaa"), + // Timestamp: to.Ptr(func() time.Time { t, _ := time.Parse(time.RFC3339Nano, "2022-09-09T05:08:24.229Z"); return t}()), + // } +} + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/LocalRules_getCounters_MinimumSet_Gen.json +func ExampleLocalRulesClient_GetCounters_localRulesGetCountersMinimumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + res, err := clientFactory.NewLocalRulesClient().GetCounters(ctx, "firewall-rg", "lrs1", "1", &armpanngfw.LocalRulesClientGetCountersOptions{FirewallName: nil}) + if err != nil { + log.Fatalf("failed to finish the request: %v", err) + } + // You could use response here. We use blank identifier for just demo purposes. + _ = res + // If the HTTP response code is 200 as defined in example definition, your response structure would look as follows. Please pay attention that all the values in the output are fake values for just demo purposes. + // res.RuleCounter = armpanngfw.RuleCounter{ + // Priority: to.Ptr("aaaaaaaaaaaaaaaaaaaa"), + // RuleName: to.Ptr("aaaa"), + // } +} + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/LocalRules_refreshCounters_MaximumSet_Gen.json +func ExampleLocalRulesClient_RefreshCounters_localRulesRefreshCountersMaximumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + _, err = clientFactory.NewLocalRulesClient().RefreshCounters(ctx, "firewall-rg", "lrs1", "1", &armpanngfw.LocalRulesClientRefreshCountersOptions{FirewallName: to.Ptr("firewall1")}) + if err != nil { + log.Fatalf("failed to finish the request: %v", err) + } +} + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/LocalRules_refreshCounters_MinimumSet_Gen.json +func ExampleLocalRulesClient_RefreshCounters_localRulesRefreshCountersMinimumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + _, err = clientFactory.NewLocalRulesClient().RefreshCounters(ctx, "firewall-rg", "lrs1", "1", &armpanngfw.LocalRulesClientRefreshCountersOptions{FirewallName: nil}) + if err != nil { + log.Fatalf("failed to finish the request: %v", err) + } +} + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/LocalRules_resetCounters_MaximumSet_Gen.json +func ExampleLocalRulesClient_ResetCounters_localRulesResetCountersMaximumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + res, err := clientFactory.NewLocalRulesClient().ResetCounters(ctx, "firewall-rg", "lrs1", "1", &armpanngfw.LocalRulesClientResetCountersOptions{FirewallName: to.Ptr("firewall1")}) + if err != nil { + log.Fatalf("failed to finish the request: %v", err) + } + // You could use response here. We use blank identifier for just demo purposes. + _ = res + // If the HTTP response code is 200 as defined in example definition, your response structure would look as follows. Please pay attention that all the values in the output are fake values for just demo purposes. + // res.RuleCounterReset = armpanngfw.RuleCounterReset{ + // FirewallName: to.Ptr("aaaaaaaaaaaaaaaaaa"), + // Priority: to.Ptr("aaaaaaa"), + // RuleListName: to.Ptr("aaaaa"), + // RuleName: to.Ptr("aaaaa"), + // RuleStackName: to.Ptr("aa"), + // } +} + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/LocalRules_resetCounters_MinimumSet_Gen.json +func ExampleLocalRulesClient_ResetCounters_localRulesResetCountersMinimumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + res, err := clientFactory.NewLocalRulesClient().ResetCounters(ctx, "firewall-rg", "lrs1", "1", &armpanngfw.LocalRulesClientResetCountersOptions{FirewallName: nil}) + if err != nil { + log.Fatalf("failed to finish the request: %v", err) + } + // You could use response here. We use blank identifier for just demo purposes. + _ = res + // If the HTTP response code is 200 as defined in example definition, your response structure would look as follows. Please pay attention that all the values in the output are fake values for just demo purposes. + // res.RuleCounterReset = armpanngfw.RuleCounterReset{ + // } +} diff --git a/sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/localrulestacks_client.go b/sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/localrulestacks_client.go new file mode 100644 index 000000000000..61d9b4d69c4e --- /dev/null +++ b/sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/localrulestacks_client.go @@ -0,0 +1,1041 @@ +//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. +// Code generated by Microsoft (R) AutoRest Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. +// DO NOT EDIT. + +package armpanngfw + +import ( + "context" + "errors" + "github.com/Azure/azure-sdk-for-go/sdk/azcore" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/arm" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/policy" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime" + "net/http" + "net/url" + "strconv" + "strings" +) + +// LocalRulestacksClient contains the methods for the LocalRulestacks group. +// Don't use this type directly, use NewLocalRulestacksClient() instead. +type LocalRulestacksClient struct { + internal *arm.Client + subscriptionID string +} + +// NewLocalRulestacksClient creates a new instance of LocalRulestacksClient with the specified values. +// - subscriptionID - The ID of the target subscription. +// - credential - used to authorize requests. Usually a credential from azidentity. +// - options - pass nil to accept the default values. +func NewLocalRulestacksClient(subscriptionID string, credential azcore.TokenCredential, options *arm.ClientOptions) (*LocalRulestacksClient, error) { + cl, err := arm.NewClient(moduleName+".LocalRulestacksClient", moduleVersion, credential, options) + if err != nil { + return nil, err + } + client := &LocalRulestacksClient{ + subscriptionID: subscriptionID, + internal: cl, + } + return client, nil +} + +// BeginCommit - Commit rulestack configuration +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2022-08-29-preview +// - resourceGroupName - The name of the resource group. The name is case insensitive. +// - localRulestackName - LocalRulestack resource name +// - options - LocalRulestacksClientBeginCommitOptions contains the optional parameters for the LocalRulestacksClient.BeginCommit +// method. +func (client *LocalRulestacksClient) BeginCommit(ctx context.Context, resourceGroupName string, localRulestackName string, options *LocalRulestacksClientBeginCommitOptions) (*runtime.Poller[LocalRulestacksClientCommitResponse], error) { + if options == nil || options.ResumeToken == "" { + resp, err := client.commit(ctx, resourceGroupName, localRulestackName, options) + if err != nil { + return nil, err + } + return runtime.NewPoller(resp, client.internal.Pipeline(), &runtime.NewPollerOptions[LocalRulestacksClientCommitResponse]{ + FinalStateVia: runtime.FinalStateViaLocation, + }) + } else { + return runtime.NewPollerFromResumeToken[LocalRulestacksClientCommitResponse](options.ResumeToken, client.internal.Pipeline(), nil) + } +} + +// Commit - Commit rulestack configuration +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2022-08-29-preview +func (client *LocalRulestacksClient) commit(ctx context.Context, resourceGroupName string, localRulestackName string, options *LocalRulestacksClientBeginCommitOptions) (*http.Response, error) { + req, err := client.commitCreateRequest(ctx, resourceGroupName, localRulestackName, options) + if err != nil { + return nil, err + } + resp, err := client.internal.Pipeline().Do(req) + if err != nil { + return nil, err + } + if !runtime.HasStatusCode(resp, http.StatusAccepted) { + return nil, runtime.NewResponseError(resp) + } + return resp, nil +} + +// commitCreateRequest creates the Commit request. +func (client *LocalRulestacksClient) commitCreateRequest(ctx context.Context, resourceGroupName string, localRulestackName string, options *LocalRulestacksClientBeginCommitOptions) (*policy.Request, error) { + urlPath := "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/PaloAltoNetworks.Cloudngfw/localRulestacks/{localRulestackName}/commit" + if client.subscriptionID == "" { + return nil, errors.New("parameter client.subscriptionID cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{subscriptionId}", url.PathEscape(client.subscriptionID)) + if resourceGroupName == "" { + return nil, errors.New("parameter resourceGroupName cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{resourceGroupName}", url.PathEscape(resourceGroupName)) + if localRulestackName == "" { + return nil, errors.New("parameter localRulestackName cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{localRulestackName}", url.PathEscape(localRulestackName)) + req, err := runtime.NewRequest(ctx, http.MethodPost, runtime.JoinPaths(client.internal.Endpoint(), urlPath)) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("api-version", "2022-08-29-preview") + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["Accept"] = []string{"application/json"} + return req, nil +} + +// BeginCreateOrUpdate - Create a LocalRulestackResource +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2022-08-29-preview +// - resourceGroupName - The name of the resource group. The name is case insensitive. +// - localRulestackName - LocalRulestack resource name +// - resource - Resource create parameters. +// - options - LocalRulestacksClientBeginCreateOrUpdateOptions contains the optional parameters for the LocalRulestacksClient.BeginCreateOrUpdate +// method. +func (client *LocalRulestacksClient) BeginCreateOrUpdate(ctx context.Context, resourceGroupName string, localRulestackName string, resource LocalRulestackResource, options *LocalRulestacksClientBeginCreateOrUpdateOptions) (*runtime.Poller[LocalRulestacksClientCreateOrUpdateResponse], error) { + if options == nil || options.ResumeToken == "" { + resp, err := client.createOrUpdate(ctx, resourceGroupName, localRulestackName, resource, options) + if err != nil { + return nil, err + } + return runtime.NewPoller(resp, client.internal.Pipeline(), &runtime.NewPollerOptions[LocalRulestacksClientCreateOrUpdateResponse]{ + FinalStateVia: runtime.FinalStateViaAzureAsyncOp, + }) + } else { + return runtime.NewPollerFromResumeToken[LocalRulestacksClientCreateOrUpdateResponse](options.ResumeToken, client.internal.Pipeline(), nil) + } +} + +// CreateOrUpdate - Create a LocalRulestackResource +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2022-08-29-preview +func (client *LocalRulestacksClient) createOrUpdate(ctx context.Context, resourceGroupName string, localRulestackName string, resource LocalRulestackResource, options *LocalRulestacksClientBeginCreateOrUpdateOptions) (*http.Response, error) { + req, err := client.createOrUpdateCreateRequest(ctx, resourceGroupName, localRulestackName, resource, options) + if err != nil { + return nil, err + } + resp, err := client.internal.Pipeline().Do(req) + if err != nil { + return nil, err + } + if !runtime.HasStatusCode(resp, http.StatusOK, http.StatusCreated) { + return nil, runtime.NewResponseError(resp) + } + return resp, nil +} + +// createOrUpdateCreateRequest creates the CreateOrUpdate request. +func (client *LocalRulestacksClient) createOrUpdateCreateRequest(ctx context.Context, resourceGroupName string, localRulestackName string, resource LocalRulestackResource, options *LocalRulestacksClientBeginCreateOrUpdateOptions) (*policy.Request, error) { + urlPath := "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/PaloAltoNetworks.Cloudngfw/localRulestacks/{localRulestackName}" + if client.subscriptionID == "" { + return nil, errors.New("parameter client.subscriptionID cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{subscriptionId}", url.PathEscape(client.subscriptionID)) + if resourceGroupName == "" { + return nil, errors.New("parameter resourceGroupName cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{resourceGroupName}", url.PathEscape(resourceGroupName)) + if localRulestackName == "" { + return nil, errors.New("parameter localRulestackName cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{localRulestackName}", url.PathEscape(localRulestackName)) + req, err := runtime.NewRequest(ctx, http.MethodPut, runtime.JoinPaths(client.internal.Endpoint(), urlPath)) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("api-version", "2022-08-29-preview") + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["Accept"] = []string{"application/json"} + return req, runtime.MarshalAsJSON(req, resource) +} + +// BeginDelete - Delete a LocalRulestackResource +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2022-08-29-preview +// - resourceGroupName - The name of the resource group. The name is case insensitive. +// - localRulestackName - LocalRulestack resource name +// - options - LocalRulestacksClientBeginDeleteOptions contains the optional parameters for the LocalRulestacksClient.BeginDelete +// method. +func (client *LocalRulestacksClient) BeginDelete(ctx context.Context, resourceGroupName string, localRulestackName string, options *LocalRulestacksClientBeginDeleteOptions) (*runtime.Poller[LocalRulestacksClientDeleteResponse], error) { + if options == nil || options.ResumeToken == "" { + resp, err := client.deleteOperation(ctx, resourceGroupName, localRulestackName, options) + if err != nil { + return nil, err + } + return runtime.NewPoller(resp, client.internal.Pipeline(), &runtime.NewPollerOptions[LocalRulestacksClientDeleteResponse]{ + FinalStateVia: runtime.FinalStateViaAzureAsyncOp, + }) + } else { + return runtime.NewPollerFromResumeToken[LocalRulestacksClientDeleteResponse](options.ResumeToken, client.internal.Pipeline(), nil) + } +} + +// Delete - Delete a LocalRulestackResource +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2022-08-29-preview +func (client *LocalRulestacksClient) deleteOperation(ctx context.Context, resourceGroupName string, localRulestackName string, options *LocalRulestacksClientBeginDeleteOptions) (*http.Response, error) { + req, err := client.deleteCreateRequest(ctx, resourceGroupName, localRulestackName, options) + if err != nil { + return nil, err + } + resp, err := client.internal.Pipeline().Do(req) + if err != nil { + return nil, err + } + if !runtime.HasStatusCode(resp, http.StatusOK, http.StatusAccepted, http.StatusNoContent) { + return nil, runtime.NewResponseError(resp) + } + return resp, nil +} + +// deleteCreateRequest creates the Delete request. +func (client *LocalRulestacksClient) deleteCreateRequest(ctx context.Context, resourceGroupName string, localRulestackName string, options *LocalRulestacksClientBeginDeleteOptions) (*policy.Request, error) { + urlPath := "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/PaloAltoNetworks.Cloudngfw/localRulestacks/{localRulestackName}" + if client.subscriptionID == "" { + return nil, errors.New("parameter client.subscriptionID cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{subscriptionId}", url.PathEscape(client.subscriptionID)) + if resourceGroupName == "" { + return nil, errors.New("parameter resourceGroupName cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{resourceGroupName}", url.PathEscape(resourceGroupName)) + if localRulestackName == "" { + return nil, errors.New("parameter localRulestackName cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{localRulestackName}", url.PathEscape(localRulestackName)) + req, err := runtime.NewRequest(ctx, http.MethodDelete, runtime.JoinPaths(client.internal.Endpoint(), urlPath)) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("api-version", "2022-08-29-preview") + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["Accept"] = []string{"application/json"} + return req, nil +} + +// Get - Get a LocalRulestackResource +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2022-08-29-preview +// - resourceGroupName - The name of the resource group. The name is case insensitive. +// - localRulestackName - LocalRulestack resource name +// - options - LocalRulestacksClientGetOptions contains the optional parameters for the LocalRulestacksClient.Get method. +func (client *LocalRulestacksClient) Get(ctx context.Context, resourceGroupName string, localRulestackName string, options *LocalRulestacksClientGetOptions) (LocalRulestacksClientGetResponse, error) { + req, err := client.getCreateRequest(ctx, resourceGroupName, localRulestackName, options) + if err != nil { + return LocalRulestacksClientGetResponse{}, err + } + resp, err := client.internal.Pipeline().Do(req) + if err != nil { + return LocalRulestacksClientGetResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusOK) { + return LocalRulestacksClientGetResponse{}, runtime.NewResponseError(resp) + } + return client.getHandleResponse(resp) +} + +// getCreateRequest creates the Get request. +func (client *LocalRulestacksClient) getCreateRequest(ctx context.Context, resourceGroupName string, localRulestackName string, options *LocalRulestacksClientGetOptions) (*policy.Request, error) { + urlPath := "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/PaloAltoNetworks.Cloudngfw/localRulestacks/{localRulestackName}" + if client.subscriptionID == "" { + return nil, errors.New("parameter client.subscriptionID cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{subscriptionId}", url.PathEscape(client.subscriptionID)) + if resourceGroupName == "" { + return nil, errors.New("parameter resourceGroupName cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{resourceGroupName}", url.PathEscape(resourceGroupName)) + if localRulestackName == "" { + return nil, errors.New("parameter localRulestackName cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{localRulestackName}", url.PathEscape(localRulestackName)) + req, err := runtime.NewRequest(ctx, http.MethodGet, runtime.JoinPaths(client.internal.Endpoint(), urlPath)) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("api-version", "2022-08-29-preview") + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["Accept"] = []string{"application/json"} + return req, nil +} + +// getHandleResponse handles the Get response. +func (client *LocalRulestacksClient) getHandleResponse(resp *http.Response) (LocalRulestacksClientGetResponse, error) { + result := LocalRulestacksClientGetResponse{} + if err := runtime.UnmarshalAsJSON(resp, &result.LocalRulestackResource); err != nil { + return LocalRulestacksClientGetResponse{}, err + } + return result, nil +} + +// GetChangeLog - Get changelog +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2022-08-29-preview +// - resourceGroupName - The name of the resource group. The name is case insensitive. +// - localRulestackName - LocalRulestack resource name +// - options - LocalRulestacksClientGetChangeLogOptions contains the optional parameters for the LocalRulestacksClient.GetChangeLog +// method. +func (client *LocalRulestacksClient) GetChangeLog(ctx context.Context, resourceGroupName string, localRulestackName string, options *LocalRulestacksClientGetChangeLogOptions) (LocalRulestacksClientGetChangeLogResponse, error) { + req, err := client.getChangeLogCreateRequest(ctx, resourceGroupName, localRulestackName, options) + if err != nil { + return LocalRulestacksClientGetChangeLogResponse{}, err + } + resp, err := client.internal.Pipeline().Do(req) + if err != nil { + return LocalRulestacksClientGetChangeLogResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusOK) { + return LocalRulestacksClientGetChangeLogResponse{}, runtime.NewResponseError(resp) + } + return client.getChangeLogHandleResponse(resp) +} + +// getChangeLogCreateRequest creates the GetChangeLog request. +func (client *LocalRulestacksClient) getChangeLogCreateRequest(ctx context.Context, resourceGroupName string, localRulestackName string, options *LocalRulestacksClientGetChangeLogOptions) (*policy.Request, error) { + urlPath := "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/PaloAltoNetworks.Cloudngfw/localRulestacks/{localRulestackName}/getChangeLog" + if client.subscriptionID == "" { + return nil, errors.New("parameter client.subscriptionID cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{subscriptionId}", url.PathEscape(client.subscriptionID)) + if resourceGroupName == "" { + return nil, errors.New("parameter resourceGroupName cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{resourceGroupName}", url.PathEscape(resourceGroupName)) + if localRulestackName == "" { + return nil, errors.New("parameter localRulestackName cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{localRulestackName}", url.PathEscape(localRulestackName)) + req, err := runtime.NewRequest(ctx, http.MethodPost, runtime.JoinPaths(client.internal.Endpoint(), urlPath)) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("api-version", "2022-08-29-preview") + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["Accept"] = []string{"application/json"} + return req, nil +} + +// getChangeLogHandleResponse handles the GetChangeLog response. +func (client *LocalRulestacksClient) getChangeLogHandleResponse(resp *http.Response) (LocalRulestacksClientGetChangeLogResponse, error) { + result := LocalRulestacksClientGetChangeLogResponse{} + if err := runtime.UnmarshalAsJSON(resp, &result.Changelog); err != nil { + return LocalRulestacksClientGetChangeLogResponse{}, err + } + return result, nil +} + +// GetSupportInfo - support info for rulestack. +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2022-08-29-preview +// - resourceGroupName - The name of the resource group. The name is case insensitive. +// - localRulestackName - LocalRulestack resource name +// - options - LocalRulestacksClientGetSupportInfoOptions contains the optional parameters for the LocalRulestacksClient.GetSupportInfo +// method. +func (client *LocalRulestacksClient) GetSupportInfo(ctx context.Context, resourceGroupName string, localRulestackName string, options *LocalRulestacksClientGetSupportInfoOptions) (LocalRulestacksClientGetSupportInfoResponse, error) { + req, err := client.getSupportInfoCreateRequest(ctx, resourceGroupName, localRulestackName, options) + if err != nil { + return LocalRulestacksClientGetSupportInfoResponse{}, err + } + resp, err := client.internal.Pipeline().Do(req) + if err != nil { + return LocalRulestacksClientGetSupportInfoResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusOK) { + return LocalRulestacksClientGetSupportInfoResponse{}, runtime.NewResponseError(resp) + } + return client.getSupportInfoHandleResponse(resp) +} + +// getSupportInfoCreateRequest creates the GetSupportInfo request. +func (client *LocalRulestacksClient) getSupportInfoCreateRequest(ctx context.Context, resourceGroupName string, localRulestackName string, options *LocalRulestacksClientGetSupportInfoOptions) (*policy.Request, error) { + urlPath := "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/PaloAltoNetworks.Cloudngfw/localRulestacks/{localRulestackName}/getSupportInfo" + if client.subscriptionID == "" { + return nil, errors.New("parameter client.subscriptionID cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{subscriptionId}", url.PathEscape(client.subscriptionID)) + if resourceGroupName == "" { + return nil, errors.New("parameter resourceGroupName cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{resourceGroupName}", url.PathEscape(resourceGroupName)) + if localRulestackName == "" { + return nil, errors.New("parameter localRulestackName cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{localRulestackName}", url.PathEscape(localRulestackName)) + req, err := runtime.NewRequest(ctx, http.MethodPost, runtime.JoinPaths(client.internal.Endpoint(), urlPath)) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("api-version", "2022-08-29-preview") + if options != nil && options.Email != nil { + reqQP.Set("email", *options.Email) + } + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["Accept"] = []string{"application/json"} + return req, nil +} + +// getSupportInfoHandleResponse handles the GetSupportInfo response. +func (client *LocalRulestacksClient) getSupportInfoHandleResponse(resp *http.Response) (LocalRulestacksClientGetSupportInfoResponse, error) { + result := LocalRulestacksClientGetSupportInfoResponse{} + if err := runtime.UnmarshalAsJSON(resp, &result.SupportInfo); err != nil { + return LocalRulestacksClientGetSupportInfoResponse{}, err + } + return result, nil +} + +// ListAdvancedSecurityObjects - Get the list of advanced security objects +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2022-08-29-preview +// - resourceGroupName - The name of the resource group. The name is case insensitive. +// - localRulestackName - LocalRulestack resource name +// - options - LocalRulestacksClientListAdvancedSecurityObjectsOptions contains the optional parameters for the LocalRulestacksClient.ListAdvancedSecurityObjects +// method. +func (client *LocalRulestacksClient) ListAdvancedSecurityObjects(ctx context.Context, resourceGroupName string, localRulestackName string, typeParam AdvSecurityObjectTypeEnum, options *LocalRulestacksClientListAdvancedSecurityObjectsOptions) (LocalRulestacksClientListAdvancedSecurityObjectsResponse, error) { + req, err := client.listAdvancedSecurityObjectsCreateRequest(ctx, resourceGroupName, localRulestackName, typeParam, options) + if err != nil { + return LocalRulestacksClientListAdvancedSecurityObjectsResponse{}, err + } + resp, err := client.internal.Pipeline().Do(req) + if err != nil { + return LocalRulestacksClientListAdvancedSecurityObjectsResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusOK) { + return LocalRulestacksClientListAdvancedSecurityObjectsResponse{}, runtime.NewResponseError(resp) + } + return client.listAdvancedSecurityObjectsHandleResponse(resp) +} + +// listAdvancedSecurityObjectsCreateRequest creates the ListAdvancedSecurityObjects request. +func (client *LocalRulestacksClient) listAdvancedSecurityObjectsCreateRequest(ctx context.Context, resourceGroupName string, localRulestackName string, typeParam AdvSecurityObjectTypeEnum, options *LocalRulestacksClientListAdvancedSecurityObjectsOptions) (*policy.Request, error) { + urlPath := "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/PaloAltoNetworks.Cloudngfw/localRulestacks/{localRulestackName}/listAdvancedSecurityObjects" + if client.subscriptionID == "" { + return nil, errors.New("parameter client.subscriptionID cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{subscriptionId}", url.PathEscape(client.subscriptionID)) + if resourceGroupName == "" { + return nil, errors.New("parameter resourceGroupName cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{resourceGroupName}", url.PathEscape(resourceGroupName)) + if localRulestackName == "" { + return nil, errors.New("parameter localRulestackName cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{localRulestackName}", url.PathEscape(localRulestackName)) + req, err := runtime.NewRequest(ctx, http.MethodPost, runtime.JoinPaths(client.internal.Endpoint(), urlPath)) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("api-version", "2022-08-29-preview") + if options != nil && options.Skip != nil { + reqQP.Set("skip", *options.Skip) + } + if options != nil && options.Top != nil { + reqQP.Set("top", strconv.FormatInt(int64(*options.Top), 10)) + } + reqQP.Set("type", string(typeParam)) + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["Accept"] = []string{"application/json"} + return req, nil +} + +// listAdvancedSecurityObjectsHandleResponse handles the ListAdvancedSecurityObjects response. +func (client *LocalRulestacksClient) listAdvancedSecurityObjectsHandleResponse(resp *http.Response) (LocalRulestacksClientListAdvancedSecurityObjectsResponse, error) { + result := LocalRulestacksClientListAdvancedSecurityObjectsResponse{} + if err := runtime.UnmarshalAsJSON(resp, &result.AdvSecurityObjectListResponse); err != nil { + return LocalRulestacksClientListAdvancedSecurityObjectsResponse{}, err + } + return result, nil +} + +// ListAppIDs - List of AppIds for LocalRulestack ApiVersion +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2022-08-29-preview +// - resourceGroupName - The name of the resource group. The name is case insensitive. +// - localRulestackName - LocalRulestack resource name +// - options - LocalRulestacksClientListAppIDsOptions contains the optional parameters for the LocalRulestacksClient.ListAppIDs +// method. +func (client *LocalRulestacksClient) ListAppIDs(ctx context.Context, resourceGroupName string, localRulestackName string, options *LocalRulestacksClientListAppIDsOptions) (LocalRulestacksClientListAppIDsResponse, error) { + req, err := client.listAppIDsCreateRequest(ctx, resourceGroupName, localRulestackName, options) + if err != nil { + return LocalRulestacksClientListAppIDsResponse{}, err + } + resp, err := client.internal.Pipeline().Do(req) + if err != nil { + return LocalRulestacksClientListAppIDsResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusOK) { + return LocalRulestacksClientListAppIDsResponse{}, runtime.NewResponseError(resp) + } + return client.listAppIDsHandleResponse(resp) +} + +// listAppIDsCreateRequest creates the ListAppIDs request. +func (client *LocalRulestacksClient) listAppIDsCreateRequest(ctx context.Context, resourceGroupName string, localRulestackName string, options *LocalRulestacksClientListAppIDsOptions) (*policy.Request, error) { + urlPath := "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/PaloAltoNetworks.Cloudngfw/localRulestacks/{localRulestackName}/listAppIds" + if client.subscriptionID == "" { + return nil, errors.New("parameter client.subscriptionID cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{subscriptionId}", url.PathEscape(client.subscriptionID)) + if resourceGroupName == "" { + return nil, errors.New("parameter resourceGroupName cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{resourceGroupName}", url.PathEscape(resourceGroupName)) + if localRulestackName == "" { + return nil, errors.New("parameter localRulestackName cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{localRulestackName}", url.PathEscape(localRulestackName)) + req, err := runtime.NewRequest(ctx, http.MethodPost, runtime.JoinPaths(client.internal.Endpoint(), urlPath)) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("api-version", "2022-08-29-preview") + if options != nil && options.AppIDVersion != nil { + reqQP.Set("appIdVersion", *options.AppIDVersion) + } + if options != nil && options.AppPrefix != nil { + reqQP.Set("appPrefix", *options.AppPrefix) + } + if options != nil && options.Skip != nil { + reqQP.Set("skip", *options.Skip) + } + if options != nil && options.Top != nil { + reqQP.Set("top", strconv.FormatInt(int64(*options.Top), 10)) + } + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["Accept"] = []string{"application/json"} + return req, nil +} + +// listAppIDsHandleResponse handles the ListAppIDs response. +func (client *LocalRulestacksClient) listAppIDsHandleResponse(resp *http.Response) (LocalRulestacksClientListAppIDsResponse, error) { + result := LocalRulestacksClientListAppIDsResponse{} + if err := runtime.UnmarshalAsJSON(resp, &result.ListAppIDResponse); err != nil { + return LocalRulestacksClientListAppIDsResponse{}, err + } + return result, nil +} + +// NewListByResourceGroupPager - List LocalRulestackResource resources by resource group +// +// Generated from API version 2022-08-29-preview +// - resourceGroupName - The name of the resource group. The name is case insensitive. +// - options - LocalRulestacksClientListByResourceGroupOptions contains the optional parameters for the LocalRulestacksClient.NewListByResourceGroupPager +// method. +func (client *LocalRulestacksClient) NewListByResourceGroupPager(resourceGroupName string, options *LocalRulestacksClientListByResourceGroupOptions) *runtime.Pager[LocalRulestacksClientListByResourceGroupResponse] { + return runtime.NewPager(runtime.PagingHandler[LocalRulestacksClientListByResourceGroupResponse]{ + More: func(page LocalRulestacksClientListByResourceGroupResponse) bool { + return page.NextLink != nil && len(*page.NextLink) > 0 + }, + Fetcher: func(ctx context.Context, page *LocalRulestacksClientListByResourceGroupResponse) (LocalRulestacksClientListByResourceGroupResponse, error) { + var req *policy.Request + var err error + if page == nil { + req, err = client.listByResourceGroupCreateRequest(ctx, resourceGroupName, options) + } else { + req, err = runtime.NewRequest(ctx, http.MethodGet, *page.NextLink) + } + if err != nil { + return LocalRulestacksClientListByResourceGroupResponse{}, err + } + resp, err := client.internal.Pipeline().Do(req) + if err != nil { + return LocalRulestacksClientListByResourceGroupResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusOK) { + return LocalRulestacksClientListByResourceGroupResponse{}, runtime.NewResponseError(resp) + } + return client.listByResourceGroupHandleResponse(resp) + }, + }) +} + +// listByResourceGroupCreateRequest creates the ListByResourceGroup request. +func (client *LocalRulestacksClient) listByResourceGroupCreateRequest(ctx context.Context, resourceGroupName string, options *LocalRulestacksClientListByResourceGroupOptions) (*policy.Request, error) { + urlPath := "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/PaloAltoNetworks.Cloudngfw/localRulestacks" + if client.subscriptionID == "" { + return nil, errors.New("parameter client.subscriptionID cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{subscriptionId}", url.PathEscape(client.subscriptionID)) + if resourceGroupName == "" { + return nil, errors.New("parameter resourceGroupName cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{resourceGroupName}", url.PathEscape(resourceGroupName)) + req, err := runtime.NewRequest(ctx, http.MethodGet, runtime.JoinPaths(client.internal.Endpoint(), urlPath)) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("api-version", "2022-08-29-preview") + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["Accept"] = []string{"application/json"} + return req, nil +} + +// listByResourceGroupHandleResponse handles the ListByResourceGroup response. +func (client *LocalRulestacksClient) listByResourceGroupHandleResponse(resp *http.Response) (LocalRulestacksClientListByResourceGroupResponse, error) { + result := LocalRulestacksClientListByResourceGroupResponse{} + if err := runtime.UnmarshalAsJSON(resp, &result.LocalRulestackResourceListResult); err != nil { + return LocalRulestacksClientListByResourceGroupResponse{}, err + } + return result, nil +} + +// NewListBySubscriptionPager - List LocalRulestackResource resources by subscription ID +// +// Generated from API version 2022-08-29-preview +// - options - LocalRulestacksClientListBySubscriptionOptions contains the optional parameters for the LocalRulestacksClient.NewListBySubscriptionPager +// method. +func (client *LocalRulestacksClient) NewListBySubscriptionPager(options *LocalRulestacksClientListBySubscriptionOptions) *runtime.Pager[LocalRulestacksClientListBySubscriptionResponse] { + return runtime.NewPager(runtime.PagingHandler[LocalRulestacksClientListBySubscriptionResponse]{ + More: func(page LocalRulestacksClientListBySubscriptionResponse) bool { + return page.NextLink != nil && len(*page.NextLink) > 0 + }, + Fetcher: func(ctx context.Context, page *LocalRulestacksClientListBySubscriptionResponse) (LocalRulestacksClientListBySubscriptionResponse, error) { + var req *policy.Request + var err error + if page == nil { + req, err = client.listBySubscriptionCreateRequest(ctx, options) + } else { + req, err = runtime.NewRequest(ctx, http.MethodGet, *page.NextLink) + } + if err != nil { + return LocalRulestacksClientListBySubscriptionResponse{}, err + } + resp, err := client.internal.Pipeline().Do(req) + if err != nil { + return LocalRulestacksClientListBySubscriptionResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusOK) { + return LocalRulestacksClientListBySubscriptionResponse{}, runtime.NewResponseError(resp) + } + return client.listBySubscriptionHandleResponse(resp) + }, + }) +} + +// listBySubscriptionCreateRequest creates the ListBySubscription request. +func (client *LocalRulestacksClient) listBySubscriptionCreateRequest(ctx context.Context, options *LocalRulestacksClientListBySubscriptionOptions) (*policy.Request, error) { + urlPath := "/subscriptions/{subscriptionId}/providers/PaloAltoNetworks.Cloudngfw/localRulestacks" + if client.subscriptionID == "" { + return nil, errors.New("parameter client.subscriptionID cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{subscriptionId}", url.PathEscape(client.subscriptionID)) + req, err := runtime.NewRequest(ctx, http.MethodGet, runtime.JoinPaths(client.internal.Endpoint(), urlPath)) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("api-version", "2022-08-29-preview") + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["Accept"] = []string{"application/json"} + return req, nil +} + +// listBySubscriptionHandleResponse handles the ListBySubscription response. +func (client *LocalRulestacksClient) listBySubscriptionHandleResponse(resp *http.Response) (LocalRulestacksClientListBySubscriptionResponse, error) { + result := LocalRulestacksClientListBySubscriptionResponse{} + if err := runtime.UnmarshalAsJSON(resp, &result.LocalRulestackResourceListResult); err != nil { + return LocalRulestacksClientListBySubscriptionResponse{}, err + } + return result, nil +} + +// ListCountries - List of countries for Rulestack +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2022-08-29-preview +// - resourceGroupName - The name of the resource group. The name is case insensitive. +// - localRulestackName - LocalRulestack resource name +// - options - LocalRulestacksClientListCountriesOptions contains the optional parameters for the LocalRulestacksClient.ListCountries +// method. +func (client *LocalRulestacksClient) ListCountries(ctx context.Context, resourceGroupName string, localRulestackName string, options *LocalRulestacksClientListCountriesOptions) (LocalRulestacksClientListCountriesResponse, error) { + req, err := client.listCountriesCreateRequest(ctx, resourceGroupName, localRulestackName, options) + if err != nil { + return LocalRulestacksClientListCountriesResponse{}, err + } + resp, err := client.internal.Pipeline().Do(req) + if err != nil { + return LocalRulestacksClientListCountriesResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusOK) { + return LocalRulestacksClientListCountriesResponse{}, runtime.NewResponseError(resp) + } + return client.listCountriesHandleResponse(resp) +} + +// listCountriesCreateRequest creates the ListCountries request. +func (client *LocalRulestacksClient) listCountriesCreateRequest(ctx context.Context, resourceGroupName string, localRulestackName string, options *LocalRulestacksClientListCountriesOptions) (*policy.Request, error) { + urlPath := "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/PaloAltoNetworks.Cloudngfw/localRulestacks/{localRulestackName}/listCountries" + if client.subscriptionID == "" { + return nil, errors.New("parameter client.subscriptionID cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{subscriptionId}", url.PathEscape(client.subscriptionID)) + if resourceGroupName == "" { + return nil, errors.New("parameter resourceGroupName cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{resourceGroupName}", url.PathEscape(resourceGroupName)) + if localRulestackName == "" { + return nil, errors.New("parameter localRulestackName cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{localRulestackName}", url.PathEscape(localRulestackName)) + req, err := runtime.NewRequest(ctx, http.MethodPost, runtime.JoinPaths(client.internal.Endpoint(), urlPath)) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("api-version", "2022-08-29-preview") + if options != nil && options.Skip != nil { + reqQP.Set("skip", *options.Skip) + } + if options != nil && options.Top != nil { + reqQP.Set("top", strconv.FormatInt(int64(*options.Top), 10)) + } + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["Accept"] = []string{"application/json"} + return req, nil +} + +// listCountriesHandleResponse handles the ListCountries response. +func (client *LocalRulestacksClient) listCountriesHandleResponse(resp *http.Response) (LocalRulestacksClientListCountriesResponse, error) { + result := LocalRulestacksClientListCountriesResponse{} + if err := runtime.UnmarshalAsJSON(resp, &result.CountriesResponse); err != nil { + return LocalRulestacksClientListCountriesResponse{}, err + } + return result, nil +} + +// ListFirewalls - List of Firewalls associated with Rulestack +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2022-08-29-preview +// - resourceGroupName - The name of the resource group. The name is case insensitive. +// - localRulestackName - LocalRulestack resource name +// - options - LocalRulestacksClientListFirewallsOptions contains the optional parameters for the LocalRulestacksClient.ListFirewalls +// method. +func (client *LocalRulestacksClient) ListFirewalls(ctx context.Context, resourceGroupName string, localRulestackName string, options *LocalRulestacksClientListFirewallsOptions) (LocalRulestacksClientListFirewallsResponse, error) { + req, err := client.listFirewallsCreateRequest(ctx, resourceGroupName, localRulestackName, options) + if err != nil { + return LocalRulestacksClientListFirewallsResponse{}, err + } + resp, err := client.internal.Pipeline().Do(req) + if err != nil { + return LocalRulestacksClientListFirewallsResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusOK) { + return LocalRulestacksClientListFirewallsResponse{}, runtime.NewResponseError(resp) + } + return client.listFirewallsHandleResponse(resp) +} + +// listFirewallsCreateRequest creates the ListFirewalls request. +func (client *LocalRulestacksClient) listFirewallsCreateRequest(ctx context.Context, resourceGroupName string, localRulestackName string, options *LocalRulestacksClientListFirewallsOptions) (*policy.Request, error) { + urlPath := "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/PaloAltoNetworks.Cloudngfw/localRulestacks/{localRulestackName}/listFirewalls" + if client.subscriptionID == "" { + return nil, errors.New("parameter client.subscriptionID cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{subscriptionId}", url.PathEscape(client.subscriptionID)) + if resourceGroupName == "" { + return nil, errors.New("parameter resourceGroupName cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{resourceGroupName}", url.PathEscape(resourceGroupName)) + if localRulestackName == "" { + return nil, errors.New("parameter localRulestackName cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{localRulestackName}", url.PathEscape(localRulestackName)) + req, err := runtime.NewRequest(ctx, http.MethodPost, runtime.JoinPaths(client.internal.Endpoint(), urlPath)) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("api-version", "2022-08-29-preview") + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["Accept"] = []string{"application/json"} + return req, nil +} + +// listFirewallsHandleResponse handles the ListFirewalls response. +func (client *LocalRulestacksClient) listFirewallsHandleResponse(resp *http.Response) (LocalRulestacksClientListFirewallsResponse, error) { + result := LocalRulestacksClientListFirewallsResponse{} + if err := runtime.UnmarshalAsJSON(resp, &result.ListFirewallsResponse); err != nil { + return LocalRulestacksClientListFirewallsResponse{}, err + } + return result, nil +} + +// ListPredefinedURLCategories - List predefined URL categories for rulestack +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2022-08-29-preview +// - resourceGroupName - The name of the resource group. The name is case insensitive. +// - localRulestackName - LocalRulestack resource name +// - options - LocalRulestacksClientListPredefinedURLCategoriesOptions contains the optional parameters for the LocalRulestacksClient.ListPredefinedURLCategories +// method. +func (client *LocalRulestacksClient) ListPredefinedURLCategories(ctx context.Context, resourceGroupName string, localRulestackName string, options *LocalRulestacksClientListPredefinedURLCategoriesOptions) (LocalRulestacksClientListPredefinedURLCategoriesResponse, error) { + req, err := client.listPredefinedURLCategoriesCreateRequest(ctx, resourceGroupName, localRulestackName, options) + if err != nil { + return LocalRulestacksClientListPredefinedURLCategoriesResponse{}, err + } + resp, err := client.internal.Pipeline().Do(req) + if err != nil { + return LocalRulestacksClientListPredefinedURLCategoriesResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusOK) { + return LocalRulestacksClientListPredefinedURLCategoriesResponse{}, runtime.NewResponseError(resp) + } + return client.listPredefinedURLCategoriesHandleResponse(resp) +} + +// listPredefinedURLCategoriesCreateRequest creates the ListPredefinedURLCategories request. +func (client *LocalRulestacksClient) listPredefinedURLCategoriesCreateRequest(ctx context.Context, resourceGroupName string, localRulestackName string, options *LocalRulestacksClientListPredefinedURLCategoriesOptions) (*policy.Request, error) { + urlPath := "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/PaloAltoNetworks.Cloudngfw/localRulestacks/{localRulestackName}/listPredefinedUrlCategories" + if client.subscriptionID == "" { + return nil, errors.New("parameter client.subscriptionID cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{subscriptionId}", url.PathEscape(client.subscriptionID)) + if resourceGroupName == "" { + return nil, errors.New("parameter resourceGroupName cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{resourceGroupName}", url.PathEscape(resourceGroupName)) + if localRulestackName == "" { + return nil, errors.New("parameter localRulestackName cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{localRulestackName}", url.PathEscape(localRulestackName)) + req, err := runtime.NewRequest(ctx, http.MethodPost, runtime.JoinPaths(client.internal.Endpoint(), urlPath)) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("api-version", "2022-08-29-preview") + if options != nil && options.Skip != nil { + reqQP.Set("skip", *options.Skip) + } + if options != nil && options.Top != nil { + reqQP.Set("top", strconv.FormatInt(int64(*options.Top), 10)) + } + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["Accept"] = []string{"application/json"} + return req, nil +} + +// listPredefinedURLCategoriesHandleResponse handles the ListPredefinedURLCategories response. +func (client *LocalRulestacksClient) listPredefinedURLCategoriesHandleResponse(resp *http.Response) (LocalRulestacksClientListPredefinedURLCategoriesResponse, error) { + result := LocalRulestacksClientListPredefinedURLCategoriesResponse{} + if err := runtime.UnmarshalAsJSON(resp, &result.PredefinedURLCategoriesResponse); err != nil { + return LocalRulestacksClientListPredefinedURLCategoriesResponse{}, err + } + return result, nil +} + +// ListSecurityServices - List the security services for rulestack +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2022-08-29-preview +// - resourceGroupName - The name of the resource group. The name is case insensitive. +// - localRulestackName - LocalRulestack resource name +// - options - LocalRulestacksClientListSecurityServicesOptions contains the optional parameters for the LocalRulestacksClient.ListSecurityServices +// method. +func (client *LocalRulestacksClient) ListSecurityServices(ctx context.Context, resourceGroupName string, localRulestackName string, typeParam SecurityServicesTypeEnum, options *LocalRulestacksClientListSecurityServicesOptions) (LocalRulestacksClientListSecurityServicesResponse, error) { + req, err := client.listSecurityServicesCreateRequest(ctx, resourceGroupName, localRulestackName, typeParam, options) + if err != nil { + return LocalRulestacksClientListSecurityServicesResponse{}, err + } + resp, err := client.internal.Pipeline().Do(req) + if err != nil { + return LocalRulestacksClientListSecurityServicesResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusOK) { + return LocalRulestacksClientListSecurityServicesResponse{}, runtime.NewResponseError(resp) + } + return client.listSecurityServicesHandleResponse(resp) +} + +// listSecurityServicesCreateRequest creates the ListSecurityServices request. +func (client *LocalRulestacksClient) listSecurityServicesCreateRequest(ctx context.Context, resourceGroupName string, localRulestackName string, typeParam SecurityServicesTypeEnum, options *LocalRulestacksClientListSecurityServicesOptions) (*policy.Request, error) { + urlPath := "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/PaloAltoNetworks.Cloudngfw/localRulestacks/{localRulestackName}/listSecurityServices" + if client.subscriptionID == "" { + return nil, errors.New("parameter client.subscriptionID cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{subscriptionId}", url.PathEscape(client.subscriptionID)) + if resourceGroupName == "" { + return nil, errors.New("parameter resourceGroupName cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{resourceGroupName}", url.PathEscape(resourceGroupName)) + if localRulestackName == "" { + return nil, errors.New("parameter localRulestackName cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{localRulestackName}", url.PathEscape(localRulestackName)) + req, err := runtime.NewRequest(ctx, http.MethodPost, runtime.JoinPaths(client.internal.Endpoint(), urlPath)) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("api-version", "2022-08-29-preview") + if options != nil && options.Skip != nil { + reqQP.Set("skip", *options.Skip) + } + if options != nil && options.Top != nil { + reqQP.Set("top", strconv.FormatInt(int64(*options.Top), 10)) + } + reqQP.Set("type", string(typeParam)) + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["Accept"] = []string{"application/json"} + return req, nil +} + +// listSecurityServicesHandleResponse handles the ListSecurityServices response. +func (client *LocalRulestacksClient) listSecurityServicesHandleResponse(resp *http.Response) (LocalRulestacksClientListSecurityServicesResponse, error) { + result := LocalRulestacksClientListSecurityServicesResponse{} + if err := runtime.UnmarshalAsJSON(resp, &result.SecurityServicesResponse); err != nil { + return LocalRulestacksClientListSecurityServicesResponse{}, err + } + return result, nil +} + +// Revert - Revert rulestack configuration +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2022-08-29-preview +// - resourceGroupName - The name of the resource group. The name is case insensitive. +// - localRulestackName - LocalRulestack resource name +// - options - LocalRulestacksClientRevertOptions contains the optional parameters for the LocalRulestacksClient.Revert method. +func (client *LocalRulestacksClient) Revert(ctx context.Context, resourceGroupName string, localRulestackName string, options *LocalRulestacksClientRevertOptions) (LocalRulestacksClientRevertResponse, error) { + req, err := client.revertCreateRequest(ctx, resourceGroupName, localRulestackName, options) + if err != nil { + return LocalRulestacksClientRevertResponse{}, err + } + resp, err := client.internal.Pipeline().Do(req) + if err != nil { + return LocalRulestacksClientRevertResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusNoContent) { + return LocalRulestacksClientRevertResponse{}, runtime.NewResponseError(resp) + } + return LocalRulestacksClientRevertResponse{}, nil +} + +// revertCreateRequest creates the Revert request. +func (client *LocalRulestacksClient) revertCreateRequest(ctx context.Context, resourceGroupName string, localRulestackName string, options *LocalRulestacksClientRevertOptions) (*policy.Request, error) { + urlPath := "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/PaloAltoNetworks.Cloudngfw/localRulestacks/{localRulestackName}/revert" + if client.subscriptionID == "" { + return nil, errors.New("parameter client.subscriptionID cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{subscriptionId}", url.PathEscape(client.subscriptionID)) + if resourceGroupName == "" { + return nil, errors.New("parameter resourceGroupName cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{resourceGroupName}", url.PathEscape(resourceGroupName)) + if localRulestackName == "" { + return nil, errors.New("parameter localRulestackName cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{localRulestackName}", url.PathEscape(localRulestackName)) + req, err := runtime.NewRequest(ctx, http.MethodPost, runtime.JoinPaths(client.internal.Endpoint(), urlPath)) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("api-version", "2022-08-29-preview") + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["Accept"] = []string{"application/json"} + return req, nil +} + +// Update - Update a LocalRulestackResource +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2022-08-29-preview +// - resourceGroupName - The name of the resource group. The name is case insensitive. +// - localRulestackName - LocalRulestack resource name +// - properties - The resource properties to be updated. +// - options - LocalRulestacksClientUpdateOptions contains the optional parameters for the LocalRulestacksClient.Update method. +func (client *LocalRulestacksClient) Update(ctx context.Context, resourceGroupName string, localRulestackName string, properties LocalRulestackResourceUpdate, options *LocalRulestacksClientUpdateOptions) (LocalRulestacksClientUpdateResponse, error) { + req, err := client.updateCreateRequest(ctx, resourceGroupName, localRulestackName, properties, options) + if err != nil { + return LocalRulestacksClientUpdateResponse{}, err + } + resp, err := client.internal.Pipeline().Do(req) + if err != nil { + return LocalRulestacksClientUpdateResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusOK) { + return LocalRulestacksClientUpdateResponse{}, runtime.NewResponseError(resp) + } + return client.updateHandleResponse(resp) +} + +// updateCreateRequest creates the Update request. +func (client *LocalRulestacksClient) updateCreateRequest(ctx context.Context, resourceGroupName string, localRulestackName string, properties LocalRulestackResourceUpdate, options *LocalRulestacksClientUpdateOptions) (*policy.Request, error) { + urlPath := "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/PaloAltoNetworks.Cloudngfw/localRulestacks/{localRulestackName}" + if client.subscriptionID == "" { + return nil, errors.New("parameter client.subscriptionID cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{subscriptionId}", url.PathEscape(client.subscriptionID)) + if resourceGroupName == "" { + return nil, errors.New("parameter resourceGroupName cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{resourceGroupName}", url.PathEscape(resourceGroupName)) + if localRulestackName == "" { + return nil, errors.New("parameter localRulestackName cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{localRulestackName}", url.PathEscape(localRulestackName)) + req, err := runtime.NewRequest(ctx, http.MethodPatch, runtime.JoinPaths(client.internal.Endpoint(), urlPath)) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("api-version", "2022-08-29-preview") + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["Accept"] = []string{"application/json"} + return req, runtime.MarshalAsJSON(req, properties) +} + +// updateHandleResponse handles the Update response. +func (client *LocalRulestacksClient) updateHandleResponse(resp *http.Response) (LocalRulestacksClientUpdateResponse, error) { + result := LocalRulestacksClientUpdateResponse{} + if err := runtime.UnmarshalAsJSON(resp, &result.LocalRulestackResource); err != nil { + return LocalRulestacksClientUpdateResponse{}, err + } + return result, nil +} diff --git a/sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/localrulestacks_client_example_test.go b/sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/localrulestacks_client_example_test.go new file mode 100644 index 000000000000..abb88a6d7f04 --- /dev/null +++ b/sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/localrulestacks_client_example_test.go @@ -0,0 +1,1171 @@ +//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. +// Code generated by Microsoft (R) AutoRest Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. +// DO NOT EDIT. + +package armpanngfw_test + +import ( + "context" + "log" + + "github.com/Azure/azure-sdk-for-go/sdk/azcore/to" + "github.com/Azure/azure-sdk-for-go/sdk/azidentity" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/paloaltonetworksngfw/armpanngfw" +) + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/LocalRulestacks_ListBySubscription_MaximumSet_Gen.json +func ExampleLocalRulestacksClient_NewListBySubscriptionPager_localRulestacksListBySubscriptionMaximumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + pager := clientFactory.NewLocalRulestacksClient().NewListBySubscriptionPager(nil) + for pager.More() { + page, err := pager.NextPage(ctx) + if err != nil { + log.Fatalf("failed to advance page: %v", err) + } + for _, v := range page.Value { + // You could use page here. We use blank identifier for just demo purposes. + _ = v + } + // If the HTTP response code is 200 as defined in example definition, your page structure would look as follows. Please pay attention that all the values in the output are fake values for just demo purposes. + // page.LocalRulestackResourceListResult = armpanngfw.LocalRulestackResourceListResult{ + // Value: []*armpanngfw.LocalRulestackResource{ + // { + // Name: to.Ptr("aaaaaaaaaaaaaaaaaaaaaaaaaaaaa"), + // Type: to.Ptr("aaaaaaaaaa"), + // ID: to.Ptr("aaaaaaaaaaaaaaaaaaaaaaaaaaaa"), + // SystemData: &armpanngfw.SystemData{ + // CreatedAt: to.Ptr(func() time.Time { t, _ := time.Parse(time.RFC3339Nano, "2022-09-09T05:08:24.229Z"); return t}()), + // CreatedBy: to.Ptr("praval"), + // CreatedByType: to.Ptr(armpanngfw.CreatedByTypeUser), + // LastModifiedAt: to.Ptr(func() time.Time { t, _ := time.Parse(time.RFC3339Nano, "2022-09-09T05:08:24.229Z"); return t}()), + // LastModifiedBy: to.Ptr("praval"), + // LastModifiedByType: to.Ptr(armpanngfw.CreatedByTypeUser), + // }, + // Location: to.Ptr("eastus"), + // Tags: map[string]*string{ + // "tagName": to.Ptr("value"), + // }, + // Identity: &armpanngfw.AzureResourceManagerManagedIdentityProperties{ + // Type: to.Ptr(armpanngfw.ManagedIdentityTypeNone), + // PrincipalID: to.Ptr("aaaaaaaaaaaaaaaaaaaaaaaaaa"), + // TenantID: to.Ptr("aaaaaaaaaaaaaaaaaaaaaaaaaaaa"), + // UserAssignedIdentities: map[string]*armpanngfw.AzureResourceManagerUserAssignedIdentity{ + // "key16": &armpanngfw.AzureResourceManagerUserAssignedIdentity{ + // ClientID: to.Ptr("aaaa"), + // PrincipalID: to.Ptr("aaaaaaaaaaaaaaa"), + // }, + // }, + // }, + // Properties: &armpanngfw.RulestackProperties{ + // Description: to.Ptr("aaaaaaaaaaaaaaaaaaaaa"), + // AssociatedSubscriptions: []*string{ + // to.Ptr("aaaaaaaaaaaaaaaaaaaaaaaaa")}, + // DefaultMode: to.Ptr(armpanngfw.DefaultModeIPS), + // MinAppIDVersion: to.Ptr("aaaaaaaaaaaaaaaaaaaaa"), + // PanEtag: to.Ptr("2bf4a339-294d-4c25-b0b2-ef649e9f5c12"), + // PanLocation: to.Ptr("eastus"), + // ProvisioningState: to.Ptr(armpanngfw.ProvisioningStateSucceeded), + // Scope: to.Ptr(armpanngfw.ScopeTypeLOCAL), + // SecurityServices: &armpanngfw.SecurityServices{ + // AntiSpywareProfile: to.Ptr("aaaaaaaaaa"), + // AntiVirusProfile: to.Ptr("aaaaaaaaaaaaaaaaaaaaaa"), + // DNSSubscription: to.Ptr("aaaaaaaaaaaaaaaaaaaaaaaaaaaa"), + // FileBlockingProfile: to.Ptr("aaaaa"), + // OutboundTrustCertificate: to.Ptr("aaaaaa"), + // OutboundUnTrustCertificate: to.Ptr("aaaaaaaa"), + // URLFilteringProfile: to.Ptr("aaaaaaaaaaaaaaaaaaaaaaaaaaa"), + // VulnerabilityProfile: to.Ptr("aaaaaaaaaa"), + // }, + // }, + // }}, + // } + } +} + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/LocalRulestacks_ListBySubscription_MinimumSet_Gen.json +func ExampleLocalRulestacksClient_NewListBySubscriptionPager_localRulestacksListBySubscriptionMinimumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + pager := clientFactory.NewLocalRulestacksClient().NewListBySubscriptionPager(nil) + for pager.More() { + page, err := pager.NextPage(ctx) + if err != nil { + log.Fatalf("failed to advance page: %v", err) + } + for _, v := range page.Value { + // You could use page here. We use blank identifier for just demo purposes. + _ = v + } + // If the HTTP response code is 200 as defined in example definition, your page structure would look as follows. Please pay attention that all the values in the output are fake values for just demo purposes. + // page.LocalRulestackResourceListResult = armpanngfw.LocalRulestackResourceListResult{ + // Value: []*armpanngfw.LocalRulestackResource{ + // { + // ID: to.Ptr("/subscriptions/2bf4a339-294d-4c25-b0b2-ef649e9f5c27/providers/PaloAltoNetworks.Cloudngfw/localRulestacks/lrs1"), + // Location: to.Ptr("eastus"), + // Properties: &armpanngfw.RulestackProperties{ + // }, + // }}, + // } + } +} + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/LocalRulestacks_ListByResourceGroup_MaximumSet_Gen.json +func ExampleLocalRulestacksClient_NewListByResourceGroupPager_localRulestacksListByResourceGroupMaximumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + pager := clientFactory.NewLocalRulestacksClient().NewListByResourceGroupPager("rgopenapi", nil) + for pager.More() { + page, err := pager.NextPage(ctx) + if err != nil { + log.Fatalf("failed to advance page: %v", err) + } + for _, v := range page.Value { + // You could use page here. We use blank identifier for just demo purposes. + _ = v + } + // If the HTTP response code is 200 as defined in example definition, your page structure would look as follows. Please pay attention that all the values in the output are fake values for just demo purposes. + // page.LocalRulestackResourceListResult = armpanngfw.LocalRulestackResourceListResult{ + // Value: []*armpanngfw.LocalRulestackResource{ + // { + // Name: to.Ptr("aaaaaaaaaaaaaaaaaaaaaaaaaaaaa"), + // Type: to.Ptr("aaaaaaaaaa"), + // ID: to.Ptr("aaaaaaaaaaaaaaaaaaaaaaaaaaaa"), + // SystemData: &armpanngfw.SystemData{ + // CreatedAt: to.Ptr(func() time.Time { t, _ := time.Parse(time.RFC3339Nano, "2022-09-09T05:08:24.229Z"); return t}()), + // CreatedBy: to.Ptr("praval"), + // CreatedByType: to.Ptr(armpanngfw.CreatedByTypeUser), + // LastModifiedAt: to.Ptr(func() time.Time { t, _ := time.Parse(time.RFC3339Nano, "2022-09-09T05:08:24.229Z"); return t}()), + // LastModifiedBy: to.Ptr("praval"), + // LastModifiedByType: to.Ptr(armpanngfw.CreatedByTypeUser), + // }, + // Location: to.Ptr("eastus"), + // Tags: map[string]*string{ + // "tagName": to.Ptr("value"), + // }, + // Identity: &armpanngfw.AzureResourceManagerManagedIdentityProperties{ + // Type: to.Ptr(armpanngfw.ManagedIdentityTypeNone), + // PrincipalID: to.Ptr("aaaaaaaaaaaaaaaaaaaaaaaaaa"), + // TenantID: to.Ptr("aaaaaaaaaaaaaaaaaaaaaaaaaaaa"), + // UserAssignedIdentities: map[string]*armpanngfw.AzureResourceManagerUserAssignedIdentity{ + // "key16": &armpanngfw.AzureResourceManagerUserAssignedIdentity{ + // ClientID: to.Ptr("aaaa"), + // PrincipalID: to.Ptr("aaaaaaaaaaaaaaa"), + // }, + // }, + // }, + // Properties: &armpanngfw.RulestackProperties{ + // Description: to.Ptr("aaaaaaaaaaaaaaaaaaaaa"), + // AssociatedSubscriptions: []*string{ + // to.Ptr("aaaaaaaaaaaaaaaaaaaaaaaaa")}, + // DefaultMode: to.Ptr(armpanngfw.DefaultModeIPS), + // MinAppIDVersion: to.Ptr("aaaaaaaaaaaaaaaaaaaaa"), + // PanEtag: to.Ptr("2bf4a339-294d-4c25-b0b2-ef649e9f5c12"), + // PanLocation: to.Ptr("eastus"), + // ProvisioningState: to.Ptr(armpanngfw.ProvisioningStateSucceeded), + // Scope: to.Ptr(armpanngfw.ScopeTypeLOCAL), + // SecurityServices: &armpanngfw.SecurityServices{ + // AntiSpywareProfile: to.Ptr("aaaaaaaaaa"), + // AntiVirusProfile: to.Ptr("aaaaaaaaaaaaaaaaaaaaaa"), + // DNSSubscription: to.Ptr("aaaaaaaaaaaaaaaaaaaaaaaaaaaa"), + // FileBlockingProfile: to.Ptr("aaaaa"), + // OutboundTrustCertificate: to.Ptr("aaaaaa"), + // OutboundUnTrustCertificate: to.Ptr("aaaaaaaa"), + // URLFilteringProfile: to.Ptr("aaaaaaaaaaaaaaaaaaaaaaaaaaa"), + // VulnerabilityProfile: to.Ptr("aaaaaaaaaa"), + // }, + // }, + // }}, + // } + } +} + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/LocalRulestacks_ListByResourceGroup_MinimumSet_Gen.json +func ExampleLocalRulestacksClient_NewListByResourceGroupPager_localRulestacksListByResourceGroupMinimumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + pager := clientFactory.NewLocalRulestacksClient().NewListByResourceGroupPager("rgopenapi", nil) + for pager.More() { + page, err := pager.NextPage(ctx) + if err != nil { + log.Fatalf("failed to advance page: %v", err) + } + for _, v := range page.Value { + // You could use page here. We use blank identifier for just demo purposes. + _ = v + } + // If the HTTP response code is 200 as defined in example definition, your page structure would look as follows. Please pay attention that all the values in the output are fake values for just demo purposes. + // page.LocalRulestackResourceListResult = armpanngfw.LocalRulestackResourceListResult{ + // Value: []*armpanngfw.LocalRulestackResource{ + // { + // ID: to.Ptr("/subscriptions/2bf4a339-294d-4c25-b0b2-ef649e9f5c27/resourcegroups/rgopenapi/providers/PaloAltoNetworks.Cloudngfw/localRulestacks/lrs1"), + // Location: to.Ptr("eastus"), + // Properties: &armpanngfw.RulestackProperties{ + // }, + // }}, + // } + } +} + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/LocalRulestacks_Get_MaximumSet_Gen.json +func ExampleLocalRulestacksClient_Get_localRulestacksGetMaximumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + res, err := clientFactory.NewLocalRulestacksClient().Get(ctx, "rgopenapi", "lrs1", nil) + if err != nil { + log.Fatalf("failed to finish the request: %v", err) + } + // You could use response here. We use blank identifier for just demo purposes. + _ = res + // If the HTTP response code is 200 as defined in example definition, your response structure would look as follows. Please pay attention that all the values in the output are fake values for just demo purposes. + // res.LocalRulestackResource = armpanngfw.LocalRulestackResource{ + // Name: to.Ptr("armid1"), + // Type: to.Ptr("localRulestacks"), + // ID: to.Ptr("/subscriptions/2bf4a339-294d-4c25-b0b2-ef649e9f5c27/resourceGroups/firewall-rg/providers/PaloAltoNetworks.Cloudngfw/localrulestacks/armid1"), + // SystemData: &armpanngfw.SystemData{ + // CreatedAt: to.Ptr(func() time.Time { t, _ := time.Parse(time.RFC3339Nano, "2022-09-09T05:08:24.229Z"); return t}()), + // CreatedBy: to.Ptr("praval"), + // CreatedByType: to.Ptr(armpanngfw.CreatedByTypeUser), + // LastModifiedAt: to.Ptr(func() time.Time { t, _ := time.Parse(time.RFC3339Nano, "2022-09-09T05:08:24.229Z"); return t}()), + // LastModifiedBy: to.Ptr("praval"), + // LastModifiedByType: to.Ptr(armpanngfw.CreatedByTypeUser), + // }, + // Location: to.Ptr("eastus"), + // Tags: map[string]*string{ + // "tagName": to.Ptr("value"), + // }, + // Identity: &armpanngfw.AzureResourceManagerManagedIdentityProperties{ + // Type: to.Ptr(armpanngfw.ManagedIdentityTypeNone), + // PrincipalID: to.Ptr("2bf4a339-294d-4c25-b0b2-ef649e9f5c27"), + // TenantID: to.Ptr("2bf4a339-294d-4c25-b0b2-ef649e9f5c27"), + // UserAssignedIdentities: map[string]*armpanngfw.AzureResourceManagerUserAssignedIdentity{ + // "key16": &armpanngfw.AzureResourceManagerUserAssignedIdentity{ + // ClientID: to.Ptr("aaaa"), + // PrincipalID: to.Ptr("aaaaaaaaaaaaaaa"), + // }, + // }, + // }, + // Properties: &armpanngfw.RulestackProperties{ + // Description: to.Ptr("local rulestacks"), + // AssociatedSubscriptions: []*string{ + // to.Ptr("2bf4a339-294d-4c25-b0b2-ef649e9f5c27")}, + // DefaultMode: to.Ptr(armpanngfw.DefaultModeIPS), + // MinAppIDVersion: to.Ptr("8.5.3"), + // PanEtag: to.Ptr("2bf4a339-294d-4c25-b0b2-ef649e9f5c12"), + // PanLocation: to.Ptr("eastus"), + // ProvisioningState: to.Ptr(armpanngfw.ProvisioningStateSucceeded), + // Scope: to.Ptr(armpanngfw.ScopeTypeLOCAL), + // SecurityServices: &armpanngfw.SecurityServices{ + // AntiSpywareProfile: to.Ptr("default"), + // AntiVirusProfile: to.Ptr("default"), + // DNSSubscription: to.Ptr("default"), + // FileBlockingProfile: to.Ptr("default"), + // OutboundTrustCertificate: to.Ptr("default"), + // OutboundUnTrustCertificate: to.Ptr("default"), + // URLFilteringProfile: to.Ptr("default"), + // VulnerabilityProfile: to.Ptr("default"), + // }, + // }, + // } +} + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/LocalRulestacks_Get_MinimumSet_Gen.json +func ExampleLocalRulestacksClient_Get_localRulestacksGetMinimumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + res, err := clientFactory.NewLocalRulestacksClient().Get(ctx, "rgopenapi", "lrs1", nil) + if err != nil { + log.Fatalf("failed to finish the request: %v", err) + } + // You could use response here. We use blank identifier for just demo purposes. + _ = res + // If the HTTP response code is 200 as defined in example definition, your response structure would look as follows. Please pay attention that all the values in the output are fake values for just demo purposes. + // res.LocalRulestackResource = armpanngfw.LocalRulestackResource{ + // ID: to.Ptr("/subscriptions/2bf4a339-294d-4c25-b0b2-ef649e9f5c27/resourcegroups/rgopenapi/providers/PaloAltoNetworks.Cloudngfw/localRulestacks/praval"), + // Location: to.Ptr("eastus"), + // Properties: &armpanngfw.RulestackProperties{ + // }, + // } +} + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/LocalRulestacks_CreateOrUpdate_MaximumSet_Gen.json +func ExampleLocalRulestacksClient_BeginCreateOrUpdate_localRulestacksCreateOrUpdateMaximumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + poller, err := clientFactory.NewLocalRulestacksClient().BeginCreateOrUpdate(ctx, "rgopenapi", "lrs1", armpanngfw.LocalRulestackResource{ + Location: to.Ptr("eastus"), + Tags: map[string]*string{ + "tagName": to.Ptr("value"), + }, + Identity: &armpanngfw.AzureResourceManagerManagedIdentityProperties{ + Type: to.Ptr(armpanngfw.ManagedIdentityTypeNone), + UserAssignedIdentities: map[string]*armpanngfw.AzureResourceManagerUserAssignedIdentity{ + "key16": { + ClientID: to.Ptr("aaaa"), + PrincipalID: to.Ptr("aaaaaaaaaaaaaaa"), + }, + }, + }, + Properties: &armpanngfw.RulestackProperties{ + Description: to.Ptr("local rulestacks"), + AssociatedSubscriptions: []*string{ + to.Ptr("2bf4a339-294d-4c25-b0b2-ef649e9f5c27")}, + DefaultMode: to.Ptr(armpanngfw.DefaultModeIPS), + MinAppIDVersion: to.Ptr("8.5.3"), + PanEtag: to.Ptr("2bf4a339-294d-4c25-b0b2-ef649e9f5c12"), + PanLocation: to.Ptr("eastus"), + ProvisioningState: to.Ptr(armpanngfw.ProvisioningStateAccepted), + Scope: to.Ptr(armpanngfw.ScopeTypeLOCAL), + SecurityServices: &armpanngfw.SecurityServices{ + AntiSpywareProfile: to.Ptr("default"), + AntiVirusProfile: to.Ptr("default"), + DNSSubscription: to.Ptr("default"), + FileBlockingProfile: to.Ptr("default"), + OutboundTrustCertificate: to.Ptr("default"), + OutboundUnTrustCertificate: to.Ptr("default"), + URLFilteringProfile: to.Ptr("default"), + VulnerabilityProfile: to.Ptr("default"), + }, + }, + }, nil) + if err != nil { + log.Fatalf("failed to finish the request: %v", err) + } + res, err := poller.PollUntilDone(ctx, nil) + if err != nil { + log.Fatalf("failed to pull the result: %v", err) + } + // You could use response here. We use blank identifier for just demo purposes. + _ = res + // If the HTTP response code is 200 as defined in example definition, your response structure would look as follows. Please pay attention that all the values in the output are fake values for just demo purposes. + // res.LocalRulestackResource = armpanngfw.LocalRulestackResource{ + // Name: to.Ptr("armid1"), + // Type: to.Ptr("localRulestacks"), + // ID: to.Ptr("/subscriptions/2bf4a339-294d-4c25-b0b2-ef649e9f5c27/resourceGroups/firewall-rg/providers/PaloAltoNetworks.Cloudngfw/localrulestacks/armid1"), + // SystemData: &armpanngfw.SystemData{ + // CreatedAt: to.Ptr(func() time.Time { t, _ := time.Parse(time.RFC3339Nano, "2022-09-09T05:08:24.229Z"); return t}()), + // CreatedBy: to.Ptr("praval"), + // CreatedByType: to.Ptr(armpanngfw.CreatedByTypeUser), + // LastModifiedAt: to.Ptr(func() time.Time { t, _ := time.Parse(time.RFC3339Nano, "2022-09-09T05:08:24.229Z"); return t}()), + // LastModifiedBy: to.Ptr("praval"), + // LastModifiedByType: to.Ptr(armpanngfw.CreatedByTypeUser), + // }, + // Location: to.Ptr("eastus"), + // Tags: map[string]*string{ + // "tagName": to.Ptr("value"), + // }, + // Identity: &armpanngfw.AzureResourceManagerManagedIdentityProperties{ + // Type: to.Ptr(armpanngfw.ManagedIdentityTypeNone), + // PrincipalID: to.Ptr("2bf4a339-294d-4c25-b0b2-ef649e9f5c27"), + // TenantID: to.Ptr("2bf4a339-294d-4c25-b0b2-ef649e9f5c27"), + // UserAssignedIdentities: map[string]*armpanngfw.AzureResourceManagerUserAssignedIdentity{ + // "key16": &armpanngfw.AzureResourceManagerUserAssignedIdentity{ + // ClientID: to.Ptr("aaaa"), + // PrincipalID: to.Ptr("aaaaaaaaaaaaaaa"), + // }, + // }, + // }, + // Properties: &armpanngfw.RulestackProperties{ + // Description: to.Ptr("local rulestacks"), + // AssociatedSubscriptions: []*string{ + // to.Ptr("2bf4a339-294d-4c25-b0b2-ef649e9f5c27")}, + // DefaultMode: to.Ptr(armpanngfw.DefaultModeIPS), + // MinAppIDVersion: to.Ptr("8.5.3"), + // PanEtag: to.Ptr("2bf4a339-294d-4c25-b0b2-ef649e9f5c12"), + // PanLocation: to.Ptr("eastus"), + // ProvisioningState: to.Ptr(armpanngfw.ProvisioningStateSucceeded), + // Scope: to.Ptr(armpanngfw.ScopeTypeLOCAL), + // SecurityServices: &armpanngfw.SecurityServices{ + // AntiSpywareProfile: to.Ptr("default"), + // AntiVirusProfile: to.Ptr("default"), + // DNSSubscription: to.Ptr("default"), + // FileBlockingProfile: to.Ptr("default"), + // OutboundTrustCertificate: to.Ptr("default"), + // OutboundUnTrustCertificate: to.Ptr("default"), + // URLFilteringProfile: to.Ptr("default"), + // VulnerabilityProfile: to.Ptr("default"), + // }, + // }, + // } +} + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/LocalRulestacks_CreateOrUpdate_MinimumSet_Gen.json +func ExampleLocalRulestacksClient_BeginCreateOrUpdate_localRulestacksCreateOrUpdateMinimumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + poller, err := clientFactory.NewLocalRulestacksClient().BeginCreateOrUpdate(ctx, "rgopenapi", "lrs1", armpanngfw.LocalRulestackResource{ + Location: to.Ptr("eastus"), + Properties: &armpanngfw.RulestackProperties{}, + }, nil) + if err != nil { + log.Fatalf("failed to finish the request: %v", err) + } + res, err := poller.PollUntilDone(ctx, nil) + if err != nil { + log.Fatalf("failed to pull the result: %v", err) + } + // You could use response here. We use blank identifier for just demo purposes. + _ = res + // If the HTTP response code is 200 as defined in example definition, your response structure would look as follows. Please pay attention that all the values in the output are fake values for just demo purposes. + // res.LocalRulestackResource = armpanngfw.LocalRulestackResource{ + // ID: to.Ptr("/subscriptions/2bf4a339-294d-4c25-b0b2-ef649e9f5c27/resourcegroups/rgopenapi/providers/PaloAltoNetworks.Cloudngfw/localRulestacks/praval"), + // Location: to.Ptr("eastus"), + // Properties: &armpanngfw.RulestackProperties{ + // }, + // } +} + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/LocalRulestacks_Update_MaximumSet_Gen.json +func ExampleLocalRulestacksClient_Update_localRulestacksUpdateMaximumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + res, err := clientFactory.NewLocalRulestacksClient().Update(ctx, "rgopenapi", "lrs1", armpanngfw.LocalRulestackResourceUpdate{ + Identity: &armpanngfw.AzureResourceManagerManagedIdentityProperties{ + Type: to.Ptr(armpanngfw.ManagedIdentityTypeNone), + UserAssignedIdentities: map[string]*armpanngfw.AzureResourceManagerUserAssignedIdentity{ + "key16": { + ClientID: to.Ptr("aaaa"), + PrincipalID: to.Ptr("aaaaaaaaaaaaaaa"), + }, + }, + }, + Properties: &armpanngfw.LocalRulestackResourceUpdateProperties{ + Description: to.Ptr("local rulestacks"), + AssociatedSubscriptions: []*string{ + to.Ptr("2bf4a339-294d-4c25-b0b2-ef649e9f5c27")}, + DefaultMode: to.Ptr(armpanngfw.DefaultModeIPS), + MinAppIDVersion: to.Ptr("8.5.3"), + PanEtag: to.Ptr("2bf4a339-294d-4c25-b0b2-ef649e9f5c12"), + PanLocation: to.Ptr("eastus"), + Scope: to.Ptr(armpanngfw.ScopeTypeLOCAL), + SecurityServices: &armpanngfw.SecurityServices{ + AntiSpywareProfile: to.Ptr("default"), + AntiVirusProfile: to.Ptr("default"), + DNSSubscription: to.Ptr("default"), + FileBlockingProfile: to.Ptr("default"), + OutboundTrustCertificate: to.Ptr("default"), + OutboundUnTrustCertificate: to.Ptr("default"), + URLFilteringProfile: to.Ptr("default"), + VulnerabilityProfile: to.Ptr("default"), + }, + }, + Tags: map[string]*string{ + "tagName": to.Ptr("value"), + }, + }, nil) + if err != nil { + log.Fatalf("failed to finish the request: %v", err) + } + // You could use response here. We use blank identifier for just demo purposes. + _ = res + // If the HTTP response code is 200 as defined in example definition, your response structure would look as follows. Please pay attention that all the values in the output are fake values for just demo purposes. + // res.LocalRulestackResource = armpanngfw.LocalRulestackResource{ + // Name: to.Ptr("armid1"), + // Type: to.Ptr("localRulestacks"), + // ID: to.Ptr("/subscriptions/2bf4a339-294d-4c25-b0b2-ef649e9f5c27/resourceGroups/firewall-rg/providers/PaloAltoNetworks.Cloudngfw/localrulestacks/armid1"), + // SystemData: &armpanngfw.SystemData{ + // CreatedAt: to.Ptr(func() time.Time { t, _ := time.Parse(time.RFC3339Nano, "2022-09-09T05:08:24.229Z"); return t}()), + // CreatedBy: to.Ptr("praval"), + // CreatedByType: to.Ptr(armpanngfw.CreatedByTypeUser), + // LastModifiedAt: to.Ptr(func() time.Time { t, _ := time.Parse(time.RFC3339Nano, "2022-09-09T05:08:24.229Z"); return t}()), + // LastModifiedBy: to.Ptr("praval"), + // LastModifiedByType: to.Ptr(armpanngfw.CreatedByTypeUser), + // }, + // Location: to.Ptr("eastus"), + // Tags: map[string]*string{ + // "tagName": to.Ptr("value"), + // }, + // Identity: &armpanngfw.AzureResourceManagerManagedIdentityProperties{ + // Type: to.Ptr(armpanngfw.ManagedIdentityTypeNone), + // PrincipalID: to.Ptr("2bf4a339-294d-4c25-b0b2-ef649e9f5c27"), + // TenantID: to.Ptr("2bf4a339-294d-4c25-b0b2-ef649e9f5c27"), + // UserAssignedIdentities: map[string]*armpanngfw.AzureResourceManagerUserAssignedIdentity{ + // "key16": &armpanngfw.AzureResourceManagerUserAssignedIdentity{ + // ClientID: to.Ptr("aaaa"), + // PrincipalID: to.Ptr("aaaaaaaaaaaaaaa"), + // }, + // }, + // }, + // Properties: &armpanngfw.RulestackProperties{ + // Description: to.Ptr("local rulestacks"), + // AssociatedSubscriptions: []*string{ + // to.Ptr("2bf4a339-294d-4c25-b0b2-ef649e9f5c27")}, + // DefaultMode: to.Ptr(armpanngfw.DefaultModeIPS), + // MinAppIDVersion: to.Ptr("8.5.3"), + // PanEtag: to.Ptr("2bf4a339-294d-4c25-b0b2-ef649e9f5c12"), + // PanLocation: to.Ptr("eastus"), + // ProvisioningState: to.Ptr(armpanngfw.ProvisioningStateSucceeded), + // Scope: to.Ptr(armpanngfw.ScopeTypeLOCAL), + // SecurityServices: &armpanngfw.SecurityServices{ + // AntiSpywareProfile: to.Ptr("default"), + // AntiVirusProfile: to.Ptr("default"), + // DNSSubscription: to.Ptr("default"), + // FileBlockingProfile: to.Ptr("default"), + // OutboundTrustCertificate: to.Ptr("default"), + // OutboundUnTrustCertificate: to.Ptr("default"), + // URLFilteringProfile: to.Ptr("default"), + // VulnerabilityProfile: to.Ptr("default"), + // }, + // }, + // } +} + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/LocalRulestacks_Update_MinimumSet_Gen.json +func ExampleLocalRulestacksClient_Update_localRulestacksUpdateMinimumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + res, err := clientFactory.NewLocalRulestacksClient().Update(ctx, "rgopenapi", "lrs1", armpanngfw.LocalRulestackResourceUpdate{}, nil) + if err != nil { + log.Fatalf("failed to finish the request: %v", err) + } + // You could use response here. We use blank identifier for just demo purposes. + _ = res + // If the HTTP response code is 200 as defined in example definition, your response structure would look as follows. Please pay attention that all the values in the output are fake values for just demo purposes. + // res.LocalRulestackResource = armpanngfw.LocalRulestackResource{ + // Location: to.Ptr("eastus"), + // Properties: &armpanngfw.RulestackProperties{ + // }, + // } +} + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/LocalRulestacks_Delete_MaximumSet_Gen.json +func ExampleLocalRulestacksClient_BeginDelete_localRulestacksDeleteMaximumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + poller, err := clientFactory.NewLocalRulestacksClient().BeginDelete(ctx, "rgopenapi", "lrs1", nil) + if err != nil { + log.Fatalf("failed to finish the request: %v", err) + } + _, err = poller.PollUntilDone(ctx, nil) + if err != nil { + log.Fatalf("failed to pull the result: %v", err) + } +} + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/LocalRulestacks_Delete_MinimumSet_Gen.json +func ExampleLocalRulestacksClient_BeginDelete_localRulestacksDeleteMinimumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + poller, err := clientFactory.NewLocalRulestacksClient().BeginDelete(ctx, "rgopenapi", "lrs1", nil) + if err != nil { + log.Fatalf("failed to finish the request: %v", err) + } + _, err = poller.PollUntilDone(ctx, nil) + if err != nil { + log.Fatalf("failed to pull the result: %v", err) + } +} + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/LocalRulestacks_commit_MaximumSet_Gen.json +func ExampleLocalRulestacksClient_BeginCommit_localRulestacksCommitMaximumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + poller, err := clientFactory.NewLocalRulestacksClient().BeginCommit(ctx, "rgopenapi", "lrs1", nil) + if err != nil { + log.Fatalf("failed to finish the request: %v", err) + } + _, err = poller.PollUntilDone(ctx, nil) + if err != nil { + log.Fatalf("failed to pull the result: %v", err) + } +} + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/LocalRulestacks_commit_MinimumSet_Gen.json +func ExampleLocalRulestacksClient_BeginCommit_localRulestacksCommitMinimumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + poller, err := clientFactory.NewLocalRulestacksClient().BeginCommit(ctx, "rgopenapi", "lrs1", nil) + if err != nil { + log.Fatalf("failed to finish the request: %v", err) + } + _, err = poller.PollUntilDone(ctx, nil) + if err != nil { + log.Fatalf("failed to pull the result: %v", err) + } +} + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/LocalRulestacks_getChangeLog_MaximumSet_Gen.json +func ExampleLocalRulestacksClient_GetChangeLog_localRulestacksGetChangeLogMaximumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + res, err := clientFactory.NewLocalRulestacksClient().GetChangeLog(ctx, "rgopenapi", "lrs1", nil) + if err != nil { + log.Fatalf("failed to finish the request: %v", err) + } + // You could use response here. We use blank identifier for just demo purposes. + _ = res + // If the HTTP response code is 200 as defined in example definition, your response structure would look as follows. Please pay attention that all the values in the output are fake values for just demo purposes. + // res.Changelog = armpanngfw.Changelog{ + // Changes: []*string{ + // to.Ptr("aaaa")}, + // LastCommitted: to.Ptr(func() time.Time { t, _ := time.Parse(time.RFC3339Nano, "2022-09-09T05:08:24.229Z"); return t}()), + // LastModified: to.Ptr(func() time.Time { t, _ := time.Parse(time.RFC3339Nano, "2022-09-09T05:08:24.229Z"); return t}()), + // } +} + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/LocalRulestacks_getChangeLog_MinimumSet_Gen.json +func ExampleLocalRulestacksClient_GetChangeLog_localRulestacksGetChangeLogMinimumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + res, err := clientFactory.NewLocalRulestacksClient().GetChangeLog(ctx, "rgopenapi", "lrs1", nil) + if err != nil { + log.Fatalf("failed to finish the request: %v", err) + } + // You could use response here. We use blank identifier for just demo purposes. + _ = res + // If the HTTP response code is 200 as defined in example definition, your response structure would look as follows. Please pay attention that all the values in the output are fake values for just demo purposes. + // res.Changelog = armpanngfw.Changelog{ + // Changes: []*string{ + // to.Ptr("aaaa")}, + // } +} + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/LocalRulestacks_getSupportInfo_MaximumSet_Gen.json +func ExampleLocalRulestacksClient_GetSupportInfo_localRulestacksGetSupportInfoMaximumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + res, err := clientFactory.NewLocalRulestacksClient().GetSupportInfo(ctx, "rgopenapi", "lrs1", &armpanngfw.LocalRulestacksClientGetSupportInfoOptions{Email: to.Ptr("user1@domain.com")}) + if err != nil { + log.Fatalf("failed to finish the request: %v", err) + } + // You could use response here. We use blank identifier for just demo purposes. + _ = res + // If the HTTP response code is 200 as defined in example definition, your response structure would look as follows. Please pay attention that all the values in the output are fake values for just demo purposes. + // res.SupportInfo = armpanngfw.SupportInfo{ + // AccountID: to.Ptr("3cg5b439-294d-4c25-b0b2-ef649e0g6d38"), + // AccountRegistered: to.Ptr(armpanngfw.BooleanEnumTRUE), + // FreeTrial: to.Ptr(armpanngfw.BooleanEnumTRUE), + // FreeTrialCreditLeft: to.Ptr[int32](10), + // FreeTrialDaysLeft: to.Ptr[int32](1), + // HelpURL: to.Ptr("https://ssopreview.paloaltonetworks.com/home/bookmark/0oa4ao61shG4rd3Ub1d7/2557"), + // ProductSerial: to.Ptr("e22715cb-7e4e-4814-ad4f-ccd1417755d7"), + // ProductSKU: to.Ptr("62f63e3c-bc5a-4d68-a8a1-fcba9f526c90"), + // RegisterURL: to.Ptr("https://ssopreview.paloaltonetworks.com/home/bookmark/0oa4ao61shG4rd3Ub1d7/2557"), + // SupportURL: to.Ptr("https://ssopreview.paloaltonetworks.com/home/bookmark/0oa4ao61shG4rd3Ub1d7/2557"), + // UserDomainSupported: to.Ptr(armpanngfw.BooleanEnumTRUE), + // UserRegistered: to.Ptr(armpanngfw.BooleanEnumTRUE), + // } +} + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/LocalRulestacks_getSupportInfo_MinimumSet_Gen.json +func ExampleLocalRulestacksClient_GetSupportInfo_localRulestacksGetSupportInfoMinimumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + res, err := clientFactory.NewLocalRulestacksClient().GetSupportInfo(ctx, "rgopenapi", "lrs1", &armpanngfw.LocalRulestacksClientGetSupportInfoOptions{Email: nil}) + if err != nil { + log.Fatalf("failed to finish the request: %v", err) + } + // You could use response here. We use blank identifier for just demo purposes. + _ = res + // If the HTTP response code is 200 as defined in example definition, your response structure would look as follows. Please pay attention that all the values in the output are fake values for just demo purposes. + // res.SupportInfo = armpanngfw.SupportInfo{ + // } +} + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/LocalRulestacks_listAdvancedSecurityObjects_MaximumSet_Gen.json +func ExampleLocalRulestacksClient_ListAdvancedSecurityObjects_localRulestacksListAdvancedSecurityObjectsMaximumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + res, err := clientFactory.NewLocalRulestacksClient().ListAdvancedSecurityObjects(ctx, "rgopenapi", "lrs1", armpanngfw.AdvSecurityObjectTypeEnum("localRulestacks"), &armpanngfw.LocalRulestacksClientListAdvancedSecurityObjectsOptions{Skip: to.Ptr("a6a321"), + Top: to.Ptr[int32](20), + }) + if err != nil { + log.Fatalf("failed to finish the request: %v", err) + } + // You could use response here. We use blank identifier for just demo purposes. + _ = res + // If the HTTP response code is 200 as defined in example definition, your response structure would look as follows. Please pay attention that all the values in the output are fake values for just demo purposes. + // res.AdvSecurityObjectListResponse = armpanngfw.AdvSecurityObjectListResponse{ + // Value: &armpanngfw.AdvSecurityObjectModel{ + // Type: to.Ptr("localRulestacks"), + // Entry: []*armpanngfw.NameDescriptionObject{ + // { + // Name: to.Ptr("aaaaaaaaaa"), + // Description: to.Ptr("aaaaaaaaaaaa"), + // }}, + // }, + // } +} + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/LocalRulestacks_listAdvancedSecurityObjects_MinimumSet_Gen.json +func ExampleLocalRulestacksClient_ListAdvancedSecurityObjects_localRulestacksListAdvancedSecurityObjectsMinimumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + res, err := clientFactory.NewLocalRulestacksClient().ListAdvancedSecurityObjects(ctx, "rgopenapi", "lrs1", armpanngfw.AdvSecurityObjectTypeEnum("localRulestacks"), &armpanngfw.LocalRulestacksClientListAdvancedSecurityObjectsOptions{Skip: nil, + Top: nil, + }) + if err != nil { + log.Fatalf("failed to finish the request: %v", err) + } + // You could use response here. We use blank identifier for just demo purposes. + _ = res + // If the HTTP response code is 200 as defined in example definition, your response structure would look as follows. Please pay attention that all the values in the output are fake values for just demo purposes. + // res.AdvSecurityObjectListResponse = armpanngfw.AdvSecurityObjectListResponse{ + // Value: &armpanngfw.AdvSecurityObjectModel{ + // Entry: []*armpanngfw.NameDescriptionObject{ + // { + // Name: to.Ptr("aaaaaaaaaa"), + // }}, + // }, + // } +} + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/LocalRulestacks_listAppIds_MaximumSet_Gen.json +func ExampleLocalRulestacksClient_ListAppIDs_localRulestacksListAppIdsMaximumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + res, err := clientFactory.NewLocalRulestacksClient().ListAppIDs(ctx, "rgopenapi", "lrs1", &armpanngfw.LocalRulestacksClientListAppIDsOptions{AppIDVersion: to.Ptr("8543"), + AppPrefix: to.Ptr("pref"), + Skip: to.Ptr("a6a321"), + Top: to.Ptr[int32](20), + }) + if err != nil { + log.Fatalf("failed to finish the request: %v", err) + } + // You could use response here. We use blank identifier for just demo purposes. + _ = res + // If the HTTP response code is 200 as defined in example definition, your response structure would look as follows. Please pay attention that all the values in the output are fake values for just demo purposes. + // res.ListAppIDResponse = armpanngfw.ListAppIDResponse{ + // Value: []*string{ + // to.Ptr("aaaaaaaaaaaaaaaaaaaaaaa")}, + // } +} + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/LocalRulestacks_listAppIds_MinimumSet_Gen.json +func ExampleLocalRulestacksClient_ListAppIDs_localRulestacksListAppIdsMinimumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + res, err := clientFactory.NewLocalRulestacksClient().ListAppIDs(ctx, "rgopenapi", "lrs1", &armpanngfw.LocalRulestacksClientListAppIDsOptions{AppIDVersion: nil, + AppPrefix: nil, + Skip: nil, + Top: nil, + }) + if err != nil { + log.Fatalf("failed to finish the request: %v", err) + } + // You could use response here. We use blank identifier for just demo purposes. + _ = res + // If the HTTP response code is 200 as defined in example definition, your response structure would look as follows. Please pay attention that all the values in the output are fake values for just demo purposes. + // res.ListAppIDResponse = armpanngfw.ListAppIDResponse{ + // Value: []*string{ + // to.Ptr("aaaaaaaaaaaaaaaaaaaaaaa")}, + // } +} + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/LocalRulestacks_listCountries_MaximumSet_Gen.json +func ExampleLocalRulestacksClient_ListCountries_localRulestacksListCountriesMaximumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + res, err := clientFactory.NewLocalRulestacksClient().ListCountries(ctx, "rgopenapi", "lrs1", &armpanngfw.LocalRulestacksClientListCountriesOptions{Skip: to.Ptr("a6a321"), + Top: to.Ptr[int32](20), + }) + if err != nil { + log.Fatalf("failed to finish the request: %v", err) + } + // You could use response here. We use blank identifier for just demo purposes. + _ = res + // If the HTTP response code is 200 as defined in example definition, your response structure would look as follows. Please pay attention that all the values in the output are fake values for just demo purposes. + // res.CountriesResponse = armpanngfw.CountriesResponse{ + // Value: []*armpanngfw.Country{ + // { + // Description: to.Ptr("aaaaa"), + // Code: to.Ptr("aaaaaaaaaaaaaaaaaaaaaaaaa"), + // }}, + // } +} + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/LocalRulestacks_listCountries_MinimumSet_Gen.json +func ExampleLocalRulestacksClient_ListCountries_localRulestacksListCountriesMinimumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + res, err := clientFactory.NewLocalRulestacksClient().ListCountries(ctx, "rgopenapi", "lrs1", &armpanngfw.LocalRulestacksClientListCountriesOptions{Skip: nil, + Top: nil, + }) + if err != nil { + log.Fatalf("failed to finish the request: %v", err) + } + // You could use response here. We use blank identifier for just demo purposes. + _ = res + // If the HTTP response code is 200 as defined in example definition, your response structure would look as follows. Please pay attention that all the values in the output are fake values for just demo purposes. + // res.CountriesResponse = armpanngfw.CountriesResponse{ + // Value: []*armpanngfw.Country{ + // { + // Code: to.Ptr("aaaaaaaaaaaaaaaaaaaaaaaaa"), + // }}, + // } +} + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/LocalRulestacks_listFirewalls_MaximumSet_Gen.json +func ExampleLocalRulestacksClient_ListFirewalls_localRulestacksListFirewallsMaximumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + res, err := clientFactory.NewLocalRulestacksClient().ListFirewalls(ctx, "rgopenapi", "lrs1", nil) + if err != nil { + log.Fatalf("failed to finish the request: %v", err) + } + // You could use response here. We use blank identifier for just demo purposes. + _ = res + // If the HTTP response code is 200 as defined in example definition, your response structure would look as follows. Please pay attention that all the values in the output are fake values for just demo purposes. + // res.ListFirewallsResponse = armpanngfw.ListFirewallsResponse{ + // Value: []*string{ + // to.Ptr("aaaaaaaaaaaaaaaaaaaaaaaaa")}, + // } +} + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/LocalRulestacks_listFirewalls_MinimumSet_Gen.json +func ExampleLocalRulestacksClient_ListFirewalls_localRulestacksListFirewallsMinimumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + res, err := clientFactory.NewLocalRulestacksClient().ListFirewalls(ctx, "rgopenapi", "lrs1", nil) + if err != nil { + log.Fatalf("failed to finish the request: %v", err) + } + // You could use response here. We use blank identifier for just demo purposes. + _ = res + // If the HTTP response code is 200 as defined in example definition, your response structure would look as follows. Please pay attention that all the values in the output are fake values for just demo purposes. + // res.ListFirewallsResponse = armpanngfw.ListFirewallsResponse{ + // Value: []*string{ + // to.Ptr("aaaaaaaaaaaaaaaaaaaaaaaaa")}, + // } +} + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/LocalRulestacks_listPredefinedUrlCategories_MaximumSet_Gen.json +func ExampleLocalRulestacksClient_ListPredefinedURLCategories_localRulestacksListPredefinedUrlCategoriesMaximumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + res, err := clientFactory.NewLocalRulestacksClient().ListPredefinedURLCategories(ctx, "rgopenapi", "lrs1", &armpanngfw.LocalRulestacksClientListPredefinedURLCategoriesOptions{Skip: to.Ptr("a6a321"), + Top: to.Ptr[int32](20), + }) + if err != nil { + log.Fatalf("failed to finish the request: %v", err) + } + // You could use response here. We use blank identifier for just demo purposes. + _ = res + // If the HTTP response code is 200 as defined in example definition, your response structure would look as follows. Please pay attention that all the values in the output are fake values for just demo purposes. + // res.PredefinedURLCategoriesResponse = armpanngfw.PredefinedURLCategoriesResponse{ + // Value: []*armpanngfw.PredefinedURLCategory{ + // { + // Name: to.Ptr("aaaaaaaaaaaaaaaaaaaaaaaaa"), + // Action: to.Ptr("aaaaaaa"), + // }}, + // } +} + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/LocalRulestacks_listPredefinedUrlCategories_MinimumSet_Gen.json +func ExampleLocalRulestacksClient_ListPredefinedURLCategories_localRulestacksListPredefinedUrlCategoriesMinimumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + res, err := clientFactory.NewLocalRulestacksClient().ListPredefinedURLCategories(ctx, "rgopenapi", "lrs1", &armpanngfw.LocalRulestacksClientListPredefinedURLCategoriesOptions{Skip: nil, + Top: nil, + }) + if err != nil { + log.Fatalf("failed to finish the request: %v", err) + } + // You could use response here. We use blank identifier for just demo purposes. + _ = res + // If the HTTP response code is 200 as defined in example definition, your response structure would look as follows. Please pay attention that all the values in the output are fake values for just demo purposes. + // res.PredefinedURLCategoriesResponse = armpanngfw.PredefinedURLCategoriesResponse{ + // Value: []*armpanngfw.PredefinedURLCategory{ + // { + // Name: to.Ptr("aaaaaaaaaaaaaaaaaaaaaaaaa"), + // Action: to.Ptr("aaaaaaa"), + // }}, + // } +} + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/LocalRulestacks_listSecurityServices_MaximumSet_Gen.json +func ExampleLocalRulestacksClient_ListSecurityServices_localRulestacksListSecurityServicesMaximumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + res, err := clientFactory.NewLocalRulestacksClient().ListSecurityServices(ctx, "rgopenapi", "lrs1", armpanngfw.SecurityServicesTypeEnum("localRulestacks"), &armpanngfw.LocalRulestacksClientListSecurityServicesOptions{Skip: to.Ptr("a6a321"), + Top: to.Ptr[int32](20), + }) + if err != nil { + log.Fatalf("failed to finish the request: %v", err) + } + // You could use response here. We use blank identifier for just demo purposes. + _ = res + // If the HTTP response code is 200 as defined in example definition, your response structure would look as follows. Please pay attention that all the values in the output are fake values for just demo purposes. + // res.SecurityServicesResponse = armpanngfw.SecurityServicesResponse{ + // Value: &armpanngfw.SecurityServicesTypeList{ + // Type: to.Ptr("localRulestacks"), + // Entry: []*armpanngfw.NameDescriptionObject{ + // { + // Name: to.Ptr("aaaaaaaaaa"), + // Description: to.Ptr("aaaaaaaaaaaa"), + // }}, + // }, + // } +} + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/LocalRulestacks_listSecurityServices_MinimumSet_Gen.json +func ExampleLocalRulestacksClient_ListSecurityServices_localRulestacksListSecurityServicesMinimumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + res, err := clientFactory.NewLocalRulestacksClient().ListSecurityServices(ctx, "rgopenapi", "lrs1", armpanngfw.SecurityServicesTypeEnum("localRulestacks"), &armpanngfw.LocalRulestacksClientListSecurityServicesOptions{Skip: nil, + Top: nil, + }) + if err != nil { + log.Fatalf("failed to finish the request: %v", err) + } + // You could use response here. We use blank identifier for just demo purposes. + _ = res + // If the HTTP response code is 200 as defined in example definition, your response structure would look as follows. Please pay attention that all the values in the output are fake values for just demo purposes. + // res.SecurityServicesResponse = armpanngfw.SecurityServicesResponse{ + // Value: &armpanngfw.SecurityServicesTypeList{ + // Entry: []*armpanngfw.NameDescriptionObject{ + // { + // Name: to.Ptr("aaaaaaaaaa"), + // }}, + // }, + // } +} + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/LocalRulestacks_revert_MaximumSet_Gen.json +func ExampleLocalRulestacksClient_Revert_localRulestacksRevertMaximumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + _, err = clientFactory.NewLocalRulestacksClient().Revert(ctx, "rgopenapi", "lrs1", nil) + if err != nil { + log.Fatalf("failed to finish the request: %v", err) + } +} + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/LocalRulestacks_revert_MinimumSet_Gen.json +func ExampleLocalRulestacksClient_Revert_localRulestacksRevertMinimumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + _, err = clientFactory.NewLocalRulestacksClient().Revert(ctx, "rgopenapi", "lrs1", nil) + if err != nil { + log.Fatalf("failed to finish the request: %v", err) + } +} diff --git a/sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/models.go b/sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/models.go new file mode 100644 index 000000000000..d786e70d9847 --- /dev/null +++ b/sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/models.go @@ -0,0 +1,1924 @@ +//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. +// Code generated by Microsoft (R) AutoRest Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. +// DO NOT EDIT. + +package armpanngfw + +import "time" + +// AdvSecurityObjectListResponse - advanced security object +type AdvSecurityObjectListResponse struct { + // REQUIRED; response value + Value *AdvSecurityObjectModel + + // next link + NextLink *string +} + +// AdvSecurityObjectModel - List of custom and predefined url category +type AdvSecurityObjectModel struct { + // REQUIRED; URL entry + Entry []*NameDescriptionObject + + // type of object + Type *string +} + +// AppSeenData - Data Type for App Seen +type AppSeenData struct { + // REQUIRED; array of appSeen + AppSeenList []*AppSeenInfo + + // REQUIRED; number of rows + Count *int32 +} + +// AppSeenInfo - Definition for App Seen +type AppSeenInfo struct { + // REQUIRED; category + Category *string + + // REQUIRED; risk + Risk *string + + // REQUIRED; standardPorts + StandardPorts *string + + // REQUIRED; subCategory + SubCategory *string + + // REQUIRED; tag + Tag *string + + // REQUIRED; technology + Technology *string + + // REQUIRED; title + Title *string +} + +// ApplicationInsights - Application Insights key +type ApplicationInsights struct { + // Resource id for Application Insights + ID *string + + // Application Insights key + Key *string +} + +// AzureResourceManagerManagedIdentityProperties - The properties of the managed service identities assigned to this resource. +type AzureResourceManagerManagedIdentityProperties struct { + // REQUIRED; The type of managed identity assigned to this resource. + Type *ManagedIdentityType + + // The identities assigned to this resource by the user. + UserAssignedIdentities map[string]*AzureResourceManagerUserAssignedIdentity + + // READ-ONLY; The active directory identifier of this principal. + PrincipalID *string + + // READ-ONLY; The Active Directory tenant id of the principal. + TenantID *string +} + +// AzureResourceManagerUserAssignedIdentity - A managed identity assigned by the user. +type AzureResourceManagerUserAssignedIdentity struct { + // The active directory client identifier for this principal. + ClientID *string + + // The active directory identifier for this principal. + PrincipalID *string +} + +// Category - URL/EDL to match +type Category struct { + // REQUIRED; feed list + Feeds []*string + + // REQUIRED; custom URL + URLCustom []*string +} + +// CertificateObject - certificate used for inbound and outbound decryption +type CertificateObject struct { + // REQUIRED; use certificate self signed + CertificateSelfSigned *BooleanEnum + + // comment for this object + AuditComment *string + + // Resource Id of certificate signer, to be populated only when certificateSelfSigned is false + CertificateSignerResourceID *string + + // user description for this object + Description *string + + // read only string representing last create or update + Etag *string + + // READ-ONLY; Provisioning state of the resource. + ProvisioningState *ProvisioningState +} + +// CertificateObjectGlobalRulestackClientBeginCreateOrUpdateOptions contains the optional parameters for the CertificateObjectGlobalRulestackClient.BeginCreateOrUpdate +// method. +type CertificateObjectGlobalRulestackClientBeginCreateOrUpdateOptions struct { + // Resumes the LRO from the provided token. + ResumeToken string +} + +// CertificateObjectGlobalRulestackClientBeginDeleteOptions contains the optional parameters for the CertificateObjectGlobalRulestackClient.BeginDelete +// method. +type CertificateObjectGlobalRulestackClientBeginDeleteOptions struct { + // Resumes the LRO from the provided token. + ResumeToken string +} + +// CertificateObjectGlobalRulestackClientGetOptions contains the optional parameters for the CertificateObjectGlobalRulestackClient.Get +// method. +type CertificateObjectGlobalRulestackClientGetOptions struct { + // placeholder for future optional parameters +} + +// CertificateObjectGlobalRulestackClientListOptions contains the optional parameters for the CertificateObjectGlobalRulestackClient.NewListPager +// method. +type CertificateObjectGlobalRulestackClientListOptions struct { + // placeholder for future optional parameters +} + +// CertificateObjectGlobalRulestackResource - GlobalRulestack Certificate Object +type CertificateObjectGlobalRulestackResource struct { + // REQUIRED; The resource-specific properties for this resource. + Properties *CertificateObject + + // READ-ONLY; Fully qualified resource ID for the resource. Ex - /subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/{resourceProviderNamespace}/{resourceType}/{resourceName} + ID *string + + // READ-ONLY; The name of the resource + Name *string + + // READ-ONLY; Azure Resource Manager metadata containing createdBy and modifiedBy information. + SystemData *SystemData + + // READ-ONLY; The type of the resource. E.g. "Microsoft.Compute/virtualMachines" or "Microsoft.Storage/storageAccounts" + Type *string +} + +// CertificateObjectGlobalRulestackResourceListResult - The response of a CertificateObjectGlobalRulestackResource list operation. +type CertificateObjectGlobalRulestackResourceListResult struct { + // REQUIRED; The items on this page + Value []*CertificateObjectGlobalRulestackResource + + // The link to the next page of items + NextLink *string +} + +// CertificateObjectLocalRulestackClientBeginCreateOrUpdateOptions contains the optional parameters for the CertificateObjectLocalRulestackClient.BeginCreateOrUpdate +// method. +type CertificateObjectLocalRulestackClientBeginCreateOrUpdateOptions struct { + // Resumes the LRO from the provided token. + ResumeToken string +} + +// CertificateObjectLocalRulestackClientBeginDeleteOptions contains the optional parameters for the CertificateObjectLocalRulestackClient.BeginDelete +// method. +type CertificateObjectLocalRulestackClientBeginDeleteOptions struct { + // Resumes the LRO from the provided token. + ResumeToken string +} + +// CertificateObjectLocalRulestackClientGetOptions contains the optional parameters for the CertificateObjectLocalRulestackClient.Get +// method. +type CertificateObjectLocalRulestackClientGetOptions struct { + // placeholder for future optional parameters +} + +// CertificateObjectLocalRulestackClientListByLocalRulestacksOptions contains the optional parameters for the CertificateObjectLocalRulestackClient.NewListByLocalRulestacksPager +// method. +type CertificateObjectLocalRulestackClientListByLocalRulestacksOptions struct { + // placeholder for future optional parameters +} + +// CertificateObjectLocalRulestackResource - LocalRulestack Certificate Object +type CertificateObjectLocalRulestackResource struct { + // REQUIRED; The resource-specific properties for this resource. + Properties *CertificateObject + + // READ-ONLY; Fully qualified resource ID for the resource. Ex - /subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/{resourceProviderNamespace}/{resourceType}/{resourceName} + ID *string + + // READ-ONLY; The name of the resource + Name *string + + // READ-ONLY; Azure Resource Manager metadata containing createdBy and modifiedBy information. + SystemData *SystemData + + // READ-ONLY; The type of the resource. E.g. "Microsoft.Compute/virtualMachines" or "Microsoft.Storage/storageAccounts" + Type *string +} + +// CertificateObjectLocalRulestackResourceListResult - The response of a CertificateObjectLocalRulestackResource list operation. +type CertificateObjectLocalRulestackResourceListResult struct { + // REQUIRED; The items on this page + Value []*CertificateObjectLocalRulestackResource + + // The link to the next page of items + NextLink *string +} + +// Changelog list +type Changelog struct { + // REQUIRED; list of changes + Changes []*string + + // lastCommitted timestamp + LastCommitted *time.Time + + // lastModified timestamp + LastModified *time.Time +} + +// CountriesResponse - Countries Response Object +type CountriesResponse struct { + // REQUIRED; List of countries + Value []*Country + + // next link + NextLink *string +} + +// Country Description +type Country struct { + // REQUIRED; country code + Code *string + + // code description + Description *string +} + +// DNSSettings - DNS Proxy settings for Firewall +type DNSSettings struct { + // List of IPs associated with the Firewall + DNSServers []*IPAddress + + // Enable DNS proxy, disabled by default + EnableDNSProxy *DNSProxy + + // Enabled DNS proxy type, disabled by default + EnabledDNSType *EnabledDNSType +} + +// DestinationAddr - destination address +type DestinationAddr struct { + // special value 'any' + Cidrs []*string + + // list of countries + Countries []*string + + // list of feeds + Feeds []*string + + // fqdn list + FqdnLists []*string + + // prefix list + PrefixLists []*string +} + +// EndpointConfiguration - Endpoint Configuration for frontend and backend +type EndpointConfiguration struct { + // REQUIRED; Address Space + Address *IPAddress + + // REQUIRED; port ID + Port *string +} + +// EventHub configurations +type EventHub struct { + // Resource ID of EventHub + ID *string + + // EventHub name + Name *string + + // EventHub namespace + NameSpace *string + + // EventHub policy name + PolicyName *string + + // Subscription Id + SubscriptionID *string +} + +// FirewallDeploymentProperties - Properties specific to the Firewall resource deployment. +type FirewallDeploymentProperties struct { + // REQUIRED; DNS settings for Firewall + DNSSettings *DNSSettings + + // REQUIRED; Marketplace details + MarketplaceDetails *MarketplaceDetails + + // REQUIRED; Network settings + NetworkProfile *NetworkProfile + + // REQUIRED; Billing plan information. + PlanData *PlanData + + // Associated Rulestack + AssociatedRulestack *RulestackDetails + + // Frontend settings for Firewall + FrontEndSettings []*FrontendSetting + + // Panorama Managed: Default is False. Default will be CloudSec managed + IsPanoramaManaged *BooleanEnum + + // panEtag info + PanEtag *string + + // Panorama Configuration + PanoramaConfig *PanoramaConfig + + // READ-ONLY; Provisioning state of the resource. + ProvisioningState *ProvisioningState +} + +// FirewallResource - PaloAltoNetworks Firewall +type FirewallResource struct { + // REQUIRED; The geo-location where the resource lives + Location *string + + // REQUIRED; The resource-specific properties for this resource. + Properties *FirewallDeploymentProperties + + // The managed service identities assigned to this resource. + Identity *AzureResourceManagerManagedIdentityProperties + + // Resource tags. + Tags map[string]*string + + // READ-ONLY; Fully qualified resource ID for the resource. Ex - /subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/{resourceProviderNamespace}/{resourceType}/{resourceName} + ID *string + + // READ-ONLY; The name of the resource + Name *string + + // READ-ONLY; Azure Resource Manager metadata containing createdBy and modifiedBy information. + SystemData *SystemData + + // READ-ONLY; The type of the resource. E.g. "Microsoft.Compute/virtualMachines" or "Microsoft.Storage/storageAccounts" + Type *string +} + +// FirewallResourceListResult - The response of a FirewallResource list operation. +type FirewallResourceListResult struct { + // REQUIRED; The items on this page + Value []*FirewallResource + + // The link to the next page of items + NextLink *string +} + +// FirewallResourceUpdate - The type used for update operations of the FirewallResource. +type FirewallResourceUpdate struct { + // The managed service identities assigned to this resource. + Identity *AzureResourceManagerManagedIdentityProperties + + // The updatable properties of the FirewallResource. + Properties *FirewallResourceUpdateProperties + + // Resource tags. + Tags map[string]*string +} + +// FirewallResourceUpdateProperties - The updatable properties of the FirewallResource. +type FirewallResourceUpdateProperties struct { + // Associated Rulestack + AssociatedRulestack *RulestackDetails + + // DNS settings for Firewall + DNSSettings *DNSSettings + + // Frontend settings for Firewall + FrontEndSettings []*FrontendSetting + + // Panorama Managed: Default is False. Default will be CloudSec managed + IsPanoramaManaged *BooleanEnum + + // Marketplace details + MarketplaceDetails *MarketplaceDetails + + // Network settings + NetworkProfile *NetworkProfile + + // panEtag info + PanEtag *string + + // Panorama Configuration + PanoramaConfig *PanoramaConfig + + // Billing plan information. + PlanData *PlanData +} + +// FirewallStatusClientGetOptions contains the optional parameters for the FirewallStatusClient.Get method. +type FirewallStatusClientGetOptions struct { + // placeholder for future optional parameters +} + +// FirewallStatusClientListByFirewallsOptions contains the optional parameters for the FirewallStatusClient.NewListByFirewallsPager +// method. +type FirewallStatusClientListByFirewallsOptions struct { + // placeholder for future optional parameters +} + +// FirewallStatusProperty - Firewall Status +type FirewallStatusProperty struct { + // READ-ONLY; Detail description of current health of the Firewall + HealthReason *string + + // READ-ONLY; Current status of the Firewall + HealthStatus *HealthStatus + + // READ-ONLY; Panorama Managed: Default is False. Default will be CloudSec managed + IsPanoramaManaged *BooleanEnum + + // READ-ONLY; Panorama Status + PanoramaStatus *PanoramaStatus + + // READ-ONLY; Provisioning state of the resource. + ProvisioningState *ReadOnlyProvisioningState +} + +// FirewallStatusResource - Firewall Status +type FirewallStatusResource struct { + // REQUIRED; The resource-specific properties for this resource. + Properties *FirewallStatusProperty + + // READ-ONLY; Fully qualified resource ID for the resource. Ex - /subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/{resourceProviderNamespace}/{resourceType}/{resourceName} + ID *string + + // READ-ONLY; The name of the resource + Name *string + + // READ-ONLY; Azure Resource Manager metadata containing createdBy and modifiedBy information. + SystemData *SystemData + + // READ-ONLY; The type of the resource. E.g. "Microsoft.Compute/virtualMachines" or "Microsoft.Storage/storageAccounts" + Type *string +} + +// FirewallStatusResourceListResult - The response of a FirewallStatusResource list operation. +type FirewallStatusResourceListResult struct { + // REQUIRED; The items on this page + Value []*FirewallStatusResource + + // The link to the next page of items + NextLink *string +} + +// FirewallsClientBeginCreateOrUpdateOptions contains the optional parameters for the FirewallsClient.BeginCreateOrUpdate +// method. +type FirewallsClientBeginCreateOrUpdateOptions struct { + // Resumes the LRO from the provided token. + ResumeToken string +} + +// FirewallsClientBeginDeleteOptions contains the optional parameters for the FirewallsClient.BeginDelete method. +type FirewallsClientBeginDeleteOptions struct { + // Resumes the LRO from the provided token. + ResumeToken string +} + +// FirewallsClientGetGlobalRulestackOptions contains the optional parameters for the FirewallsClient.GetGlobalRulestack method. +type FirewallsClientGetGlobalRulestackOptions struct { + // placeholder for future optional parameters +} + +// FirewallsClientGetLogProfileOptions contains the optional parameters for the FirewallsClient.GetLogProfile method. +type FirewallsClientGetLogProfileOptions struct { + // placeholder for future optional parameters +} + +// FirewallsClientGetOptions contains the optional parameters for the FirewallsClient.Get method. +type FirewallsClientGetOptions struct { + // placeholder for future optional parameters +} + +// FirewallsClientGetSupportInfoOptions contains the optional parameters for the FirewallsClient.GetSupportInfo method. +type FirewallsClientGetSupportInfoOptions struct { + // email address on behalf of which this API called + Email *string +} + +// FirewallsClientListByResourceGroupOptions contains the optional parameters for the FirewallsClient.NewListByResourceGroupPager +// method. +type FirewallsClientListByResourceGroupOptions struct { + // placeholder for future optional parameters +} + +// FirewallsClientListBySubscriptionOptions contains the optional parameters for the FirewallsClient.NewListBySubscriptionPager +// method. +type FirewallsClientListBySubscriptionOptions struct { + // placeholder for future optional parameters +} + +// FirewallsClientSaveLogProfileOptions contains the optional parameters for the FirewallsClient.SaveLogProfile method. +type FirewallsClientSaveLogProfileOptions struct { + LogSettings *LogSettings +} + +// FirewallsClientUpdateOptions contains the optional parameters for the FirewallsClient.Update method. +type FirewallsClientUpdateOptions struct { + // placeholder for future optional parameters +} + +// FqdnListGlobalRulestackClientBeginCreateOrUpdateOptions contains the optional parameters for the FqdnListGlobalRulestackClient.BeginCreateOrUpdate +// method. +type FqdnListGlobalRulestackClientBeginCreateOrUpdateOptions struct { + // Resumes the LRO from the provided token. + ResumeToken string +} + +// FqdnListGlobalRulestackClientBeginDeleteOptions contains the optional parameters for the FqdnListGlobalRulestackClient.BeginDelete +// method. +type FqdnListGlobalRulestackClientBeginDeleteOptions struct { + // Resumes the LRO from the provided token. + ResumeToken string +} + +// FqdnListGlobalRulestackClientGetOptions contains the optional parameters for the FqdnListGlobalRulestackClient.Get method. +type FqdnListGlobalRulestackClientGetOptions struct { + // placeholder for future optional parameters +} + +// FqdnListGlobalRulestackClientListOptions contains the optional parameters for the FqdnListGlobalRulestackClient.NewListPager +// method. +type FqdnListGlobalRulestackClientListOptions struct { + // placeholder for future optional parameters +} + +// FqdnListGlobalRulestackResource - GlobalRulestack fqdnList +type FqdnListGlobalRulestackResource struct { + // REQUIRED; The resource-specific properties for this resource. + Properties *FqdnObject + + // READ-ONLY; Fully qualified resource ID for the resource. Ex - /subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/{resourceProviderNamespace}/{resourceType}/{resourceName} + ID *string + + // READ-ONLY; The name of the resource + Name *string + + // READ-ONLY; Azure Resource Manager metadata containing createdBy and modifiedBy information. + SystemData *SystemData + + // READ-ONLY; The type of the resource. E.g. "Microsoft.Compute/virtualMachines" or "Microsoft.Storage/storageAccounts" + Type *string +} + +// FqdnListGlobalRulestackResourceListResult - The response of a FqdnListGlobalRulestackResource list operation. +type FqdnListGlobalRulestackResourceListResult struct { + // REQUIRED; The items on this page + Value []*FqdnListGlobalRulestackResource + + // The link to the next page of items + NextLink *string +} + +// FqdnListLocalRulestackClientBeginCreateOrUpdateOptions contains the optional parameters for the FqdnListLocalRulestackClient.BeginCreateOrUpdate +// method. +type FqdnListLocalRulestackClientBeginCreateOrUpdateOptions struct { + // Resumes the LRO from the provided token. + ResumeToken string +} + +// FqdnListLocalRulestackClientBeginDeleteOptions contains the optional parameters for the FqdnListLocalRulestackClient.BeginDelete +// method. +type FqdnListLocalRulestackClientBeginDeleteOptions struct { + // Resumes the LRO from the provided token. + ResumeToken string +} + +// FqdnListLocalRulestackClientGetOptions contains the optional parameters for the FqdnListLocalRulestackClient.Get method. +type FqdnListLocalRulestackClientGetOptions struct { + // placeholder for future optional parameters +} + +// FqdnListLocalRulestackClientListByLocalRulestacksOptions contains the optional parameters for the FqdnListLocalRulestackClient.NewListByLocalRulestacksPager +// method. +type FqdnListLocalRulestackClientListByLocalRulestacksOptions struct { + // placeholder for future optional parameters +} + +// FqdnListLocalRulestackResource - LocalRulestack fqdnList +type FqdnListLocalRulestackResource struct { + // REQUIRED; The resource-specific properties for this resource. + Properties *FqdnObject + + // READ-ONLY; Fully qualified resource ID for the resource. Ex - /subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/{resourceProviderNamespace}/{resourceType}/{resourceName} + ID *string + + // READ-ONLY; The name of the resource + Name *string + + // READ-ONLY; Azure Resource Manager metadata containing createdBy and modifiedBy information. + SystemData *SystemData + + // READ-ONLY; The type of the resource. E.g. "Microsoft.Compute/virtualMachines" or "Microsoft.Storage/storageAccounts" + Type *string +} + +// FqdnListLocalRulestackResourceListResult - The response of a FqdnListLocalRulestackResource list operation. +type FqdnListLocalRulestackResourceListResult struct { + // REQUIRED; The items on this page + Value []*FqdnListLocalRulestackResource + + // The link to the next page of items + NextLink *string +} + +// FqdnObject - fqdn object +type FqdnObject struct { + // REQUIRED; fqdn list + FqdnList []*string + + // comment for this object + AuditComment *string + + // fqdn object description + Description *string + + // etag info + Etag *string + + // READ-ONLY; Provisioning state of the resource. + ProvisioningState *ProvisioningState +} + +// FrontendSetting - Frontend setting for Firewall +type FrontendSetting struct { + // REQUIRED; Backend configurations + BackendConfiguration *EndpointConfiguration + + // REQUIRED; Frontend configurations + FrontendConfiguration *EndpointConfiguration + + // REQUIRED; Settings name + Name *string + + // REQUIRED; Protocol Type + Protocol *ProtocolType +} + +// GlobalRulestackClientBeginCommitOptions contains the optional parameters for the GlobalRulestackClient.BeginCommit method. +type GlobalRulestackClientBeginCommitOptions struct { + // Resumes the LRO from the provided token. + ResumeToken string +} + +// GlobalRulestackClientBeginCreateOrUpdateOptions contains the optional parameters for the GlobalRulestackClient.BeginCreateOrUpdate +// method. +type GlobalRulestackClientBeginCreateOrUpdateOptions struct { + // Resumes the LRO from the provided token. + ResumeToken string +} + +// GlobalRulestackClientBeginDeleteOptions contains the optional parameters for the GlobalRulestackClient.BeginDelete method. +type GlobalRulestackClientBeginDeleteOptions struct { + // Resumes the LRO from the provided token. + ResumeToken string +} + +// GlobalRulestackClientGetChangeLogOptions contains the optional parameters for the GlobalRulestackClient.GetChangeLog method. +type GlobalRulestackClientGetChangeLogOptions struct { + // placeholder for future optional parameters +} + +// GlobalRulestackClientGetOptions contains the optional parameters for the GlobalRulestackClient.Get method. +type GlobalRulestackClientGetOptions struct { + // placeholder for future optional parameters +} + +// GlobalRulestackClientListAdvancedSecurityObjectsOptions contains the optional parameters for the GlobalRulestackClient.ListAdvancedSecurityObjects +// method. +type GlobalRulestackClientListAdvancedSecurityObjectsOptions struct { + Skip *string + Top *int32 +} + +// GlobalRulestackClientListAppIDsOptions contains the optional parameters for the GlobalRulestackClient.ListAppIDs method. +type GlobalRulestackClientListAppIDsOptions struct { + AppIDVersion *string + AppPrefix *string + Skip *string + Top *int32 +} + +// GlobalRulestackClientListCountriesOptions contains the optional parameters for the GlobalRulestackClient.ListCountries +// method. +type GlobalRulestackClientListCountriesOptions struct { + Skip *string + Top *int32 +} + +// GlobalRulestackClientListFirewallsOptions contains the optional parameters for the GlobalRulestackClient.ListFirewalls +// method. +type GlobalRulestackClientListFirewallsOptions struct { + // placeholder for future optional parameters +} + +// GlobalRulestackClientListOptions contains the optional parameters for the GlobalRulestackClient.NewListPager method. +type GlobalRulestackClientListOptions struct { + // placeholder for future optional parameters +} + +// GlobalRulestackClientListPredefinedURLCategoriesOptions contains the optional parameters for the GlobalRulestackClient.ListPredefinedURLCategories +// method. +type GlobalRulestackClientListPredefinedURLCategoriesOptions struct { + Skip *string + Top *int32 +} + +// GlobalRulestackClientListSecurityServicesOptions contains the optional parameters for the GlobalRulestackClient.ListSecurityServices +// method. +type GlobalRulestackClientListSecurityServicesOptions struct { + Skip *string + Top *int32 +} + +// GlobalRulestackClientRevertOptions contains the optional parameters for the GlobalRulestackClient.Revert method. +type GlobalRulestackClientRevertOptions struct { + // placeholder for future optional parameters +} + +// GlobalRulestackClientUpdateOptions contains the optional parameters for the GlobalRulestackClient.Update method. +type GlobalRulestackClientUpdateOptions struct { + // placeholder for future optional parameters +} + +// GlobalRulestackInfo - PAN Rulestack Describe Object +type GlobalRulestackInfo struct { + // REQUIRED; rulestack description + AzureID *string +} + +// GlobalRulestackResource - PaloAltoNetworks GlobalRulestack +type GlobalRulestackResource struct { + // REQUIRED; Global Location + Location *string + + // REQUIRED; The resource-specific properties for this resource. + Properties *RulestackProperties + + // The managed service identities assigned to this resource. + Identity *AzureResourceManagerManagedIdentityProperties + + // READ-ONLY; Fully qualified resource ID for the resource. Ex - /subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/{resourceProviderNamespace}/{resourceType}/{resourceName} + ID *string + + // READ-ONLY; The name of the resource + Name *string + + // READ-ONLY; Azure Resource Manager metadata containing createdBy and modifiedBy information. + SystemData *SystemData + + // READ-ONLY; The type of the resource. E.g. "Microsoft.Compute/virtualMachines" or "Microsoft.Storage/storageAccounts" + Type *string +} + +// GlobalRulestackResourceListResult - The response of a GlobalRulestackResource list operation. +type GlobalRulestackResourceListResult struct { + // REQUIRED; The items on this page + Value []*GlobalRulestackResource + + // The link to the next page of items + NextLink *string +} + +// GlobalRulestackResourceUpdate - The type used for update operations of the GlobalRulestackResource. +type GlobalRulestackResourceUpdate struct { + // The managed service identities assigned to this resource. + Identity *AzureResourceManagerManagedIdentityProperties + + // Global Location + Location *string + + // The updatable properties of the GlobalRulestackResource. + Properties *GlobalRulestackResourceUpdateProperties +} + +// GlobalRulestackResourceUpdateProperties - The updatable properties of the GlobalRulestackResource. +type GlobalRulestackResourceUpdateProperties struct { + // subscription scope of global rulestack + AssociatedSubscriptions []*string + + // Mode for default rules creation + DefaultMode *DefaultMode + + // rulestack description + Description *string + + // minimum version + MinAppIDVersion *string + + // PanEtag info + PanEtag *string + + // Rulestack Location, Required for GlobalRulestacks, Not for LocalRulestacks + PanLocation *string + + // Rulestack Type + Scope *ScopeType + + // Security Profile + SecurityServices *SecurityServices +} + +// IPAddress - IP Address +type IPAddress struct { + // Address value + Address *string + + // Resource Id + ResourceID *string +} + +// IPAddressSpace - IP Address Space +type IPAddressSpace struct { + // Address Space + AddressSpace *string + + // Resource Id + ResourceID *string +} + +type ListAppIDResponse struct { + // REQUIRED; List of AppIds + Value []*string + + // next Link + NextLink *string +} + +// ListFirewallsResponse - List firewalls response +type ListFirewallsResponse struct { + // REQUIRED; firewalls list + Value []*string + + // next link + NextLink *string +} + +// LocalRulesClientBeginCreateOrUpdateOptions contains the optional parameters for the LocalRulesClient.BeginCreateOrUpdate +// method. +type LocalRulesClientBeginCreateOrUpdateOptions struct { + // Resumes the LRO from the provided token. + ResumeToken string +} + +// LocalRulesClientBeginDeleteOptions contains the optional parameters for the LocalRulesClient.BeginDelete method. +type LocalRulesClientBeginDeleteOptions struct { + // Resumes the LRO from the provided token. + ResumeToken string +} + +// LocalRulesClientGetCountersOptions contains the optional parameters for the LocalRulesClient.GetCounters method. +type LocalRulesClientGetCountersOptions struct { + FirewallName *string +} + +// LocalRulesClientGetOptions contains the optional parameters for the LocalRulesClient.Get method. +type LocalRulesClientGetOptions struct { + // placeholder for future optional parameters +} + +// LocalRulesClientListByLocalRulestacksOptions contains the optional parameters for the LocalRulesClient.NewListByLocalRulestacksPager +// method. +type LocalRulesClientListByLocalRulestacksOptions struct { + // placeholder for future optional parameters +} + +// LocalRulesClientRefreshCountersOptions contains the optional parameters for the LocalRulesClient.RefreshCounters method. +type LocalRulesClientRefreshCountersOptions struct { + FirewallName *string +} + +// LocalRulesClientResetCountersOptions contains the optional parameters for the LocalRulesClient.ResetCounters method. +type LocalRulesClientResetCountersOptions struct { + FirewallName *string +} + +// LocalRulesResource - LocalRulestack rule list +type LocalRulesResource struct { + // REQUIRED; The resource-specific properties for this resource. + Properties *RuleEntry + + // READ-ONLY; Fully qualified resource ID for the resource. Ex - /subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/{resourceProviderNamespace}/{resourceType}/{resourceName} + ID *string + + // READ-ONLY; The name of the resource + Name *string + + // READ-ONLY; Azure Resource Manager metadata containing createdBy and modifiedBy information. + SystemData *SystemData + + // READ-ONLY; The type of the resource. E.g. "Microsoft.Compute/virtualMachines" or "Microsoft.Storage/storageAccounts" + Type *string +} + +// LocalRulesResourceListResult - The response of a LocalRulesResource list operation. +type LocalRulesResourceListResult struct { + // REQUIRED; The items on this page + Value []*LocalRulesResource + + // The link to the next page of items + NextLink *string +} + +// LocalRulestackResource - PaloAltoNetworks LocalRulestack +type LocalRulestackResource struct { + // REQUIRED; The geo-location where the resource lives + Location *string + + // REQUIRED; The resource-specific properties for this resource. + Properties *RulestackProperties + + // The managed service identities assigned to this resource. + Identity *AzureResourceManagerManagedIdentityProperties + + // Resource tags. + Tags map[string]*string + + // READ-ONLY; Fully qualified resource ID for the resource. Ex - /subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/{resourceProviderNamespace}/{resourceType}/{resourceName} + ID *string + + // READ-ONLY; The name of the resource + Name *string + + // READ-ONLY; Azure Resource Manager metadata containing createdBy and modifiedBy information. + SystemData *SystemData + + // READ-ONLY; The type of the resource. E.g. "Microsoft.Compute/virtualMachines" or "Microsoft.Storage/storageAccounts" + Type *string +} + +// LocalRulestackResourceListResult - The response of a LocalRulestackResource list operation. +type LocalRulestackResourceListResult struct { + // REQUIRED; The items on this page + Value []*LocalRulestackResource + + // The link to the next page of items + NextLink *string +} + +// LocalRulestackResourceUpdate - The type used for update operations of the LocalRulestackResource. +type LocalRulestackResourceUpdate struct { + // The managed service identities assigned to this resource. + Identity *AzureResourceManagerManagedIdentityProperties + + // The updatable properties of the LocalRulestackResource. + Properties *LocalRulestackResourceUpdateProperties + + // Resource tags. + Tags map[string]*string +} + +// LocalRulestackResourceUpdateProperties - The updatable properties of the LocalRulestackResource. +type LocalRulestackResourceUpdateProperties struct { + // subscription scope of global rulestack + AssociatedSubscriptions []*string + + // Mode for default rules creation + DefaultMode *DefaultMode + + // rulestack description + Description *string + + // minimum version + MinAppIDVersion *string + + // PanEtag info + PanEtag *string + + // Rulestack Location, Required for GlobalRulestacks, Not for LocalRulestacks + PanLocation *string + + // Rulestack Type + Scope *ScopeType + + // Security Profile + SecurityServices *SecurityServices +} + +// LocalRulestacksClientBeginCommitOptions contains the optional parameters for the LocalRulestacksClient.BeginCommit method. +type LocalRulestacksClientBeginCommitOptions struct { + // Resumes the LRO from the provided token. + ResumeToken string +} + +// LocalRulestacksClientBeginCreateOrUpdateOptions contains the optional parameters for the LocalRulestacksClient.BeginCreateOrUpdate +// method. +type LocalRulestacksClientBeginCreateOrUpdateOptions struct { + // Resumes the LRO from the provided token. + ResumeToken string +} + +// LocalRulestacksClientBeginDeleteOptions contains the optional parameters for the LocalRulestacksClient.BeginDelete method. +type LocalRulestacksClientBeginDeleteOptions struct { + // Resumes the LRO from the provided token. + ResumeToken string +} + +// LocalRulestacksClientGetChangeLogOptions contains the optional parameters for the LocalRulestacksClient.GetChangeLog method. +type LocalRulestacksClientGetChangeLogOptions struct { + // placeholder for future optional parameters +} + +// LocalRulestacksClientGetOptions contains the optional parameters for the LocalRulestacksClient.Get method. +type LocalRulestacksClientGetOptions struct { + // placeholder for future optional parameters +} + +// LocalRulestacksClientGetSupportInfoOptions contains the optional parameters for the LocalRulestacksClient.GetSupportInfo +// method. +type LocalRulestacksClientGetSupportInfoOptions struct { + // email address on behalf of which this API called + Email *string +} + +// LocalRulestacksClientListAdvancedSecurityObjectsOptions contains the optional parameters for the LocalRulestacksClient.ListAdvancedSecurityObjects +// method. +type LocalRulestacksClientListAdvancedSecurityObjectsOptions struct { + Skip *string + Top *int32 +} + +// LocalRulestacksClientListAppIDsOptions contains the optional parameters for the LocalRulestacksClient.ListAppIDs method. +type LocalRulestacksClientListAppIDsOptions struct { + AppIDVersion *string + AppPrefix *string + Skip *string + Top *int32 +} + +// LocalRulestacksClientListByResourceGroupOptions contains the optional parameters for the LocalRulestacksClient.NewListByResourceGroupPager +// method. +type LocalRulestacksClientListByResourceGroupOptions struct { + // placeholder for future optional parameters +} + +// LocalRulestacksClientListBySubscriptionOptions contains the optional parameters for the LocalRulestacksClient.NewListBySubscriptionPager +// method. +type LocalRulestacksClientListBySubscriptionOptions struct { + // placeholder for future optional parameters +} + +// LocalRulestacksClientListCountriesOptions contains the optional parameters for the LocalRulestacksClient.ListCountries +// method. +type LocalRulestacksClientListCountriesOptions struct { + Skip *string + Top *int32 +} + +// LocalRulestacksClientListFirewallsOptions contains the optional parameters for the LocalRulestacksClient.ListFirewalls +// method. +type LocalRulestacksClientListFirewallsOptions struct { + // placeholder for future optional parameters +} + +// LocalRulestacksClientListPredefinedURLCategoriesOptions contains the optional parameters for the LocalRulestacksClient.ListPredefinedURLCategories +// method. +type LocalRulestacksClientListPredefinedURLCategoriesOptions struct { + Skip *string + Top *int32 +} + +// LocalRulestacksClientListSecurityServicesOptions contains the optional parameters for the LocalRulestacksClient.ListSecurityServices +// method. +type LocalRulestacksClientListSecurityServicesOptions struct { + Skip *string + Top *int32 +} + +// LocalRulestacksClientRevertOptions contains the optional parameters for the LocalRulestacksClient.Revert method. +type LocalRulestacksClientRevertOptions struct { + // placeholder for future optional parameters +} + +// LocalRulestacksClientUpdateOptions contains the optional parameters for the LocalRulestacksClient.Update method. +type LocalRulestacksClientUpdateOptions struct { + // placeholder for future optional parameters +} + +// LogDestination - Log Destination +type LogDestination struct { + // Event Hub configurations + EventHubConfigurations *EventHub + + // Monitor Log configurations + MonitorConfigurations *MonitorLog + + // Storage account configurations + StorageConfigurations *StorageAccount +} + +// LogSettings - Log Settings for Firewall +type LogSettings struct { + // Application Insight details + ApplicationInsights *ApplicationInsights + + // Common destination configurations + CommonDestination *LogDestination + + // Decrypt destination configurations + DecryptLogDestination *LogDestination + + // Log option SAME/INDIVIDUAL + LogOption *LogOption + + // One of possible log type + LogType *LogType + + // Threat destination configurations + ThreatLogDestination *LogDestination + + // Traffic destination configurations + TrafficLogDestination *LogDestination +} + +// MarketplaceDetails of PAN Firewall resource +type MarketplaceDetails struct { + // REQUIRED; Offer Id + OfferID *string + + // REQUIRED; Publisher Id + PublisherID *string + + // Marketplace Subscription Status + MarketplaceSubscriptionStatus *MarketplaceSubscriptionStatus + + // READ-ONLY; Marketplace Subscription Id + MarketplaceSubscriptionID *string +} + +// MonitorLog configurations +type MonitorLog struct { + // Resource ID of MonitorLog + ID *string + + // Primary Key value for Monitor + PrimaryKey *string + + // Secondary Key value for Monitor + SecondaryKey *string + + // Subscription Id + SubscriptionID *string + + // MonitorLog workspace + Workspace *string +} + +// NameDescriptionObject - object type info +type NameDescriptionObject struct { + // REQUIRED; name value + Name *string + + // description value + Description *string +} + +// NetworkProfile - Network settings for Firewall +type NetworkProfile struct { + // REQUIRED; Enable egress NAT, enabled by default + EnableEgressNat *EgressNat + + // REQUIRED; vnet or vwan, cannot be updated + NetworkType *NetworkType + + // REQUIRED; List of IPs associated with the Firewall + PublicIPs []*IPAddress + + // Egress nat IP to use + EgressNatIP []*IPAddress + + // Vnet configurations + VnetConfiguration *VnetConfiguration + + // Vwan configurations + VwanConfiguration *VwanConfiguration +} + +// Operation - Details of a REST API operation, returned from the Resource Provider Operations API +type Operation struct { + // Localized display information for this particular operation. + Display *OperationDisplay + + // READ-ONLY; Enum. Indicates the action type. "Internal" refers to actions that are for internal only APIs. + ActionType *ActionType + + // READ-ONLY; Whether the operation applies to data-plane. This is "true" for data-plane operations and "false" for ARM/control-plane + // operations. + IsDataAction *bool + + // READ-ONLY; The name of the operation, as per Resource-Based Access Control (RBAC). Examples: "Microsoft.Compute/virtualMachines/write", + // "Microsoft.Compute/virtualMachines/capture/action" + Name *string + + // READ-ONLY; The intended executor of the operation; as in Resource Based Access Control (RBAC) and audit logs UX. Default + // value is "user,system" + Origin *Origin +} + +// OperationDisplay - Localized display information for this particular operation. +type OperationDisplay struct { + // READ-ONLY; The short, localized friendly description of the operation; suitable for tool tips and detailed views. + Description *string + + // READ-ONLY; The concise, localized friendly name for the operation; suitable for dropdowns. E.g. "Create or Update Virtual + // Machine", "Restart Virtual Machine". + Operation *string + + // READ-ONLY; The localized friendly form of the resource provider name, e.g. "Microsoft Monitoring Insights" or "Microsoft + // Compute". + Provider *string + + // READ-ONLY; The localized friendly name of the resource type related to this operation. E.g. "Virtual Machines" or "Job + // Schedule Collections". + Resource *string +} + +// OperationListResult - A list of REST API operations supported by an Azure Resource Provider. It contains an URL link to +// get the next set of results. +type OperationListResult struct { + // READ-ONLY; URL to get the next set of operation list results (if there are any). + NextLink *string + + // READ-ONLY; List of operations supported by the resource provider + Value []*Operation +} + +// OperationsClientListOptions contains the optional parameters for the OperationsClient.NewListPager method. +type OperationsClientListOptions struct { + // placeholder for future optional parameters +} + +// PanoramaConfig - Panorama Config +type PanoramaConfig struct { + // REQUIRED; Base64 encoded string representing Panorama parameters to be used by Firewall to connect to Panorama. This string + // is generated via azure plugin in Panorama + ConfigString *string + + // READ-ONLY; Panorama Collector Group to join - (Once configured we can not edit the value) + CgName *string + + // READ-ONLY; Panorama Device Group to join + DgName *string + + // READ-ONLY; Resource name(may be unique) for PN admin + HostName *string + + // READ-ONLY; Primary Panorama Server IP address value in dotted format for IPv4 + PanoramaServer *string + + // READ-ONLY; Secondary Panorama Server IP address value in dotted format for IPv4 + PanoramaServer2 *string + + // READ-ONLY; Panorama Template Stack to join - (Once configured we can not edit the value) + TplName *string + + // READ-ONLY; VM auth key for panorama connectivity + VMAuthKey *string +} + +// PanoramaStatus - Panorama connectivity information +type PanoramaStatus struct { + // READ-ONLY; Secondary Panorama connection status + PanoramaServer2Status *ServerStatus + + // READ-ONLY; Primary Panorama connection status + PanoramaServerStatus *ServerStatus +} + +// PlanData - Billing plan information. +type PlanData struct { + // REQUIRED; different billing cycles like MONTHLY/WEEKLY + BillingCycle *BillingCycle + + // REQUIRED; plan id as published by Liftr.PAN + PlanID *string + + // different usage type like PAYG/COMMITTED + UsageType *UsageType + + // READ-ONLY; date when plan was applied + EffectiveDate *time.Time +} + +// PostRulesClientBeginCreateOrUpdateOptions contains the optional parameters for the PostRulesClient.BeginCreateOrUpdate +// method. +type PostRulesClientBeginCreateOrUpdateOptions struct { + // Resumes the LRO from the provided token. + ResumeToken string +} + +// PostRulesClientBeginDeleteOptions contains the optional parameters for the PostRulesClient.BeginDelete method. +type PostRulesClientBeginDeleteOptions struct { + // Resumes the LRO from the provided token. + ResumeToken string +} + +// PostRulesClientGetCountersOptions contains the optional parameters for the PostRulesClient.GetCounters method. +type PostRulesClientGetCountersOptions struct { + FirewallName *string +} + +// PostRulesClientGetOptions contains the optional parameters for the PostRulesClient.Get method. +type PostRulesClientGetOptions struct { + // placeholder for future optional parameters +} + +// PostRulesClientListOptions contains the optional parameters for the PostRulesClient.NewListPager method. +type PostRulesClientListOptions struct { + // placeholder for future optional parameters +} + +// PostRulesClientRefreshCountersOptions contains the optional parameters for the PostRulesClient.RefreshCounters method. +type PostRulesClientRefreshCountersOptions struct { + FirewallName *string +} + +// PostRulesClientResetCountersOptions contains the optional parameters for the PostRulesClient.ResetCounters method. +type PostRulesClientResetCountersOptions struct { + FirewallName *string +} + +// PostRulesResource - PostRulestack rule list +type PostRulesResource struct { + // REQUIRED; The resource-specific properties for this resource. + Properties *RuleEntry + + // READ-ONLY; Fully qualified resource ID for the resource. Ex - /subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/{resourceProviderNamespace}/{resourceType}/{resourceName} + ID *string + + // READ-ONLY; The name of the resource + Name *string + + // READ-ONLY; Azure Resource Manager metadata containing createdBy and modifiedBy information. + SystemData *SystemData + + // READ-ONLY; The type of the resource. E.g. "Microsoft.Compute/virtualMachines" or "Microsoft.Storage/storageAccounts" + Type *string +} + +// PostRulesResourceListResult - The response of a PostRulesResource list operation. +type PostRulesResourceListResult struct { + // REQUIRED; The items on this page + Value []*PostRulesResource + + // The link to the next page of items + NextLink *string +} + +// PreRulesClientBeginCreateOrUpdateOptions contains the optional parameters for the PreRulesClient.BeginCreateOrUpdate method. +type PreRulesClientBeginCreateOrUpdateOptions struct { + // Resumes the LRO from the provided token. + ResumeToken string +} + +// PreRulesClientBeginDeleteOptions contains the optional parameters for the PreRulesClient.BeginDelete method. +type PreRulesClientBeginDeleteOptions struct { + // Resumes the LRO from the provided token. + ResumeToken string +} + +// PreRulesClientGetCountersOptions contains the optional parameters for the PreRulesClient.GetCounters method. +type PreRulesClientGetCountersOptions struct { + FirewallName *string +} + +// PreRulesClientGetOptions contains the optional parameters for the PreRulesClient.Get method. +type PreRulesClientGetOptions struct { + // placeholder for future optional parameters +} + +// PreRulesClientListOptions contains the optional parameters for the PreRulesClient.NewListPager method. +type PreRulesClientListOptions struct { + // placeholder for future optional parameters +} + +// PreRulesClientRefreshCountersOptions contains the optional parameters for the PreRulesClient.RefreshCounters method. +type PreRulesClientRefreshCountersOptions struct { + FirewallName *string +} + +// PreRulesClientResetCountersOptions contains the optional parameters for the PreRulesClient.ResetCounters method. +type PreRulesClientResetCountersOptions struct { + FirewallName *string +} + +// PreRulesResource - PreRulestack rule list +type PreRulesResource struct { + // REQUIRED; The resource-specific properties for this resource. + Properties *RuleEntry + + // READ-ONLY; Fully qualified resource ID for the resource. Ex - /subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/{resourceProviderNamespace}/{resourceType}/{resourceName} + ID *string + + // READ-ONLY; The name of the resource + Name *string + + // READ-ONLY; Azure Resource Manager metadata containing createdBy and modifiedBy information. + SystemData *SystemData + + // READ-ONLY; The type of the resource. E.g. "Microsoft.Compute/virtualMachines" or "Microsoft.Storage/storageAccounts" + Type *string +} + +// PreRulesResourceListResult - The response of a PreRulesResource list operation. +type PreRulesResourceListResult struct { + // REQUIRED; The items on this page + Value []*PreRulesResource + + // The link to the next page of items + NextLink *string +} + +// PredefinedURLCategoriesResponse - predefined url categories response +type PredefinedURLCategoriesResponse struct { + // REQUIRED; predefined url categories + Value []*PredefinedURLCategory + + // next link + NextLink *string +} + +// PredefinedURLCategory - Predefined URL category object +type PredefinedURLCategory struct { + // REQUIRED + Action *string + + // REQUIRED + Name *string +} + +// PrefixListGlobalRulestackClientBeginCreateOrUpdateOptions contains the optional parameters for the PrefixListGlobalRulestackClient.BeginCreateOrUpdate +// method. +type PrefixListGlobalRulestackClientBeginCreateOrUpdateOptions struct { + // Resumes the LRO from the provided token. + ResumeToken string +} + +// PrefixListGlobalRulestackClientBeginDeleteOptions contains the optional parameters for the PrefixListGlobalRulestackClient.BeginDelete +// method. +type PrefixListGlobalRulestackClientBeginDeleteOptions struct { + // Resumes the LRO from the provided token. + ResumeToken string +} + +// PrefixListGlobalRulestackClientGetOptions contains the optional parameters for the PrefixListGlobalRulestackClient.Get +// method. +type PrefixListGlobalRulestackClientGetOptions struct { + // placeholder for future optional parameters +} + +// PrefixListGlobalRulestackClientListOptions contains the optional parameters for the PrefixListGlobalRulestackClient.NewListPager +// method. +type PrefixListGlobalRulestackClientListOptions struct { + // placeholder for future optional parameters +} + +// PrefixListGlobalRulestackResource - GlobalRulestack prefixList +type PrefixListGlobalRulestackResource struct { + // REQUIRED; The resource-specific properties for this resource. + Properties *PrefixObject + + // READ-ONLY; Fully qualified resource ID for the resource. Ex - /subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/{resourceProviderNamespace}/{resourceType}/{resourceName} + ID *string + + // READ-ONLY; The name of the resource + Name *string + + // READ-ONLY; Azure Resource Manager metadata containing createdBy and modifiedBy information. + SystemData *SystemData + + // READ-ONLY; The type of the resource. E.g. "Microsoft.Compute/virtualMachines" or "Microsoft.Storage/storageAccounts" + Type *string +} + +// PrefixListGlobalRulestackResourceListResult - The response of a PrefixListGlobalRulestackResource list operation. +type PrefixListGlobalRulestackResourceListResult struct { + // REQUIRED; The items on this page + Value []*PrefixListGlobalRulestackResource + + // The link to the next page of items + NextLink *string +} + +// PrefixListLocalRulestackClientBeginCreateOrUpdateOptions contains the optional parameters for the PrefixListLocalRulestackClient.BeginCreateOrUpdate +// method. +type PrefixListLocalRulestackClientBeginCreateOrUpdateOptions struct { + // Resumes the LRO from the provided token. + ResumeToken string +} + +// PrefixListLocalRulestackClientBeginDeleteOptions contains the optional parameters for the PrefixListLocalRulestackClient.BeginDelete +// method. +type PrefixListLocalRulestackClientBeginDeleteOptions struct { + // Resumes the LRO from the provided token. + ResumeToken string +} + +// PrefixListLocalRulestackClientGetOptions contains the optional parameters for the PrefixListLocalRulestackClient.Get method. +type PrefixListLocalRulestackClientGetOptions struct { + // placeholder for future optional parameters +} + +// PrefixListLocalRulestackClientListByLocalRulestacksOptions contains the optional parameters for the PrefixListLocalRulestackClient.NewListByLocalRulestacksPager +// method. +type PrefixListLocalRulestackClientListByLocalRulestacksOptions struct { + // placeholder for future optional parameters +} + +// PrefixListResource - LocalRulestack prefixList +type PrefixListResource struct { + // REQUIRED; The resource-specific properties for this resource. + Properties *PrefixObject + + // READ-ONLY; Fully qualified resource ID for the resource. Ex - /subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/{resourceProviderNamespace}/{resourceType}/{resourceName} + ID *string + + // READ-ONLY; The name of the resource + Name *string + + // READ-ONLY; Azure Resource Manager metadata containing createdBy and modifiedBy information. + SystemData *SystemData + + // READ-ONLY; The type of the resource. E.g. "Microsoft.Compute/virtualMachines" or "Microsoft.Storage/storageAccounts" + Type *string +} + +// PrefixListResourceListResult - The response of a PrefixListResource list operation. +type PrefixListResourceListResult struct { + // REQUIRED; The items on this page + Value []*PrefixListResource + + // The link to the next page of items + NextLink *string +} + +// PrefixObject - prefix entry +type PrefixObject struct { + // REQUIRED; prefix list + PrefixList []*string + + // comment for this object + AuditComment *string + + // prefix description + Description *string + + // etag info + Etag *string + + // READ-ONLY; Provisioning state of the resource. + ProvisioningState *ProvisioningState +} + +// RuleCounter - Rule counter +type RuleCounter struct { + // REQUIRED; priority number + Priority *string + + // REQUIRED; rule name + RuleName *string + + // apps seen + AppSeen *AppSeenData + + // firewall name + FirewallName *string + + // hit count + HitCount *int32 + + // last updated timestamp + LastUpdatedTimestamp *time.Time + + // timestamp of request + RequestTimestamp *time.Time + + // rule list name + RuleListName *string + + // rule Stack Name + RuleStackName *string + + // timestamp of response + Timestamp *time.Time +} + +// RuleCounterReset - Rule counter reset +type RuleCounterReset struct { + // firewall name + FirewallName *string + + // rule list name + RuleListName *string + + // rule name + RuleName *string + + // rule Stack Name + RuleStackName *string + + // READ-ONLY; priority number + Priority *string +} + +// RuleEntry - definition of rule +type RuleEntry struct { + // REQUIRED; rule name + RuleName *string + + // rule action + ActionType *ActionEnum + + // array of rule applications + Applications []*string + + // rule comment + AuditComment *string + + // rule category + Category *Category + + // enable or disable decryption + DecryptionRuleType *DecryptionRuleTypeEnum + + // rule description + Description *string + + // destination address + Destination *DestinationAddr + + // enable or disable logging + EnableLogging *StateEnum + + // etag info + Etag *string + + // inbound Inspection Certificate + InboundInspectionCertificate *string + + // cidr should not be 'any' + NegateDestination *BooleanEnum + + // cidr should not be 'any' + NegateSource *BooleanEnum + + // any, application-default, TCP:number, UDP:number + Protocol *string + + // prot port list + ProtocolPortList []*string + + // state of this rule + RuleState *StateEnum + + // source address + Source *SourceAddr + + // tag for rule + Tags []*TagInfo + + // READ-ONLY + Priority *int32 + + // READ-ONLY; Provisioning state of the resource. + ProvisioningState *ProvisioningState +} + +// RulestackDetails - Associated rulestack details +type RulestackDetails struct { + // Rulestack location + Location *string + + // Resource Id + ResourceID *string + + // Associated rulestack Id + RulestackID *string +} + +// RulestackProperties - PAN Rulestack Describe Object +type RulestackProperties struct { + // subscription scope of global rulestack + AssociatedSubscriptions []*string + + // Mode for default rules creation + DefaultMode *DefaultMode + + // rulestack description + Description *string + + // minimum version + MinAppIDVersion *string + + // PanEtag info + PanEtag *string + + // Rulestack Location, Required for GlobalRulestacks, Not for LocalRulestacks + PanLocation *string + + // Rulestack Type + Scope *ScopeType + + // Security Profile + SecurityServices *SecurityServices + + // READ-ONLY; Provisioning state of the resource. + ProvisioningState *ProvisioningState +} + +// SecurityServices - security services +type SecurityServices struct { + // Anti spyware Profile data + AntiSpywareProfile *string + + // anti virus profile data + AntiVirusProfile *string + + // DNS Subscription profile data + DNSSubscription *string + + // File blocking profile data + FileBlockingProfile *string + + // Trusted Egress Decryption profile data + OutboundTrustCertificate *string + + // Untrusted Egress Decryption profile data + OutboundUnTrustCertificate *string + + // URL filtering profile data + URLFilteringProfile *string + + // IPs Vulnerability Profile Data + VulnerabilityProfile *string +} + +// SecurityServicesResponse - Security services list response +type SecurityServicesResponse struct { + // REQUIRED; response value + Value *SecurityServicesTypeList + + // next link + NextLink *string +} + +// SecurityServicesTypeList - Security services type list +type SecurityServicesTypeList struct { + // REQUIRED; list + Entry []*NameDescriptionObject + + // security services type + Type *string +} + +// SourceAddr - Address properties +type SourceAddr struct { + // special value 'any' + Cidrs []*string + + // list of countries + Countries []*string + + // list of feeds + Feeds []*string + + // prefix list + PrefixLists []*string +} + +// StorageAccount - Storage Account configurations +type StorageAccount struct { + // Storage account name + AccountName *string + + // Resource ID of storage account + ID *string + + // Subscription Id + SubscriptionID *string +} + +// SupportInfo - Support information for the resource +type SupportInfo struct { + // Support account associated with given resource + AccountID *string + + // account registered in Customer Support Portal + AccountRegistered *BooleanEnum + + // Product usage is in free trial period + FreeTrial *BooleanEnum + + // Free trial credit remaining + FreeTrialCreditLeft *int32 + + // Free trial days remaining + FreeTrialDaysLeft *int32 + + // URL for paloaltonetworks live community + HelpURL *string + + // product SKU associated with given resource + ProductSKU *string + + // product Serial associated with given resource + ProductSerial *string + + // URL for registering product in paloaltonetworks Customer Service Portal + RegisterURL *string + + // URL for paloaltonetworks Customer Service Portal + SupportURL *string + + // user domain is supported in Customer Support Portal + UserDomainSupported *BooleanEnum + + // user registered in Customer Support Portal + UserRegistered *BooleanEnum +} + +// SystemData - Metadata pertaining to creation and last modification of the resource. +type SystemData struct { + // The timestamp of resource creation (UTC). + CreatedAt *time.Time + + // The identity that created the resource. + CreatedBy *string + + // The type of identity that created the resource. + CreatedByType *CreatedByType + + // The timestamp of resource last modification (UTC) + LastModifiedAt *time.Time + + // The identity that last modified the resource. + LastModifiedBy *string + + // The type of identity that last modified the resource. + LastModifiedByType *CreatedByType +} + +// TagInfo - Tag +type TagInfo struct { + // REQUIRED; tag name + Key *string + + // REQUIRED; tag value + Value *string +} + +// VnetConfiguration - VnetInfo for Firewall Networking +type VnetConfiguration struct { + // REQUIRED; Trust Subnet + TrustSubnet *IPAddressSpace + + // REQUIRED; Untrust Subnet + UnTrustSubnet *IPAddressSpace + + // REQUIRED; Azure Virtual Network + Vnet *IPAddressSpace + + // IP of trust subnet for UDR + IPOfTrustSubnetForUdr *IPAddress +} + +// VwanConfiguration - VwanInfo for Firewall Networking +type VwanConfiguration struct { + // REQUIRED; vHub Address + VHub *IPAddressSpace + + // IP of trust subnet for UDR + IPOfTrustSubnetForUdr *IPAddress + + // Network Virtual Appliance resource ID + NetworkVirtualApplianceID *string + + // Trust Subnet + TrustSubnet *IPAddressSpace + + // Untrust Subnet + UnTrustSubnet *IPAddressSpace +} diff --git a/sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/models_serde.go b/sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/models_serde.go new file mode 100644 index 000000000000..578fddec7e83 --- /dev/null +++ b/sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/models_serde.go @@ -0,0 +1,3530 @@ +//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. +// Code generated by Microsoft (R) AutoRest Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. +// DO NOT EDIT. + +package armpanngfw + +import ( + "encoding/json" + "fmt" + "github.com/Azure/azure-sdk-for-go/sdk/azcore" + "reflect" +) + +// MarshalJSON implements the json.Marshaller interface for type AdvSecurityObjectListResponse. +func (a AdvSecurityObjectListResponse) MarshalJSON() ([]byte, error) { + objectMap := make(map[string]any) + populate(objectMap, "nextLink", a.NextLink) + populate(objectMap, "value", a.Value) + return json.Marshal(objectMap) +} + +// UnmarshalJSON implements the json.Unmarshaller interface for type AdvSecurityObjectListResponse. +func (a *AdvSecurityObjectListResponse) UnmarshalJSON(data []byte) error { + var rawMsg map[string]json.RawMessage + if err := json.Unmarshal(data, &rawMsg); err != nil { + return fmt.Errorf("unmarshalling type %T: %v", a, err) + } + for key, val := range rawMsg { + var err error + switch key { + case "nextLink": + err = unpopulate(val, "NextLink", &a.NextLink) + delete(rawMsg, key) + case "value": + err = unpopulate(val, "Value", &a.Value) + delete(rawMsg, key) + } + if err != nil { + return fmt.Errorf("unmarshalling type %T: %v", a, err) + } + } + return nil +} + +// MarshalJSON implements the json.Marshaller interface for type AdvSecurityObjectModel. +func (a AdvSecurityObjectModel) MarshalJSON() ([]byte, error) { + objectMap := make(map[string]any) + populate(objectMap, "entry", a.Entry) + populate(objectMap, "type", a.Type) + return json.Marshal(objectMap) +} + +// UnmarshalJSON implements the json.Unmarshaller interface for type AdvSecurityObjectModel. +func (a *AdvSecurityObjectModel) UnmarshalJSON(data []byte) error { + var rawMsg map[string]json.RawMessage + if err := json.Unmarshal(data, &rawMsg); err != nil { + return fmt.Errorf("unmarshalling type %T: %v", a, err) + } + for key, val := range rawMsg { + var err error + switch key { + case "entry": + err = unpopulate(val, "Entry", &a.Entry) + delete(rawMsg, key) + case "type": + err = unpopulate(val, "Type", &a.Type) + delete(rawMsg, key) + } + if err != nil { + return fmt.Errorf("unmarshalling type %T: %v", a, err) + } + } + return nil +} + +// MarshalJSON implements the json.Marshaller interface for type AppSeenData. +func (a AppSeenData) MarshalJSON() ([]byte, error) { + objectMap := make(map[string]any) + populate(objectMap, "appSeenList", a.AppSeenList) + populate(objectMap, "count", a.Count) + return json.Marshal(objectMap) +} + +// UnmarshalJSON implements the json.Unmarshaller interface for type AppSeenData. +func (a *AppSeenData) UnmarshalJSON(data []byte) error { + var rawMsg map[string]json.RawMessage + if err := json.Unmarshal(data, &rawMsg); err != nil { + return fmt.Errorf("unmarshalling type %T: %v", a, err) + } + for key, val := range rawMsg { + var err error + switch key { + case "appSeenList": + err = unpopulate(val, "AppSeenList", &a.AppSeenList) + delete(rawMsg, key) + case "count": + err = unpopulate(val, "Count", &a.Count) + delete(rawMsg, key) + } + if err != nil { + return fmt.Errorf("unmarshalling type %T: %v", a, err) + } + } + return nil +} + +// MarshalJSON implements the json.Marshaller interface for type AppSeenInfo. +func (a AppSeenInfo) MarshalJSON() ([]byte, error) { + objectMap := make(map[string]any) + populate(objectMap, "category", a.Category) + populate(objectMap, "risk", a.Risk) + populate(objectMap, "standardPorts", a.StandardPorts) + populate(objectMap, "subCategory", a.SubCategory) + populate(objectMap, "tag", a.Tag) + populate(objectMap, "technology", a.Technology) + populate(objectMap, "title", a.Title) + return json.Marshal(objectMap) +} + +// UnmarshalJSON implements the json.Unmarshaller interface for type AppSeenInfo. +func (a *AppSeenInfo) UnmarshalJSON(data []byte) error { + var rawMsg map[string]json.RawMessage + if err := json.Unmarshal(data, &rawMsg); err != nil { + return fmt.Errorf("unmarshalling type %T: %v", a, err) + } + for key, val := range rawMsg { + var err error + switch key { + case "category": + err = unpopulate(val, "Category", &a.Category) + delete(rawMsg, key) + case "risk": + err = unpopulate(val, "Risk", &a.Risk) + delete(rawMsg, key) + case "standardPorts": + err = unpopulate(val, "StandardPorts", &a.StandardPorts) + delete(rawMsg, key) + case "subCategory": + err = unpopulate(val, "SubCategory", &a.SubCategory) + delete(rawMsg, key) + case "tag": + err = unpopulate(val, "Tag", &a.Tag) + delete(rawMsg, key) + case "technology": + err = unpopulate(val, "Technology", &a.Technology) + delete(rawMsg, key) + case "title": + err = unpopulate(val, "Title", &a.Title) + delete(rawMsg, key) + } + if err != nil { + return fmt.Errorf("unmarshalling type %T: %v", a, err) + } + } + return nil +} + +// MarshalJSON implements the json.Marshaller interface for type ApplicationInsights. +func (a ApplicationInsights) MarshalJSON() ([]byte, error) { + objectMap := make(map[string]any) + populate(objectMap, "id", a.ID) + populate(objectMap, "key", a.Key) + return json.Marshal(objectMap) +} + +// UnmarshalJSON implements the json.Unmarshaller interface for type ApplicationInsights. +func (a *ApplicationInsights) UnmarshalJSON(data []byte) error { + var rawMsg map[string]json.RawMessage + if err := json.Unmarshal(data, &rawMsg); err != nil { + return fmt.Errorf("unmarshalling type %T: %v", a, err) + } + for key, val := range rawMsg { + var err error + switch key { + case "id": + err = unpopulate(val, "ID", &a.ID) + delete(rawMsg, key) + case "key": + err = unpopulate(val, "Key", &a.Key) + delete(rawMsg, key) + } + if err != nil { + return fmt.Errorf("unmarshalling type %T: %v", a, err) + } + } + return nil +} + +// MarshalJSON implements the json.Marshaller interface for type AzureResourceManagerManagedIdentityProperties. +func (a AzureResourceManagerManagedIdentityProperties) MarshalJSON() ([]byte, error) { + objectMap := make(map[string]any) + populate(objectMap, "principalId", a.PrincipalID) + populate(objectMap, "tenantId", a.TenantID) + populate(objectMap, "type", a.Type) + populate(objectMap, "userAssignedIdentities", a.UserAssignedIdentities) + return json.Marshal(objectMap) +} + +// UnmarshalJSON implements the json.Unmarshaller interface for type AzureResourceManagerManagedIdentityProperties. +func (a *AzureResourceManagerManagedIdentityProperties) UnmarshalJSON(data []byte) error { + var rawMsg map[string]json.RawMessage + if err := json.Unmarshal(data, &rawMsg); err != nil { + return fmt.Errorf("unmarshalling type %T: %v", a, err) + } + for key, val := range rawMsg { + var err error + switch key { + case "principalId": + err = unpopulate(val, "PrincipalID", &a.PrincipalID) + delete(rawMsg, key) + case "tenantId": + err = unpopulate(val, "TenantID", &a.TenantID) + delete(rawMsg, key) + case "type": + err = unpopulate(val, "Type", &a.Type) + delete(rawMsg, key) + case "userAssignedIdentities": + err = unpopulate(val, "UserAssignedIdentities", &a.UserAssignedIdentities) + delete(rawMsg, key) + } + if err != nil { + return fmt.Errorf("unmarshalling type %T: %v", a, err) + } + } + return nil +} + +// MarshalJSON implements the json.Marshaller interface for type AzureResourceManagerUserAssignedIdentity. +func (a AzureResourceManagerUserAssignedIdentity) MarshalJSON() ([]byte, error) { + objectMap := make(map[string]any) + populate(objectMap, "clientId", a.ClientID) + populate(objectMap, "principalId", a.PrincipalID) + return json.Marshal(objectMap) +} + +// UnmarshalJSON implements the json.Unmarshaller interface for type AzureResourceManagerUserAssignedIdentity. +func (a *AzureResourceManagerUserAssignedIdentity) UnmarshalJSON(data []byte) error { + var rawMsg map[string]json.RawMessage + if err := json.Unmarshal(data, &rawMsg); err != nil { + return fmt.Errorf("unmarshalling type %T: %v", a, err) + } + for key, val := range rawMsg { + var err error + switch key { + case "clientId": + err = unpopulate(val, "ClientID", &a.ClientID) + delete(rawMsg, key) + case "principalId": + err = unpopulate(val, "PrincipalID", &a.PrincipalID) + delete(rawMsg, key) + } + if err != nil { + return fmt.Errorf("unmarshalling type %T: %v", a, err) + } + } + return nil +} + +// MarshalJSON implements the json.Marshaller interface for type Category. +func (c Category) MarshalJSON() ([]byte, error) { + objectMap := make(map[string]any) + populate(objectMap, "feeds", c.Feeds) + populate(objectMap, "urlCustom", c.URLCustom) + return json.Marshal(objectMap) +} + +// UnmarshalJSON implements the json.Unmarshaller interface for type Category. +func (c *Category) UnmarshalJSON(data []byte) error { + var rawMsg map[string]json.RawMessage + if err := json.Unmarshal(data, &rawMsg); err != nil { + return fmt.Errorf("unmarshalling type %T: %v", c, err) + } + for key, val := range rawMsg { + var err error + switch key { + case "feeds": + err = unpopulate(val, "Feeds", &c.Feeds) + delete(rawMsg, key) + case "urlCustom": + err = unpopulate(val, "URLCustom", &c.URLCustom) + delete(rawMsg, key) + } + if err != nil { + return fmt.Errorf("unmarshalling type %T: %v", c, err) + } + } + return nil +} + +// MarshalJSON implements the json.Marshaller interface for type CertificateObject. +func (c CertificateObject) MarshalJSON() ([]byte, error) { + objectMap := make(map[string]any) + populate(objectMap, "auditComment", c.AuditComment) + populate(objectMap, "certificateSelfSigned", c.CertificateSelfSigned) + populate(objectMap, "certificateSignerResourceId", c.CertificateSignerResourceID) + populate(objectMap, "description", c.Description) + populate(objectMap, "etag", c.Etag) + populate(objectMap, "provisioningState", c.ProvisioningState) + return json.Marshal(objectMap) +} + +// UnmarshalJSON implements the json.Unmarshaller interface for type CertificateObject. +func (c *CertificateObject) UnmarshalJSON(data []byte) error { + var rawMsg map[string]json.RawMessage + if err := json.Unmarshal(data, &rawMsg); err != nil { + return fmt.Errorf("unmarshalling type %T: %v", c, err) + } + for key, val := range rawMsg { + var err error + switch key { + case "auditComment": + err = unpopulate(val, "AuditComment", &c.AuditComment) + delete(rawMsg, key) + case "certificateSelfSigned": + err = unpopulate(val, "CertificateSelfSigned", &c.CertificateSelfSigned) + delete(rawMsg, key) + case "certificateSignerResourceId": + err = unpopulate(val, "CertificateSignerResourceID", &c.CertificateSignerResourceID) + delete(rawMsg, key) + case "description": + err = unpopulate(val, "Description", &c.Description) + delete(rawMsg, key) + case "etag": + err = unpopulate(val, "Etag", &c.Etag) + delete(rawMsg, key) + case "provisioningState": + err = unpopulate(val, "ProvisioningState", &c.ProvisioningState) + delete(rawMsg, key) + } + if err != nil { + return fmt.Errorf("unmarshalling type %T: %v", c, err) + } + } + return nil +} + +// MarshalJSON implements the json.Marshaller interface for type CertificateObjectGlobalRulestackResource. +func (c CertificateObjectGlobalRulestackResource) MarshalJSON() ([]byte, error) { + objectMap := make(map[string]any) + populate(objectMap, "id", c.ID) + populate(objectMap, "name", c.Name) + populate(objectMap, "properties", c.Properties) + populate(objectMap, "systemData", c.SystemData) + populate(objectMap, "type", c.Type) + return json.Marshal(objectMap) +} + +// UnmarshalJSON implements the json.Unmarshaller interface for type CertificateObjectGlobalRulestackResource. +func (c *CertificateObjectGlobalRulestackResource) UnmarshalJSON(data []byte) error { + var rawMsg map[string]json.RawMessage + if err := json.Unmarshal(data, &rawMsg); err != nil { + return fmt.Errorf("unmarshalling type %T: %v", c, err) + } + for key, val := range rawMsg { + var err error + switch key { + case "id": + err = unpopulate(val, "ID", &c.ID) + delete(rawMsg, key) + case "name": + err = unpopulate(val, "Name", &c.Name) + delete(rawMsg, key) + case "properties": + err = unpopulate(val, "Properties", &c.Properties) + delete(rawMsg, key) + case "systemData": + err = unpopulate(val, "SystemData", &c.SystemData) + delete(rawMsg, key) + case "type": + err = unpopulate(val, "Type", &c.Type) + delete(rawMsg, key) + } + if err != nil { + return fmt.Errorf("unmarshalling type %T: %v", c, err) + } + } + return nil +} + +// MarshalJSON implements the json.Marshaller interface for type CertificateObjectGlobalRulestackResourceListResult. +func (c CertificateObjectGlobalRulestackResourceListResult) MarshalJSON() ([]byte, error) { + objectMap := make(map[string]any) + populate(objectMap, "nextLink", c.NextLink) + populate(objectMap, "value", c.Value) + return json.Marshal(objectMap) +} + +// UnmarshalJSON implements the json.Unmarshaller interface for type CertificateObjectGlobalRulestackResourceListResult. +func (c *CertificateObjectGlobalRulestackResourceListResult) UnmarshalJSON(data []byte) error { + var rawMsg map[string]json.RawMessage + if err := json.Unmarshal(data, &rawMsg); err != nil { + return fmt.Errorf("unmarshalling type %T: %v", c, err) + } + for key, val := range rawMsg { + var err error + switch key { + case "nextLink": + err = unpopulate(val, "NextLink", &c.NextLink) + delete(rawMsg, key) + case "value": + err = unpopulate(val, "Value", &c.Value) + delete(rawMsg, key) + } + if err != nil { + return fmt.Errorf("unmarshalling type %T: %v", c, err) + } + } + return nil +} + +// MarshalJSON implements the json.Marshaller interface for type CertificateObjectLocalRulestackResource. +func (c CertificateObjectLocalRulestackResource) MarshalJSON() ([]byte, error) { + objectMap := make(map[string]any) + populate(objectMap, "id", c.ID) + populate(objectMap, "name", c.Name) + populate(objectMap, "properties", c.Properties) + populate(objectMap, "systemData", c.SystemData) + populate(objectMap, "type", c.Type) + return json.Marshal(objectMap) +} + +// UnmarshalJSON implements the json.Unmarshaller interface for type CertificateObjectLocalRulestackResource. +func (c *CertificateObjectLocalRulestackResource) UnmarshalJSON(data []byte) error { + var rawMsg map[string]json.RawMessage + if err := json.Unmarshal(data, &rawMsg); err != nil { + return fmt.Errorf("unmarshalling type %T: %v", c, err) + } + for key, val := range rawMsg { + var err error + switch key { + case "id": + err = unpopulate(val, "ID", &c.ID) + delete(rawMsg, key) + case "name": + err = unpopulate(val, "Name", &c.Name) + delete(rawMsg, key) + case "properties": + err = unpopulate(val, "Properties", &c.Properties) + delete(rawMsg, key) + case "systemData": + err = unpopulate(val, "SystemData", &c.SystemData) + delete(rawMsg, key) + case "type": + err = unpopulate(val, "Type", &c.Type) + delete(rawMsg, key) + } + if err != nil { + return fmt.Errorf("unmarshalling type %T: %v", c, err) + } + } + return nil +} + +// MarshalJSON implements the json.Marshaller interface for type CertificateObjectLocalRulestackResourceListResult. +func (c CertificateObjectLocalRulestackResourceListResult) MarshalJSON() ([]byte, error) { + objectMap := make(map[string]any) + populate(objectMap, "nextLink", c.NextLink) + populate(objectMap, "value", c.Value) + return json.Marshal(objectMap) +} + +// UnmarshalJSON implements the json.Unmarshaller interface for type CertificateObjectLocalRulestackResourceListResult. +func (c *CertificateObjectLocalRulestackResourceListResult) UnmarshalJSON(data []byte) error { + var rawMsg map[string]json.RawMessage + if err := json.Unmarshal(data, &rawMsg); err != nil { + return fmt.Errorf("unmarshalling type %T: %v", c, err) + } + for key, val := range rawMsg { + var err error + switch key { + case "nextLink": + err = unpopulate(val, "NextLink", &c.NextLink) + delete(rawMsg, key) + case "value": + err = unpopulate(val, "Value", &c.Value) + delete(rawMsg, key) + } + if err != nil { + return fmt.Errorf("unmarshalling type %T: %v", c, err) + } + } + return nil +} + +// MarshalJSON implements the json.Marshaller interface for type Changelog. +func (c Changelog) MarshalJSON() ([]byte, error) { + objectMap := make(map[string]any) + populate(objectMap, "changes", c.Changes) + populateTimeRFC3339(objectMap, "lastCommitted", c.LastCommitted) + populateTimeRFC3339(objectMap, "lastModified", c.LastModified) + return json.Marshal(objectMap) +} + +// UnmarshalJSON implements the json.Unmarshaller interface for type Changelog. +func (c *Changelog) UnmarshalJSON(data []byte) error { + var rawMsg map[string]json.RawMessage + if err := json.Unmarshal(data, &rawMsg); err != nil { + return fmt.Errorf("unmarshalling type %T: %v", c, err) + } + for key, val := range rawMsg { + var err error + switch key { + case "changes": + err = unpopulate(val, "Changes", &c.Changes) + delete(rawMsg, key) + case "lastCommitted": + err = unpopulateTimeRFC3339(val, "LastCommitted", &c.LastCommitted) + delete(rawMsg, key) + case "lastModified": + err = unpopulateTimeRFC3339(val, "LastModified", &c.LastModified) + delete(rawMsg, key) + } + if err != nil { + return fmt.Errorf("unmarshalling type %T: %v", c, err) + } + } + return nil +} + +// MarshalJSON implements the json.Marshaller interface for type CountriesResponse. +func (c CountriesResponse) MarshalJSON() ([]byte, error) { + objectMap := make(map[string]any) + populate(objectMap, "nextLink", c.NextLink) + populate(objectMap, "value", c.Value) + return json.Marshal(objectMap) +} + +// UnmarshalJSON implements the json.Unmarshaller interface for type CountriesResponse. +func (c *CountriesResponse) UnmarshalJSON(data []byte) error { + var rawMsg map[string]json.RawMessage + if err := json.Unmarshal(data, &rawMsg); err != nil { + return fmt.Errorf("unmarshalling type %T: %v", c, err) + } + for key, val := range rawMsg { + var err error + switch key { + case "nextLink": + err = unpopulate(val, "NextLink", &c.NextLink) + delete(rawMsg, key) + case "value": + err = unpopulate(val, "Value", &c.Value) + delete(rawMsg, key) + } + if err != nil { + return fmt.Errorf("unmarshalling type %T: %v", c, err) + } + } + return nil +} + +// MarshalJSON implements the json.Marshaller interface for type Country. +func (c Country) MarshalJSON() ([]byte, error) { + objectMap := make(map[string]any) + populate(objectMap, "code", c.Code) + populate(objectMap, "description", c.Description) + return json.Marshal(objectMap) +} + +// UnmarshalJSON implements the json.Unmarshaller interface for type Country. +func (c *Country) UnmarshalJSON(data []byte) error { + var rawMsg map[string]json.RawMessage + if err := json.Unmarshal(data, &rawMsg); err != nil { + return fmt.Errorf("unmarshalling type %T: %v", c, err) + } + for key, val := range rawMsg { + var err error + switch key { + case "code": + err = unpopulate(val, "Code", &c.Code) + delete(rawMsg, key) + case "description": + err = unpopulate(val, "Description", &c.Description) + delete(rawMsg, key) + } + if err != nil { + return fmt.Errorf("unmarshalling type %T: %v", c, err) + } + } + return nil +} + +// MarshalJSON implements the json.Marshaller interface for type DNSSettings. +func (d DNSSettings) MarshalJSON() ([]byte, error) { + objectMap := make(map[string]any) + populate(objectMap, "dnsServers", d.DNSServers) + populate(objectMap, "enableDnsProxy", d.EnableDNSProxy) + populate(objectMap, "enabledDnsType", d.EnabledDNSType) + return json.Marshal(objectMap) +} + +// UnmarshalJSON implements the json.Unmarshaller interface for type DNSSettings. +func (d *DNSSettings) UnmarshalJSON(data []byte) error { + var rawMsg map[string]json.RawMessage + if err := json.Unmarshal(data, &rawMsg); err != nil { + return fmt.Errorf("unmarshalling type %T: %v", d, err) + } + for key, val := range rawMsg { + var err error + switch key { + case "dnsServers": + err = unpopulate(val, "DNSServers", &d.DNSServers) + delete(rawMsg, key) + case "enableDnsProxy": + err = unpopulate(val, "EnableDNSProxy", &d.EnableDNSProxy) + delete(rawMsg, key) + case "enabledDnsType": + err = unpopulate(val, "EnabledDNSType", &d.EnabledDNSType) + delete(rawMsg, key) + } + if err != nil { + return fmt.Errorf("unmarshalling type %T: %v", d, err) + } + } + return nil +} + +// MarshalJSON implements the json.Marshaller interface for type DestinationAddr. +func (d DestinationAddr) MarshalJSON() ([]byte, error) { + objectMap := make(map[string]any) + populate(objectMap, "cidrs", d.Cidrs) + populate(objectMap, "countries", d.Countries) + populate(objectMap, "feeds", d.Feeds) + populate(objectMap, "fqdnLists", d.FqdnLists) + populate(objectMap, "prefixLists", d.PrefixLists) + return json.Marshal(objectMap) +} + +// UnmarshalJSON implements the json.Unmarshaller interface for type DestinationAddr. +func (d *DestinationAddr) UnmarshalJSON(data []byte) error { + var rawMsg map[string]json.RawMessage + if err := json.Unmarshal(data, &rawMsg); err != nil { + return fmt.Errorf("unmarshalling type %T: %v", d, err) + } + for key, val := range rawMsg { + var err error + switch key { + case "cidrs": + err = unpopulate(val, "Cidrs", &d.Cidrs) + delete(rawMsg, key) + case "countries": + err = unpopulate(val, "Countries", &d.Countries) + delete(rawMsg, key) + case "feeds": + err = unpopulate(val, "Feeds", &d.Feeds) + delete(rawMsg, key) + case "fqdnLists": + err = unpopulate(val, "FqdnLists", &d.FqdnLists) + delete(rawMsg, key) + case "prefixLists": + err = unpopulate(val, "PrefixLists", &d.PrefixLists) + delete(rawMsg, key) + } + if err != nil { + return fmt.Errorf("unmarshalling type %T: %v", d, err) + } + } + return nil +} + +// MarshalJSON implements the json.Marshaller interface for type EndpointConfiguration. +func (e EndpointConfiguration) MarshalJSON() ([]byte, error) { + objectMap := make(map[string]any) + populate(objectMap, "address", e.Address) + populate(objectMap, "port", e.Port) + return json.Marshal(objectMap) +} + +// UnmarshalJSON implements the json.Unmarshaller interface for type EndpointConfiguration. +func (e *EndpointConfiguration) UnmarshalJSON(data []byte) error { + var rawMsg map[string]json.RawMessage + if err := json.Unmarshal(data, &rawMsg); err != nil { + return fmt.Errorf("unmarshalling type %T: %v", e, err) + } + for key, val := range rawMsg { + var err error + switch key { + case "address": + err = unpopulate(val, "Address", &e.Address) + delete(rawMsg, key) + case "port": + err = unpopulate(val, "Port", &e.Port) + delete(rawMsg, key) + } + if err != nil { + return fmt.Errorf("unmarshalling type %T: %v", e, err) + } + } + return nil +} + +// MarshalJSON implements the json.Marshaller interface for type EventHub. +func (e EventHub) MarshalJSON() ([]byte, error) { + objectMap := make(map[string]any) + populate(objectMap, "id", e.ID) + populate(objectMap, "name", e.Name) + populate(objectMap, "nameSpace", e.NameSpace) + populate(objectMap, "policyName", e.PolicyName) + populate(objectMap, "subscriptionId", e.SubscriptionID) + return json.Marshal(objectMap) +} + +// UnmarshalJSON implements the json.Unmarshaller interface for type EventHub. +func (e *EventHub) UnmarshalJSON(data []byte) error { + var rawMsg map[string]json.RawMessage + if err := json.Unmarshal(data, &rawMsg); err != nil { + return fmt.Errorf("unmarshalling type %T: %v", e, err) + } + for key, val := range rawMsg { + var err error + switch key { + case "id": + err = unpopulate(val, "ID", &e.ID) + delete(rawMsg, key) + case "name": + err = unpopulate(val, "Name", &e.Name) + delete(rawMsg, key) + case "nameSpace": + err = unpopulate(val, "NameSpace", &e.NameSpace) + delete(rawMsg, key) + case "policyName": + err = unpopulate(val, "PolicyName", &e.PolicyName) + delete(rawMsg, key) + case "subscriptionId": + err = unpopulate(val, "SubscriptionID", &e.SubscriptionID) + delete(rawMsg, key) + } + if err != nil { + return fmt.Errorf("unmarshalling type %T: %v", e, err) + } + } + return nil +} + +// MarshalJSON implements the json.Marshaller interface for type FirewallDeploymentProperties. +func (f FirewallDeploymentProperties) MarshalJSON() ([]byte, error) { + objectMap := make(map[string]any) + populate(objectMap, "associatedRulestack", f.AssociatedRulestack) + populate(objectMap, "dnsSettings", f.DNSSettings) + populate(objectMap, "frontEndSettings", f.FrontEndSettings) + populate(objectMap, "isPanoramaManaged", f.IsPanoramaManaged) + populate(objectMap, "marketplaceDetails", f.MarketplaceDetails) + populate(objectMap, "networkProfile", f.NetworkProfile) + populate(objectMap, "panEtag", f.PanEtag) + populate(objectMap, "panoramaConfig", f.PanoramaConfig) + populate(objectMap, "planData", f.PlanData) + populate(objectMap, "provisioningState", f.ProvisioningState) + return json.Marshal(objectMap) +} + +// UnmarshalJSON implements the json.Unmarshaller interface for type FirewallDeploymentProperties. +func (f *FirewallDeploymentProperties) UnmarshalJSON(data []byte) error { + var rawMsg map[string]json.RawMessage + if err := json.Unmarshal(data, &rawMsg); err != nil { + return fmt.Errorf("unmarshalling type %T: %v", f, err) + } + for key, val := range rawMsg { + var err error + switch key { + case "associatedRulestack": + err = unpopulate(val, "AssociatedRulestack", &f.AssociatedRulestack) + delete(rawMsg, key) + case "dnsSettings": + err = unpopulate(val, "DNSSettings", &f.DNSSettings) + delete(rawMsg, key) + case "frontEndSettings": + err = unpopulate(val, "FrontEndSettings", &f.FrontEndSettings) + delete(rawMsg, key) + case "isPanoramaManaged": + err = unpopulate(val, "IsPanoramaManaged", &f.IsPanoramaManaged) + delete(rawMsg, key) + case "marketplaceDetails": + err = unpopulate(val, "MarketplaceDetails", &f.MarketplaceDetails) + delete(rawMsg, key) + case "networkProfile": + err = unpopulate(val, "NetworkProfile", &f.NetworkProfile) + delete(rawMsg, key) + case "panEtag": + err = unpopulate(val, "PanEtag", &f.PanEtag) + delete(rawMsg, key) + case "panoramaConfig": + err = unpopulate(val, "PanoramaConfig", &f.PanoramaConfig) + delete(rawMsg, key) + case "planData": + err = unpopulate(val, "PlanData", &f.PlanData) + delete(rawMsg, key) + case "provisioningState": + err = unpopulate(val, "ProvisioningState", &f.ProvisioningState) + delete(rawMsg, key) + } + if err != nil { + return fmt.Errorf("unmarshalling type %T: %v", f, err) + } + } + return nil +} + +// MarshalJSON implements the json.Marshaller interface for type FirewallResource. +func (f FirewallResource) MarshalJSON() ([]byte, error) { + objectMap := make(map[string]any) + populate(objectMap, "id", f.ID) + populate(objectMap, "identity", f.Identity) + populate(objectMap, "location", f.Location) + populate(objectMap, "name", f.Name) + populate(objectMap, "properties", f.Properties) + populate(objectMap, "systemData", f.SystemData) + populate(objectMap, "tags", f.Tags) + populate(objectMap, "type", f.Type) + return json.Marshal(objectMap) +} + +// UnmarshalJSON implements the json.Unmarshaller interface for type FirewallResource. +func (f *FirewallResource) UnmarshalJSON(data []byte) error { + var rawMsg map[string]json.RawMessage + if err := json.Unmarshal(data, &rawMsg); err != nil { + return fmt.Errorf("unmarshalling type %T: %v", f, err) + } + for key, val := range rawMsg { + var err error + switch key { + case "id": + err = unpopulate(val, "ID", &f.ID) + delete(rawMsg, key) + case "identity": + err = unpopulate(val, "Identity", &f.Identity) + delete(rawMsg, key) + case "location": + err = unpopulate(val, "Location", &f.Location) + delete(rawMsg, key) + case "name": + err = unpopulate(val, "Name", &f.Name) + delete(rawMsg, key) + case "properties": + err = unpopulate(val, "Properties", &f.Properties) + delete(rawMsg, key) + case "systemData": + err = unpopulate(val, "SystemData", &f.SystemData) + delete(rawMsg, key) + case "tags": + err = unpopulate(val, "Tags", &f.Tags) + delete(rawMsg, key) + case "type": + err = unpopulate(val, "Type", &f.Type) + delete(rawMsg, key) + } + if err != nil { + return fmt.Errorf("unmarshalling type %T: %v", f, err) + } + } + return nil +} + +// MarshalJSON implements the json.Marshaller interface for type FirewallResourceListResult. +func (f FirewallResourceListResult) MarshalJSON() ([]byte, error) { + objectMap := make(map[string]any) + populate(objectMap, "nextLink", f.NextLink) + populate(objectMap, "value", f.Value) + return json.Marshal(objectMap) +} + +// UnmarshalJSON implements the json.Unmarshaller interface for type FirewallResourceListResult. +func (f *FirewallResourceListResult) UnmarshalJSON(data []byte) error { + var rawMsg map[string]json.RawMessage + if err := json.Unmarshal(data, &rawMsg); err != nil { + return fmt.Errorf("unmarshalling type %T: %v", f, err) + } + for key, val := range rawMsg { + var err error + switch key { + case "nextLink": + err = unpopulate(val, "NextLink", &f.NextLink) + delete(rawMsg, key) + case "value": + err = unpopulate(val, "Value", &f.Value) + delete(rawMsg, key) + } + if err != nil { + return fmt.Errorf("unmarshalling type %T: %v", f, err) + } + } + return nil +} + +// MarshalJSON implements the json.Marshaller interface for type FirewallResourceUpdate. +func (f FirewallResourceUpdate) MarshalJSON() ([]byte, error) { + objectMap := make(map[string]any) + populate(objectMap, "identity", f.Identity) + populate(objectMap, "properties", f.Properties) + populate(objectMap, "tags", f.Tags) + return json.Marshal(objectMap) +} + +// UnmarshalJSON implements the json.Unmarshaller interface for type FirewallResourceUpdate. +func (f *FirewallResourceUpdate) UnmarshalJSON(data []byte) error { + var rawMsg map[string]json.RawMessage + if err := json.Unmarshal(data, &rawMsg); err != nil { + return fmt.Errorf("unmarshalling type %T: %v", f, err) + } + for key, val := range rawMsg { + var err error + switch key { + case "identity": + err = unpopulate(val, "Identity", &f.Identity) + delete(rawMsg, key) + case "properties": + err = unpopulate(val, "Properties", &f.Properties) + delete(rawMsg, key) + case "tags": + err = unpopulate(val, "Tags", &f.Tags) + delete(rawMsg, key) + } + if err != nil { + return fmt.Errorf("unmarshalling type %T: %v", f, err) + } + } + return nil +} + +// MarshalJSON implements the json.Marshaller interface for type FirewallResourceUpdateProperties. +func (f FirewallResourceUpdateProperties) MarshalJSON() ([]byte, error) { + objectMap := make(map[string]any) + populate(objectMap, "associatedRulestack", f.AssociatedRulestack) + populate(objectMap, "dnsSettings", f.DNSSettings) + populate(objectMap, "frontEndSettings", f.FrontEndSettings) + populate(objectMap, "isPanoramaManaged", f.IsPanoramaManaged) + populate(objectMap, "marketplaceDetails", f.MarketplaceDetails) + populate(objectMap, "networkProfile", f.NetworkProfile) + populate(objectMap, "panEtag", f.PanEtag) + populate(objectMap, "panoramaConfig", f.PanoramaConfig) + populate(objectMap, "planData", f.PlanData) + return json.Marshal(objectMap) +} + +// UnmarshalJSON implements the json.Unmarshaller interface for type FirewallResourceUpdateProperties. +func (f *FirewallResourceUpdateProperties) UnmarshalJSON(data []byte) error { + var rawMsg map[string]json.RawMessage + if err := json.Unmarshal(data, &rawMsg); err != nil { + return fmt.Errorf("unmarshalling type %T: %v", f, err) + } + for key, val := range rawMsg { + var err error + switch key { + case "associatedRulestack": + err = unpopulate(val, "AssociatedRulestack", &f.AssociatedRulestack) + delete(rawMsg, key) + case "dnsSettings": + err = unpopulate(val, "DNSSettings", &f.DNSSettings) + delete(rawMsg, key) + case "frontEndSettings": + err = unpopulate(val, "FrontEndSettings", &f.FrontEndSettings) + delete(rawMsg, key) + case "isPanoramaManaged": + err = unpopulate(val, "IsPanoramaManaged", &f.IsPanoramaManaged) + delete(rawMsg, key) + case "marketplaceDetails": + err = unpopulate(val, "MarketplaceDetails", &f.MarketplaceDetails) + delete(rawMsg, key) + case "networkProfile": + err = unpopulate(val, "NetworkProfile", &f.NetworkProfile) + delete(rawMsg, key) + case "panEtag": + err = unpopulate(val, "PanEtag", &f.PanEtag) + delete(rawMsg, key) + case "panoramaConfig": + err = unpopulate(val, "PanoramaConfig", &f.PanoramaConfig) + delete(rawMsg, key) + case "planData": + err = unpopulate(val, "PlanData", &f.PlanData) + delete(rawMsg, key) + } + if err != nil { + return fmt.Errorf("unmarshalling type %T: %v", f, err) + } + } + return nil +} + +// MarshalJSON implements the json.Marshaller interface for type FirewallStatusProperty. +func (f FirewallStatusProperty) MarshalJSON() ([]byte, error) { + objectMap := make(map[string]any) + populate(objectMap, "healthReason", f.HealthReason) + populate(objectMap, "healthStatus", f.HealthStatus) + populate(objectMap, "isPanoramaManaged", f.IsPanoramaManaged) + populate(objectMap, "panoramaStatus", f.PanoramaStatus) + populate(objectMap, "provisioningState", f.ProvisioningState) + return json.Marshal(objectMap) +} + +// UnmarshalJSON implements the json.Unmarshaller interface for type FirewallStatusProperty. +func (f *FirewallStatusProperty) UnmarshalJSON(data []byte) error { + var rawMsg map[string]json.RawMessage + if err := json.Unmarshal(data, &rawMsg); err != nil { + return fmt.Errorf("unmarshalling type %T: %v", f, err) + } + for key, val := range rawMsg { + var err error + switch key { + case "healthReason": + err = unpopulate(val, "HealthReason", &f.HealthReason) + delete(rawMsg, key) + case "healthStatus": + err = unpopulate(val, "HealthStatus", &f.HealthStatus) + delete(rawMsg, key) + case "isPanoramaManaged": + err = unpopulate(val, "IsPanoramaManaged", &f.IsPanoramaManaged) + delete(rawMsg, key) + case "panoramaStatus": + err = unpopulate(val, "PanoramaStatus", &f.PanoramaStatus) + delete(rawMsg, key) + case "provisioningState": + err = unpopulate(val, "ProvisioningState", &f.ProvisioningState) + delete(rawMsg, key) + } + if err != nil { + return fmt.Errorf("unmarshalling type %T: %v", f, err) + } + } + return nil +} + +// MarshalJSON implements the json.Marshaller interface for type FirewallStatusResource. +func (f FirewallStatusResource) MarshalJSON() ([]byte, error) { + objectMap := make(map[string]any) + populate(objectMap, "id", f.ID) + populate(objectMap, "name", f.Name) + populate(objectMap, "properties", f.Properties) + populate(objectMap, "systemData", f.SystemData) + populate(objectMap, "type", f.Type) + return json.Marshal(objectMap) +} + +// UnmarshalJSON implements the json.Unmarshaller interface for type FirewallStatusResource. +func (f *FirewallStatusResource) UnmarshalJSON(data []byte) error { + var rawMsg map[string]json.RawMessage + if err := json.Unmarshal(data, &rawMsg); err != nil { + return fmt.Errorf("unmarshalling type %T: %v", f, err) + } + for key, val := range rawMsg { + var err error + switch key { + case "id": + err = unpopulate(val, "ID", &f.ID) + delete(rawMsg, key) + case "name": + err = unpopulate(val, "Name", &f.Name) + delete(rawMsg, key) + case "properties": + err = unpopulate(val, "Properties", &f.Properties) + delete(rawMsg, key) + case "systemData": + err = unpopulate(val, "SystemData", &f.SystemData) + delete(rawMsg, key) + case "type": + err = unpopulate(val, "Type", &f.Type) + delete(rawMsg, key) + } + if err != nil { + return fmt.Errorf("unmarshalling type %T: %v", f, err) + } + } + return nil +} + +// MarshalJSON implements the json.Marshaller interface for type FirewallStatusResourceListResult. +func (f FirewallStatusResourceListResult) MarshalJSON() ([]byte, error) { + objectMap := make(map[string]any) + populate(objectMap, "nextLink", f.NextLink) + populate(objectMap, "value", f.Value) + return json.Marshal(objectMap) +} + +// UnmarshalJSON implements the json.Unmarshaller interface for type FirewallStatusResourceListResult. +func (f *FirewallStatusResourceListResult) UnmarshalJSON(data []byte) error { + var rawMsg map[string]json.RawMessage + if err := json.Unmarshal(data, &rawMsg); err != nil { + return fmt.Errorf("unmarshalling type %T: %v", f, err) + } + for key, val := range rawMsg { + var err error + switch key { + case "nextLink": + err = unpopulate(val, "NextLink", &f.NextLink) + delete(rawMsg, key) + case "value": + err = unpopulate(val, "Value", &f.Value) + delete(rawMsg, key) + } + if err != nil { + return fmt.Errorf("unmarshalling type %T: %v", f, err) + } + } + return nil +} + +// MarshalJSON implements the json.Marshaller interface for type FqdnListGlobalRulestackResource. +func (f FqdnListGlobalRulestackResource) MarshalJSON() ([]byte, error) { + objectMap := make(map[string]any) + populate(objectMap, "id", f.ID) + populate(objectMap, "name", f.Name) + populate(objectMap, "properties", f.Properties) + populate(objectMap, "systemData", f.SystemData) + populate(objectMap, "type", f.Type) + return json.Marshal(objectMap) +} + +// UnmarshalJSON implements the json.Unmarshaller interface for type FqdnListGlobalRulestackResource. +func (f *FqdnListGlobalRulestackResource) UnmarshalJSON(data []byte) error { + var rawMsg map[string]json.RawMessage + if err := json.Unmarshal(data, &rawMsg); err != nil { + return fmt.Errorf("unmarshalling type %T: %v", f, err) + } + for key, val := range rawMsg { + var err error + switch key { + case "id": + err = unpopulate(val, "ID", &f.ID) + delete(rawMsg, key) + case "name": + err = unpopulate(val, "Name", &f.Name) + delete(rawMsg, key) + case "properties": + err = unpopulate(val, "Properties", &f.Properties) + delete(rawMsg, key) + case "systemData": + err = unpopulate(val, "SystemData", &f.SystemData) + delete(rawMsg, key) + case "type": + err = unpopulate(val, "Type", &f.Type) + delete(rawMsg, key) + } + if err != nil { + return fmt.Errorf("unmarshalling type %T: %v", f, err) + } + } + return nil +} + +// MarshalJSON implements the json.Marshaller interface for type FqdnListGlobalRulestackResourceListResult. +func (f FqdnListGlobalRulestackResourceListResult) MarshalJSON() ([]byte, error) { + objectMap := make(map[string]any) + populate(objectMap, "nextLink", f.NextLink) + populate(objectMap, "value", f.Value) + return json.Marshal(objectMap) +} + +// UnmarshalJSON implements the json.Unmarshaller interface for type FqdnListGlobalRulestackResourceListResult. +func (f *FqdnListGlobalRulestackResourceListResult) UnmarshalJSON(data []byte) error { + var rawMsg map[string]json.RawMessage + if err := json.Unmarshal(data, &rawMsg); err != nil { + return fmt.Errorf("unmarshalling type %T: %v", f, err) + } + for key, val := range rawMsg { + var err error + switch key { + case "nextLink": + err = unpopulate(val, "NextLink", &f.NextLink) + delete(rawMsg, key) + case "value": + err = unpopulate(val, "Value", &f.Value) + delete(rawMsg, key) + } + if err != nil { + return fmt.Errorf("unmarshalling type %T: %v", f, err) + } + } + return nil +} + +// MarshalJSON implements the json.Marshaller interface for type FqdnListLocalRulestackResource. +func (f FqdnListLocalRulestackResource) MarshalJSON() ([]byte, error) { + objectMap := make(map[string]any) + populate(objectMap, "id", f.ID) + populate(objectMap, "name", f.Name) + populate(objectMap, "properties", f.Properties) + populate(objectMap, "systemData", f.SystemData) + populate(objectMap, "type", f.Type) + return json.Marshal(objectMap) +} + +// UnmarshalJSON implements the json.Unmarshaller interface for type FqdnListLocalRulestackResource. +func (f *FqdnListLocalRulestackResource) UnmarshalJSON(data []byte) error { + var rawMsg map[string]json.RawMessage + if err := json.Unmarshal(data, &rawMsg); err != nil { + return fmt.Errorf("unmarshalling type %T: %v", f, err) + } + for key, val := range rawMsg { + var err error + switch key { + case "id": + err = unpopulate(val, "ID", &f.ID) + delete(rawMsg, key) + case "name": + err = unpopulate(val, "Name", &f.Name) + delete(rawMsg, key) + case "properties": + err = unpopulate(val, "Properties", &f.Properties) + delete(rawMsg, key) + case "systemData": + err = unpopulate(val, "SystemData", &f.SystemData) + delete(rawMsg, key) + case "type": + err = unpopulate(val, "Type", &f.Type) + delete(rawMsg, key) + } + if err != nil { + return fmt.Errorf("unmarshalling type %T: %v", f, err) + } + } + return nil +} + +// MarshalJSON implements the json.Marshaller interface for type FqdnListLocalRulestackResourceListResult. +func (f FqdnListLocalRulestackResourceListResult) MarshalJSON() ([]byte, error) { + objectMap := make(map[string]any) + populate(objectMap, "nextLink", f.NextLink) + populate(objectMap, "value", f.Value) + return json.Marshal(objectMap) +} + +// UnmarshalJSON implements the json.Unmarshaller interface for type FqdnListLocalRulestackResourceListResult. +func (f *FqdnListLocalRulestackResourceListResult) UnmarshalJSON(data []byte) error { + var rawMsg map[string]json.RawMessage + if err := json.Unmarshal(data, &rawMsg); err != nil { + return fmt.Errorf("unmarshalling type %T: %v", f, err) + } + for key, val := range rawMsg { + var err error + switch key { + case "nextLink": + err = unpopulate(val, "NextLink", &f.NextLink) + delete(rawMsg, key) + case "value": + err = unpopulate(val, "Value", &f.Value) + delete(rawMsg, key) + } + if err != nil { + return fmt.Errorf("unmarshalling type %T: %v", f, err) + } + } + return nil +} + +// MarshalJSON implements the json.Marshaller interface for type FqdnObject. +func (f FqdnObject) MarshalJSON() ([]byte, error) { + objectMap := make(map[string]any) + populate(objectMap, "auditComment", f.AuditComment) + populate(objectMap, "description", f.Description) + populate(objectMap, "etag", f.Etag) + populate(objectMap, "fqdnList", f.FqdnList) + populate(objectMap, "provisioningState", f.ProvisioningState) + return json.Marshal(objectMap) +} + +// UnmarshalJSON implements the json.Unmarshaller interface for type FqdnObject. +func (f *FqdnObject) UnmarshalJSON(data []byte) error { + var rawMsg map[string]json.RawMessage + if err := json.Unmarshal(data, &rawMsg); err != nil { + return fmt.Errorf("unmarshalling type %T: %v", f, err) + } + for key, val := range rawMsg { + var err error + switch key { + case "auditComment": + err = unpopulate(val, "AuditComment", &f.AuditComment) + delete(rawMsg, key) + case "description": + err = unpopulate(val, "Description", &f.Description) + delete(rawMsg, key) + case "etag": + err = unpopulate(val, "Etag", &f.Etag) + delete(rawMsg, key) + case "fqdnList": + err = unpopulate(val, "FqdnList", &f.FqdnList) + delete(rawMsg, key) + case "provisioningState": + err = unpopulate(val, "ProvisioningState", &f.ProvisioningState) + delete(rawMsg, key) + } + if err != nil { + return fmt.Errorf("unmarshalling type %T: %v", f, err) + } + } + return nil +} + +// MarshalJSON implements the json.Marshaller interface for type FrontendSetting. +func (f FrontendSetting) MarshalJSON() ([]byte, error) { + objectMap := make(map[string]any) + populate(objectMap, "backendConfiguration", f.BackendConfiguration) + populate(objectMap, "frontendConfiguration", f.FrontendConfiguration) + populate(objectMap, "name", f.Name) + populate(objectMap, "protocol", f.Protocol) + return json.Marshal(objectMap) +} + +// UnmarshalJSON implements the json.Unmarshaller interface for type FrontendSetting. +func (f *FrontendSetting) UnmarshalJSON(data []byte) error { + var rawMsg map[string]json.RawMessage + if err := json.Unmarshal(data, &rawMsg); err != nil { + return fmt.Errorf("unmarshalling type %T: %v", f, err) + } + for key, val := range rawMsg { + var err error + switch key { + case "backendConfiguration": + err = unpopulate(val, "BackendConfiguration", &f.BackendConfiguration) + delete(rawMsg, key) + case "frontendConfiguration": + err = unpopulate(val, "FrontendConfiguration", &f.FrontendConfiguration) + delete(rawMsg, key) + case "name": + err = unpopulate(val, "Name", &f.Name) + delete(rawMsg, key) + case "protocol": + err = unpopulate(val, "Protocol", &f.Protocol) + delete(rawMsg, key) + } + if err != nil { + return fmt.Errorf("unmarshalling type %T: %v", f, err) + } + } + return nil +} + +// MarshalJSON implements the json.Marshaller interface for type GlobalRulestackInfo. +func (g GlobalRulestackInfo) MarshalJSON() ([]byte, error) { + objectMap := make(map[string]any) + populate(objectMap, "azureId", g.AzureID) + return json.Marshal(objectMap) +} + +// UnmarshalJSON implements the json.Unmarshaller interface for type GlobalRulestackInfo. +func (g *GlobalRulestackInfo) UnmarshalJSON(data []byte) error { + var rawMsg map[string]json.RawMessage + if err := json.Unmarshal(data, &rawMsg); err != nil { + return fmt.Errorf("unmarshalling type %T: %v", g, err) + } + for key, val := range rawMsg { + var err error + switch key { + case "azureId": + err = unpopulate(val, "AzureID", &g.AzureID) + delete(rawMsg, key) + } + if err != nil { + return fmt.Errorf("unmarshalling type %T: %v", g, err) + } + } + return nil +} + +// MarshalJSON implements the json.Marshaller interface for type GlobalRulestackResource. +func (g GlobalRulestackResource) MarshalJSON() ([]byte, error) { + objectMap := make(map[string]any) + populate(objectMap, "id", g.ID) + populate(objectMap, "identity", g.Identity) + populate(objectMap, "location", g.Location) + populate(objectMap, "name", g.Name) + populate(objectMap, "properties", g.Properties) + populate(objectMap, "systemData", g.SystemData) + populate(objectMap, "type", g.Type) + return json.Marshal(objectMap) +} + +// UnmarshalJSON implements the json.Unmarshaller interface for type GlobalRulestackResource. +func (g *GlobalRulestackResource) UnmarshalJSON(data []byte) error { + var rawMsg map[string]json.RawMessage + if err := json.Unmarshal(data, &rawMsg); err != nil { + return fmt.Errorf("unmarshalling type %T: %v", g, err) + } + for key, val := range rawMsg { + var err error + switch key { + case "id": + err = unpopulate(val, "ID", &g.ID) + delete(rawMsg, key) + case "identity": + err = unpopulate(val, "Identity", &g.Identity) + delete(rawMsg, key) + case "location": + err = unpopulate(val, "Location", &g.Location) + delete(rawMsg, key) + case "name": + err = unpopulate(val, "Name", &g.Name) + delete(rawMsg, key) + case "properties": + err = unpopulate(val, "Properties", &g.Properties) + delete(rawMsg, key) + case "systemData": + err = unpopulate(val, "SystemData", &g.SystemData) + delete(rawMsg, key) + case "type": + err = unpopulate(val, "Type", &g.Type) + delete(rawMsg, key) + } + if err != nil { + return fmt.Errorf("unmarshalling type %T: %v", g, err) + } + } + return nil +} + +// MarshalJSON implements the json.Marshaller interface for type GlobalRulestackResourceListResult. +func (g GlobalRulestackResourceListResult) MarshalJSON() ([]byte, error) { + objectMap := make(map[string]any) + populate(objectMap, "nextLink", g.NextLink) + populate(objectMap, "value", g.Value) + return json.Marshal(objectMap) +} + +// UnmarshalJSON implements the json.Unmarshaller interface for type GlobalRulestackResourceListResult. +func (g *GlobalRulestackResourceListResult) UnmarshalJSON(data []byte) error { + var rawMsg map[string]json.RawMessage + if err := json.Unmarshal(data, &rawMsg); err != nil { + return fmt.Errorf("unmarshalling type %T: %v", g, err) + } + for key, val := range rawMsg { + var err error + switch key { + case "nextLink": + err = unpopulate(val, "NextLink", &g.NextLink) + delete(rawMsg, key) + case "value": + err = unpopulate(val, "Value", &g.Value) + delete(rawMsg, key) + } + if err != nil { + return fmt.Errorf("unmarshalling type %T: %v", g, err) + } + } + return nil +} + +// MarshalJSON implements the json.Marshaller interface for type GlobalRulestackResourceUpdate. +func (g GlobalRulestackResourceUpdate) MarshalJSON() ([]byte, error) { + objectMap := make(map[string]any) + populate(objectMap, "identity", g.Identity) + populate(objectMap, "location", g.Location) + populate(objectMap, "properties", g.Properties) + return json.Marshal(objectMap) +} + +// UnmarshalJSON implements the json.Unmarshaller interface for type GlobalRulestackResourceUpdate. +func (g *GlobalRulestackResourceUpdate) UnmarshalJSON(data []byte) error { + var rawMsg map[string]json.RawMessage + if err := json.Unmarshal(data, &rawMsg); err != nil { + return fmt.Errorf("unmarshalling type %T: %v", g, err) + } + for key, val := range rawMsg { + var err error + switch key { + case "identity": + err = unpopulate(val, "Identity", &g.Identity) + delete(rawMsg, key) + case "location": + err = unpopulate(val, "Location", &g.Location) + delete(rawMsg, key) + case "properties": + err = unpopulate(val, "Properties", &g.Properties) + delete(rawMsg, key) + } + if err != nil { + return fmt.Errorf("unmarshalling type %T: %v", g, err) + } + } + return nil +} + +// MarshalJSON implements the json.Marshaller interface for type GlobalRulestackResourceUpdateProperties. +func (g GlobalRulestackResourceUpdateProperties) MarshalJSON() ([]byte, error) { + objectMap := make(map[string]any) + populate(objectMap, "associatedSubscriptions", g.AssociatedSubscriptions) + populate(objectMap, "defaultMode", g.DefaultMode) + populate(objectMap, "description", g.Description) + populate(objectMap, "minAppIdVersion", g.MinAppIDVersion) + populate(objectMap, "panEtag", g.PanEtag) + populate(objectMap, "panLocation", g.PanLocation) + populate(objectMap, "scope", g.Scope) + populate(objectMap, "securityServices", g.SecurityServices) + return json.Marshal(objectMap) +} + +// UnmarshalJSON implements the json.Unmarshaller interface for type GlobalRulestackResourceUpdateProperties. +func (g *GlobalRulestackResourceUpdateProperties) UnmarshalJSON(data []byte) error { + var rawMsg map[string]json.RawMessage + if err := json.Unmarshal(data, &rawMsg); err != nil { + return fmt.Errorf("unmarshalling type %T: %v", g, err) + } + for key, val := range rawMsg { + var err error + switch key { + case "associatedSubscriptions": + err = unpopulate(val, "AssociatedSubscriptions", &g.AssociatedSubscriptions) + delete(rawMsg, key) + case "defaultMode": + err = unpopulate(val, "DefaultMode", &g.DefaultMode) + delete(rawMsg, key) + case "description": + err = unpopulate(val, "Description", &g.Description) + delete(rawMsg, key) + case "minAppIdVersion": + err = unpopulate(val, "MinAppIDVersion", &g.MinAppIDVersion) + delete(rawMsg, key) + case "panEtag": + err = unpopulate(val, "PanEtag", &g.PanEtag) + delete(rawMsg, key) + case "panLocation": + err = unpopulate(val, "PanLocation", &g.PanLocation) + delete(rawMsg, key) + case "scope": + err = unpopulate(val, "Scope", &g.Scope) + delete(rawMsg, key) + case "securityServices": + err = unpopulate(val, "SecurityServices", &g.SecurityServices) + delete(rawMsg, key) + } + if err != nil { + return fmt.Errorf("unmarshalling type %T: %v", g, err) + } + } + return nil +} + +// MarshalJSON implements the json.Marshaller interface for type IPAddress. +func (i IPAddress) MarshalJSON() ([]byte, error) { + objectMap := make(map[string]any) + populate(objectMap, "address", i.Address) + populate(objectMap, "resourceId", i.ResourceID) + return json.Marshal(objectMap) +} + +// UnmarshalJSON implements the json.Unmarshaller interface for type IPAddress. +func (i *IPAddress) UnmarshalJSON(data []byte) error { + var rawMsg map[string]json.RawMessage + if err := json.Unmarshal(data, &rawMsg); err != nil { + return fmt.Errorf("unmarshalling type %T: %v", i, err) + } + for key, val := range rawMsg { + var err error + switch key { + case "address": + err = unpopulate(val, "Address", &i.Address) + delete(rawMsg, key) + case "resourceId": + err = unpopulate(val, "ResourceID", &i.ResourceID) + delete(rawMsg, key) + } + if err != nil { + return fmt.Errorf("unmarshalling type %T: %v", i, err) + } + } + return nil +} + +// MarshalJSON implements the json.Marshaller interface for type IPAddressSpace. +func (i IPAddressSpace) MarshalJSON() ([]byte, error) { + objectMap := make(map[string]any) + populate(objectMap, "addressSpace", i.AddressSpace) + populate(objectMap, "resourceId", i.ResourceID) + return json.Marshal(objectMap) +} + +// UnmarshalJSON implements the json.Unmarshaller interface for type IPAddressSpace. +func (i *IPAddressSpace) UnmarshalJSON(data []byte) error { + var rawMsg map[string]json.RawMessage + if err := json.Unmarshal(data, &rawMsg); err != nil { + return fmt.Errorf("unmarshalling type %T: %v", i, err) + } + for key, val := range rawMsg { + var err error + switch key { + case "addressSpace": + err = unpopulate(val, "AddressSpace", &i.AddressSpace) + delete(rawMsg, key) + case "resourceId": + err = unpopulate(val, "ResourceID", &i.ResourceID) + delete(rawMsg, key) + } + if err != nil { + return fmt.Errorf("unmarshalling type %T: %v", i, err) + } + } + return nil +} + +// MarshalJSON implements the json.Marshaller interface for type ListAppIDResponse. +func (l ListAppIDResponse) MarshalJSON() ([]byte, error) { + objectMap := make(map[string]any) + populate(objectMap, "nextLink", l.NextLink) + populate(objectMap, "value", l.Value) + return json.Marshal(objectMap) +} + +// UnmarshalJSON implements the json.Unmarshaller interface for type ListAppIDResponse. +func (l *ListAppIDResponse) UnmarshalJSON(data []byte) error { + var rawMsg map[string]json.RawMessage + if err := json.Unmarshal(data, &rawMsg); err != nil { + return fmt.Errorf("unmarshalling type %T: %v", l, err) + } + for key, val := range rawMsg { + var err error + switch key { + case "nextLink": + err = unpopulate(val, "NextLink", &l.NextLink) + delete(rawMsg, key) + case "value": + err = unpopulate(val, "Value", &l.Value) + delete(rawMsg, key) + } + if err != nil { + return fmt.Errorf("unmarshalling type %T: %v", l, err) + } + } + return nil +} + +// MarshalJSON implements the json.Marshaller interface for type ListFirewallsResponse. +func (l ListFirewallsResponse) MarshalJSON() ([]byte, error) { + objectMap := make(map[string]any) + populate(objectMap, "nextLink", l.NextLink) + populate(objectMap, "value", l.Value) + return json.Marshal(objectMap) +} + +// UnmarshalJSON implements the json.Unmarshaller interface for type ListFirewallsResponse. +func (l *ListFirewallsResponse) UnmarshalJSON(data []byte) error { + var rawMsg map[string]json.RawMessage + if err := json.Unmarshal(data, &rawMsg); err != nil { + return fmt.Errorf("unmarshalling type %T: %v", l, err) + } + for key, val := range rawMsg { + var err error + switch key { + case "nextLink": + err = unpopulate(val, "NextLink", &l.NextLink) + delete(rawMsg, key) + case "value": + err = unpopulate(val, "Value", &l.Value) + delete(rawMsg, key) + } + if err != nil { + return fmt.Errorf("unmarshalling type %T: %v", l, err) + } + } + return nil +} + +// MarshalJSON implements the json.Marshaller interface for type LocalRulesResource. +func (l LocalRulesResource) MarshalJSON() ([]byte, error) { + objectMap := make(map[string]any) + populate(objectMap, "id", l.ID) + populate(objectMap, "name", l.Name) + populate(objectMap, "properties", l.Properties) + populate(objectMap, "systemData", l.SystemData) + populate(objectMap, "type", l.Type) + return json.Marshal(objectMap) +} + +// UnmarshalJSON implements the json.Unmarshaller interface for type LocalRulesResource. +func (l *LocalRulesResource) UnmarshalJSON(data []byte) error { + var rawMsg map[string]json.RawMessage + if err := json.Unmarshal(data, &rawMsg); err != nil { + return fmt.Errorf("unmarshalling type %T: %v", l, err) + } + for key, val := range rawMsg { + var err error + switch key { + case "id": + err = unpopulate(val, "ID", &l.ID) + delete(rawMsg, key) + case "name": + err = unpopulate(val, "Name", &l.Name) + delete(rawMsg, key) + case "properties": + err = unpopulate(val, "Properties", &l.Properties) + delete(rawMsg, key) + case "systemData": + err = unpopulate(val, "SystemData", &l.SystemData) + delete(rawMsg, key) + case "type": + err = unpopulate(val, "Type", &l.Type) + delete(rawMsg, key) + } + if err != nil { + return fmt.Errorf("unmarshalling type %T: %v", l, err) + } + } + return nil +} + +// MarshalJSON implements the json.Marshaller interface for type LocalRulesResourceListResult. +func (l LocalRulesResourceListResult) MarshalJSON() ([]byte, error) { + objectMap := make(map[string]any) + populate(objectMap, "nextLink", l.NextLink) + populate(objectMap, "value", l.Value) + return json.Marshal(objectMap) +} + +// UnmarshalJSON implements the json.Unmarshaller interface for type LocalRulesResourceListResult. +func (l *LocalRulesResourceListResult) UnmarshalJSON(data []byte) error { + var rawMsg map[string]json.RawMessage + if err := json.Unmarshal(data, &rawMsg); err != nil { + return fmt.Errorf("unmarshalling type %T: %v", l, err) + } + for key, val := range rawMsg { + var err error + switch key { + case "nextLink": + err = unpopulate(val, "NextLink", &l.NextLink) + delete(rawMsg, key) + case "value": + err = unpopulate(val, "Value", &l.Value) + delete(rawMsg, key) + } + if err != nil { + return fmt.Errorf("unmarshalling type %T: %v", l, err) + } + } + return nil +} + +// MarshalJSON implements the json.Marshaller interface for type LocalRulestackResource. +func (l LocalRulestackResource) MarshalJSON() ([]byte, error) { + objectMap := make(map[string]any) + populate(objectMap, "id", l.ID) + populate(objectMap, "identity", l.Identity) + populate(objectMap, "location", l.Location) + populate(objectMap, "name", l.Name) + populate(objectMap, "properties", l.Properties) + populate(objectMap, "systemData", l.SystemData) + populate(objectMap, "tags", l.Tags) + populate(objectMap, "type", l.Type) + return json.Marshal(objectMap) +} + +// UnmarshalJSON implements the json.Unmarshaller interface for type LocalRulestackResource. +func (l *LocalRulestackResource) UnmarshalJSON(data []byte) error { + var rawMsg map[string]json.RawMessage + if err := json.Unmarshal(data, &rawMsg); err != nil { + return fmt.Errorf("unmarshalling type %T: %v", l, err) + } + for key, val := range rawMsg { + var err error + switch key { + case "id": + err = unpopulate(val, "ID", &l.ID) + delete(rawMsg, key) + case "identity": + err = unpopulate(val, "Identity", &l.Identity) + delete(rawMsg, key) + case "location": + err = unpopulate(val, "Location", &l.Location) + delete(rawMsg, key) + case "name": + err = unpopulate(val, "Name", &l.Name) + delete(rawMsg, key) + case "properties": + err = unpopulate(val, "Properties", &l.Properties) + delete(rawMsg, key) + case "systemData": + err = unpopulate(val, "SystemData", &l.SystemData) + delete(rawMsg, key) + case "tags": + err = unpopulate(val, "Tags", &l.Tags) + delete(rawMsg, key) + case "type": + err = unpopulate(val, "Type", &l.Type) + delete(rawMsg, key) + } + if err != nil { + return fmt.Errorf("unmarshalling type %T: %v", l, err) + } + } + return nil +} + +// MarshalJSON implements the json.Marshaller interface for type LocalRulestackResourceListResult. +func (l LocalRulestackResourceListResult) MarshalJSON() ([]byte, error) { + objectMap := make(map[string]any) + populate(objectMap, "nextLink", l.NextLink) + populate(objectMap, "value", l.Value) + return json.Marshal(objectMap) +} + +// UnmarshalJSON implements the json.Unmarshaller interface for type LocalRulestackResourceListResult. +func (l *LocalRulestackResourceListResult) UnmarshalJSON(data []byte) error { + var rawMsg map[string]json.RawMessage + if err := json.Unmarshal(data, &rawMsg); err != nil { + return fmt.Errorf("unmarshalling type %T: %v", l, err) + } + for key, val := range rawMsg { + var err error + switch key { + case "nextLink": + err = unpopulate(val, "NextLink", &l.NextLink) + delete(rawMsg, key) + case "value": + err = unpopulate(val, "Value", &l.Value) + delete(rawMsg, key) + } + if err != nil { + return fmt.Errorf("unmarshalling type %T: %v", l, err) + } + } + return nil +} + +// MarshalJSON implements the json.Marshaller interface for type LocalRulestackResourceUpdate. +func (l LocalRulestackResourceUpdate) MarshalJSON() ([]byte, error) { + objectMap := make(map[string]any) + populate(objectMap, "identity", l.Identity) + populate(objectMap, "properties", l.Properties) + populate(objectMap, "tags", l.Tags) + return json.Marshal(objectMap) +} + +// UnmarshalJSON implements the json.Unmarshaller interface for type LocalRulestackResourceUpdate. +func (l *LocalRulestackResourceUpdate) UnmarshalJSON(data []byte) error { + var rawMsg map[string]json.RawMessage + if err := json.Unmarshal(data, &rawMsg); err != nil { + return fmt.Errorf("unmarshalling type %T: %v", l, err) + } + for key, val := range rawMsg { + var err error + switch key { + case "identity": + err = unpopulate(val, "Identity", &l.Identity) + delete(rawMsg, key) + case "properties": + err = unpopulate(val, "Properties", &l.Properties) + delete(rawMsg, key) + case "tags": + err = unpopulate(val, "Tags", &l.Tags) + delete(rawMsg, key) + } + if err != nil { + return fmt.Errorf("unmarshalling type %T: %v", l, err) + } + } + return nil +} + +// MarshalJSON implements the json.Marshaller interface for type LocalRulestackResourceUpdateProperties. +func (l LocalRulestackResourceUpdateProperties) MarshalJSON() ([]byte, error) { + objectMap := make(map[string]any) + populate(objectMap, "associatedSubscriptions", l.AssociatedSubscriptions) + populate(objectMap, "defaultMode", l.DefaultMode) + populate(objectMap, "description", l.Description) + populate(objectMap, "minAppIdVersion", l.MinAppIDVersion) + populate(objectMap, "panEtag", l.PanEtag) + populate(objectMap, "panLocation", l.PanLocation) + populate(objectMap, "scope", l.Scope) + populate(objectMap, "securityServices", l.SecurityServices) + return json.Marshal(objectMap) +} + +// UnmarshalJSON implements the json.Unmarshaller interface for type LocalRulestackResourceUpdateProperties. +func (l *LocalRulestackResourceUpdateProperties) UnmarshalJSON(data []byte) error { + var rawMsg map[string]json.RawMessage + if err := json.Unmarshal(data, &rawMsg); err != nil { + return fmt.Errorf("unmarshalling type %T: %v", l, err) + } + for key, val := range rawMsg { + var err error + switch key { + case "associatedSubscriptions": + err = unpopulate(val, "AssociatedSubscriptions", &l.AssociatedSubscriptions) + delete(rawMsg, key) + case "defaultMode": + err = unpopulate(val, "DefaultMode", &l.DefaultMode) + delete(rawMsg, key) + case "description": + err = unpopulate(val, "Description", &l.Description) + delete(rawMsg, key) + case "minAppIdVersion": + err = unpopulate(val, "MinAppIDVersion", &l.MinAppIDVersion) + delete(rawMsg, key) + case "panEtag": + err = unpopulate(val, "PanEtag", &l.PanEtag) + delete(rawMsg, key) + case "panLocation": + err = unpopulate(val, "PanLocation", &l.PanLocation) + delete(rawMsg, key) + case "scope": + err = unpopulate(val, "Scope", &l.Scope) + delete(rawMsg, key) + case "securityServices": + err = unpopulate(val, "SecurityServices", &l.SecurityServices) + delete(rawMsg, key) + } + if err != nil { + return fmt.Errorf("unmarshalling type %T: %v", l, err) + } + } + return nil +} + +// MarshalJSON implements the json.Marshaller interface for type LogDestination. +func (l LogDestination) MarshalJSON() ([]byte, error) { + objectMap := make(map[string]any) + populate(objectMap, "eventHubConfigurations", l.EventHubConfigurations) + populate(objectMap, "monitorConfigurations", l.MonitorConfigurations) + populate(objectMap, "storageConfigurations", l.StorageConfigurations) + return json.Marshal(objectMap) +} + +// UnmarshalJSON implements the json.Unmarshaller interface for type LogDestination. +func (l *LogDestination) UnmarshalJSON(data []byte) error { + var rawMsg map[string]json.RawMessage + if err := json.Unmarshal(data, &rawMsg); err != nil { + return fmt.Errorf("unmarshalling type %T: %v", l, err) + } + for key, val := range rawMsg { + var err error + switch key { + case "eventHubConfigurations": + err = unpopulate(val, "EventHubConfigurations", &l.EventHubConfigurations) + delete(rawMsg, key) + case "monitorConfigurations": + err = unpopulate(val, "MonitorConfigurations", &l.MonitorConfigurations) + delete(rawMsg, key) + case "storageConfigurations": + err = unpopulate(val, "StorageConfigurations", &l.StorageConfigurations) + delete(rawMsg, key) + } + if err != nil { + return fmt.Errorf("unmarshalling type %T: %v", l, err) + } + } + return nil +} + +// MarshalJSON implements the json.Marshaller interface for type LogSettings. +func (l LogSettings) MarshalJSON() ([]byte, error) { + objectMap := make(map[string]any) + populate(objectMap, "applicationInsights", l.ApplicationInsights) + populate(objectMap, "commonDestination", l.CommonDestination) + populate(objectMap, "decryptLogDestination", l.DecryptLogDestination) + populate(objectMap, "logOption", l.LogOption) + populate(objectMap, "logType", l.LogType) + populate(objectMap, "threatLogDestination", l.ThreatLogDestination) + populate(objectMap, "trafficLogDestination", l.TrafficLogDestination) + return json.Marshal(objectMap) +} + +// UnmarshalJSON implements the json.Unmarshaller interface for type LogSettings. +func (l *LogSettings) UnmarshalJSON(data []byte) error { + var rawMsg map[string]json.RawMessage + if err := json.Unmarshal(data, &rawMsg); err != nil { + return fmt.Errorf("unmarshalling type %T: %v", l, err) + } + for key, val := range rawMsg { + var err error + switch key { + case "applicationInsights": + err = unpopulate(val, "ApplicationInsights", &l.ApplicationInsights) + delete(rawMsg, key) + case "commonDestination": + err = unpopulate(val, "CommonDestination", &l.CommonDestination) + delete(rawMsg, key) + case "decryptLogDestination": + err = unpopulate(val, "DecryptLogDestination", &l.DecryptLogDestination) + delete(rawMsg, key) + case "logOption": + err = unpopulate(val, "LogOption", &l.LogOption) + delete(rawMsg, key) + case "logType": + err = unpopulate(val, "LogType", &l.LogType) + delete(rawMsg, key) + case "threatLogDestination": + err = unpopulate(val, "ThreatLogDestination", &l.ThreatLogDestination) + delete(rawMsg, key) + case "trafficLogDestination": + err = unpopulate(val, "TrafficLogDestination", &l.TrafficLogDestination) + delete(rawMsg, key) + } + if err != nil { + return fmt.Errorf("unmarshalling type %T: %v", l, err) + } + } + return nil +} + +// MarshalJSON implements the json.Marshaller interface for type MarketplaceDetails. +func (m MarketplaceDetails) MarshalJSON() ([]byte, error) { + objectMap := make(map[string]any) + populate(objectMap, "marketplaceSubscriptionId", m.MarketplaceSubscriptionID) + populate(objectMap, "marketplaceSubscriptionStatus", m.MarketplaceSubscriptionStatus) + populate(objectMap, "offerId", m.OfferID) + populate(objectMap, "publisherId", m.PublisherID) + return json.Marshal(objectMap) +} + +// UnmarshalJSON implements the json.Unmarshaller interface for type MarketplaceDetails. +func (m *MarketplaceDetails) UnmarshalJSON(data []byte) error { + var rawMsg map[string]json.RawMessage + if err := json.Unmarshal(data, &rawMsg); err != nil { + return fmt.Errorf("unmarshalling type %T: %v", m, err) + } + for key, val := range rawMsg { + var err error + switch key { + case "marketplaceSubscriptionId": + err = unpopulate(val, "MarketplaceSubscriptionID", &m.MarketplaceSubscriptionID) + delete(rawMsg, key) + case "marketplaceSubscriptionStatus": + err = unpopulate(val, "MarketplaceSubscriptionStatus", &m.MarketplaceSubscriptionStatus) + delete(rawMsg, key) + case "offerId": + err = unpopulate(val, "OfferID", &m.OfferID) + delete(rawMsg, key) + case "publisherId": + err = unpopulate(val, "PublisherID", &m.PublisherID) + delete(rawMsg, key) + } + if err != nil { + return fmt.Errorf("unmarshalling type %T: %v", m, err) + } + } + return nil +} + +// MarshalJSON implements the json.Marshaller interface for type MonitorLog. +func (m MonitorLog) MarshalJSON() ([]byte, error) { + objectMap := make(map[string]any) + populate(objectMap, "id", m.ID) + populate(objectMap, "primaryKey", m.PrimaryKey) + populate(objectMap, "secondaryKey", m.SecondaryKey) + populate(objectMap, "subscriptionId", m.SubscriptionID) + populate(objectMap, "workspace", m.Workspace) + return json.Marshal(objectMap) +} + +// UnmarshalJSON implements the json.Unmarshaller interface for type MonitorLog. +func (m *MonitorLog) UnmarshalJSON(data []byte) error { + var rawMsg map[string]json.RawMessage + if err := json.Unmarshal(data, &rawMsg); err != nil { + return fmt.Errorf("unmarshalling type %T: %v", m, err) + } + for key, val := range rawMsg { + var err error + switch key { + case "id": + err = unpopulate(val, "ID", &m.ID) + delete(rawMsg, key) + case "primaryKey": + err = unpopulate(val, "PrimaryKey", &m.PrimaryKey) + delete(rawMsg, key) + case "secondaryKey": + err = unpopulate(val, "SecondaryKey", &m.SecondaryKey) + delete(rawMsg, key) + case "subscriptionId": + err = unpopulate(val, "SubscriptionID", &m.SubscriptionID) + delete(rawMsg, key) + case "workspace": + err = unpopulate(val, "Workspace", &m.Workspace) + delete(rawMsg, key) + } + if err != nil { + return fmt.Errorf("unmarshalling type %T: %v", m, err) + } + } + return nil +} + +// MarshalJSON implements the json.Marshaller interface for type NameDescriptionObject. +func (n NameDescriptionObject) MarshalJSON() ([]byte, error) { + objectMap := make(map[string]any) + populate(objectMap, "description", n.Description) + populate(objectMap, "name", n.Name) + return json.Marshal(objectMap) +} + +// UnmarshalJSON implements the json.Unmarshaller interface for type NameDescriptionObject. +func (n *NameDescriptionObject) UnmarshalJSON(data []byte) error { + var rawMsg map[string]json.RawMessage + if err := json.Unmarshal(data, &rawMsg); err != nil { + return fmt.Errorf("unmarshalling type %T: %v", n, err) + } + for key, val := range rawMsg { + var err error + switch key { + case "description": + err = unpopulate(val, "Description", &n.Description) + delete(rawMsg, key) + case "name": + err = unpopulate(val, "Name", &n.Name) + delete(rawMsg, key) + } + if err != nil { + return fmt.Errorf("unmarshalling type %T: %v", n, err) + } + } + return nil +} + +// MarshalJSON implements the json.Marshaller interface for type NetworkProfile. +func (n NetworkProfile) MarshalJSON() ([]byte, error) { + objectMap := make(map[string]any) + populate(objectMap, "egressNatIp", n.EgressNatIP) + populate(objectMap, "enableEgressNat", n.EnableEgressNat) + populate(objectMap, "networkType", n.NetworkType) + populate(objectMap, "publicIps", n.PublicIPs) + populate(objectMap, "vnetConfiguration", n.VnetConfiguration) + populate(objectMap, "vwanConfiguration", n.VwanConfiguration) + return json.Marshal(objectMap) +} + +// UnmarshalJSON implements the json.Unmarshaller interface for type NetworkProfile. +func (n *NetworkProfile) UnmarshalJSON(data []byte) error { + var rawMsg map[string]json.RawMessage + if err := json.Unmarshal(data, &rawMsg); err != nil { + return fmt.Errorf("unmarshalling type %T: %v", n, err) + } + for key, val := range rawMsg { + var err error + switch key { + case "egressNatIp": + err = unpopulate(val, "EgressNatIP", &n.EgressNatIP) + delete(rawMsg, key) + case "enableEgressNat": + err = unpopulate(val, "EnableEgressNat", &n.EnableEgressNat) + delete(rawMsg, key) + case "networkType": + err = unpopulate(val, "NetworkType", &n.NetworkType) + delete(rawMsg, key) + case "publicIps": + err = unpopulate(val, "PublicIPs", &n.PublicIPs) + delete(rawMsg, key) + case "vnetConfiguration": + err = unpopulate(val, "VnetConfiguration", &n.VnetConfiguration) + delete(rawMsg, key) + case "vwanConfiguration": + err = unpopulate(val, "VwanConfiguration", &n.VwanConfiguration) + delete(rawMsg, key) + } + if err != nil { + return fmt.Errorf("unmarshalling type %T: %v", n, err) + } + } + return nil +} + +// MarshalJSON implements the json.Marshaller interface for type Operation. +func (o Operation) MarshalJSON() ([]byte, error) { + objectMap := make(map[string]any) + populate(objectMap, "actionType", o.ActionType) + populate(objectMap, "display", o.Display) + populate(objectMap, "isDataAction", o.IsDataAction) + populate(objectMap, "name", o.Name) + populate(objectMap, "origin", o.Origin) + return json.Marshal(objectMap) +} + +// UnmarshalJSON implements the json.Unmarshaller interface for type Operation. +func (o *Operation) UnmarshalJSON(data []byte) error { + var rawMsg map[string]json.RawMessage + if err := json.Unmarshal(data, &rawMsg); err != nil { + return fmt.Errorf("unmarshalling type %T: %v", o, err) + } + for key, val := range rawMsg { + var err error + switch key { + case "actionType": + err = unpopulate(val, "ActionType", &o.ActionType) + delete(rawMsg, key) + case "display": + err = unpopulate(val, "Display", &o.Display) + delete(rawMsg, key) + case "isDataAction": + err = unpopulate(val, "IsDataAction", &o.IsDataAction) + delete(rawMsg, key) + case "name": + err = unpopulate(val, "Name", &o.Name) + delete(rawMsg, key) + case "origin": + err = unpopulate(val, "Origin", &o.Origin) + delete(rawMsg, key) + } + if err != nil { + return fmt.Errorf("unmarshalling type %T: %v", o, err) + } + } + return nil +} + +// MarshalJSON implements the json.Marshaller interface for type OperationDisplay. +func (o OperationDisplay) MarshalJSON() ([]byte, error) { + objectMap := make(map[string]any) + populate(objectMap, "description", o.Description) + populate(objectMap, "operation", o.Operation) + populate(objectMap, "provider", o.Provider) + populate(objectMap, "resource", o.Resource) + return json.Marshal(objectMap) +} + +// UnmarshalJSON implements the json.Unmarshaller interface for type OperationDisplay. +func (o *OperationDisplay) UnmarshalJSON(data []byte) error { + var rawMsg map[string]json.RawMessage + if err := json.Unmarshal(data, &rawMsg); err != nil { + return fmt.Errorf("unmarshalling type %T: %v", o, err) + } + for key, val := range rawMsg { + var err error + switch key { + case "description": + err = unpopulate(val, "Description", &o.Description) + delete(rawMsg, key) + case "operation": + err = unpopulate(val, "Operation", &o.Operation) + delete(rawMsg, key) + case "provider": + err = unpopulate(val, "Provider", &o.Provider) + delete(rawMsg, key) + case "resource": + err = unpopulate(val, "Resource", &o.Resource) + delete(rawMsg, key) + } + if err != nil { + return fmt.Errorf("unmarshalling type %T: %v", o, err) + } + } + return nil +} + +// MarshalJSON implements the json.Marshaller interface for type OperationListResult. +func (o OperationListResult) MarshalJSON() ([]byte, error) { + objectMap := make(map[string]any) + populate(objectMap, "nextLink", o.NextLink) + populate(objectMap, "value", o.Value) + return json.Marshal(objectMap) +} + +// UnmarshalJSON implements the json.Unmarshaller interface for type OperationListResult. +func (o *OperationListResult) UnmarshalJSON(data []byte) error { + var rawMsg map[string]json.RawMessage + if err := json.Unmarshal(data, &rawMsg); err != nil { + return fmt.Errorf("unmarshalling type %T: %v", o, err) + } + for key, val := range rawMsg { + var err error + switch key { + case "nextLink": + err = unpopulate(val, "NextLink", &o.NextLink) + delete(rawMsg, key) + case "value": + err = unpopulate(val, "Value", &o.Value) + delete(rawMsg, key) + } + if err != nil { + return fmt.Errorf("unmarshalling type %T: %v", o, err) + } + } + return nil +} + +// MarshalJSON implements the json.Marshaller interface for type PanoramaConfig. +func (p PanoramaConfig) MarshalJSON() ([]byte, error) { + objectMap := make(map[string]any) + populate(objectMap, "cgName", p.CgName) + populate(objectMap, "configString", p.ConfigString) + populate(objectMap, "dgName", p.DgName) + populate(objectMap, "hostName", p.HostName) + populate(objectMap, "panoramaServer", p.PanoramaServer) + populate(objectMap, "panoramaServer2", p.PanoramaServer2) + populate(objectMap, "tplName", p.TplName) + populate(objectMap, "vmAuthKey", p.VMAuthKey) + return json.Marshal(objectMap) +} + +// UnmarshalJSON implements the json.Unmarshaller interface for type PanoramaConfig. +func (p *PanoramaConfig) UnmarshalJSON(data []byte) error { + var rawMsg map[string]json.RawMessage + if err := json.Unmarshal(data, &rawMsg); err != nil { + return fmt.Errorf("unmarshalling type %T: %v", p, err) + } + for key, val := range rawMsg { + var err error + switch key { + case "cgName": + err = unpopulate(val, "CgName", &p.CgName) + delete(rawMsg, key) + case "configString": + err = unpopulate(val, "ConfigString", &p.ConfigString) + delete(rawMsg, key) + case "dgName": + err = unpopulate(val, "DgName", &p.DgName) + delete(rawMsg, key) + case "hostName": + err = unpopulate(val, "HostName", &p.HostName) + delete(rawMsg, key) + case "panoramaServer": + err = unpopulate(val, "PanoramaServer", &p.PanoramaServer) + delete(rawMsg, key) + case "panoramaServer2": + err = unpopulate(val, "PanoramaServer2", &p.PanoramaServer2) + delete(rawMsg, key) + case "tplName": + err = unpopulate(val, "TplName", &p.TplName) + delete(rawMsg, key) + case "vmAuthKey": + err = unpopulate(val, "VMAuthKey", &p.VMAuthKey) + delete(rawMsg, key) + } + if err != nil { + return fmt.Errorf("unmarshalling type %T: %v", p, err) + } + } + return nil +} + +// MarshalJSON implements the json.Marshaller interface for type PanoramaStatus. +func (p PanoramaStatus) MarshalJSON() ([]byte, error) { + objectMap := make(map[string]any) + populate(objectMap, "panoramaServer2Status", p.PanoramaServer2Status) + populate(objectMap, "panoramaServerStatus", p.PanoramaServerStatus) + return json.Marshal(objectMap) +} + +// UnmarshalJSON implements the json.Unmarshaller interface for type PanoramaStatus. +func (p *PanoramaStatus) UnmarshalJSON(data []byte) error { + var rawMsg map[string]json.RawMessage + if err := json.Unmarshal(data, &rawMsg); err != nil { + return fmt.Errorf("unmarshalling type %T: %v", p, err) + } + for key, val := range rawMsg { + var err error + switch key { + case "panoramaServer2Status": + err = unpopulate(val, "PanoramaServer2Status", &p.PanoramaServer2Status) + delete(rawMsg, key) + case "panoramaServerStatus": + err = unpopulate(val, "PanoramaServerStatus", &p.PanoramaServerStatus) + delete(rawMsg, key) + } + if err != nil { + return fmt.Errorf("unmarshalling type %T: %v", p, err) + } + } + return nil +} + +// MarshalJSON implements the json.Marshaller interface for type PlanData. +func (p PlanData) MarshalJSON() ([]byte, error) { + objectMap := make(map[string]any) + populate(objectMap, "billingCycle", p.BillingCycle) + populateTimeRFC3339(objectMap, "effectiveDate", p.EffectiveDate) + populate(objectMap, "planId", p.PlanID) + populate(objectMap, "usageType", p.UsageType) + return json.Marshal(objectMap) +} + +// UnmarshalJSON implements the json.Unmarshaller interface for type PlanData. +func (p *PlanData) UnmarshalJSON(data []byte) error { + var rawMsg map[string]json.RawMessage + if err := json.Unmarshal(data, &rawMsg); err != nil { + return fmt.Errorf("unmarshalling type %T: %v", p, err) + } + for key, val := range rawMsg { + var err error + switch key { + case "billingCycle": + err = unpopulate(val, "BillingCycle", &p.BillingCycle) + delete(rawMsg, key) + case "effectiveDate": + err = unpopulateTimeRFC3339(val, "EffectiveDate", &p.EffectiveDate) + delete(rawMsg, key) + case "planId": + err = unpopulate(val, "PlanID", &p.PlanID) + delete(rawMsg, key) + case "usageType": + err = unpopulate(val, "UsageType", &p.UsageType) + delete(rawMsg, key) + } + if err != nil { + return fmt.Errorf("unmarshalling type %T: %v", p, err) + } + } + return nil +} + +// MarshalJSON implements the json.Marshaller interface for type PostRulesResource. +func (p PostRulesResource) MarshalJSON() ([]byte, error) { + objectMap := make(map[string]any) + populate(objectMap, "id", p.ID) + populate(objectMap, "name", p.Name) + populate(objectMap, "properties", p.Properties) + populate(objectMap, "systemData", p.SystemData) + populate(objectMap, "type", p.Type) + return json.Marshal(objectMap) +} + +// UnmarshalJSON implements the json.Unmarshaller interface for type PostRulesResource. +func (p *PostRulesResource) UnmarshalJSON(data []byte) error { + var rawMsg map[string]json.RawMessage + if err := json.Unmarshal(data, &rawMsg); err != nil { + return fmt.Errorf("unmarshalling type %T: %v", p, err) + } + for key, val := range rawMsg { + var err error + switch key { + case "id": + err = unpopulate(val, "ID", &p.ID) + delete(rawMsg, key) + case "name": + err = unpopulate(val, "Name", &p.Name) + delete(rawMsg, key) + case "properties": + err = unpopulate(val, "Properties", &p.Properties) + delete(rawMsg, key) + case "systemData": + err = unpopulate(val, "SystemData", &p.SystemData) + delete(rawMsg, key) + case "type": + err = unpopulate(val, "Type", &p.Type) + delete(rawMsg, key) + } + if err != nil { + return fmt.Errorf("unmarshalling type %T: %v", p, err) + } + } + return nil +} + +// MarshalJSON implements the json.Marshaller interface for type PostRulesResourceListResult. +func (p PostRulesResourceListResult) MarshalJSON() ([]byte, error) { + objectMap := make(map[string]any) + populate(objectMap, "nextLink", p.NextLink) + populate(objectMap, "value", p.Value) + return json.Marshal(objectMap) +} + +// UnmarshalJSON implements the json.Unmarshaller interface for type PostRulesResourceListResult. +func (p *PostRulesResourceListResult) UnmarshalJSON(data []byte) error { + var rawMsg map[string]json.RawMessage + if err := json.Unmarshal(data, &rawMsg); err != nil { + return fmt.Errorf("unmarshalling type %T: %v", p, err) + } + for key, val := range rawMsg { + var err error + switch key { + case "nextLink": + err = unpopulate(val, "NextLink", &p.NextLink) + delete(rawMsg, key) + case "value": + err = unpopulate(val, "Value", &p.Value) + delete(rawMsg, key) + } + if err != nil { + return fmt.Errorf("unmarshalling type %T: %v", p, err) + } + } + return nil +} + +// MarshalJSON implements the json.Marshaller interface for type PreRulesResource. +func (p PreRulesResource) MarshalJSON() ([]byte, error) { + objectMap := make(map[string]any) + populate(objectMap, "id", p.ID) + populate(objectMap, "name", p.Name) + populate(objectMap, "properties", p.Properties) + populate(objectMap, "systemData", p.SystemData) + populate(objectMap, "type", p.Type) + return json.Marshal(objectMap) +} + +// UnmarshalJSON implements the json.Unmarshaller interface for type PreRulesResource. +func (p *PreRulesResource) UnmarshalJSON(data []byte) error { + var rawMsg map[string]json.RawMessage + if err := json.Unmarshal(data, &rawMsg); err != nil { + return fmt.Errorf("unmarshalling type %T: %v", p, err) + } + for key, val := range rawMsg { + var err error + switch key { + case "id": + err = unpopulate(val, "ID", &p.ID) + delete(rawMsg, key) + case "name": + err = unpopulate(val, "Name", &p.Name) + delete(rawMsg, key) + case "properties": + err = unpopulate(val, "Properties", &p.Properties) + delete(rawMsg, key) + case "systemData": + err = unpopulate(val, "SystemData", &p.SystemData) + delete(rawMsg, key) + case "type": + err = unpopulate(val, "Type", &p.Type) + delete(rawMsg, key) + } + if err != nil { + return fmt.Errorf("unmarshalling type %T: %v", p, err) + } + } + return nil +} + +// MarshalJSON implements the json.Marshaller interface for type PreRulesResourceListResult. +func (p PreRulesResourceListResult) MarshalJSON() ([]byte, error) { + objectMap := make(map[string]any) + populate(objectMap, "nextLink", p.NextLink) + populate(objectMap, "value", p.Value) + return json.Marshal(objectMap) +} + +// UnmarshalJSON implements the json.Unmarshaller interface for type PreRulesResourceListResult. +func (p *PreRulesResourceListResult) UnmarshalJSON(data []byte) error { + var rawMsg map[string]json.RawMessage + if err := json.Unmarshal(data, &rawMsg); err != nil { + return fmt.Errorf("unmarshalling type %T: %v", p, err) + } + for key, val := range rawMsg { + var err error + switch key { + case "nextLink": + err = unpopulate(val, "NextLink", &p.NextLink) + delete(rawMsg, key) + case "value": + err = unpopulate(val, "Value", &p.Value) + delete(rawMsg, key) + } + if err != nil { + return fmt.Errorf("unmarshalling type %T: %v", p, err) + } + } + return nil +} + +// MarshalJSON implements the json.Marshaller interface for type PredefinedURLCategoriesResponse. +func (p PredefinedURLCategoriesResponse) MarshalJSON() ([]byte, error) { + objectMap := make(map[string]any) + populate(objectMap, "nextLink", p.NextLink) + populate(objectMap, "value", p.Value) + return json.Marshal(objectMap) +} + +// UnmarshalJSON implements the json.Unmarshaller interface for type PredefinedURLCategoriesResponse. +func (p *PredefinedURLCategoriesResponse) UnmarshalJSON(data []byte) error { + var rawMsg map[string]json.RawMessage + if err := json.Unmarshal(data, &rawMsg); err != nil { + return fmt.Errorf("unmarshalling type %T: %v", p, err) + } + for key, val := range rawMsg { + var err error + switch key { + case "nextLink": + err = unpopulate(val, "NextLink", &p.NextLink) + delete(rawMsg, key) + case "value": + err = unpopulate(val, "Value", &p.Value) + delete(rawMsg, key) + } + if err != nil { + return fmt.Errorf("unmarshalling type %T: %v", p, err) + } + } + return nil +} + +// MarshalJSON implements the json.Marshaller interface for type PredefinedURLCategory. +func (p PredefinedURLCategory) MarshalJSON() ([]byte, error) { + objectMap := make(map[string]any) + populate(objectMap, "action", p.Action) + populate(objectMap, "name", p.Name) + return json.Marshal(objectMap) +} + +// UnmarshalJSON implements the json.Unmarshaller interface for type PredefinedURLCategory. +func (p *PredefinedURLCategory) UnmarshalJSON(data []byte) error { + var rawMsg map[string]json.RawMessage + if err := json.Unmarshal(data, &rawMsg); err != nil { + return fmt.Errorf("unmarshalling type %T: %v", p, err) + } + for key, val := range rawMsg { + var err error + switch key { + case "action": + err = unpopulate(val, "Action", &p.Action) + delete(rawMsg, key) + case "name": + err = unpopulate(val, "Name", &p.Name) + delete(rawMsg, key) + } + if err != nil { + return fmt.Errorf("unmarshalling type %T: %v", p, err) + } + } + return nil +} + +// MarshalJSON implements the json.Marshaller interface for type PrefixListGlobalRulestackResource. +func (p PrefixListGlobalRulestackResource) MarshalJSON() ([]byte, error) { + objectMap := make(map[string]any) + populate(objectMap, "id", p.ID) + populate(objectMap, "name", p.Name) + populate(objectMap, "properties", p.Properties) + populate(objectMap, "systemData", p.SystemData) + populate(objectMap, "type", p.Type) + return json.Marshal(objectMap) +} + +// UnmarshalJSON implements the json.Unmarshaller interface for type PrefixListGlobalRulestackResource. +func (p *PrefixListGlobalRulestackResource) UnmarshalJSON(data []byte) error { + var rawMsg map[string]json.RawMessage + if err := json.Unmarshal(data, &rawMsg); err != nil { + return fmt.Errorf("unmarshalling type %T: %v", p, err) + } + for key, val := range rawMsg { + var err error + switch key { + case "id": + err = unpopulate(val, "ID", &p.ID) + delete(rawMsg, key) + case "name": + err = unpopulate(val, "Name", &p.Name) + delete(rawMsg, key) + case "properties": + err = unpopulate(val, "Properties", &p.Properties) + delete(rawMsg, key) + case "systemData": + err = unpopulate(val, "SystemData", &p.SystemData) + delete(rawMsg, key) + case "type": + err = unpopulate(val, "Type", &p.Type) + delete(rawMsg, key) + } + if err != nil { + return fmt.Errorf("unmarshalling type %T: %v", p, err) + } + } + return nil +} + +// MarshalJSON implements the json.Marshaller interface for type PrefixListGlobalRulestackResourceListResult. +func (p PrefixListGlobalRulestackResourceListResult) MarshalJSON() ([]byte, error) { + objectMap := make(map[string]any) + populate(objectMap, "nextLink", p.NextLink) + populate(objectMap, "value", p.Value) + return json.Marshal(objectMap) +} + +// UnmarshalJSON implements the json.Unmarshaller interface for type PrefixListGlobalRulestackResourceListResult. +func (p *PrefixListGlobalRulestackResourceListResult) UnmarshalJSON(data []byte) error { + var rawMsg map[string]json.RawMessage + if err := json.Unmarshal(data, &rawMsg); err != nil { + return fmt.Errorf("unmarshalling type %T: %v", p, err) + } + for key, val := range rawMsg { + var err error + switch key { + case "nextLink": + err = unpopulate(val, "NextLink", &p.NextLink) + delete(rawMsg, key) + case "value": + err = unpopulate(val, "Value", &p.Value) + delete(rawMsg, key) + } + if err != nil { + return fmt.Errorf("unmarshalling type %T: %v", p, err) + } + } + return nil +} + +// MarshalJSON implements the json.Marshaller interface for type PrefixListResource. +func (p PrefixListResource) MarshalJSON() ([]byte, error) { + objectMap := make(map[string]any) + populate(objectMap, "id", p.ID) + populate(objectMap, "name", p.Name) + populate(objectMap, "properties", p.Properties) + populate(objectMap, "systemData", p.SystemData) + populate(objectMap, "type", p.Type) + return json.Marshal(objectMap) +} + +// UnmarshalJSON implements the json.Unmarshaller interface for type PrefixListResource. +func (p *PrefixListResource) UnmarshalJSON(data []byte) error { + var rawMsg map[string]json.RawMessage + if err := json.Unmarshal(data, &rawMsg); err != nil { + return fmt.Errorf("unmarshalling type %T: %v", p, err) + } + for key, val := range rawMsg { + var err error + switch key { + case "id": + err = unpopulate(val, "ID", &p.ID) + delete(rawMsg, key) + case "name": + err = unpopulate(val, "Name", &p.Name) + delete(rawMsg, key) + case "properties": + err = unpopulate(val, "Properties", &p.Properties) + delete(rawMsg, key) + case "systemData": + err = unpopulate(val, "SystemData", &p.SystemData) + delete(rawMsg, key) + case "type": + err = unpopulate(val, "Type", &p.Type) + delete(rawMsg, key) + } + if err != nil { + return fmt.Errorf("unmarshalling type %T: %v", p, err) + } + } + return nil +} + +// MarshalJSON implements the json.Marshaller interface for type PrefixListResourceListResult. +func (p PrefixListResourceListResult) MarshalJSON() ([]byte, error) { + objectMap := make(map[string]any) + populate(objectMap, "nextLink", p.NextLink) + populate(objectMap, "value", p.Value) + return json.Marshal(objectMap) +} + +// UnmarshalJSON implements the json.Unmarshaller interface for type PrefixListResourceListResult. +func (p *PrefixListResourceListResult) UnmarshalJSON(data []byte) error { + var rawMsg map[string]json.RawMessage + if err := json.Unmarshal(data, &rawMsg); err != nil { + return fmt.Errorf("unmarshalling type %T: %v", p, err) + } + for key, val := range rawMsg { + var err error + switch key { + case "nextLink": + err = unpopulate(val, "NextLink", &p.NextLink) + delete(rawMsg, key) + case "value": + err = unpopulate(val, "Value", &p.Value) + delete(rawMsg, key) + } + if err != nil { + return fmt.Errorf("unmarshalling type %T: %v", p, err) + } + } + return nil +} + +// MarshalJSON implements the json.Marshaller interface for type PrefixObject. +func (p PrefixObject) MarshalJSON() ([]byte, error) { + objectMap := make(map[string]any) + populate(objectMap, "auditComment", p.AuditComment) + populate(objectMap, "description", p.Description) + populate(objectMap, "etag", p.Etag) + populate(objectMap, "prefixList", p.PrefixList) + populate(objectMap, "provisioningState", p.ProvisioningState) + return json.Marshal(objectMap) +} + +// UnmarshalJSON implements the json.Unmarshaller interface for type PrefixObject. +func (p *PrefixObject) UnmarshalJSON(data []byte) error { + var rawMsg map[string]json.RawMessage + if err := json.Unmarshal(data, &rawMsg); err != nil { + return fmt.Errorf("unmarshalling type %T: %v", p, err) + } + for key, val := range rawMsg { + var err error + switch key { + case "auditComment": + err = unpopulate(val, "AuditComment", &p.AuditComment) + delete(rawMsg, key) + case "description": + err = unpopulate(val, "Description", &p.Description) + delete(rawMsg, key) + case "etag": + err = unpopulate(val, "Etag", &p.Etag) + delete(rawMsg, key) + case "prefixList": + err = unpopulate(val, "PrefixList", &p.PrefixList) + delete(rawMsg, key) + case "provisioningState": + err = unpopulate(val, "ProvisioningState", &p.ProvisioningState) + delete(rawMsg, key) + } + if err != nil { + return fmt.Errorf("unmarshalling type %T: %v", p, err) + } + } + return nil +} + +// MarshalJSON implements the json.Marshaller interface for type RuleCounter. +func (r RuleCounter) MarshalJSON() ([]byte, error) { + objectMap := make(map[string]any) + populate(objectMap, "appSeen", r.AppSeen) + populate(objectMap, "firewallName", r.FirewallName) + populate(objectMap, "hitCount", r.HitCount) + populateTimeRFC3339(objectMap, "lastUpdatedTimestamp", r.LastUpdatedTimestamp) + populate(objectMap, "priority", r.Priority) + populateTimeRFC3339(objectMap, "requestTimestamp", r.RequestTimestamp) + populate(objectMap, "ruleListName", r.RuleListName) + populate(objectMap, "ruleName", r.RuleName) + populate(objectMap, "ruleStackName", r.RuleStackName) + populateTimeRFC3339(objectMap, "timestamp", r.Timestamp) + return json.Marshal(objectMap) +} + +// UnmarshalJSON implements the json.Unmarshaller interface for type RuleCounter. +func (r *RuleCounter) UnmarshalJSON(data []byte) error { + var rawMsg map[string]json.RawMessage + if err := json.Unmarshal(data, &rawMsg); err != nil { + return fmt.Errorf("unmarshalling type %T: %v", r, err) + } + for key, val := range rawMsg { + var err error + switch key { + case "appSeen": + err = unpopulate(val, "AppSeen", &r.AppSeen) + delete(rawMsg, key) + case "firewallName": + err = unpopulate(val, "FirewallName", &r.FirewallName) + delete(rawMsg, key) + case "hitCount": + err = unpopulate(val, "HitCount", &r.HitCount) + delete(rawMsg, key) + case "lastUpdatedTimestamp": + err = unpopulateTimeRFC3339(val, "LastUpdatedTimestamp", &r.LastUpdatedTimestamp) + delete(rawMsg, key) + case "priority": + err = unpopulate(val, "Priority", &r.Priority) + delete(rawMsg, key) + case "requestTimestamp": + err = unpopulateTimeRFC3339(val, "RequestTimestamp", &r.RequestTimestamp) + delete(rawMsg, key) + case "ruleListName": + err = unpopulate(val, "RuleListName", &r.RuleListName) + delete(rawMsg, key) + case "ruleName": + err = unpopulate(val, "RuleName", &r.RuleName) + delete(rawMsg, key) + case "ruleStackName": + err = unpopulate(val, "RuleStackName", &r.RuleStackName) + delete(rawMsg, key) + case "timestamp": + err = unpopulateTimeRFC3339(val, "Timestamp", &r.Timestamp) + delete(rawMsg, key) + } + if err != nil { + return fmt.Errorf("unmarshalling type %T: %v", r, err) + } + } + return nil +} + +// MarshalJSON implements the json.Marshaller interface for type RuleCounterReset. +func (r RuleCounterReset) MarshalJSON() ([]byte, error) { + objectMap := make(map[string]any) + populate(objectMap, "firewallName", r.FirewallName) + populate(objectMap, "priority", r.Priority) + populate(objectMap, "ruleListName", r.RuleListName) + populate(objectMap, "ruleName", r.RuleName) + populate(objectMap, "ruleStackName", r.RuleStackName) + return json.Marshal(objectMap) +} + +// UnmarshalJSON implements the json.Unmarshaller interface for type RuleCounterReset. +func (r *RuleCounterReset) UnmarshalJSON(data []byte) error { + var rawMsg map[string]json.RawMessage + if err := json.Unmarshal(data, &rawMsg); err != nil { + return fmt.Errorf("unmarshalling type %T: %v", r, err) + } + for key, val := range rawMsg { + var err error + switch key { + case "firewallName": + err = unpopulate(val, "FirewallName", &r.FirewallName) + delete(rawMsg, key) + case "priority": + err = unpopulate(val, "Priority", &r.Priority) + delete(rawMsg, key) + case "ruleListName": + err = unpopulate(val, "RuleListName", &r.RuleListName) + delete(rawMsg, key) + case "ruleName": + err = unpopulate(val, "RuleName", &r.RuleName) + delete(rawMsg, key) + case "ruleStackName": + err = unpopulate(val, "RuleStackName", &r.RuleStackName) + delete(rawMsg, key) + } + if err != nil { + return fmt.Errorf("unmarshalling type %T: %v", r, err) + } + } + return nil +} + +// MarshalJSON implements the json.Marshaller interface for type RuleEntry. +func (r RuleEntry) MarshalJSON() ([]byte, error) { + objectMap := make(map[string]any) + populate(objectMap, "actionType", r.ActionType) + populate(objectMap, "applications", r.Applications) + populate(objectMap, "auditComment", r.AuditComment) + populate(objectMap, "category", r.Category) + populate(objectMap, "decryptionRuleType", r.DecryptionRuleType) + populate(objectMap, "description", r.Description) + populate(objectMap, "destination", r.Destination) + populate(objectMap, "enableLogging", r.EnableLogging) + populate(objectMap, "etag", r.Etag) + populate(objectMap, "inboundInspectionCertificate", r.InboundInspectionCertificate) + populate(objectMap, "negateDestination", r.NegateDestination) + populate(objectMap, "negateSource", r.NegateSource) + populate(objectMap, "priority", r.Priority) + populate(objectMap, "protocol", r.Protocol) + populate(objectMap, "protocolPortList", r.ProtocolPortList) + populate(objectMap, "provisioningState", r.ProvisioningState) + populate(objectMap, "ruleName", r.RuleName) + populate(objectMap, "ruleState", r.RuleState) + populate(objectMap, "source", r.Source) + populate(objectMap, "tags", r.Tags) + return json.Marshal(objectMap) +} + +// UnmarshalJSON implements the json.Unmarshaller interface for type RuleEntry. +func (r *RuleEntry) UnmarshalJSON(data []byte) error { + var rawMsg map[string]json.RawMessage + if err := json.Unmarshal(data, &rawMsg); err != nil { + return fmt.Errorf("unmarshalling type %T: %v", r, err) + } + for key, val := range rawMsg { + var err error + switch key { + case "actionType": + err = unpopulate(val, "ActionType", &r.ActionType) + delete(rawMsg, key) + case "applications": + err = unpopulate(val, "Applications", &r.Applications) + delete(rawMsg, key) + case "auditComment": + err = unpopulate(val, "AuditComment", &r.AuditComment) + delete(rawMsg, key) + case "category": + err = unpopulate(val, "Category", &r.Category) + delete(rawMsg, key) + case "decryptionRuleType": + err = unpopulate(val, "DecryptionRuleType", &r.DecryptionRuleType) + delete(rawMsg, key) + case "description": + err = unpopulate(val, "Description", &r.Description) + delete(rawMsg, key) + case "destination": + err = unpopulate(val, "Destination", &r.Destination) + delete(rawMsg, key) + case "enableLogging": + err = unpopulate(val, "EnableLogging", &r.EnableLogging) + delete(rawMsg, key) + case "etag": + err = unpopulate(val, "Etag", &r.Etag) + delete(rawMsg, key) + case "inboundInspectionCertificate": + err = unpopulate(val, "InboundInspectionCertificate", &r.InboundInspectionCertificate) + delete(rawMsg, key) + case "negateDestination": + err = unpopulate(val, "NegateDestination", &r.NegateDestination) + delete(rawMsg, key) + case "negateSource": + err = unpopulate(val, "NegateSource", &r.NegateSource) + delete(rawMsg, key) + case "priority": + err = unpopulate(val, "Priority", &r.Priority) + delete(rawMsg, key) + case "protocol": + err = unpopulate(val, "Protocol", &r.Protocol) + delete(rawMsg, key) + case "protocolPortList": + err = unpopulate(val, "ProtocolPortList", &r.ProtocolPortList) + delete(rawMsg, key) + case "provisioningState": + err = unpopulate(val, "ProvisioningState", &r.ProvisioningState) + delete(rawMsg, key) + case "ruleName": + err = unpopulate(val, "RuleName", &r.RuleName) + delete(rawMsg, key) + case "ruleState": + err = unpopulate(val, "RuleState", &r.RuleState) + delete(rawMsg, key) + case "source": + err = unpopulate(val, "Source", &r.Source) + delete(rawMsg, key) + case "tags": + err = unpopulate(val, "Tags", &r.Tags) + delete(rawMsg, key) + } + if err != nil { + return fmt.Errorf("unmarshalling type %T: %v", r, err) + } + } + return nil +} + +// MarshalJSON implements the json.Marshaller interface for type RulestackDetails. +func (r RulestackDetails) MarshalJSON() ([]byte, error) { + objectMap := make(map[string]any) + populate(objectMap, "location", r.Location) + populate(objectMap, "resourceId", r.ResourceID) + populate(objectMap, "rulestackId", r.RulestackID) + return json.Marshal(objectMap) +} + +// UnmarshalJSON implements the json.Unmarshaller interface for type RulestackDetails. +func (r *RulestackDetails) UnmarshalJSON(data []byte) error { + var rawMsg map[string]json.RawMessage + if err := json.Unmarshal(data, &rawMsg); err != nil { + return fmt.Errorf("unmarshalling type %T: %v", r, err) + } + for key, val := range rawMsg { + var err error + switch key { + case "location": + err = unpopulate(val, "Location", &r.Location) + delete(rawMsg, key) + case "resourceId": + err = unpopulate(val, "ResourceID", &r.ResourceID) + delete(rawMsg, key) + case "rulestackId": + err = unpopulate(val, "RulestackID", &r.RulestackID) + delete(rawMsg, key) + } + if err != nil { + return fmt.Errorf("unmarshalling type %T: %v", r, err) + } + } + return nil +} + +// MarshalJSON implements the json.Marshaller interface for type RulestackProperties. +func (r RulestackProperties) MarshalJSON() ([]byte, error) { + objectMap := make(map[string]any) + populate(objectMap, "associatedSubscriptions", r.AssociatedSubscriptions) + populate(objectMap, "defaultMode", r.DefaultMode) + populate(objectMap, "description", r.Description) + populate(objectMap, "minAppIdVersion", r.MinAppIDVersion) + populate(objectMap, "panEtag", r.PanEtag) + populate(objectMap, "panLocation", r.PanLocation) + populate(objectMap, "provisioningState", r.ProvisioningState) + populate(objectMap, "scope", r.Scope) + populate(objectMap, "securityServices", r.SecurityServices) + return json.Marshal(objectMap) +} + +// UnmarshalJSON implements the json.Unmarshaller interface for type RulestackProperties. +func (r *RulestackProperties) UnmarshalJSON(data []byte) error { + var rawMsg map[string]json.RawMessage + if err := json.Unmarshal(data, &rawMsg); err != nil { + return fmt.Errorf("unmarshalling type %T: %v", r, err) + } + for key, val := range rawMsg { + var err error + switch key { + case "associatedSubscriptions": + err = unpopulate(val, "AssociatedSubscriptions", &r.AssociatedSubscriptions) + delete(rawMsg, key) + case "defaultMode": + err = unpopulate(val, "DefaultMode", &r.DefaultMode) + delete(rawMsg, key) + case "description": + err = unpopulate(val, "Description", &r.Description) + delete(rawMsg, key) + case "minAppIdVersion": + err = unpopulate(val, "MinAppIDVersion", &r.MinAppIDVersion) + delete(rawMsg, key) + case "panEtag": + err = unpopulate(val, "PanEtag", &r.PanEtag) + delete(rawMsg, key) + case "panLocation": + err = unpopulate(val, "PanLocation", &r.PanLocation) + delete(rawMsg, key) + case "provisioningState": + err = unpopulate(val, "ProvisioningState", &r.ProvisioningState) + delete(rawMsg, key) + case "scope": + err = unpopulate(val, "Scope", &r.Scope) + delete(rawMsg, key) + case "securityServices": + err = unpopulate(val, "SecurityServices", &r.SecurityServices) + delete(rawMsg, key) + } + if err != nil { + return fmt.Errorf("unmarshalling type %T: %v", r, err) + } + } + return nil +} + +// MarshalJSON implements the json.Marshaller interface for type SecurityServices. +func (s SecurityServices) MarshalJSON() ([]byte, error) { + objectMap := make(map[string]any) + populate(objectMap, "antiSpywareProfile", s.AntiSpywareProfile) + populate(objectMap, "antiVirusProfile", s.AntiVirusProfile) + populate(objectMap, "dnsSubscription", s.DNSSubscription) + populate(objectMap, "fileBlockingProfile", s.FileBlockingProfile) + populate(objectMap, "outboundTrustCertificate", s.OutboundTrustCertificate) + populate(objectMap, "outboundUnTrustCertificate", s.OutboundUnTrustCertificate) + populate(objectMap, "urlFilteringProfile", s.URLFilteringProfile) + populate(objectMap, "vulnerabilityProfile", s.VulnerabilityProfile) + return json.Marshal(objectMap) +} + +// UnmarshalJSON implements the json.Unmarshaller interface for type SecurityServices. +func (s *SecurityServices) UnmarshalJSON(data []byte) error { + var rawMsg map[string]json.RawMessage + if err := json.Unmarshal(data, &rawMsg); err != nil { + return fmt.Errorf("unmarshalling type %T: %v", s, err) + } + for key, val := range rawMsg { + var err error + switch key { + case "antiSpywareProfile": + err = unpopulate(val, "AntiSpywareProfile", &s.AntiSpywareProfile) + delete(rawMsg, key) + case "antiVirusProfile": + err = unpopulate(val, "AntiVirusProfile", &s.AntiVirusProfile) + delete(rawMsg, key) + case "dnsSubscription": + err = unpopulate(val, "DNSSubscription", &s.DNSSubscription) + delete(rawMsg, key) + case "fileBlockingProfile": + err = unpopulate(val, "FileBlockingProfile", &s.FileBlockingProfile) + delete(rawMsg, key) + case "outboundTrustCertificate": + err = unpopulate(val, "OutboundTrustCertificate", &s.OutboundTrustCertificate) + delete(rawMsg, key) + case "outboundUnTrustCertificate": + err = unpopulate(val, "OutboundUnTrustCertificate", &s.OutboundUnTrustCertificate) + delete(rawMsg, key) + case "urlFilteringProfile": + err = unpopulate(val, "URLFilteringProfile", &s.URLFilteringProfile) + delete(rawMsg, key) + case "vulnerabilityProfile": + err = unpopulate(val, "VulnerabilityProfile", &s.VulnerabilityProfile) + delete(rawMsg, key) + } + if err != nil { + return fmt.Errorf("unmarshalling type %T: %v", s, err) + } + } + return nil +} + +// MarshalJSON implements the json.Marshaller interface for type SecurityServicesResponse. +func (s SecurityServicesResponse) MarshalJSON() ([]byte, error) { + objectMap := make(map[string]any) + populate(objectMap, "nextLink", s.NextLink) + populate(objectMap, "value", s.Value) + return json.Marshal(objectMap) +} + +// UnmarshalJSON implements the json.Unmarshaller interface for type SecurityServicesResponse. +func (s *SecurityServicesResponse) UnmarshalJSON(data []byte) error { + var rawMsg map[string]json.RawMessage + if err := json.Unmarshal(data, &rawMsg); err != nil { + return fmt.Errorf("unmarshalling type %T: %v", s, err) + } + for key, val := range rawMsg { + var err error + switch key { + case "nextLink": + err = unpopulate(val, "NextLink", &s.NextLink) + delete(rawMsg, key) + case "value": + err = unpopulate(val, "Value", &s.Value) + delete(rawMsg, key) + } + if err != nil { + return fmt.Errorf("unmarshalling type %T: %v", s, err) + } + } + return nil +} + +// MarshalJSON implements the json.Marshaller interface for type SecurityServicesTypeList. +func (s SecurityServicesTypeList) MarshalJSON() ([]byte, error) { + objectMap := make(map[string]any) + populate(objectMap, "entry", s.Entry) + populate(objectMap, "type", s.Type) + return json.Marshal(objectMap) +} + +// UnmarshalJSON implements the json.Unmarshaller interface for type SecurityServicesTypeList. +func (s *SecurityServicesTypeList) UnmarshalJSON(data []byte) error { + var rawMsg map[string]json.RawMessage + if err := json.Unmarshal(data, &rawMsg); err != nil { + return fmt.Errorf("unmarshalling type %T: %v", s, err) + } + for key, val := range rawMsg { + var err error + switch key { + case "entry": + err = unpopulate(val, "Entry", &s.Entry) + delete(rawMsg, key) + case "type": + err = unpopulate(val, "Type", &s.Type) + delete(rawMsg, key) + } + if err != nil { + return fmt.Errorf("unmarshalling type %T: %v", s, err) + } + } + return nil +} + +// MarshalJSON implements the json.Marshaller interface for type SourceAddr. +func (s SourceAddr) MarshalJSON() ([]byte, error) { + objectMap := make(map[string]any) + populate(objectMap, "cidrs", s.Cidrs) + populate(objectMap, "countries", s.Countries) + populate(objectMap, "feeds", s.Feeds) + populate(objectMap, "prefixLists", s.PrefixLists) + return json.Marshal(objectMap) +} + +// UnmarshalJSON implements the json.Unmarshaller interface for type SourceAddr. +func (s *SourceAddr) UnmarshalJSON(data []byte) error { + var rawMsg map[string]json.RawMessage + if err := json.Unmarshal(data, &rawMsg); err != nil { + return fmt.Errorf("unmarshalling type %T: %v", s, err) + } + for key, val := range rawMsg { + var err error + switch key { + case "cidrs": + err = unpopulate(val, "Cidrs", &s.Cidrs) + delete(rawMsg, key) + case "countries": + err = unpopulate(val, "Countries", &s.Countries) + delete(rawMsg, key) + case "feeds": + err = unpopulate(val, "Feeds", &s.Feeds) + delete(rawMsg, key) + case "prefixLists": + err = unpopulate(val, "PrefixLists", &s.PrefixLists) + delete(rawMsg, key) + } + if err != nil { + return fmt.Errorf("unmarshalling type %T: %v", s, err) + } + } + return nil +} + +// MarshalJSON implements the json.Marshaller interface for type StorageAccount. +func (s StorageAccount) MarshalJSON() ([]byte, error) { + objectMap := make(map[string]any) + populate(objectMap, "accountName", s.AccountName) + populate(objectMap, "id", s.ID) + populate(objectMap, "subscriptionId", s.SubscriptionID) + return json.Marshal(objectMap) +} + +// UnmarshalJSON implements the json.Unmarshaller interface for type StorageAccount. +func (s *StorageAccount) UnmarshalJSON(data []byte) error { + var rawMsg map[string]json.RawMessage + if err := json.Unmarshal(data, &rawMsg); err != nil { + return fmt.Errorf("unmarshalling type %T: %v", s, err) + } + for key, val := range rawMsg { + var err error + switch key { + case "accountName": + err = unpopulate(val, "AccountName", &s.AccountName) + delete(rawMsg, key) + case "id": + err = unpopulate(val, "ID", &s.ID) + delete(rawMsg, key) + case "subscriptionId": + err = unpopulate(val, "SubscriptionID", &s.SubscriptionID) + delete(rawMsg, key) + } + if err != nil { + return fmt.Errorf("unmarshalling type %T: %v", s, err) + } + } + return nil +} + +// MarshalJSON implements the json.Marshaller interface for type SupportInfo. +func (s SupportInfo) MarshalJSON() ([]byte, error) { + objectMap := make(map[string]any) + populate(objectMap, "accountId", s.AccountID) + populate(objectMap, "accountRegistered", s.AccountRegistered) + populate(objectMap, "freeTrial", s.FreeTrial) + populate(objectMap, "freeTrialCreditLeft", s.FreeTrialCreditLeft) + populate(objectMap, "freeTrialDaysLeft", s.FreeTrialDaysLeft) + populate(objectMap, "helpURL", s.HelpURL) + populate(objectMap, "productSku", s.ProductSKU) + populate(objectMap, "productSerial", s.ProductSerial) + populate(objectMap, "registerURL", s.RegisterURL) + populate(objectMap, "supportURL", s.SupportURL) + populate(objectMap, "userDomainSupported", s.UserDomainSupported) + populate(objectMap, "userRegistered", s.UserRegistered) + return json.Marshal(objectMap) +} + +// UnmarshalJSON implements the json.Unmarshaller interface for type SupportInfo. +func (s *SupportInfo) UnmarshalJSON(data []byte) error { + var rawMsg map[string]json.RawMessage + if err := json.Unmarshal(data, &rawMsg); err != nil { + return fmt.Errorf("unmarshalling type %T: %v", s, err) + } + for key, val := range rawMsg { + var err error + switch key { + case "accountId": + err = unpopulate(val, "AccountID", &s.AccountID) + delete(rawMsg, key) + case "accountRegistered": + err = unpopulate(val, "AccountRegistered", &s.AccountRegistered) + delete(rawMsg, key) + case "freeTrial": + err = unpopulate(val, "FreeTrial", &s.FreeTrial) + delete(rawMsg, key) + case "freeTrialCreditLeft": + err = unpopulate(val, "FreeTrialCreditLeft", &s.FreeTrialCreditLeft) + delete(rawMsg, key) + case "freeTrialDaysLeft": + err = unpopulate(val, "FreeTrialDaysLeft", &s.FreeTrialDaysLeft) + delete(rawMsg, key) + case "helpURL": + err = unpopulate(val, "HelpURL", &s.HelpURL) + delete(rawMsg, key) + case "productSku": + err = unpopulate(val, "ProductSKU", &s.ProductSKU) + delete(rawMsg, key) + case "productSerial": + err = unpopulate(val, "ProductSerial", &s.ProductSerial) + delete(rawMsg, key) + case "registerURL": + err = unpopulate(val, "RegisterURL", &s.RegisterURL) + delete(rawMsg, key) + case "supportURL": + err = unpopulate(val, "SupportURL", &s.SupportURL) + delete(rawMsg, key) + case "userDomainSupported": + err = unpopulate(val, "UserDomainSupported", &s.UserDomainSupported) + delete(rawMsg, key) + case "userRegistered": + err = unpopulate(val, "UserRegistered", &s.UserRegistered) + delete(rawMsg, key) + } + if err != nil { + return fmt.Errorf("unmarshalling type %T: %v", s, err) + } + } + return nil +} + +// MarshalJSON implements the json.Marshaller interface for type SystemData. +func (s SystemData) MarshalJSON() ([]byte, error) { + objectMap := make(map[string]any) + populateTimeRFC3339(objectMap, "createdAt", s.CreatedAt) + populate(objectMap, "createdBy", s.CreatedBy) + populate(objectMap, "createdByType", s.CreatedByType) + populateTimeRFC3339(objectMap, "lastModifiedAt", s.LastModifiedAt) + populate(objectMap, "lastModifiedBy", s.LastModifiedBy) + populate(objectMap, "lastModifiedByType", s.LastModifiedByType) + return json.Marshal(objectMap) +} + +// UnmarshalJSON implements the json.Unmarshaller interface for type SystemData. +func (s *SystemData) UnmarshalJSON(data []byte) error { + var rawMsg map[string]json.RawMessage + if err := json.Unmarshal(data, &rawMsg); err != nil { + return fmt.Errorf("unmarshalling type %T: %v", s, err) + } + for key, val := range rawMsg { + var err error + switch key { + case "createdAt": + err = unpopulateTimeRFC3339(val, "CreatedAt", &s.CreatedAt) + delete(rawMsg, key) + case "createdBy": + err = unpopulate(val, "CreatedBy", &s.CreatedBy) + delete(rawMsg, key) + case "createdByType": + err = unpopulate(val, "CreatedByType", &s.CreatedByType) + delete(rawMsg, key) + case "lastModifiedAt": + err = unpopulateTimeRFC3339(val, "LastModifiedAt", &s.LastModifiedAt) + delete(rawMsg, key) + case "lastModifiedBy": + err = unpopulate(val, "LastModifiedBy", &s.LastModifiedBy) + delete(rawMsg, key) + case "lastModifiedByType": + err = unpopulate(val, "LastModifiedByType", &s.LastModifiedByType) + delete(rawMsg, key) + } + if err != nil { + return fmt.Errorf("unmarshalling type %T: %v", s, err) + } + } + return nil +} + +// MarshalJSON implements the json.Marshaller interface for type TagInfo. +func (t TagInfo) MarshalJSON() ([]byte, error) { + objectMap := make(map[string]any) + populate(objectMap, "key", t.Key) + populate(objectMap, "value", t.Value) + return json.Marshal(objectMap) +} + +// UnmarshalJSON implements the json.Unmarshaller interface for type TagInfo. +func (t *TagInfo) UnmarshalJSON(data []byte) error { + var rawMsg map[string]json.RawMessage + if err := json.Unmarshal(data, &rawMsg); err != nil { + return fmt.Errorf("unmarshalling type %T: %v", t, err) + } + for key, val := range rawMsg { + var err error + switch key { + case "key": + err = unpopulate(val, "Key", &t.Key) + delete(rawMsg, key) + case "value": + err = unpopulate(val, "Value", &t.Value) + delete(rawMsg, key) + } + if err != nil { + return fmt.Errorf("unmarshalling type %T: %v", t, err) + } + } + return nil +} + +// MarshalJSON implements the json.Marshaller interface for type VnetConfiguration. +func (v VnetConfiguration) MarshalJSON() ([]byte, error) { + objectMap := make(map[string]any) + populate(objectMap, "ipOfTrustSubnetForUdr", v.IPOfTrustSubnetForUdr) + populate(objectMap, "trustSubnet", v.TrustSubnet) + populate(objectMap, "unTrustSubnet", v.UnTrustSubnet) + populate(objectMap, "vnet", v.Vnet) + return json.Marshal(objectMap) +} + +// UnmarshalJSON implements the json.Unmarshaller interface for type VnetConfiguration. +func (v *VnetConfiguration) UnmarshalJSON(data []byte) error { + var rawMsg map[string]json.RawMessage + if err := json.Unmarshal(data, &rawMsg); err != nil { + return fmt.Errorf("unmarshalling type %T: %v", v, err) + } + for key, val := range rawMsg { + var err error + switch key { + case "ipOfTrustSubnetForUdr": + err = unpopulate(val, "IPOfTrustSubnetForUdr", &v.IPOfTrustSubnetForUdr) + delete(rawMsg, key) + case "trustSubnet": + err = unpopulate(val, "TrustSubnet", &v.TrustSubnet) + delete(rawMsg, key) + case "unTrustSubnet": + err = unpopulate(val, "UnTrustSubnet", &v.UnTrustSubnet) + delete(rawMsg, key) + case "vnet": + err = unpopulate(val, "Vnet", &v.Vnet) + delete(rawMsg, key) + } + if err != nil { + return fmt.Errorf("unmarshalling type %T: %v", v, err) + } + } + return nil +} + +// MarshalJSON implements the json.Marshaller interface for type VwanConfiguration. +func (v VwanConfiguration) MarshalJSON() ([]byte, error) { + objectMap := make(map[string]any) + populate(objectMap, "ipOfTrustSubnetForUdr", v.IPOfTrustSubnetForUdr) + populate(objectMap, "networkVirtualApplianceId", v.NetworkVirtualApplianceID) + populate(objectMap, "trustSubnet", v.TrustSubnet) + populate(objectMap, "unTrustSubnet", v.UnTrustSubnet) + populate(objectMap, "vHub", v.VHub) + return json.Marshal(objectMap) +} + +// UnmarshalJSON implements the json.Unmarshaller interface for type VwanConfiguration. +func (v *VwanConfiguration) UnmarshalJSON(data []byte) error { + var rawMsg map[string]json.RawMessage + if err := json.Unmarshal(data, &rawMsg); err != nil { + return fmt.Errorf("unmarshalling type %T: %v", v, err) + } + for key, val := range rawMsg { + var err error + switch key { + case "ipOfTrustSubnetForUdr": + err = unpopulate(val, "IPOfTrustSubnetForUdr", &v.IPOfTrustSubnetForUdr) + delete(rawMsg, key) + case "networkVirtualApplianceId": + err = unpopulate(val, "NetworkVirtualApplianceID", &v.NetworkVirtualApplianceID) + delete(rawMsg, key) + case "trustSubnet": + err = unpopulate(val, "TrustSubnet", &v.TrustSubnet) + delete(rawMsg, key) + case "unTrustSubnet": + err = unpopulate(val, "UnTrustSubnet", &v.UnTrustSubnet) + delete(rawMsg, key) + case "vHub": + err = unpopulate(val, "VHub", &v.VHub) + delete(rawMsg, key) + } + if err != nil { + return fmt.Errorf("unmarshalling type %T: %v", v, err) + } + } + return nil +} + +func populate(m map[string]any, k string, v any) { + if v == nil { + return + } else if azcore.IsNullValue(v) { + m[k] = nil + } else if !reflect.ValueOf(v).IsNil() { + m[k] = v + } +} + +func unpopulate(data json.RawMessage, fn string, v any) error { + if data == nil { + return nil + } + if err := json.Unmarshal(data, v); err != nil { + return fmt.Errorf("struct field %s: %v", fn, err) + } + return nil +} diff --git a/sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/operations_client.go b/sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/operations_client.go new file mode 100644 index 000000000000..78a6eb8a14b1 --- /dev/null +++ b/sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/operations_client.go @@ -0,0 +1,94 @@ +//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. +// Code generated by Microsoft (R) AutoRest Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. +// DO NOT EDIT. + +package armpanngfw + +import ( + "context" + "github.com/Azure/azure-sdk-for-go/sdk/azcore" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/arm" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/policy" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime" + "net/http" +) + +// OperationsClient contains the methods for the Operations group. +// Don't use this type directly, use NewOperationsClient() instead. +type OperationsClient struct { + internal *arm.Client +} + +// NewOperationsClient creates a new instance of OperationsClient with the specified values. +// - credential - used to authorize requests. Usually a credential from azidentity. +// - options - pass nil to accept the default values. +func NewOperationsClient(credential azcore.TokenCredential, options *arm.ClientOptions) (*OperationsClient, error) { + cl, err := arm.NewClient(moduleName+".OperationsClient", moduleVersion, credential, options) + if err != nil { + return nil, err + } + client := &OperationsClient{ + internal: cl, + } + return client, nil +} + +// NewListPager - List the operations for the provider +// +// Generated from API version 2022-08-29-preview +// - options - OperationsClientListOptions contains the optional parameters for the OperationsClient.NewListPager method. +func (client *OperationsClient) NewListPager(options *OperationsClientListOptions) *runtime.Pager[OperationsClientListResponse] { + return runtime.NewPager(runtime.PagingHandler[OperationsClientListResponse]{ + More: func(page OperationsClientListResponse) bool { + return page.NextLink != nil && len(*page.NextLink) > 0 + }, + Fetcher: func(ctx context.Context, page *OperationsClientListResponse) (OperationsClientListResponse, error) { + var req *policy.Request + var err error + if page == nil { + req, err = client.listCreateRequest(ctx, options) + } else { + req, err = runtime.NewRequest(ctx, http.MethodGet, *page.NextLink) + } + if err != nil { + return OperationsClientListResponse{}, err + } + resp, err := client.internal.Pipeline().Do(req) + if err != nil { + return OperationsClientListResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusOK) { + return OperationsClientListResponse{}, runtime.NewResponseError(resp) + } + return client.listHandleResponse(resp) + }, + }) +} + +// listCreateRequest creates the List request. +func (client *OperationsClient) listCreateRequest(ctx context.Context, options *OperationsClientListOptions) (*policy.Request, error) { + urlPath := "/providers/PaloAltoNetworks.Cloudngfw/operations" + req, err := runtime.NewRequest(ctx, http.MethodGet, runtime.JoinPaths(client.internal.Endpoint(), urlPath)) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("api-version", "2022-08-29-preview") + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["Accept"] = []string{"application/json"} + return req, nil +} + +// listHandleResponse handles the List response. +func (client *OperationsClient) listHandleResponse(resp *http.Response) (OperationsClientListResponse, error) { + result := OperationsClientListResponse{} + if err := runtime.UnmarshalAsJSON(resp, &result.OperationListResult); err != nil { + return OperationsClientListResponse{}, err + } + return result, nil +} diff --git a/sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/operations_client_example_test.go b/sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/operations_client_example_test.go new file mode 100644 index 000000000000..e2b9dff810bb --- /dev/null +++ b/sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/operations_client_example_test.go @@ -0,0 +1,85 @@ +//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. +// Code generated by Microsoft (R) AutoRest Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. +// DO NOT EDIT. + +package armpanngfw_test + +import ( + "context" + "log" + + "github.com/Azure/azure-sdk-for-go/sdk/azidentity" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/paloaltonetworksngfw/armpanngfw" +) + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/Operations_List_MaximumSet_Gen.json +func ExampleOperationsClient_NewListPager_operationsListMaximumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + pager := clientFactory.NewOperationsClient().NewListPager(nil) + for pager.More() { + page, err := pager.NextPage(ctx) + if err != nil { + log.Fatalf("failed to advance page: %v", err) + } + for _, v := range page.Value { + // You could use page here. We use blank identifier for just demo purposes. + _ = v + } + // If the HTTP response code is 200 as defined in example definition, your page structure would look as follows. Please pay attention that all the values in the output are fake values for just demo purposes. + // page.OperationListResult = armpanngfw.OperationListResult{ + // Value: []*armpanngfw.Operation{ + // { + // Name: to.Ptr("aaa"), + // ActionType: to.Ptr(armpanngfw.ActionTypeInternal), + // Display: &armpanngfw.OperationDisplay{ + // Description: to.Ptr("aaaaaaaa"), + // Operation: to.Ptr("aaaaaaaaaaaaaaaaaaaaaaaaa"), + // Provider: to.Ptr("aaaaaaaaaaa"), + // Resource: to.Ptr("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"), + // }, + // IsDataAction: to.Ptr(true), + // Origin: to.Ptr(armpanngfw.OriginUser), + // }}, + // } + } +} + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/Operations_List_MinimumSet_Gen.json +func ExampleOperationsClient_NewListPager_operationsListMinimumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + pager := clientFactory.NewOperationsClient().NewListPager(nil) + for pager.More() { + page, err := pager.NextPage(ctx) + if err != nil { + log.Fatalf("failed to advance page: %v", err) + } + for _, v := range page.Value { + // You could use page here. We use blank identifier for just demo purposes. + _ = v + } + // If the HTTP response code is 200 as defined in example definition, your page structure would look as follows. Please pay attention that all the values in the output are fake values for just demo purposes. + // page.OperationListResult = armpanngfw.OperationListResult{ + // } + } +} diff --git a/sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/postrules_client.go b/sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/postrules_client.go new file mode 100644 index 000000000000..4d5021eef05b --- /dev/null +++ b/sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/postrules_client.go @@ -0,0 +1,441 @@ +//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. +// Code generated by Microsoft (R) AutoRest Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. +// DO NOT EDIT. + +package armpanngfw + +import ( + "context" + "errors" + "github.com/Azure/azure-sdk-for-go/sdk/azcore" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/arm" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/policy" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime" + "net/http" + "net/url" + "strings" +) + +// PostRulesClient contains the methods for the PostRules group. +// Don't use this type directly, use NewPostRulesClient() instead. +type PostRulesClient struct { + internal *arm.Client +} + +// NewPostRulesClient creates a new instance of PostRulesClient with the specified values. +// - credential - used to authorize requests. Usually a credential from azidentity. +// - options - pass nil to accept the default values. +func NewPostRulesClient(credential azcore.TokenCredential, options *arm.ClientOptions) (*PostRulesClient, error) { + cl, err := arm.NewClient(moduleName+".PostRulesClient", moduleVersion, credential, options) + if err != nil { + return nil, err + } + client := &PostRulesClient{ + internal: cl, + } + return client, nil +} + +// BeginCreateOrUpdate - Create a PostRulesResource +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2022-08-29-preview +// - globalRulestackName - GlobalRulestack resource name +// - priority - Post Rule priority +// - resource - Resource create parameters. +// - options - PostRulesClientBeginCreateOrUpdateOptions contains the optional parameters for the PostRulesClient.BeginCreateOrUpdate +// method. +func (client *PostRulesClient) BeginCreateOrUpdate(ctx context.Context, globalRulestackName string, priority string, resource PostRulesResource, options *PostRulesClientBeginCreateOrUpdateOptions) (*runtime.Poller[PostRulesClientCreateOrUpdateResponse], error) { + if options == nil || options.ResumeToken == "" { + resp, err := client.createOrUpdate(ctx, globalRulestackName, priority, resource, options) + if err != nil { + return nil, err + } + return runtime.NewPoller(resp, client.internal.Pipeline(), &runtime.NewPollerOptions[PostRulesClientCreateOrUpdateResponse]{ + FinalStateVia: runtime.FinalStateViaAzureAsyncOp, + }) + } else { + return runtime.NewPollerFromResumeToken[PostRulesClientCreateOrUpdateResponse](options.ResumeToken, client.internal.Pipeline(), nil) + } +} + +// CreateOrUpdate - Create a PostRulesResource +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2022-08-29-preview +func (client *PostRulesClient) createOrUpdate(ctx context.Context, globalRulestackName string, priority string, resource PostRulesResource, options *PostRulesClientBeginCreateOrUpdateOptions) (*http.Response, error) { + req, err := client.createOrUpdateCreateRequest(ctx, globalRulestackName, priority, resource, options) + if err != nil { + return nil, err + } + resp, err := client.internal.Pipeline().Do(req) + if err != nil { + return nil, err + } + if !runtime.HasStatusCode(resp, http.StatusOK, http.StatusCreated) { + return nil, runtime.NewResponseError(resp) + } + return resp, nil +} + +// createOrUpdateCreateRequest creates the CreateOrUpdate request. +func (client *PostRulesClient) createOrUpdateCreateRequest(ctx context.Context, globalRulestackName string, priority string, resource PostRulesResource, options *PostRulesClientBeginCreateOrUpdateOptions) (*policy.Request, error) { + urlPath := "/providers/PaloAltoNetworks.Cloudngfw/globalRulestacks/{globalRulestackName}/postRules/{priority}" + if globalRulestackName == "" { + return nil, errors.New("parameter globalRulestackName cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{globalRulestackName}", url.PathEscape(globalRulestackName)) + if priority == "" { + return nil, errors.New("parameter priority cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{priority}", url.PathEscape(priority)) + req, err := runtime.NewRequest(ctx, http.MethodPut, runtime.JoinPaths(client.internal.Endpoint(), urlPath)) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("api-version", "2022-08-29-preview") + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["Accept"] = []string{"application/json"} + return req, runtime.MarshalAsJSON(req, resource) +} + +// BeginDelete - Delete a PostRulesResource +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2022-08-29-preview +// - globalRulestackName - GlobalRulestack resource name +// - priority - Post Rule priority +// - options - PostRulesClientBeginDeleteOptions contains the optional parameters for the PostRulesClient.BeginDelete method. +func (client *PostRulesClient) BeginDelete(ctx context.Context, globalRulestackName string, priority string, options *PostRulesClientBeginDeleteOptions) (*runtime.Poller[PostRulesClientDeleteResponse], error) { + if options == nil || options.ResumeToken == "" { + resp, err := client.deleteOperation(ctx, globalRulestackName, priority, options) + if err != nil { + return nil, err + } + return runtime.NewPoller(resp, client.internal.Pipeline(), &runtime.NewPollerOptions[PostRulesClientDeleteResponse]{ + FinalStateVia: runtime.FinalStateViaAzureAsyncOp, + }) + } else { + return runtime.NewPollerFromResumeToken[PostRulesClientDeleteResponse](options.ResumeToken, client.internal.Pipeline(), nil) + } +} + +// Delete - Delete a PostRulesResource +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2022-08-29-preview +func (client *PostRulesClient) deleteOperation(ctx context.Context, globalRulestackName string, priority string, options *PostRulesClientBeginDeleteOptions) (*http.Response, error) { + req, err := client.deleteCreateRequest(ctx, globalRulestackName, priority, options) + if err != nil { + return nil, err + } + resp, err := client.internal.Pipeline().Do(req) + if err != nil { + return nil, err + } + if !runtime.HasStatusCode(resp, http.StatusOK, http.StatusAccepted, http.StatusNoContent) { + return nil, runtime.NewResponseError(resp) + } + return resp, nil +} + +// deleteCreateRequest creates the Delete request. +func (client *PostRulesClient) deleteCreateRequest(ctx context.Context, globalRulestackName string, priority string, options *PostRulesClientBeginDeleteOptions) (*policy.Request, error) { + urlPath := "/providers/PaloAltoNetworks.Cloudngfw/globalRulestacks/{globalRulestackName}/postRules/{priority}" + if globalRulestackName == "" { + return nil, errors.New("parameter globalRulestackName cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{globalRulestackName}", url.PathEscape(globalRulestackName)) + if priority == "" { + return nil, errors.New("parameter priority cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{priority}", url.PathEscape(priority)) + req, err := runtime.NewRequest(ctx, http.MethodDelete, runtime.JoinPaths(client.internal.Endpoint(), urlPath)) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("api-version", "2022-08-29-preview") + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["Accept"] = []string{"application/json"} + return req, nil +} + +// Get - Get a PostRulesResource +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2022-08-29-preview +// - globalRulestackName - GlobalRulestack resource name +// - priority - Post Rule priority +// - options - PostRulesClientGetOptions contains the optional parameters for the PostRulesClient.Get method. +func (client *PostRulesClient) Get(ctx context.Context, globalRulestackName string, priority string, options *PostRulesClientGetOptions) (PostRulesClientGetResponse, error) { + req, err := client.getCreateRequest(ctx, globalRulestackName, priority, options) + if err != nil { + return PostRulesClientGetResponse{}, err + } + resp, err := client.internal.Pipeline().Do(req) + if err != nil { + return PostRulesClientGetResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusOK) { + return PostRulesClientGetResponse{}, runtime.NewResponseError(resp) + } + return client.getHandleResponse(resp) +} + +// getCreateRequest creates the Get request. +func (client *PostRulesClient) getCreateRequest(ctx context.Context, globalRulestackName string, priority string, options *PostRulesClientGetOptions) (*policy.Request, error) { + urlPath := "/providers/PaloAltoNetworks.Cloudngfw/globalRulestacks/{globalRulestackName}/postRules/{priority}" + if globalRulestackName == "" { + return nil, errors.New("parameter globalRulestackName cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{globalRulestackName}", url.PathEscape(globalRulestackName)) + if priority == "" { + return nil, errors.New("parameter priority cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{priority}", url.PathEscape(priority)) + req, err := runtime.NewRequest(ctx, http.MethodGet, runtime.JoinPaths(client.internal.Endpoint(), urlPath)) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("api-version", "2022-08-29-preview") + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["Accept"] = []string{"application/json"} + return req, nil +} + +// getHandleResponse handles the Get response. +func (client *PostRulesClient) getHandleResponse(resp *http.Response) (PostRulesClientGetResponse, error) { + result := PostRulesClientGetResponse{} + if err := runtime.UnmarshalAsJSON(resp, &result.PostRulesResource); err != nil { + return PostRulesClientGetResponse{}, err + } + return result, nil +} + +// GetCounters - Get counters +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2022-08-29-preview +// - globalRulestackName - GlobalRulestack resource name +// - priority - Post Rule priority +// - options - PostRulesClientGetCountersOptions contains the optional parameters for the PostRulesClient.GetCounters method. +func (client *PostRulesClient) GetCounters(ctx context.Context, globalRulestackName string, priority string, options *PostRulesClientGetCountersOptions) (PostRulesClientGetCountersResponse, error) { + req, err := client.getCountersCreateRequest(ctx, globalRulestackName, priority, options) + if err != nil { + return PostRulesClientGetCountersResponse{}, err + } + resp, err := client.internal.Pipeline().Do(req) + if err != nil { + return PostRulesClientGetCountersResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusOK) { + return PostRulesClientGetCountersResponse{}, runtime.NewResponseError(resp) + } + return client.getCountersHandleResponse(resp) +} + +// getCountersCreateRequest creates the GetCounters request. +func (client *PostRulesClient) getCountersCreateRequest(ctx context.Context, globalRulestackName string, priority string, options *PostRulesClientGetCountersOptions) (*policy.Request, error) { + urlPath := "/providers/PaloAltoNetworks.Cloudngfw/globalRulestacks/{globalRulestackName}/postRules/{priority}/getCounters" + if globalRulestackName == "" { + return nil, errors.New("parameter globalRulestackName cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{globalRulestackName}", url.PathEscape(globalRulestackName)) + if priority == "" { + return nil, errors.New("parameter priority cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{priority}", url.PathEscape(priority)) + req, err := runtime.NewRequest(ctx, http.MethodPost, runtime.JoinPaths(client.internal.Endpoint(), urlPath)) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("api-version", "2022-08-29-preview") + if options != nil && options.FirewallName != nil { + reqQP.Set("firewallName", *options.FirewallName) + } + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["Accept"] = []string{"application/json"} + return req, nil +} + +// getCountersHandleResponse handles the GetCounters response. +func (client *PostRulesClient) getCountersHandleResponse(resp *http.Response) (PostRulesClientGetCountersResponse, error) { + result := PostRulesClientGetCountersResponse{} + if err := runtime.UnmarshalAsJSON(resp, &result.RuleCounter); err != nil { + return PostRulesClientGetCountersResponse{}, err + } + return result, nil +} + +// NewListPager - List PostRulesResource resources by Tenant +// +// Generated from API version 2022-08-29-preview +// - globalRulestackName - GlobalRulestack resource name +// - options - PostRulesClientListOptions contains the optional parameters for the PostRulesClient.NewListPager method. +func (client *PostRulesClient) NewListPager(globalRulestackName string, options *PostRulesClientListOptions) *runtime.Pager[PostRulesClientListResponse] { + return runtime.NewPager(runtime.PagingHandler[PostRulesClientListResponse]{ + More: func(page PostRulesClientListResponse) bool { + return page.NextLink != nil && len(*page.NextLink) > 0 + }, + Fetcher: func(ctx context.Context, page *PostRulesClientListResponse) (PostRulesClientListResponse, error) { + var req *policy.Request + var err error + if page == nil { + req, err = client.listCreateRequest(ctx, globalRulestackName, options) + } else { + req, err = runtime.NewRequest(ctx, http.MethodGet, *page.NextLink) + } + if err != nil { + return PostRulesClientListResponse{}, err + } + resp, err := client.internal.Pipeline().Do(req) + if err != nil { + return PostRulesClientListResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusOK) { + return PostRulesClientListResponse{}, runtime.NewResponseError(resp) + } + return client.listHandleResponse(resp) + }, + }) +} + +// listCreateRequest creates the List request. +func (client *PostRulesClient) listCreateRequest(ctx context.Context, globalRulestackName string, options *PostRulesClientListOptions) (*policy.Request, error) { + urlPath := "/providers/PaloAltoNetworks.Cloudngfw/globalRulestacks/{globalRulestackName}/postRules" + if globalRulestackName == "" { + return nil, errors.New("parameter globalRulestackName cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{globalRulestackName}", url.PathEscape(globalRulestackName)) + req, err := runtime.NewRequest(ctx, http.MethodGet, runtime.JoinPaths(client.internal.Endpoint(), urlPath)) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("api-version", "2022-08-29-preview") + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["Accept"] = []string{"application/json"} + return req, nil +} + +// listHandleResponse handles the List response. +func (client *PostRulesClient) listHandleResponse(resp *http.Response) (PostRulesClientListResponse, error) { + result := PostRulesClientListResponse{} + if err := runtime.UnmarshalAsJSON(resp, &result.PostRulesResourceListResult); err != nil { + return PostRulesClientListResponse{}, err + } + return result, nil +} + +// RefreshCounters - Refresh counters +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2022-08-29-preview +// - globalRulestackName - GlobalRulestack resource name +// - priority - Post Rule priority +// - options - PostRulesClientRefreshCountersOptions contains the optional parameters for the PostRulesClient.RefreshCounters +// method. +func (client *PostRulesClient) RefreshCounters(ctx context.Context, globalRulestackName string, priority string, options *PostRulesClientRefreshCountersOptions) (PostRulesClientRefreshCountersResponse, error) { + req, err := client.refreshCountersCreateRequest(ctx, globalRulestackName, priority, options) + if err != nil { + return PostRulesClientRefreshCountersResponse{}, err + } + resp, err := client.internal.Pipeline().Do(req) + if err != nil { + return PostRulesClientRefreshCountersResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusNoContent) { + return PostRulesClientRefreshCountersResponse{}, runtime.NewResponseError(resp) + } + return PostRulesClientRefreshCountersResponse{}, nil +} + +// refreshCountersCreateRequest creates the RefreshCounters request. +func (client *PostRulesClient) refreshCountersCreateRequest(ctx context.Context, globalRulestackName string, priority string, options *PostRulesClientRefreshCountersOptions) (*policy.Request, error) { + urlPath := "/providers/PaloAltoNetworks.Cloudngfw/globalRulestacks/{globalRulestackName}/postRules/{priority}/refreshCounters" + if globalRulestackName == "" { + return nil, errors.New("parameter globalRulestackName cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{globalRulestackName}", url.PathEscape(globalRulestackName)) + if priority == "" { + return nil, errors.New("parameter priority cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{priority}", url.PathEscape(priority)) + req, err := runtime.NewRequest(ctx, http.MethodPost, runtime.JoinPaths(client.internal.Endpoint(), urlPath)) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("api-version", "2022-08-29-preview") + if options != nil && options.FirewallName != nil { + reqQP.Set("firewallName", *options.FirewallName) + } + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["Accept"] = []string{"application/json"} + return req, nil +} + +// ResetCounters - Reset counters +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2022-08-29-preview +// - globalRulestackName - GlobalRulestack resource name +// - priority - Post Rule priority +// - options - PostRulesClientResetCountersOptions contains the optional parameters for the PostRulesClient.ResetCounters method. +func (client *PostRulesClient) ResetCounters(ctx context.Context, globalRulestackName string, priority string, options *PostRulesClientResetCountersOptions) (PostRulesClientResetCountersResponse, error) { + req, err := client.resetCountersCreateRequest(ctx, globalRulestackName, priority, options) + if err != nil { + return PostRulesClientResetCountersResponse{}, err + } + resp, err := client.internal.Pipeline().Do(req) + if err != nil { + return PostRulesClientResetCountersResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusOK) { + return PostRulesClientResetCountersResponse{}, runtime.NewResponseError(resp) + } + return client.resetCountersHandleResponse(resp) +} + +// resetCountersCreateRequest creates the ResetCounters request. +func (client *PostRulesClient) resetCountersCreateRequest(ctx context.Context, globalRulestackName string, priority string, options *PostRulesClientResetCountersOptions) (*policy.Request, error) { + urlPath := "/providers/PaloAltoNetworks.Cloudngfw/globalRulestacks/{globalRulestackName}/postRules/{priority}/resetCounters" + if globalRulestackName == "" { + return nil, errors.New("parameter globalRulestackName cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{globalRulestackName}", url.PathEscape(globalRulestackName)) + if priority == "" { + return nil, errors.New("parameter priority cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{priority}", url.PathEscape(priority)) + req, err := runtime.NewRequest(ctx, http.MethodPost, runtime.JoinPaths(client.internal.Endpoint(), urlPath)) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("api-version", "2022-08-29-preview") + if options != nil && options.FirewallName != nil { + reqQP.Set("firewallName", *options.FirewallName) + } + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["Accept"] = []string{"application/json"} + return req, nil +} + +// resetCountersHandleResponse handles the ResetCounters response. +func (client *PostRulesClient) resetCountersHandleResponse(resp *http.Response) (PostRulesClientResetCountersResponse, error) { + result := PostRulesClientResetCountersResponse{} + if err := runtime.UnmarshalAsJSON(resp, &result.RuleCounterReset); err != nil { + return PostRulesClientResetCountersResponse{}, err + } + return result, nil +} diff --git a/sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/postrules_client_example_test.go b/sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/postrules_client_example_test.go new file mode 100644 index 000000000000..70d6be251a30 --- /dev/null +++ b/sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/postrules_client_example_test.go @@ -0,0 +1,629 @@ +//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. +// Code generated by Microsoft (R) AutoRest Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. +// DO NOT EDIT. + +package armpanngfw_test + +import ( + "context" + "log" + + "github.com/Azure/azure-sdk-for-go/sdk/azcore/to" + "github.com/Azure/azure-sdk-for-go/sdk/azidentity" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/paloaltonetworksngfw/armpanngfw" +) + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/PostRules_List_MaximumSet_Gen.json +func ExamplePostRulesClient_NewListPager_postRulesListMaximumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + pager := clientFactory.NewPostRulesClient().NewListPager("lrs1", nil) + for pager.More() { + page, err := pager.NextPage(ctx) + if err != nil { + log.Fatalf("failed to advance page: %v", err) + } + for _, v := range page.Value { + // You could use page here. We use blank identifier for just demo purposes. + _ = v + } + // If the HTTP response code is 200 as defined in example definition, your page structure would look as follows. Please pay attention that all the values in the output are fake values for just demo purposes. + // page.PostRulesResourceListResult = armpanngfw.PostRulesResourceListResult{ + // Value: []*armpanngfw.PostRulesResource{ + // { + // Name: to.Ptr("aaaaaaaaaa"), + // Type: to.Ptr("aaaaaaaaaaaaaaaaaaaaaaaaaaaa"), + // ID: to.Ptr("aaaaaaaaaaaaaaaaaa"), + // SystemData: &armpanngfw.SystemData{ + // CreatedAt: to.Ptr(func() time.Time { t, _ := time.Parse(time.RFC3339Nano, "2022-09-09T05:08:24.229Z"); return t}()), + // CreatedBy: to.Ptr("praval"), + // CreatedByType: to.Ptr(armpanngfw.CreatedByTypeUser), + // LastModifiedAt: to.Ptr(func() time.Time { t, _ := time.Parse(time.RFC3339Nano, "2022-09-09T05:08:24.229Z"); return t}()), + // LastModifiedBy: to.Ptr("praval"), + // LastModifiedByType: to.Ptr(armpanngfw.CreatedByTypeUser), + // }, + // Properties: &armpanngfw.RuleEntry{ + // Description: to.Ptr("aaaaaaaaaaaaaaaaaaaaaaaaaaaa"), + // ActionType: to.Ptr(armpanngfw.ActionEnumAllow), + // Applications: []*string{ + // to.Ptr("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")}, + // AuditComment: to.Ptr("aaa"), + // Category: &armpanngfw.Category{ + // Feeds: []*string{ + // to.Ptr("aaaaaaaaaaaa")}, + // URLCustom: []*string{ + // to.Ptr("aaaaa")}, + // }, + // DecryptionRuleType: to.Ptr(armpanngfw.DecryptionRuleTypeEnumSSLOutboundInspection), + // Destination: &armpanngfw.DestinationAddr{ + // Cidrs: []*string{ + // to.Ptr("aaaaaaa")}, + // Countries: []*string{ + // to.Ptr("aaaaaaaaaaaaaa")}, + // Feeds: []*string{ + // to.Ptr("aaaaaaaaaaaaaaaaaaaaaaaaaa")}, + // FqdnLists: []*string{ + // to.Ptr("aaaaaaaaaaaaa")}, + // PrefixLists: []*string{ + // to.Ptr("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")}, + // }, + // EnableLogging: to.Ptr(armpanngfw.StateEnumDISABLED), + // Etag: to.Ptr("aaaaaaaaaaaaaaaaaaaa"), + // InboundInspectionCertificate: to.Ptr("aaaaaaaaaaaaaaaaaaaaaaaaaaa"), + // NegateDestination: to.Ptr(armpanngfw.BooleanEnumTRUE), + // NegateSource: to.Ptr(armpanngfw.BooleanEnumTRUE), + // Priority: to.Ptr[int32](24), + // ProtocolPortList: []*string{ + // to.Ptr("aaaaaaaaaaaa")}, + // ProvisioningState: to.Ptr(armpanngfw.ProvisioningStateSucceeded), + // RuleName: to.Ptr("aaaaaaaaaaaaaaaaaaaaaaaaa"), + // RuleState: to.Ptr(armpanngfw.StateEnumDISABLED), + // Source: &armpanngfw.SourceAddr{ + // Cidrs: []*string{ + // to.Ptr("aaa")}, + // Countries: []*string{ + // to.Ptr("aaaaa")}, + // Feeds: []*string{ + // to.Ptr("aaaaaaaaaaaaaaaaaaa")}, + // PrefixLists: []*string{ + // to.Ptr("aaaaaaaaaaaaaaaaaaaa")}, + // }, + // Tags: []*armpanngfw.TagInfo{ + // { + // Key: to.Ptr("keyName"), + // Value: to.Ptr("value"), + // }}, + // Protocol: to.Ptr("aaaa"), + // }, + // }}, + // } + } +} + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/PostRules_List_MinimumSet_Gen.json +func ExamplePostRulesClient_NewListPager_postRulesListMinimumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + pager := clientFactory.NewPostRulesClient().NewListPager("lrs1", nil) + for pager.More() { + page, err := pager.NextPage(ctx) + if err != nil { + log.Fatalf("failed to advance page: %v", err) + } + for _, v := range page.Value { + // You could use page here. We use blank identifier for just demo purposes. + _ = v + } + // If the HTTP response code is 200 as defined in example definition, your page structure would look as follows. Please pay attention that all the values in the output are fake values for just demo purposes. + // page.PostRulesResourceListResult = armpanngfw.PostRulesResourceListResult{ + // Value: []*armpanngfw.PostRulesResource{ + // { + // ID: to.Ptr("/providers/PaloAltoNetworks.Cloudngfw/globalRulestacks/lrs1/postrules/1"), + // Properties: &armpanngfw.RuleEntry{ + // RuleName: to.Ptr("aaaaaaaaaaaaaaaaaaaaaaaaa"), + // }, + // }}, + // } + } +} + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/PostRules_Get_MaximumSet_Gen.json +func ExamplePostRulesClient_Get_postRulesGetMaximumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + res, err := clientFactory.NewPostRulesClient().Get(ctx, "lrs1", "1", nil) + if err != nil { + log.Fatalf("failed to finish the request: %v", err) + } + // You could use response here. We use blank identifier for just demo purposes. + _ = res + // If the HTTP response code is 200 as defined in example definition, your response structure would look as follows. Please pay attention that all the values in the output are fake values for just demo purposes. + // res.PostRulesResource = armpanngfw.PostRulesResource{ + // Name: to.Ptr("aaaaaaaaaa"), + // Type: to.Ptr("aaaaaaaaaaaaaaaaaaaaaaaaaaaa"), + // ID: to.Ptr("aaaaaaaaaaaaaaaaaa"), + // SystemData: &armpanngfw.SystemData{ + // CreatedAt: to.Ptr(func() time.Time { t, _ := time.Parse(time.RFC3339Nano, "2022-09-09T05:08:24.229Z"); return t}()), + // CreatedBy: to.Ptr("praval"), + // CreatedByType: to.Ptr(armpanngfw.CreatedByTypeUser), + // LastModifiedAt: to.Ptr(func() time.Time { t, _ := time.Parse(time.RFC3339Nano, "2022-09-09T05:08:24.229Z"); return t}()), + // LastModifiedBy: to.Ptr("praval"), + // LastModifiedByType: to.Ptr(armpanngfw.CreatedByTypeUser), + // }, + // Properties: &armpanngfw.RuleEntry{ + // Description: to.Ptr("aaaaaaaaaaaaaaaaaaaaaaaaaaaa"), + // ActionType: to.Ptr(armpanngfw.ActionEnumAllow), + // Applications: []*string{ + // to.Ptr("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")}, + // AuditComment: to.Ptr("aaa"), + // Category: &armpanngfw.Category{ + // Feeds: []*string{ + // to.Ptr("aaaaaaaaaaaa")}, + // URLCustom: []*string{ + // to.Ptr("aaaaa")}, + // }, + // DecryptionRuleType: to.Ptr(armpanngfw.DecryptionRuleTypeEnumSSLOutboundInspection), + // Destination: &armpanngfw.DestinationAddr{ + // Cidrs: []*string{ + // to.Ptr("aaaaaaa")}, + // Countries: []*string{ + // to.Ptr("aaaaaaaaaaaaaa")}, + // Feeds: []*string{ + // to.Ptr("aaaaaaaaaaaaaaaaaaaaaaaaaa")}, + // FqdnLists: []*string{ + // to.Ptr("aaaaaaaaaaaaa")}, + // PrefixLists: []*string{ + // to.Ptr("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")}, + // }, + // EnableLogging: to.Ptr(armpanngfw.StateEnumDISABLED), + // Etag: to.Ptr("aaaaaaaaaaaaaaaaaaaa"), + // InboundInspectionCertificate: to.Ptr("aaaaaaaaaaaaaaaaaaaaaaaaaaa"), + // NegateDestination: to.Ptr(armpanngfw.BooleanEnumTRUE), + // NegateSource: to.Ptr(armpanngfw.BooleanEnumTRUE), + // Priority: to.Ptr[int32](24), + // ProtocolPortList: []*string{ + // to.Ptr("aaaaaaaaaaaa")}, + // ProvisioningState: to.Ptr(armpanngfw.ProvisioningStateSucceeded), + // RuleName: to.Ptr("aaaaaaaaaaaaaaaaaaaaaaaaa"), + // RuleState: to.Ptr(armpanngfw.StateEnumDISABLED), + // Source: &armpanngfw.SourceAddr{ + // Cidrs: []*string{ + // to.Ptr("aaa")}, + // Countries: []*string{ + // to.Ptr("aaaaa")}, + // Feeds: []*string{ + // to.Ptr("aaaaaaaaaaaaaaaaaaa")}, + // PrefixLists: []*string{ + // to.Ptr("aaaaaaaaaaaaaaaaaaaa")}, + // }, + // Tags: []*armpanngfw.TagInfo{ + // { + // Key: to.Ptr("keyName"), + // Value: to.Ptr("value"), + // }}, + // Protocol: to.Ptr("aaaa"), + // }, + // } +} + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/PostRules_Get_MinimumSet_Gen.json +func ExamplePostRulesClient_Get_postRulesGetMinimumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + res, err := clientFactory.NewPostRulesClient().Get(ctx, "lrs1", "1", nil) + if err != nil { + log.Fatalf("failed to finish the request: %v", err) + } + // You could use response here. We use blank identifier for just demo purposes. + _ = res + // If the HTTP response code is 200 as defined in example definition, your response structure would look as follows. Please pay attention that all the values in the output are fake values for just demo purposes. + // res.PostRulesResource = armpanngfw.PostRulesResource{ + // ID: to.Ptr("/providers/PaloAltoNetworks.Cloudngfw/globalRulestacks/lrs1/postrules/1"), + // Properties: &armpanngfw.RuleEntry{ + // RuleName: to.Ptr("aaaaaaaaaaaaaaaaaaaaaaaaa"), + // }, + // } +} + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/PostRules_CreateOrUpdate_MaximumSet_Gen.json +func ExamplePostRulesClient_BeginCreateOrUpdate_postRulesCreateOrUpdateMaximumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + poller, err := clientFactory.NewPostRulesClient().BeginCreateOrUpdate(ctx, "lrs1", "1", armpanngfw.PostRulesResource{ + Properties: &armpanngfw.RuleEntry{ + Description: to.Ptr("description of post rule"), + ActionType: to.Ptr(armpanngfw.ActionEnumAllow), + Applications: []*string{ + to.Ptr("app1")}, + AuditComment: to.Ptr("example comment"), + Category: &armpanngfw.Category{ + Feeds: []*string{ + to.Ptr("feed")}, + URLCustom: []*string{ + to.Ptr("https://microsoft.com")}, + }, + DecryptionRuleType: to.Ptr(armpanngfw.DecryptionRuleTypeEnumSSLOutboundInspection), + Destination: &armpanngfw.DestinationAddr{ + Cidrs: []*string{ + to.Ptr("1.0.0.1/10")}, + Countries: []*string{ + to.Ptr("India")}, + Feeds: []*string{ + to.Ptr("feed")}, + FqdnLists: []*string{ + to.Ptr("FQDN1")}, + PrefixLists: []*string{ + to.Ptr("PL1")}, + }, + EnableLogging: to.Ptr(armpanngfw.StateEnumDISABLED), + Etag: to.Ptr("c18e6eef-ba3e-49ee-8a85-2b36c863a9d0"), + InboundInspectionCertificate: to.Ptr("cert1"), + NegateDestination: to.Ptr(armpanngfw.BooleanEnumTRUE), + NegateSource: to.Ptr(armpanngfw.BooleanEnumTRUE), + ProtocolPortList: []*string{ + to.Ptr("80")}, + ProvisioningState: to.Ptr(armpanngfw.ProvisioningStateAccepted), + RuleName: to.Ptr("postRule1"), + RuleState: to.Ptr(armpanngfw.StateEnumDISABLED), + Source: &armpanngfw.SourceAddr{ + Cidrs: []*string{ + to.Ptr("1.0.0.1/10")}, + Countries: []*string{ + to.Ptr("India")}, + Feeds: []*string{ + to.Ptr("feed")}, + PrefixLists: []*string{ + to.Ptr("PL1")}, + }, + Tags: []*armpanngfw.TagInfo{ + { + Key: to.Ptr("keyName"), + Value: to.Ptr("value"), + }}, + Protocol: to.Ptr("HTTP"), + }, + }, nil) + if err != nil { + log.Fatalf("failed to finish the request: %v", err) + } + res, err := poller.PollUntilDone(ctx, nil) + if err != nil { + log.Fatalf("failed to pull the result: %v", err) + } + // You could use response here. We use blank identifier for just demo purposes. + _ = res + // If the HTTP response code is 200 as defined in example definition, your response structure would look as follows. Please pay attention that all the values in the output are fake values for just demo purposes. + // res.PostRulesResource = armpanngfw.PostRulesResource{ + // Name: to.Ptr("aaaaaaaaaa"), + // Type: to.Ptr("aaaaaaaaaaaaaaaaaaaaaaaaaaaa"), + // ID: to.Ptr("aaaaaaaaaaaaaaaaaa"), + // SystemData: &armpanngfw.SystemData{ + // CreatedAt: to.Ptr(func() time.Time { t, _ := time.Parse(time.RFC3339Nano, "2022-09-09T05:08:24.229Z"); return t}()), + // CreatedBy: to.Ptr("praval"), + // CreatedByType: to.Ptr(armpanngfw.CreatedByTypeUser), + // LastModifiedAt: to.Ptr(func() time.Time { t, _ := time.Parse(time.RFC3339Nano, "2022-09-09T05:08:24.229Z"); return t}()), + // LastModifiedBy: to.Ptr("praval"), + // LastModifiedByType: to.Ptr(armpanngfw.CreatedByTypeUser), + // }, + // Properties: &armpanngfw.RuleEntry{ + // Description: to.Ptr("aaaaaaaaaaaaaaaaaaaaaaaaaaaa"), + // ActionType: to.Ptr(armpanngfw.ActionEnumAllow), + // Applications: []*string{ + // to.Ptr("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")}, + // AuditComment: to.Ptr("aaa"), + // Category: &armpanngfw.Category{ + // Feeds: []*string{ + // to.Ptr("aaaaaaaaaaaa")}, + // URLCustom: []*string{ + // to.Ptr("aaaaa")}, + // }, + // DecryptionRuleType: to.Ptr(armpanngfw.DecryptionRuleTypeEnumSSLOutboundInspection), + // Destination: &armpanngfw.DestinationAddr{ + // Cidrs: []*string{ + // to.Ptr("aaaaaaa")}, + // Countries: []*string{ + // to.Ptr("aaaaaaaaaaaaaa")}, + // Feeds: []*string{ + // to.Ptr("aaaaaaaaaaaaaaaaaaaaaaaaaa")}, + // FqdnLists: []*string{ + // to.Ptr("aaaaaaaaaaaaa")}, + // PrefixLists: []*string{ + // to.Ptr("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")}, + // }, + // EnableLogging: to.Ptr(armpanngfw.StateEnumDISABLED), + // Etag: to.Ptr("aaaaaaaaaaaaaaaaaaaa"), + // InboundInspectionCertificate: to.Ptr("aaaaaaaaaaaaaaaaaaaaaaaaaaa"), + // NegateDestination: to.Ptr(armpanngfw.BooleanEnumTRUE), + // NegateSource: to.Ptr(armpanngfw.BooleanEnumTRUE), + // Priority: to.Ptr[int32](24), + // ProtocolPortList: []*string{ + // to.Ptr("aaaaaaaaaaaa")}, + // ProvisioningState: to.Ptr(armpanngfw.ProvisioningStateSucceeded), + // RuleName: to.Ptr("aaaaaaaaaaaaaaaaaaaaaaaaa"), + // RuleState: to.Ptr(armpanngfw.StateEnumDISABLED), + // Source: &armpanngfw.SourceAddr{ + // Cidrs: []*string{ + // to.Ptr("aaa")}, + // Countries: []*string{ + // to.Ptr("aaaaa")}, + // Feeds: []*string{ + // to.Ptr("aaaaaaaaaaaaaaaaaaa")}, + // PrefixLists: []*string{ + // to.Ptr("aaaaaaaaaaaaaaaaaaaa")}, + // }, + // Tags: []*armpanngfw.TagInfo{ + // { + // Key: to.Ptr("keyName"), + // Value: to.Ptr("value"), + // }}, + // Protocol: to.Ptr("aaaa"), + // }, + // } +} + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/PostRules_CreateOrUpdate_MinimumSet_Gen.json +func ExamplePostRulesClient_BeginCreateOrUpdate_postRulesCreateOrUpdateMinimumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + poller, err := clientFactory.NewPostRulesClient().BeginCreateOrUpdate(ctx, "lrs1", "1", armpanngfw.PostRulesResource{ + Properties: &armpanngfw.RuleEntry{ + RuleName: to.Ptr("postRule1"), + }, + }, nil) + if err != nil { + log.Fatalf("failed to finish the request: %v", err) + } + res, err := poller.PollUntilDone(ctx, nil) + if err != nil { + log.Fatalf("failed to pull the result: %v", err) + } + // You could use response here. We use blank identifier for just demo purposes. + _ = res + // If the HTTP response code is 200 as defined in example definition, your response structure would look as follows. Please pay attention that all the values in the output are fake values for just demo purposes. + // res.PostRulesResource = armpanngfw.PostRulesResource{ + // ID: to.Ptr("/providers/PaloAltoNetworks.Cloudngfw/globalRulestacks/lrs1/postrules/1"), + // Properties: &armpanngfw.RuleEntry{ + // RuleName: to.Ptr("aaaaaaaaaaaaaaaaaaaaaaaaa"), + // }, + // } +} + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/PostRules_Delete_MaximumSet_Gen.json +func ExamplePostRulesClient_BeginDelete_postRulesDeleteMaximumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + poller, err := clientFactory.NewPostRulesClient().BeginDelete(ctx, "lrs1", "1", nil) + if err != nil { + log.Fatalf("failed to finish the request: %v", err) + } + _, err = poller.PollUntilDone(ctx, nil) + if err != nil { + log.Fatalf("failed to pull the result: %v", err) + } +} + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/PostRules_Delete_MinimumSet_Gen.json +func ExamplePostRulesClient_BeginDelete_postRulesDeleteMinimumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + poller, err := clientFactory.NewPostRulesClient().BeginDelete(ctx, "lrs1", "1", nil) + if err != nil { + log.Fatalf("failed to finish the request: %v", err) + } + _, err = poller.PollUntilDone(ctx, nil) + if err != nil { + log.Fatalf("failed to pull the result: %v", err) + } +} + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/PostRules_getCounters_MaximumSet_Gen.json +func ExamplePostRulesClient_GetCounters_postRulesGetCountersMaximumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + res, err := clientFactory.NewPostRulesClient().GetCounters(ctx, "lrs1", "1", &armpanngfw.PostRulesClientGetCountersOptions{FirewallName: to.Ptr("firewall1")}) + if err != nil { + log.Fatalf("failed to finish the request: %v", err) + } + // You could use response here. We use blank identifier for just demo purposes. + _ = res + // If the HTTP response code is 200 as defined in example definition, your response structure would look as follows. Please pay attention that all the values in the output are fake values for just demo purposes. + // res.RuleCounter = armpanngfw.RuleCounter{ + // AppSeen: &armpanngfw.AppSeenData{ + // AppSeenList: []*armpanngfw.AppSeenInfo{ + // { + // Category: to.Ptr("aaaaaaaaaaaaaaaaaaa"), + // Risk: to.Ptr("aaaaaaaaaaaaaaaaaaaaaaaaaa"), + // StandardPorts: to.Ptr("aaaaaaaaaaaaaaaaaa"), + // SubCategory: to.Ptr("aaaaaaaaaaaaaaaaa"), + // Tag: to.Ptr("aaaaaaaaaa"), + // Technology: to.Ptr("aaaaaaaaaaaaaaaaaaaa"), + // Title: to.Ptr("aaaaaaaaaaaaaaaaaaaaaaaaaaaa"), + // }}, + // Count: to.Ptr[int32](13), + // }, + // FirewallName: to.Ptr("aaaaaaaaaaaaaaaaaa"), + // HitCount: to.Ptr[int32](20), + // LastUpdatedTimestamp: to.Ptr(func() time.Time { t, _ := time.Parse(time.RFC3339Nano, "2022-09-09T05:08:24.229Z"); return t}()), + // Priority: to.Ptr("aaaaaaaaaaaaaaaaaaaa"), + // RequestTimestamp: to.Ptr(func() time.Time { t, _ := time.Parse(time.RFC3339Nano, "2022-09-09T05:08:24.229Z"); return t}()), + // RuleListName: to.Ptr("aaaaaaaaaaaaaaaaaaa"), + // RuleName: to.Ptr("aaaa"), + // RuleStackName: to.Ptr("aaaaaaaaaaaaaaaaa"), + // Timestamp: to.Ptr(func() time.Time { t, _ := time.Parse(time.RFC3339Nano, "2022-09-09T05:08:24.229Z"); return t}()), + // } +} + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/PostRules_getCounters_MinimumSet_Gen.json +func ExamplePostRulesClient_GetCounters_postRulesGetCountersMinimumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + res, err := clientFactory.NewPostRulesClient().GetCounters(ctx, "lrs1", "1", &armpanngfw.PostRulesClientGetCountersOptions{FirewallName: nil}) + if err != nil { + log.Fatalf("failed to finish the request: %v", err) + } + // You could use response here. We use blank identifier for just demo purposes. + _ = res + // If the HTTP response code is 200 as defined in example definition, your response structure would look as follows. Please pay attention that all the values in the output are fake values for just demo purposes. + // res.RuleCounter = armpanngfw.RuleCounter{ + // Priority: to.Ptr("aaaaaaaaaaaaaaaaaaaa"), + // RuleName: to.Ptr("aaaa"), + // } +} + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/PostRules_refreshCounters_MaximumSet_Gen.json +func ExamplePostRulesClient_RefreshCounters_postRulesRefreshCountersMaximumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + _, err = clientFactory.NewPostRulesClient().RefreshCounters(ctx, "lrs1", "1", &armpanngfw.PostRulesClientRefreshCountersOptions{FirewallName: to.Ptr("firewall1")}) + if err != nil { + log.Fatalf("failed to finish the request: %v", err) + } +} + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/PostRules_refreshCounters_MinimumSet_Gen.json +func ExamplePostRulesClient_RefreshCounters_postRulesRefreshCountersMinimumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + _, err = clientFactory.NewPostRulesClient().RefreshCounters(ctx, "lrs1", "1", &armpanngfw.PostRulesClientRefreshCountersOptions{FirewallName: nil}) + if err != nil { + log.Fatalf("failed to finish the request: %v", err) + } +} + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/PostRules_resetCounters_MaximumSet_Gen.json +func ExamplePostRulesClient_ResetCounters_postRulesResetCountersMaximumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + res, err := clientFactory.NewPostRulesClient().ResetCounters(ctx, "lrs1", "1", &armpanngfw.PostRulesClientResetCountersOptions{FirewallName: to.Ptr("firewall1")}) + if err != nil { + log.Fatalf("failed to finish the request: %v", err) + } + // You could use response here. We use blank identifier for just demo purposes. + _ = res + // If the HTTP response code is 200 as defined in example definition, your response structure would look as follows. Please pay attention that all the values in the output are fake values for just demo purposes. + // res.RuleCounterReset = armpanngfw.RuleCounterReset{ + // FirewallName: to.Ptr("aaaaaaaaaaaaaaaaaa"), + // Priority: to.Ptr("aaaaaaa"), + // RuleListName: to.Ptr("aaaaa"), + // RuleName: to.Ptr("aaaaa"), + // RuleStackName: to.Ptr("aa"), + // } +} + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/PostRules_resetCounters_MinimumSet_Gen.json +func ExamplePostRulesClient_ResetCounters_postRulesResetCountersMinimumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + res, err := clientFactory.NewPostRulesClient().ResetCounters(ctx, "lrs1", "1", &armpanngfw.PostRulesClientResetCountersOptions{FirewallName: nil}) + if err != nil { + log.Fatalf("failed to finish the request: %v", err) + } + // You could use response here. We use blank identifier for just demo purposes. + _ = res + // If the HTTP response code is 200 as defined in example definition, your response structure would look as follows. Please pay attention that all the values in the output are fake values for just demo purposes. + // res.RuleCounterReset = armpanngfw.RuleCounterReset{ + // } +} diff --git a/sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/prefixlistglobalrulestack_client.go b/sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/prefixlistglobalrulestack_client.go new file mode 100644 index 000000000000..12dc57df8b7e --- /dev/null +++ b/sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/prefixlistglobalrulestack_client.go @@ -0,0 +1,284 @@ +//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. +// Code generated by Microsoft (R) AutoRest Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. +// DO NOT EDIT. + +package armpanngfw + +import ( + "context" + "errors" + "github.com/Azure/azure-sdk-for-go/sdk/azcore" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/arm" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/policy" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime" + "net/http" + "net/url" + "strings" +) + +// PrefixListGlobalRulestackClient contains the methods for the PrefixListGlobalRulestack group. +// Don't use this type directly, use NewPrefixListGlobalRulestackClient() instead. +type PrefixListGlobalRulestackClient struct { + internal *arm.Client +} + +// NewPrefixListGlobalRulestackClient creates a new instance of PrefixListGlobalRulestackClient with the specified values. +// - credential - used to authorize requests. Usually a credential from azidentity. +// - options - pass nil to accept the default values. +func NewPrefixListGlobalRulestackClient(credential azcore.TokenCredential, options *arm.ClientOptions) (*PrefixListGlobalRulestackClient, error) { + cl, err := arm.NewClient(moduleName+".PrefixListGlobalRulestackClient", moduleVersion, credential, options) + if err != nil { + return nil, err + } + client := &PrefixListGlobalRulestackClient{ + internal: cl, + } + return client, nil +} + +// BeginCreateOrUpdate - Create a PrefixListGlobalRulestackResource +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2022-08-29-preview +// - globalRulestackName - GlobalRulestack resource name +// - name - Local Rule priority +// - resource - Resource create parameters. +// - options - PrefixListGlobalRulestackClientBeginCreateOrUpdateOptions contains the optional parameters for the PrefixListGlobalRulestackClient.BeginCreateOrUpdate +// method. +func (client *PrefixListGlobalRulestackClient) BeginCreateOrUpdate(ctx context.Context, globalRulestackName string, name string, resource PrefixListGlobalRulestackResource, options *PrefixListGlobalRulestackClientBeginCreateOrUpdateOptions) (*runtime.Poller[PrefixListGlobalRulestackClientCreateOrUpdateResponse], error) { + if options == nil || options.ResumeToken == "" { + resp, err := client.createOrUpdate(ctx, globalRulestackName, name, resource, options) + if err != nil { + return nil, err + } + return runtime.NewPoller(resp, client.internal.Pipeline(), &runtime.NewPollerOptions[PrefixListGlobalRulestackClientCreateOrUpdateResponse]{ + FinalStateVia: runtime.FinalStateViaAzureAsyncOp, + }) + } else { + return runtime.NewPollerFromResumeToken[PrefixListGlobalRulestackClientCreateOrUpdateResponse](options.ResumeToken, client.internal.Pipeline(), nil) + } +} + +// CreateOrUpdate - Create a PrefixListGlobalRulestackResource +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2022-08-29-preview +func (client *PrefixListGlobalRulestackClient) createOrUpdate(ctx context.Context, globalRulestackName string, name string, resource PrefixListGlobalRulestackResource, options *PrefixListGlobalRulestackClientBeginCreateOrUpdateOptions) (*http.Response, error) { + req, err := client.createOrUpdateCreateRequest(ctx, globalRulestackName, name, resource, options) + if err != nil { + return nil, err + } + resp, err := client.internal.Pipeline().Do(req) + if err != nil { + return nil, err + } + if !runtime.HasStatusCode(resp, http.StatusOK, http.StatusCreated) { + return nil, runtime.NewResponseError(resp) + } + return resp, nil +} + +// createOrUpdateCreateRequest creates the CreateOrUpdate request. +func (client *PrefixListGlobalRulestackClient) createOrUpdateCreateRequest(ctx context.Context, globalRulestackName string, name string, resource PrefixListGlobalRulestackResource, options *PrefixListGlobalRulestackClientBeginCreateOrUpdateOptions) (*policy.Request, error) { + urlPath := "/providers/PaloAltoNetworks.Cloudngfw/globalRulestacks/{globalRulestackName}/prefixlists/{name}" + if globalRulestackName == "" { + return nil, errors.New("parameter globalRulestackName cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{globalRulestackName}", url.PathEscape(globalRulestackName)) + if name == "" { + return nil, errors.New("parameter name cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{name}", url.PathEscape(name)) + req, err := runtime.NewRequest(ctx, http.MethodPut, runtime.JoinPaths(client.internal.Endpoint(), urlPath)) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("api-version", "2022-08-29-preview") + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["Accept"] = []string{"application/json"} + return req, runtime.MarshalAsJSON(req, resource) +} + +// BeginDelete - Delete a PrefixListGlobalRulestackResource +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2022-08-29-preview +// - globalRulestackName - GlobalRulestack resource name +// - name - Local Rule priority +// - options - PrefixListGlobalRulestackClientBeginDeleteOptions contains the optional parameters for the PrefixListGlobalRulestackClient.BeginDelete +// method. +func (client *PrefixListGlobalRulestackClient) BeginDelete(ctx context.Context, globalRulestackName string, name string, options *PrefixListGlobalRulestackClientBeginDeleteOptions) (*runtime.Poller[PrefixListGlobalRulestackClientDeleteResponse], error) { + if options == nil || options.ResumeToken == "" { + resp, err := client.deleteOperation(ctx, globalRulestackName, name, options) + if err != nil { + return nil, err + } + return runtime.NewPoller(resp, client.internal.Pipeline(), &runtime.NewPollerOptions[PrefixListGlobalRulestackClientDeleteResponse]{ + FinalStateVia: runtime.FinalStateViaAzureAsyncOp, + }) + } else { + return runtime.NewPollerFromResumeToken[PrefixListGlobalRulestackClientDeleteResponse](options.ResumeToken, client.internal.Pipeline(), nil) + } +} + +// Delete - Delete a PrefixListGlobalRulestackResource +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2022-08-29-preview +func (client *PrefixListGlobalRulestackClient) deleteOperation(ctx context.Context, globalRulestackName string, name string, options *PrefixListGlobalRulestackClientBeginDeleteOptions) (*http.Response, error) { + req, err := client.deleteCreateRequest(ctx, globalRulestackName, name, options) + if err != nil { + return nil, err + } + resp, err := client.internal.Pipeline().Do(req) + if err != nil { + return nil, err + } + if !runtime.HasStatusCode(resp, http.StatusOK, http.StatusAccepted, http.StatusNoContent) { + return nil, runtime.NewResponseError(resp) + } + return resp, nil +} + +// deleteCreateRequest creates the Delete request. +func (client *PrefixListGlobalRulestackClient) deleteCreateRequest(ctx context.Context, globalRulestackName string, name string, options *PrefixListGlobalRulestackClientBeginDeleteOptions) (*policy.Request, error) { + urlPath := "/providers/PaloAltoNetworks.Cloudngfw/globalRulestacks/{globalRulestackName}/prefixlists/{name}" + if globalRulestackName == "" { + return nil, errors.New("parameter globalRulestackName cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{globalRulestackName}", url.PathEscape(globalRulestackName)) + if name == "" { + return nil, errors.New("parameter name cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{name}", url.PathEscape(name)) + req, err := runtime.NewRequest(ctx, http.MethodDelete, runtime.JoinPaths(client.internal.Endpoint(), urlPath)) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("api-version", "2022-08-29-preview") + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["Accept"] = []string{"application/json"} + return req, nil +} + +// Get - Get a PrefixListGlobalRulestackResource +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2022-08-29-preview +// - globalRulestackName - GlobalRulestack resource name +// - name - Local Rule priority +// - options - PrefixListGlobalRulestackClientGetOptions contains the optional parameters for the PrefixListGlobalRulestackClient.Get +// method. +func (client *PrefixListGlobalRulestackClient) Get(ctx context.Context, globalRulestackName string, name string, options *PrefixListGlobalRulestackClientGetOptions) (PrefixListGlobalRulestackClientGetResponse, error) { + req, err := client.getCreateRequest(ctx, globalRulestackName, name, options) + if err != nil { + return PrefixListGlobalRulestackClientGetResponse{}, err + } + resp, err := client.internal.Pipeline().Do(req) + if err != nil { + return PrefixListGlobalRulestackClientGetResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusOK) { + return PrefixListGlobalRulestackClientGetResponse{}, runtime.NewResponseError(resp) + } + return client.getHandleResponse(resp) +} + +// getCreateRequest creates the Get request. +func (client *PrefixListGlobalRulestackClient) getCreateRequest(ctx context.Context, globalRulestackName string, name string, options *PrefixListGlobalRulestackClientGetOptions) (*policy.Request, error) { + urlPath := "/providers/PaloAltoNetworks.Cloudngfw/globalRulestacks/{globalRulestackName}/prefixlists/{name}" + if globalRulestackName == "" { + return nil, errors.New("parameter globalRulestackName cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{globalRulestackName}", url.PathEscape(globalRulestackName)) + if name == "" { + return nil, errors.New("parameter name cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{name}", url.PathEscape(name)) + req, err := runtime.NewRequest(ctx, http.MethodGet, runtime.JoinPaths(client.internal.Endpoint(), urlPath)) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("api-version", "2022-08-29-preview") + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["Accept"] = []string{"application/json"} + return req, nil +} + +// getHandleResponse handles the Get response. +func (client *PrefixListGlobalRulestackClient) getHandleResponse(resp *http.Response) (PrefixListGlobalRulestackClientGetResponse, error) { + result := PrefixListGlobalRulestackClientGetResponse{} + if err := runtime.UnmarshalAsJSON(resp, &result.PrefixListGlobalRulestackResource); err != nil { + return PrefixListGlobalRulestackClientGetResponse{}, err + } + return result, nil +} + +// NewListPager - List PrefixListGlobalRulestackResource resources by Tenant +// +// Generated from API version 2022-08-29-preview +// - globalRulestackName - GlobalRulestack resource name +// - options - PrefixListGlobalRulestackClientListOptions contains the optional parameters for the PrefixListGlobalRulestackClient.NewListPager +// method. +func (client *PrefixListGlobalRulestackClient) NewListPager(globalRulestackName string, options *PrefixListGlobalRulestackClientListOptions) *runtime.Pager[PrefixListGlobalRulestackClientListResponse] { + return runtime.NewPager(runtime.PagingHandler[PrefixListGlobalRulestackClientListResponse]{ + More: func(page PrefixListGlobalRulestackClientListResponse) bool { + return page.NextLink != nil && len(*page.NextLink) > 0 + }, + Fetcher: func(ctx context.Context, page *PrefixListGlobalRulestackClientListResponse) (PrefixListGlobalRulestackClientListResponse, error) { + var req *policy.Request + var err error + if page == nil { + req, err = client.listCreateRequest(ctx, globalRulestackName, options) + } else { + req, err = runtime.NewRequest(ctx, http.MethodGet, *page.NextLink) + } + if err != nil { + return PrefixListGlobalRulestackClientListResponse{}, err + } + resp, err := client.internal.Pipeline().Do(req) + if err != nil { + return PrefixListGlobalRulestackClientListResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusOK) { + return PrefixListGlobalRulestackClientListResponse{}, runtime.NewResponseError(resp) + } + return client.listHandleResponse(resp) + }, + }) +} + +// listCreateRequest creates the List request. +func (client *PrefixListGlobalRulestackClient) listCreateRequest(ctx context.Context, globalRulestackName string, options *PrefixListGlobalRulestackClientListOptions) (*policy.Request, error) { + urlPath := "/providers/PaloAltoNetworks.Cloudngfw/globalRulestacks/{globalRulestackName}/prefixlists" + if globalRulestackName == "" { + return nil, errors.New("parameter globalRulestackName cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{globalRulestackName}", url.PathEscape(globalRulestackName)) + req, err := runtime.NewRequest(ctx, http.MethodGet, runtime.JoinPaths(client.internal.Endpoint(), urlPath)) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("api-version", "2022-08-29-preview") + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["Accept"] = []string{"application/json"} + return req, nil +} + +// listHandleResponse handles the List response. +func (client *PrefixListGlobalRulestackClient) listHandleResponse(resp *http.Response) (PrefixListGlobalRulestackClientListResponse, error) { + result := PrefixListGlobalRulestackClientListResponse{} + if err := runtime.UnmarshalAsJSON(resp, &result.PrefixListGlobalRulestackResourceListResult); err != nil { + return PrefixListGlobalRulestackClientListResponse{}, err + } + return result, nil +} diff --git a/sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/prefixlistglobalrulestack_client_example_test.go b/sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/prefixlistglobalrulestack_client_example_test.go new file mode 100644 index 000000000000..e5b66dd44d85 --- /dev/null +++ b/sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/prefixlistglobalrulestack_client_example_test.go @@ -0,0 +1,303 @@ +//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. +// Code generated by Microsoft (R) AutoRest Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. +// DO NOT EDIT. + +package armpanngfw_test + +import ( + "context" + "log" + + "github.com/Azure/azure-sdk-for-go/sdk/azcore/to" + "github.com/Azure/azure-sdk-for-go/sdk/azidentity" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/paloaltonetworksngfw/armpanngfw" +) + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/PrefixListGlobalRulestack_List_MaximumSet_Gen.json +func ExamplePrefixListGlobalRulestackClient_NewListPager_prefixListGlobalRulestackListMaximumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + pager := clientFactory.NewPrefixListGlobalRulestackClient().NewListPager("praval", nil) + for pager.More() { + page, err := pager.NextPage(ctx) + if err != nil { + log.Fatalf("failed to advance page: %v", err) + } + for _, v := range page.Value { + // You could use page here. We use blank identifier for just demo purposes. + _ = v + } + // If the HTTP response code is 200 as defined in example definition, your page structure would look as follows. Please pay attention that all the values in the output are fake values for just demo purposes. + // page.PrefixListGlobalRulestackResourceListResult = armpanngfw.PrefixListGlobalRulestackResourceListResult{ + // Value: []*armpanngfw.PrefixListGlobalRulestackResource{ + // { + // Name: to.Ptr("aaaaaaaaaaaaaaaaaaaaaaaaaaaa"), + // Type: to.Ptr("aaaaaaaaaaaaaaaaaaaaaaaaaaaaa"), + // ID: to.Ptr("aaaaaaaaaaaaaaaaaa"), + // SystemData: &armpanngfw.SystemData{ + // CreatedAt: to.Ptr(func() time.Time { t, _ := time.Parse(time.RFC3339Nano, "2022-09-09T05:08:24.229Z"); return t}()), + // CreatedBy: to.Ptr("praval"), + // CreatedByType: to.Ptr(armpanngfw.CreatedByTypeUser), + // LastModifiedAt: to.Ptr(func() time.Time { t, _ := time.Parse(time.RFC3339Nano, "2022-09-09T05:08:24.229Z"); return t}()), + // LastModifiedBy: to.Ptr("praval"), + // LastModifiedByType: to.Ptr(armpanngfw.CreatedByTypeUser), + // }, + // Properties: &armpanngfw.PrefixObject{ + // Description: to.Ptr("aaaaaaaaaaaaaaaaaaa"), + // AuditComment: to.Ptr("aaaaaaaaaaaaaaaaaaaaaaaaaaa"), + // Etag: to.Ptr("aaaaaaaaaaaaaaaaaaaaaaa"), + // PrefixList: []*string{ + // to.Ptr("aaaaaaaaaaaaaaaaaaaaaaaaaaaaa")}, + // ProvisioningState: to.Ptr(armpanngfw.ProvisioningStateSucceeded), + // }, + // }}, + // } + } +} + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/PrefixListGlobalRulestack_List_MinimumSet_Gen.json +func ExamplePrefixListGlobalRulestackClient_NewListPager_prefixListGlobalRulestackListMinimumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + pager := clientFactory.NewPrefixListGlobalRulestackClient().NewListPager("praval", nil) + for pager.More() { + page, err := pager.NextPage(ctx) + if err != nil { + log.Fatalf("failed to advance page: %v", err) + } + for _, v := range page.Value { + // You could use page here. We use blank identifier for just demo purposes. + _ = v + } + // If the HTTP response code is 200 as defined in example definition, your page structure would look as follows. Please pay attention that all the values in the output are fake values for just demo purposes. + // page.PrefixListGlobalRulestackResourceListResult = armpanngfw.PrefixListGlobalRulestackResourceListResult{ + // Value: []*armpanngfw.PrefixListGlobalRulestackResource{ + // { + // ID: to.Ptr("/providers/PaloAltoNetworks.Cloudngfw/globalRulestacks/praval/prefixlists/prefixlists1"), + // Properties: &armpanngfw.PrefixObject{ + // PrefixList: []*string{ + // to.Ptr("aaaaaaaaaaaaaaaaaaaaaaaaaaaaa")}, + // }, + // }}, + // } + } +} + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/PrefixListGlobalRulestack_Get_MaximumSet_Gen.json +func ExamplePrefixListGlobalRulestackClient_Get_prefixListGlobalRulestackGetMaximumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + res, err := clientFactory.NewPrefixListGlobalRulestackClient().Get(ctx, "praval", "armid1", nil) + if err != nil { + log.Fatalf("failed to finish the request: %v", err) + } + // You could use response here. We use blank identifier for just demo purposes. + _ = res + // If the HTTP response code is 200 as defined in example definition, your response structure would look as follows. Please pay attention that all the values in the output are fake values for just demo purposes. + // res.PrefixListGlobalRulestackResource = armpanngfw.PrefixListGlobalRulestackResource{ + // Name: to.Ptr("armid1"), + // Type: to.Ptr("certificates"), + // ID: to.Ptr("/providers/PaloAltoNetworks.Cloudngfw/globalrulestacks/armid1/certificates/armid1"), + // SystemData: &armpanngfw.SystemData{ + // CreatedAt: to.Ptr(func() time.Time { t, _ := time.Parse(time.RFC3339Nano, "2022-09-09T05:08:24.229Z"); return t}()), + // CreatedBy: to.Ptr("praval"), + // CreatedByType: to.Ptr(armpanngfw.CreatedByTypeUser), + // LastModifiedAt: to.Ptr(func() time.Time { t, _ := time.Parse(time.RFC3339Nano, "2022-09-09T05:08:24.229Z"); return t}()), + // LastModifiedBy: to.Ptr("praval"), + // LastModifiedByType: to.Ptr(armpanngfw.CreatedByTypeUser), + // }, + // Properties: &armpanngfw.PrefixObject{ + // Description: to.Ptr("string"), + // AuditComment: to.Ptr("comment"), + // Etag: to.Ptr("2bf4a339-294d-4c25-b0b2-ef649e9f5c27"), + // PrefixList: []*string{ + // to.Ptr("1.0.0.0/24")}, + // ProvisioningState: to.Ptr(armpanngfw.ProvisioningStateSucceeded), + // }, + // } +} + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/PrefixListGlobalRulestack_Get_MinimumSet_Gen.json +func ExamplePrefixListGlobalRulestackClient_Get_prefixListGlobalRulestackGetMinimumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + res, err := clientFactory.NewPrefixListGlobalRulestackClient().Get(ctx, "praval", "armid1", nil) + if err != nil { + log.Fatalf("failed to finish the request: %v", err) + } + // You could use response here. We use blank identifier for just demo purposes. + _ = res + // If the HTTP response code is 200 as defined in example definition, your response structure would look as follows. Please pay attention that all the values in the output are fake values for just demo purposes. + // res.PrefixListGlobalRulestackResource = armpanngfw.PrefixListGlobalRulestackResource{ + // ID: to.Ptr("/providers/PaloAltoNetworks.Cloudngfw/globalRulestacks/praval/prefixlists/armid1"), + // Properties: &armpanngfw.PrefixObject{ + // PrefixList: []*string{ + // to.Ptr("1.0.0.0/24")}, + // }, + // } +} + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/PrefixListGlobalRulestack_CreateOrUpdate_MaximumSet_Gen.json +func ExamplePrefixListGlobalRulestackClient_BeginCreateOrUpdate_prefixListGlobalRulestackCreateOrUpdateMaximumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + poller, err := clientFactory.NewPrefixListGlobalRulestackClient().BeginCreateOrUpdate(ctx, "praval", "armid1", armpanngfw.PrefixListGlobalRulestackResource{ + Properties: &armpanngfw.PrefixObject{ + Description: to.Ptr("string"), + AuditComment: to.Ptr("comment"), + Etag: to.Ptr("2bf4a339-294d-4c25-b0b2-ef649e9f5c27"), + PrefixList: []*string{ + to.Ptr("1.0.0.0/24")}, + ProvisioningState: to.Ptr(armpanngfw.ProvisioningStateAccepted), + }, + }, nil) + if err != nil { + log.Fatalf("failed to finish the request: %v", err) + } + res, err := poller.PollUntilDone(ctx, nil) + if err != nil { + log.Fatalf("failed to pull the result: %v", err) + } + // You could use response here. We use blank identifier for just demo purposes. + _ = res + // If the HTTP response code is 200 as defined in example definition, your response structure would look as follows. Please pay attention that all the values in the output are fake values for just demo purposes. + // res.PrefixListGlobalRulestackResource = armpanngfw.PrefixListGlobalRulestackResource{ + // Name: to.Ptr("armid1"), + // Type: to.Ptr("certificates"), + // ID: to.Ptr("/providers/PaloAltoNetworks.Cloudngfw/globalrulestacks/armid1/certificates/armid1"), + // SystemData: &armpanngfw.SystemData{ + // CreatedAt: to.Ptr(func() time.Time { t, _ := time.Parse(time.RFC3339Nano, "2022-09-09T05:08:24.229Z"); return t}()), + // CreatedBy: to.Ptr("praval"), + // CreatedByType: to.Ptr(armpanngfw.CreatedByTypeUser), + // LastModifiedAt: to.Ptr(func() time.Time { t, _ := time.Parse(time.RFC3339Nano, "2022-09-09T05:08:24.229Z"); return t}()), + // LastModifiedBy: to.Ptr("praval"), + // LastModifiedByType: to.Ptr(armpanngfw.CreatedByTypeUser), + // }, + // Properties: &armpanngfw.PrefixObject{ + // Description: to.Ptr("string"), + // AuditComment: to.Ptr("comment"), + // Etag: to.Ptr("2bf4a339-294d-4c25-b0b2-ef649e9f5c27"), + // PrefixList: []*string{ + // to.Ptr("1.0.0.0/24")}, + // ProvisioningState: to.Ptr(armpanngfw.ProvisioningStateSucceeded), + // }, + // } +} + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/PrefixListGlobalRulestack_CreateOrUpdate_MinimumSet_Gen.json +func ExamplePrefixListGlobalRulestackClient_BeginCreateOrUpdate_prefixListGlobalRulestackCreateOrUpdateMinimumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + poller, err := clientFactory.NewPrefixListGlobalRulestackClient().BeginCreateOrUpdate(ctx, "praval", "armid1", armpanngfw.PrefixListGlobalRulestackResource{ + Properties: &armpanngfw.PrefixObject{ + PrefixList: []*string{ + to.Ptr("1.0.0.0/24")}, + }, + }, nil) + if err != nil { + log.Fatalf("failed to finish the request: %v", err) + } + res, err := poller.PollUntilDone(ctx, nil) + if err != nil { + log.Fatalf("failed to pull the result: %v", err) + } + // You could use response here. We use blank identifier for just demo purposes. + _ = res + // If the HTTP response code is 200 as defined in example definition, your response structure would look as follows. Please pay attention that all the values in the output are fake values for just demo purposes. + // res.PrefixListGlobalRulestackResource = armpanngfw.PrefixListGlobalRulestackResource{ + // ID: to.Ptr("/providers/PaloAltoNetworks.Cloudngfw/globalRulestacks/praval/prefixlists/armid1"), + // Properties: &armpanngfw.PrefixObject{ + // PrefixList: []*string{ + // to.Ptr("1.0.0.0/24")}, + // }, + // } +} + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/PrefixListGlobalRulestack_Delete_MaximumSet_Gen.json +func ExamplePrefixListGlobalRulestackClient_BeginDelete_prefixListGlobalRulestackDeleteMaximumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + poller, err := clientFactory.NewPrefixListGlobalRulestackClient().BeginDelete(ctx, "praval", "armid1", nil) + if err != nil { + log.Fatalf("failed to finish the request: %v", err) + } + _, err = poller.PollUntilDone(ctx, nil) + if err != nil { + log.Fatalf("failed to pull the result: %v", err) + } +} + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/PrefixListGlobalRulestack_Delete_MinimumSet_Gen.json +func ExamplePrefixListGlobalRulestackClient_BeginDelete_prefixListGlobalRulestackDeleteMinimumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + poller, err := clientFactory.NewPrefixListGlobalRulestackClient().BeginDelete(ctx, "praval", "armid1", nil) + if err != nil { + log.Fatalf("failed to finish the request: %v", err) + } + _, err = poller.PollUntilDone(ctx, nil) + if err != nil { + log.Fatalf("failed to pull the result: %v", err) + } +} diff --git a/sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/prefixlistlocalrulestack_client.go b/sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/prefixlistlocalrulestack_client.go new file mode 100644 index 000000000000..da9bd36daec7 --- /dev/null +++ b/sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/prefixlistlocalrulestack_client.go @@ -0,0 +1,323 @@ +//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. +// Code generated by Microsoft (R) AutoRest Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. +// DO NOT EDIT. + +package armpanngfw + +import ( + "context" + "errors" + "github.com/Azure/azure-sdk-for-go/sdk/azcore" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/arm" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/policy" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime" + "net/http" + "net/url" + "strings" +) + +// PrefixListLocalRulestackClient contains the methods for the PrefixListLocalRulestack group. +// Don't use this type directly, use NewPrefixListLocalRulestackClient() instead. +type PrefixListLocalRulestackClient struct { + internal *arm.Client + subscriptionID string +} + +// NewPrefixListLocalRulestackClient creates a new instance of PrefixListLocalRulestackClient with the specified values. +// - subscriptionID - The ID of the target subscription. +// - credential - used to authorize requests. Usually a credential from azidentity. +// - options - pass nil to accept the default values. +func NewPrefixListLocalRulestackClient(subscriptionID string, credential azcore.TokenCredential, options *arm.ClientOptions) (*PrefixListLocalRulestackClient, error) { + cl, err := arm.NewClient(moduleName+".PrefixListLocalRulestackClient", moduleVersion, credential, options) + if err != nil { + return nil, err + } + client := &PrefixListLocalRulestackClient{ + subscriptionID: subscriptionID, + internal: cl, + } + return client, nil +} + +// BeginCreateOrUpdate - Create a PrefixListResource +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2022-08-29-preview +// - resourceGroupName - The name of the resource group. The name is case insensitive. +// - localRulestackName - LocalRulestack resource name +// - name - Local Rule priority +// - resource - Resource create parameters. +// - options - PrefixListLocalRulestackClientBeginCreateOrUpdateOptions contains the optional parameters for the PrefixListLocalRulestackClient.BeginCreateOrUpdate +// method. +func (client *PrefixListLocalRulestackClient) BeginCreateOrUpdate(ctx context.Context, resourceGroupName string, localRulestackName string, name string, resource PrefixListResource, options *PrefixListLocalRulestackClientBeginCreateOrUpdateOptions) (*runtime.Poller[PrefixListLocalRulestackClientCreateOrUpdateResponse], error) { + if options == nil || options.ResumeToken == "" { + resp, err := client.createOrUpdate(ctx, resourceGroupName, localRulestackName, name, resource, options) + if err != nil { + return nil, err + } + return runtime.NewPoller(resp, client.internal.Pipeline(), &runtime.NewPollerOptions[PrefixListLocalRulestackClientCreateOrUpdateResponse]{ + FinalStateVia: runtime.FinalStateViaAzureAsyncOp, + }) + } else { + return runtime.NewPollerFromResumeToken[PrefixListLocalRulestackClientCreateOrUpdateResponse](options.ResumeToken, client.internal.Pipeline(), nil) + } +} + +// CreateOrUpdate - Create a PrefixListResource +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2022-08-29-preview +func (client *PrefixListLocalRulestackClient) createOrUpdate(ctx context.Context, resourceGroupName string, localRulestackName string, name string, resource PrefixListResource, options *PrefixListLocalRulestackClientBeginCreateOrUpdateOptions) (*http.Response, error) { + req, err := client.createOrUpdateCreateRequest(ctx, resourceGroupName, localRulestackName, name, resource, options) + if err != nil { + return nil, err + } + resp, err := client.internal.Pipeline().Do(req) + if err != nil { + return nil, err + } + if !runtime.HasStatusCode(resp, http.StatusOK, http.StatusCreated) { + return nil, runtime.NewResponseError(resp) + } + return resp, nil +} + +// createOrUpdateCreateRequest creates the CreateOrUpdate request. +func (client *PrefixListLocalRulestackClient) createOrUpdateCreateRequest(ctx context.Context, resourceGroupName string, localRulestackName string, name string, resource PrefixListResource, options *PrefixListLocalRulestackClientBeginCreateOrUpdateOptions) (*policy.Request, error) { + urlPath := "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/PaloAltoNetworks.Cloudngfw/localRulestacks/{localRulestackName}/prefixlists/{name}" + if client.subscriptionID == "" { + return nil, errors.New("parameter client.subscriptionID cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{subscriptionId}", url.PathEscape(client.subscriptionID)) + if resourceGroupName == "" { + return nil, errors.New("parameter resourceGroupName cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{resourceGroupName}", url.PathEscape(resourceGroupName)) + if localRulestackName == "" { + return nil, errors.New("parameter localRulestackName cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{localRulestackName}", url.PathEscape(localRulestackName)) + if name == "" { + return nil, errors.New("parameter name cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{name}", url.PathEscape(name)) + req, err := runtime.NewRequest(ctx, http.MethodPut, runtime.JoinPaths(client.internal.Endpoint(), urlPath)) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("api-version", "2022-08-29-preview") + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["Accept"] = []string{"application/json"} + return req, runtime.MarshalAsJSON(req, resource) +} + +// BeginDelete - Delete a PrefixListResource +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2022-08-29-preview +// - resourceGroupName - The name of the resource group. The name is case insensitive. +// - localRulestackName - LocalRulestack resource name +// - name - Local Rule priority +// - options - PrefixListLocalRulestackClientBeginDeleteOptions contains the optional parameters for the PrefixListLocalRulestackClient.BeginDelete +// method. +func (client *PrefixListLocalRulestackClient) BeginDelete(ctx context.Context, resourceGroupName string, localRulestackName string, name string, options *PrefixListLocalRulestackClientBeginDeleteOptions) (*runtime.Poller[PrefixListLocalRulestackClientDeleteResponse], error) { + if options == nil || options.ResumeToken == "" { + resp, err := client.deleteOperation(ctx, resourceGroupName, localRulestackName, name, options) + if err != nil { + return nil, err + } + return runtime.NewPoller(resp, client.internal.Pipeline(), &runtime.NewPollerOptions[PrefixListLocalRulestackClientDeleteResponse]{ + FinalStateVia: runtime.FinalStateViaAzureAsyncOp, + }) + } else { + return runtime.NewPollerFromResumeToken[PrefixListLocalRulestackClientDeleteResponse](options.ResumeToken, client.internal.Pipeline(), nil) + } +} + +// Delete - Delete a PrefixListResource +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2022-08-29-preview +func (client *PrefixListLocalRulestackClient) deleteOperation(ctx context.Context, resourceGroupName string, localRulestackName string, name string, options *PrefixListLocalRulestackClientBeginDeleteOptions) (*http.Response, error) { + req, err := client.deleteCreateRequest(ctx, resourceGroupName, localRulestackName, name, options) + if err != nil { + return nil, err + } + resp, err := client.internal.Pipeline().Do(req) + if err != nil { + return nil, err + } + if !runtime.HasStatusCode(resp, http.StatusOK, http.StatusAccepted, http.StatusNoContent) { + return nil, runtime.NewResponseError(resp) + } + return resp, nil +} + +// deleteCreateRequest creates the Delete request. +func (client *PrefixListLocalRulestackClient) deleteCreateRequest(ctx context.Context, resourceGroupName string, localRulestackName string, name string, options *PrefixListLocalRulestackClientBeginDeleteOptions) (*policy.Request, error) { + urlPath := "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/PaloAltoNetworks.Cloudngfw/localRulestacks/{localRulestackName}/prefixlists/{name}" + if client.subscriptionID == "" { + return nil, errors.New("parameter client.subscriptionID cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{subscriptionId}", url.PathEscape(client.subscriptionID)) + if resourceGroupName == "" { + return nil, errors.New("parameter resourceGroupName cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{resourceGroupName}", url.PathEscape(resourceGroupName)) + if localRulestackName == "" { + return nil, errors.New("parameter localRulestackName cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{localRulestackName}", url.PathEscape(localRulestackName)) + if name == "" { + return nil, errors.New("parameter name cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{name}", url.PathEscape(name)) + req, err := runtime.NewRequest(ctx, http.MethodDelete, runtime.JoinPaths(client.internal.Endpoint(), urlPath)) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("api-version", "2022-08-29-preview") + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["Accept"] = []string{"application/json"} + return req, nil +} + +// Get - Get a PrefixListResource +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2022-08-29-preview +// - resourceGroupName - The name of the resource group. The name is case insensitive. +// - localRulestackName - LocalRulestack resource name +// - name - Local Rule priority +// - options - PrefixListLocalRulestackClientGetOptions contains the optional parameters for the PrefixListLocalRulestackClient.Get +// method. +func (client *PrefixListLocalRulestackClient) Get(ctx context.Context, resourceGroupName string, localRulestackName string, name string, options *PrefixListLocalRulestackClientGetOptions) (PrefixListLocalRulestackClientGetResponse, error) { + req, err := client.getCreateRequest(ctx, resourceGroupName, localRulestackName, name, options) + if err != nil { + return PrefixListLocalRulestackClientGetResponse{}, err + } + resp, err := client.internal.Pipeline().Do(req) + if err != nil { + return PrefixListLocalRulestackClientGetResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusOK) { + return PrefixListLocalRulestackClientGetResponse{}, runtime.NewResponseError(resp) + } + return client.getHandleResponse(resp) +} + +// getCreateRequest creates the Get request. +func (client *PrefixListLocalRulestackClient) getCreateRequest(ctx context.Context, resourceGroupName string, localRulestackName string, name string, options *PrefixListLocalRulestackClientGetOptions) (*policy.Request, error) { + urlPath := "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/PaloAltoNetworks.Cloudngfw/localRulestacks/{localRulestackName}/prefixlists/{name}" + if client.subscriptionID == "" { + return nil, errors.New("parameter client.subscriptionID cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{subscriptionId}", url.PathEscape(client.subscriptionID)) + if resourceGroupName == "" { + return nil, errors.New("parameter resourceGroupName cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{resourceGroupName}", url.PathEscape(resourceGroupName)) + if localRulestackName == "" { + return nil, errors.New("parameter localRulestackName cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{localRulestackName}", url.PathEscape(localRulestackName)) + if name == "" { + return nil, errors.New("parameter name cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{name}", url.PathEscape(name)) + req, err := runtime.NewRequest(ctx, http.MethodGet, runtime.JoinPaths(client.internal.Endpoint(), urlPath)) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("api-version", "2022-08-29-preview") + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["Accept"] = []string{"application/json"} + return req, nil +} + +// getHandleResponse handles the Get response. +func (client *PrefixListLocalRulestackClient) getHandleResponse(resp *http.Response) (PrefixListLocalRulestackClientGetResponse, error) { + result := PrefixListLocalRulestackClientGetResponse{} + if err := runtime.UnmarshalAsJSON(resp, &result.PrefixListResource); err != nil { + return PrefixListLocalRulestackClientGetResponse{}, err + } + return result, nil +} + +// NewListByLocalRulestacksPager - List PrefixListResource resources by LocalRulestacks +// +// Generated from API version 2022-08-29-preview +// - resourceGroupName - The name of the resource group. The name is case insensitive. +// - localRulestackName - LocalRulestack resource name +// - options - PrefixListLocalRulestackClientListByLocalRulestacksOptions contains the optional parameters for the PrefixListLocalRulestackClient.NewListByLocalRulestacksPager +// method. +func (client *PrefixListLocalRulestackClient) NewListByLocalRulestacksPager(resourceGroupName string, localRulestackName string, options *PrefixListLocalRulestackClientListByLocalRulestacksOptions) *runtime.Pager[PrefixListLocalRulestackClientListByLocalRulestacksResponse] { + return runtime.NewPager(runtime.PagingHandler[PrefixListLocalRulestackClientListByLocalRulestacksResponse]{ + More: func(page PrefixListLocalRulestackClientListByLocalRulestacksResponse) bool { + return page.NextLink != nil && len(*page.NextLink) > 0 + }, + Fetcher: func(ctx context.Context, page *PrefixListLocalRulestackClientListByLocalRulestacksResponse) (PrefixListLocalRulestackClientListByLocalRulestacksResponse, error) { + var req *policy.Request + var err error + if page == nil { + req, err = client.listByLocalRulestacksCreateRequest(ctx, resourceGroupName, localRulestackName, options) + } else { + req, err = runtime.NewRequest(ctx, http.MethodGet, *page.NextLink) + } + if err != nil { + return PrefixListLocalRulestackClientListByLocalRulestacksResponse{}, err + } + resp, err := client.internal.Pipeline().Do(req) + if err != nil { + return PrefixListLocalRulestackClientListByLocalRulestacksResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusOK) { + return PrefixListLocalRulestackClientListByLocalRulestacksResponse{}, runtime.NewResponseError(resp) + } + return client.listByLocalRulestacksHandleResponse(resp) + }, + }) +} + +// listByLocalRulestacksCreateRequest creates the ListByLocalRulestacks request. +func (client *PrefixListLocalRulestackClient) listByLocalRulestacksCreateRequest(ctx context.Context, resourceGroupName string, localRulestackName string, options *PrefixListLocalRulestackClientListByLocalRulestacksOptions) (*policy.Request, error) { + urlPath := "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/PaloAltoNetworks.Cloudngfw/localRulestacks/{localRulestackName}/prefixlists" + if client.subscriptionID == "" { + return nil, errors.New("parameter client.subscriptionID cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{subscriptionId}", url.PathEscape(client.subscriptionID)) + if resourceGroupName == "" { + return nil, errors.New("parameter resourceGroupName cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{resourceGroupName}", url.PathEscape(resourceGroupName)) + if localRulestackName == "" { + return nil, errors.New("parameter localRulestackName cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{localRulestackName}", url.PathEscape(localRulestackName)) + req, err := runtime.NewRequest(ctx, http.MethodGet, runtime.JoinPaths(client.internal.Endpoint(), urlPath)) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("api-version", "2022-08-29-preview") + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["Accept"] = []string{"application/json"} + return req, nil +} + +// listByLocalRulestacksHandleResponse handles the ListByLocalRulestacks response. +func (client *PrefixListLocalRulestackClient) listByLocalRulestacksHandleResponse(resp *http.Response) (PrefixListLocalRulestackClientListByLocalRulestacksResponse, error) { + result := PrefixListLocalRulestackClientListByLocalRulestacksResponse{} + if err := runtime.UnmarshalAsJSON(resp, &result.PrefixListResourceListResult); err != nil { + return PrefixListLocalRulestackClientListByLocalRulestacksResponse{}, err + } + return result, nil +} diff --git a/sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/prefixlistlocalrulestack_client_example_test.go b/sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/prefixlistlocalrulestack_client_example_test.go new file mode 100644 index 000000000000..71dc87c5e2c5 --- /dev/null +++ b/sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/prefixlistlocalrulestack_client_example_test.go @@ -0,0 +1,303 @@ +//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. +// Code generated by Microsoft (R) AutoRest Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. +// DO NOT EDIT. + +package armpanngfw_test + +import ( + "context" + "log" + + "github.com/Azure/azure-sdk-for-go/sdk/azcore/to" + "github.com/Azure/azure-sdk-for-go/sdk/azidentity" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/paloaltonetworksngfw/armpanngfw" +) + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/PrefixListLocalRulestack_ListByLocalRulestacks_MaximumSet_Gen.json +func ExamplePrefixListLocalRulestackClient_NewListByLocalRulestacksPager_prefixListLocalRulestackListByLocalRulestacksMaximumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + pager := clientFactory.NewPrefixListLocalRulestackClient().NewListByLocalRulestacksPager("rgopenapi", "lrs1", nil) + for pager.More() { + page, err := pager.NextPage(ctx) + if err != nil { + log.Fatalf("failed to advance page: %v", err) + } + for _, v := range page.Value { + // You could use page here. We use blank identifier for just demo purposes. + _ = v + } + // If the HTTP response code is 200 as defined in example definition, your page structure would look as follows. Please pay attention that all the values in the output are fake values for just demo purposes. + // page.PrefixListResourceListResult = armpanngfw.PrefixListResourceListResult{ + // Value: []*armpanngfw.PrefixListResource{ + // { + // Name: to.Ptr("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"), + // Type: to.Ptr("aa"), + // ID: to.Ptr("aaa"), + // SystemData: &armpanngfw.SystemData{ + // CreatedAt: to.Ptr(func() time.Time { t, _ := time.Parse(time.RFC3339Nano, "2022-09-09T05:08:24.229Z"); return t}()), + // CreatedBy: to.Ptr("praval"), + // CreatedByType: to.Ptr(armpanngfw.CreatedByTypeUser), + // LastModifiedAt: to.Ptr(func() time.Time { t, _ := time.Parse(time.RFC3339Nano, "2022-09-09T05:08:24.229Z"); return t}()), + // LastModifiedBy: to.Ptr("praval"), + // LastModifiedByType: to.Ptr(armpanngfw.CreatedByTypeUser), + // }, + // Properties: &armpanngfw.PrefixObject{ + // Description: to.Ptr("aaaaaaaaaaaaaaaaaaa"), + // AuditComment: to.Ptr("aaaaaaaaaaaaaaaaaaaaaaaaaaa"), + // Etag: to.Ptr("aaaaaaaaaaaaaaaaaaaaaaa"), + // PrefixList: []*string{ + // to.Ptr("aaaaaaaaaaaaaaaaaaaaaaaaaaaaa")}, + // ProvisioningState: to.Ptr(armpanngfw.ProvisioningStateSucceeded), + // }, + // }}, + // } + } +} + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/PrefixListLocalRulestack_ListByLocalRulestacks_MinimumSet_Gen.json +func ExamplePrefixListLocalRulestackClient_NewListByLocalRulestacksPager_prefixListLocalRulestackListByLocalRulestacksMinimumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + pager := clientFactory.NewPrefixListLocalRulestackClient().NewListByLocalRulestacksPager("rgopenapi", "lrs1", nil) + for pager.More() { + page, err := pager.NextPage(ctx) + if err != nil { + log.Fatalf("failed to advance page: %v", err) + } + for _, v := range page.Value { + // You could use page here. We use blank identifier for just demo purposes. + _ = v + } + // If the HTTP response code is 200 as defined in example definition, your page structure would look as follows. Please pay attention that all the values in the output are fake values for just demo purposes. + // page.PrefixListResourceListResult = armpanngfw.PrefixListResourceListResult{ + // Value: []*armpanngfw.PrefixListResource{ + // { + // ID: to.Ptr("/subscriptions/2bf4a339-294d-4c25-b0b2-ef649e9f5c27/resourcegroups/rgopenapi/providers/PaloAltoNetworks.Cloudngfw/localRulestacks/praval/prefixlists/prefixlists1"), + // Properties: &armpanngfw.PrefixObject{ + // PrefixList: []*string{ + // to.Ptr("aaaaaaaaaaaaaaaaaaaaaaaaaaaaa")}, + // }, + // }}, + // } + } +} + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/PrefixListLocalRulestack_Get_MaximumSet_Gen.json +func ExamplePrefixListLocalRulestackClient_Get_prefixListLocalRulestackGetMaximumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + res, err := clientFactory.NewPrefixListLocalRulestackClient().Get(ctx, "rgopenapi", "lrs1", "armid1", nil) + if err != nil { + log.Fatalf("failed to finish the request: %v", err) + } + // You could use response here. We use blank identifier for just demo purposes. + _ = res + // If the HTTP response code is 200 as defined in example definition, your response structure would look as follows. Please pay attention that all the values in the output are fake values for just demo purposes. + // res.PrefixListResource = armpanngfw.PrefixListResource{ + // Name: to.Ptr("armid1"), + // Type: to.Ptr("certificates"), + // ID: to.Ptr("/providers/PaloAltoNetworks.Cloudngfw/globalrulestacks/armid1/certificates/armid1"), + // SystemData: &armpanngfw.SystemData{ + // CreatedAt: to.Ptr(func() time.Time { t, _ := time.Parse(time.RFC3339Nano, "2022-09-09T05:08:24.229Z"); return t}()), + // CreatedBy: to.Ptr("praval"), + // CreatedByType: to.Ptr(armpanngfw.CreatedByTypeUser), + // LastModifiedAt: to.Ptr(func() time.Time { t, _ := time.Parse(time.RFC3339Nano, "2022-09-09T05:08:24.229Z"); return t}()), + // LastModifiedBy: to.Ptr("praval"), + // LastModifiedByType: to.Ptr(armpanngfw.CreatedByTypeUser), + // }, + // Properties: &armpanngfw.PrefixObject{ + // Description: to.Ptr("string"), + // AuditComment: to.Ptr("comment"), + // Etag: to.Ptr("2bf4a339-294d-4c25-b0b2-ef649e9f5c27"), + // PrefixList: []*string{ + // to.Ptr("1.0.0.0/24")}, + // ProvisioningState: to.Ptr(armpanngfw.ProvisioningStateSucceeded), + // }, + // } +} + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/PrefixListLocalRulestack_Get_MinimumSet_Gen.json +func ExamplePrefixListLocalRulestackClient_Get_prefixListLocalRulestackGetMinimumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + res, err := clientFactory.NewPrefixListLocalRulestackClient().Get(ctx, "rgopenapi", "lrs1", "armid1", nil) + if err != nil { + log.Fatalf("failed to finish the request: %v", err) + } + // You could use response here. We use blank identifier for just demo purposes. + _ = res + // If the HTTP response code is 200 as defined in example definition, your response structure would look as follows. Please pay attention that all the values in the output are fake values for just demo purposes. + // res.PrefixListResource = armpanngfw.PrefixListResource{ + // ID: to.Ptr("/subscriptions/2bf4a339-294d-4c25-b0b2-ef649e9f5c27/resourcegroups/rgopenapi/providers/PaloAltoNetworks.Cloudngfw/localRulestacks/praval/prefixlists/armid1"), + // Properties: &armpanngfw.PrefixObject{ + // PrefixList: []*string{ + // to.Ptr("1.0.0.0/24")}, + // }, + // } +} + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/PrefixListLocalRulestack_CreateOrUpdate_MaximumSet_Gen.json +func ExamplePrefixListLocalRulestackClient_BeginCreateOrUpdate_prefixListLocalRulestackCreateOrUpdateMaximumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + poller, err := clientFactory.NewPrefixListLocalRulestackClient().BeginCreateOrUpdate(ctx, "rgopenapi", "lrs1", "armid1", armpanngfw.PrefixListResource{ + Properties: &armpanngfw.PrefixObject{ + Description: to.Ptr("string"), + AuditComment: to.Ptr("comment"), + Etag: to.Ptr("2bf4a339-294d-4c25-b0b2-ef649e9f5c27"), + PrefixList: []*string{ + to.Ptr("1.0.0.0/24")}, + ProvisioningState: to.Ptr(armpanngfw.ProvisioningStateAccepted), + }, + }, nil) + if err != nil { + log.Fatalf("failed to finish the request: %v", err) + } + res, err := poller.PollUntilDone(ctx, nil) + if err != nil { + log.Fatalf("failed to pull the result: %v", err) + } + // You could use response here. We use blank identifier for just demo purposes. + _ = res + // If the HTTP response code is 200 as defined in example definition, your response structure would look as follows. Please pay attention that all the values in the output are fake values for just demo purposes. + // res.PrefixListResource = armpanngfw.PrefixListResource{ + // Name: to.Ptr("armid1"), + // Type: to.Ptr("certificates"), + // ID: to.Ptr("/providers/PaloAltoNetworks.Cloudngfw/globalrulestacks/armid1/certificates/armid1"), + // SystemData: &armpanngfw.SystemData{ + // CreatedAt: to.Ptr(func() time.Time { t, _ := time.Parse(time.RFC3339Nano, "2022-09-09T05:08:24.229Z"); return t}()), + // CreatedBy: to.Ptr("praval"), + // CreatedByType: to.Ptr(armpanngfw.CreatedByTypeUser), + // LastModifiedAt: to.Ptr(func() time.Time { t, _ := time.Parse(time.RFC3339Nano, "2022-09-09T05:08:24.229Z"); return t}()), + // LastModifiedBy: to.Ptr("praval"), + // LastModifiedByType: to.Ptr(armpanngfw.CreatedByTypeUser), + // }, + // Properties: &armpanngfw.PrefixObject{ + // Description: to.Ptr("string"), + // AuditComment: to.Ptr("comment"), + // Etag: to.Ptr("2bf4a339-294d-4c25-b0b2-ef649e9f5c27"), + // PrefixList: []*string{ + // to.Ptr("1.0.0.0/24")}, + // ProvisioningState: to.Ptr(armpanngfw.ProvisioningStateSucceeded), + // }, + // } +} + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/PrefixListLocalRulestack_CreateOrUpdate_MinimumSet_Gen.json +func ExamplePrefixListLocalRulestackClient_BeginCreateOrUpdate_prefixListLocalRulestackCreateOrUpdateMinimumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + poller, err := clientFactory.NewPrefixListLocalRulestackClient().BeginCreateOrUpdate(ctx, "rgopenapi", "lrs1", "armid1", armpanngfw.PrefixListResource{ + Properties: &armpanngfw.PrefixObject{ + PrefixList: []*string{ + to.Ptr("1.0.0.0/24")}, + }, + }, nil) + if err != nil { + log.Fatalf("failed to finish the request: %v", err) + } + res, err := poller.PollUntilDone(ctx, nil) + if err != nil { + log.Fatalf("failed to pull the result: %v", err) + } + // You could use response here. We use blank identifier for just demo purposes. + _ = res + // If the HTTP response code is 200 as defined in example definition, your response structure would look as follows. Please pay attention that all the values in the output are fake values for just demo purposes. + // res.PrefixListResource = armpanngfw.PrefixListResource{ + // ID: to.Ptr("/subscriptions/2bf4a339-294d-4c25-b0b2-ef649e9f5c27/resourcegroups/rgopenapi/providers/PaloAltoNetworks.Cloudngfw/localRulestacks/praval/prefixlists/armid1"), + // Properties: &armpanngfw.PrefixObject{ + // PrefixList: []*string{ + // to.Ptr("1.0.0.0/24")}, + // }, + // } +} + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/PrefixListLocalRulestack_Delete_MaximumSet_Gen.json +func ExamplePrefixListLocalRulestackClient_BeginDelete_prefixListLocalRulestackDeleteMaximumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + poller, err := clientFactory.NewPrefixListLocalRulestackClient().BeginDelete(ctx, "rgopenapi", "lrs1", "armid1", nil) + if err != nil { + log.Fatalf("failed to finish the request: %v", err) + } + _, err = poller.PollUntilDone(ctx, nil) + if err != nil { + log.Fatalf("failed to pull the result: %v", err) + } +} + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/PrefixListLocalRulestack_Delete_MinimumSet_Gen.json +func ExamplePrefixListLocalRulestackClient_BeginDelete_prefixListLocalRulestackDeleteMinimumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + poller, err := clientFactory.NewPrefixListLocalRulestackClient().BeginDelete(ctx, "rgopenapi", "lrs1", "armid1", nil) + if err != nil { + log.Fatalf("failed to finish the request: %v", err) + } + _, err = poller.PollUntilDone(ctx, nil) + if err != nil { + log.Fatalf("failed to pull the result: %v", err) + } +} diff --git a/sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/prerules_client.go b/sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/prerules_client.go new file mode 100644 index 000000000000..4fbd9b8ed729 --- /dev/null +++ b/sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/prerules_client.go @@ -0,0 +1,441 @@ +//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. +// Code generated by Microsoft (R) AutoRest Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. +// DO NOT EDIT. + +package armpanngfw + +import ( + "context" + "errors" + "github.com/Azure/azure-sdk-for-go/sdk/azcore" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/arm" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/policy" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime" + "net/http" + "net/url" + "strings" +) + +// PreRulesClient contains the methods for the PreRules group. +// Don't use this type directly, use NewPreRulesClient() instead. +type PreRulesClient struct { + internal *arm.Client +} + +// NewPreRulesClient creates a new instance of PreRulesClient with the specified values. +// - credential - used to authorize requests. Usually a credential from azidentity. +// - options - pass nil to accept the default values. +func NewPreRulesClient(credential azcore.TokenCredential, options *arm.ClientOptions) (*PreRulesClient, error) { + cl, err := arm.NewClient(moduleName+".PreRulesClient", moduleVersion, credential, options) + if err != nil { + return nil, err + } + client := &PreRulesClient{ + internal: cl, + } + return client, nil +} + +// BeginCreateOrUpdate - Create a PreRulesResource +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2022-08-29-preview +// - globalRulestackName - GlobalRulestack resource name +// - priority - Pre Rule priority +// - resource - Resource create parameters. +// - options - PreRulesClientBeginCreateOrUpdateOptions contains the optional parameters for the PreRulesClient.BeginCreateOrUpdate +// method. +func (client *PreRulesClient) BeginCreateOrUpdate(ctx context.Context, globalRulestackName string, priority string, resource PreRulesResource, options *PreRulesClientBeginCreateOrUpdateOptions) (*runtime.Poller[PreRulesClientCreateOrUpdateResponse], error) { + if options == nil || options.ResumeToken == "" { + resp, err := client.createOrUpdate(ctx, globalRulestackName, priority, resource, options) + if err != nil { + return nil, err + } + return runtime.NewPoller(resp, client.internal.Pipeline(), &runtime.NewPollerOptions[PreRulesClientCreateOrUpdateResponse]{ + FinalStateVia: runtime.FinalStateViaAzureAsyncOp, + }) + } else { + return runtime.NewPollerFromResumeToken[PreRulesClientCreateOrUpdateResponse](options.ResumeToken, client.internal.Pipeline(), nil) + } +} + +// CreateOrUpdate - Create a PreRulesResource +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2022-08-29-preview +func (client *PreRulesClient) createOrUpdate(ctx context.Context, globalRulestackName string, priority string, resource PreRulesResource, options *PreRulesClientBeginCreateOrUpdateOptions) (*http.Response, error) { + req, err := client.createOrUpdateCreateRequest(ctx, globalRulestackName, priority, resource, options) + if err != nil { + return nil, err + } + resp, err := client.internal.Pipeline().Do(req) + if err != nil { + return nil, err + } + if !runtime.HasStatusCode(resp, http.StatusOK, http.StatusCreated) { + return nil, runtime.NewResponseError(resp) + } + return resp, nil +} + +// createOrUpdateCreateRequest creates the CreateOrUpdate request. +func (client *PreRulesClient) createOrUpdateCreateRequest(ctx context.Context, globalRulestackName string, priority string, resource PreRulesResource, options *PreRulesClientBeginCreateOrUpdateOptions) (*policy.Request, error) { + urlPath := "/providers/PaloAltoNetworks.Cloudngfw/globalRulestacks/{globalRulestackName}/preRules/{priority}" + if globalRulestackName == "" { + return nil, errors.New("parameter globalRulestackName cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{globalRulestackName}", url.PathEscape(globalRulestackName)) + if priority == "" { + return nil, errors.New("parameter priority cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{priority}", url.PathEscape(priority)) + req, err := runtime.NewRequest(ctx, http.MethodPut, runtime.JoinPaths(client.internal.Endpoint(), urlPath)) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("api-version", "2022-08-29-preview") + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["Accept"] = []string{"application/json"} + return req, runtime.MarshalAsJSON(req, resource) +} + +// BeginDelete - Delete a PreRulesResource +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2022-08-29-preview +// - globalRulestackName - GlobalRulestack resource name +// - priority - Pre Rule priority +// - options - PreRulesClientBeginDeleteOptions contains the optional parameters for the PreRulesClient.BeginDelete method. +func (client *PreRulesClient) BeginDelete(ctx context.Context, globalRulestackName string, priority string, options *PreRulesClientBeginDeleteOptions) (*runtime.Poller[PreRulesClientDeleteResponse], error) { + if options == nil || options.ResumeToken == "" { + resp, err := client.deleteOperation(ctx, globalRulestackName, priority, options) + if err != nil { + return nil, err + } + return runtime.NewPoller(resp, client.internal.Pipeline(), &runtime.NewPollerOptions[PreRulesClientDeleteResponse]{ + FinalStateVia: runtime.FinalStateViaAzureAsyncOp, + }) + } else { + return runtime.NewPollerFromResumeToken[PreRulesClientDeleteResponse](options.ResumeToken, client.internal.Pipeline(), nil) + } +} + +// Delete - Delete a PreRulesResource +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2022-08-29-preview +func (client *PreRulesClient) deleteOperation(ctx context.Context, globalRulestackName string, priority string, options *PreRulesClientBeginDeleteOptions) (*http.Response, error) { + req, err := client.deleteCreateRequest(ctx, globalRulestackName, priority, options) + if err != nil { + return nil, err + } + resp, err := client.internal.Pipeline().Do(req) + if err != nil { + return nil, err + } + if !runtime.HasStatusCode(resp, http.StatusOK, http.StatusAccepted, http.StatusNoContent) { + return nil, runtime.NewResponseError(resp) + } + return resp, nil +} + +// deleteCreateRequest creates the Delete request. +func (client *PreRulesClient) deleteCreateRequest(ctx context.Context, globalRulestackName string, priority string, options *PreRulesClientBeginDeleteOptions) (*policy.Request, error) { + urlPath := "/providers/PaloAltoNetworks.Cloudngfw/globalRulestacks/{globalRulestackName}/preRules/{priority}" + if globalRulestackName == "" { + return nil, errors.New("parameter globalRulestackName cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{globalRulestackName}", url.PathEscape(globalRulestackName)) + if priority == "" { + return nil, errors.New("parameter priority cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{priority}", url.PathEscape(priority)) + req, err := runtime.NewRequest(ctx, http.MethodDelete, runtime.JoinPaths(client.internal.Endpoint(), urlPath)) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("api-version", "2022-08-29-preview") + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["Accept"] = []string{"application/json"} + return req, nil +} + +// Get - Get a PreRulesResource +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2022-08-29-preview +// - globalRulestackName - GlobalRulestack resource name +// - priority - Pre Rule priority +// - options - PreRulesClientGetOptions contains the optional parameters for the PreRulesClient.Get method. +func (client *PreRulesClient) Get(ctx context.Context, globalRulestackName string, priority string, options *PreRulesClientGetOptions) (PreRulesClientGetResponse, error) { + req, err := client.getCreateRequest(ctx, globalRulestackName, priority, options) + if err != nil { + return PreRulesClientGetResponse{}, err + } + resp, err := client.internal.Pipeline().Do(req) + if err != nil { + return PreRulesClientGetResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusOK) { + return PreRulesClientGetResponse{}, runtime.NewResponseError(resp) + } + return client.getHandleResponse(resp) +} + +// getCreateRequest creates the Get request. +func (client *PreRulesClient) getCreateRequest(ctx context.Context, globalRulestackName string, priority string, options *PreRulesClientGetOptions) (*policy.Request, error) { + urlPath := "/providers/PaloAltoNetworks.Cloudngfw/globalRulestacks/{globalRulestackName}/preRules/{priority}" + if globalRulestackName == "" { + return nil, errors.New("parameter globalRulestackName cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{globalRulestackName}", url.PathEscape(globalRulestackName)) + if priority == "" { + return nil, errors.New("parameter priority cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{priority}", url.PathEscape(priority)) + req, err := runtime.NewRequest(ctx, http.MethodGet, runtime.JoinPaths(client.internal.Endpoint(), urlPath)) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("api-version", "2022-08-29-preview") + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["Accept"] = []string{"application/json"} + return req, nil +} + +// getHandleResponse handles the Get response. +func (client *PreRulesClient) getHandleResponse(resp *http.Response) (PreRulesClientGetResponse, error) { + result := PreRulesClientGetResponse{} + if err := runtime.UnmarshalAsJSON(resp, &result.PreRulesResource); err != nil { + return PreRulesClientGetResponse{}, err + } + return result, nil +} + +// GetCounters - Get counters +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2022-08-29-preview +// - globalRulestackName - GlobalRulestack resource name +// - priority - Pre Rule priority +// - options - PreRulesClientGetCountersOptions contains the optional parameters for the PreRulesClient.GetCounters method. +func (client *PreRulesClient) GetCounters(ctx context.Context, globalRulestackName string, priority string, options *PreRulesClientGetCountersOptions) (PreRulesClientGetCountersResponse, error) { + req, err := client.getCountersCreateRequest(ctx, globalRulestackName, priority, options) + if err != nil { + return PreRulesClientGetCountersResponse{}, err + } + resp, err := client.internal.Pipeline().Do(req) + if err != nil { + return PreRulesClientGetCountersResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusOK) { + return PreRulesClientGetCountersResponse{}, runtime.NewResponseError(resp) + } + return client.getCountersHandleResponse(resp) +} + +// getCountersCreateRequest creates the GetCounters request. +func (client *PreRulesClient) getCountersCreateRequest(ctx context.Context, globalRulestackName string, priority string, options *PreRulesClientGetCountersOptions) (*policy.Request, error) { + urlPath := "/providers/PaloAltoNetworks.Cloudngfw/globalRulestacks/{globalRulestackName}/preRules/{priority}/getCounters" + if globalRulestackName == "" { + return nil, errors.New("parameter globalRulestackName cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{globalRulestackName}", url.PathEscape(globalRulestackName)) + if priority == "" { + return nil, errors.New("parameter priority cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{priority}", url.PathEscape(priority)) + req, err := runtime.NewRequest(ctx, http.MethodPost, runtime.JoinPaths(client.internal.Endpoint(), urlPath)) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("api-version", "2022-08-29-preview") + if options != nil && options.FirewallName != nil { + reqQP.Set("firewallName", *options.FirewallName) + } + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["Accept"] = []string{"application/json"} + return req, nil +} + +// getCountersHandleResponse handles the GetCounters response. +func (client *PreRulesClient) getCountersHandleResponse(resp *http.Response) (PreRulesClientGetCountersResponse, error) { + result := PreRulesClientGetCountersResponse{} + if err := runtime.UnmarshalAsJSON(resp, &result.RuleCounter); err != nil { + return PreRulesClientGetCountersResponse{}, err + } + return result, nil +} + +// NewListPager - List PreRulesResource resources by Tenant +// +// Generated from API version 2022-08-29-preview +// - globalRulestackName - GlobalRulestack resource name +// - options - PreRulesClientListOptions contains the optional parameters for the PreRulesClient.NewListPager method. +func (client *PreRulesClient) NewListPager(globalRulestackName string, options *PreRulesClientListOptions) *runtime.Pager[PreRulesClientListResponse] { + return runtime.NewPager(runtime.PagingHandler[PreRulesClientListResponse]{ + More: func(page PreRulesClientListResponse) bool { + return page.NextLink != nil && len(*page.NextLink) > 0 + }, + Fetcher: func(ctx context.Context, page *PreRulesClientListResponse) (PreRulesClientListResponse, error) { + var req *policy.Request + var err error + if page == nil { + req, err = client.listCreateRequest(ctx, globalRulestackName, options) + } else { + req, err = runtime.NewRequest(ctx, http.MethodGet, *page.NextLink) + } + if err != nil { + return PreRulesClientListResponse{}, err + } + resp, err := client.internal.Pipeline().Do(req) + if err != nil { + return PreRulesClientListResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusOK) { + return PreRulesClientListResponse{}, runtime.NewResponseError(resp) + } + return client.listHandleResponse(resp) + }, + }) +} + +// listCreateRequest creates the List request. +func (client *PreRulesClient) listCreateRequest(ctx context.Context, globalRulestackName string, options *PreRulesClientListOptions) (*policy.Request, error) { + urlPath := "/providers/PaloAltoNetworks.Cloudngfw/globalRulestacks/{globalRulestackName}/preRules" + if globalRulestackName == "" { + return nil, errors.New("parameter globalRulestackName cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{globalRulestackName}", url.PathEscape(globalRulestackName)) + req, err := runtime.NewRequest(ctx, http.MethodGet, runtime.JoinPaths(client.internal.Endpoint(), urlPath)) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("api-version", "2022-08-29-preview") + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["Accept"] = []string{"application/json"} + return req, nil +} + +// listHandleResponse handles the List response. +func (client *PreRulesClient) listHandleResponse(resp *http.Response) (PreRulesClientListResponse, error) { + result := PreRulesClientListResponse{} + if err := runtime.UnmarshalAsJSON(resp, &result.PreRulesResourceListResult); err != nil { + return PreRulesClientListResponse{}, err + } + return result, nil +} + +// RefreshCounters - Refresh counters +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2022-08-29-preview +// - globalRulestackName - GlobalRulestack resource name +// - priority - Pre Rule priority +// - options - PreRulesClientRefreshCountersOptions contains the optional parameters for the PreRulesClient.RefreshCounters +// method. +func (client *PreRulesClient) RefreshCounters(ctx context.Context, globalRulestackName string, priority string, options *PreRulesClientRefreshCountersOptions) (PreRulesClientRefreshCountersResponse, error) { + req, err := client.refreshCountersCreateRequest(ctx, globalRulestackName, priority, options) + if err != nil { + return PreRulesClientRefreshCountersResponse{}, err + } + resp, err := client.internal.Pipeline().Do(req) + if err != nil { + return PreRulesClientRefreshCountersResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusNoContent) { + return PreRulesClientRefreshCountersResponse{}, runtime.NewResponseError(resp) + } + return PreRulesClientRefreshCountersResponse{}, nil +} + +// refreshCountersCreateRequest creates the RefreshCounters request. +func (client *PreRulesClient) refreshCountersCreateRequest(ctx context.Context, globalRulestackName string, priority string, options *PreRulesClientRefreshCountersOptions) (*policy.Request, error) { + urlPath := "/providers/PaloAltoNetworks.Cloudngfw/globalRulestacks/{globalRulestackName}/preRules/{priority}/refreshCounters" + if globalRulestackName == "" { + return nil, errors.New("parameter globalRulestackName cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{globalRulestackName}", url.PathEscape(globalRulestackName)) + if priority == "" { + return nil, errors.New("parameter priority cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{priority}", url.PathEscape(priority)) + req, err := runtime.NewRequest(ctx, http.MethodPost, runtime.JoinPaths(client.internal.Endpoint(), urlPath)) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("api-version", "2022-08-29-preview") + if options != nil && options.FirewallName != nil { + reqQP.Set("firewallName", *options.FirewallName) + } + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["Accept"] = []string{"application/json"} + return req, nil +} + +// ResetCounters - Reset counters +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2022-08-29-preview +// - globalRulestackName - GlobalRulestack resource name +// - priority - Pre Rule priority +// - options - PreRulesClientResetCountersOptions contains the optional parameters for the PreRulesClient.ResetCounters method. +func (client *PreRulesClient) ResetCounters(ctx context.Context, globalRulestackName string, priority string, options *PreRulesClientResetCountersOptions) (PreRulesClientResetCountersResponse, error) { + req, err := client.resetCountersCreateRequest(ctx, globalRulestackName, priority, options) + if err != nil { + return PreRulesClientResetCountersResponse{}, err + } + resp, err := client.internal.Pipeline().Do(req) + if err != nil { + return PreRulesClientResetCountersResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusOK) { + return PreRulesClientResetCountersResponse{}, runtime.NewResponseError(resp) + } + return client.resetCountersHandleResponse(resp) +} + +// resetCountersCreateRequest creates the ResetCounters request. +func (client *PreRulesClient) resetCountersCreateRequest(ctx context.Context, globalRulestackName string, priority string, options *PreRulesClientResetCountersOptions) (*policy.Request, error) { + urlPath := "/providers/PaloAltoNetworks.Cloudngfw/globalRulestacks/{globalRulestackName}/preRules/{priority}/resetCounters" + if globalRulestackName == "" { + return nil, errors.New("parameter globalRulestackName cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{globalRulestackName}", url.PathEscape(globalRulestackName)) + if priority == "" { + return nil, errors.New("parameter priority cannot be empty") + } + urlPath = strings.ReplaceAll(urlPath, "{priority}", url.PathEscape(priority)) + req, err := runtime.NewRequest(ctx, http.MethodPost, runtime.JoinPaths(client.internal.Endpoint(), urlPath)) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("api-version", "2022-08-29-preview") + if options != nil && options.FirewallName != nil { + reqQP.Set("firewallName", *options.FirewallName) + } + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["Accept"] = []string{"application/json"} + return req, nil +} + +// resetCountersHandleResponse handles the ResetCounters response. +func (client *PreRulesClient) resetCountersHandleResponse(resp *http.Response) (PreRulesClientResetCountersResponse, error) { + result := PreRulesClientResetCountersResponse{} + if err := runtime.UnmarshalAsJSON(resp, &result.RuleCounterReset); err != nil { + return PreRulesClientResetCountersResponse{}, err + } + return result, nil +} diff --git a/sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/prerules_client_example_test.go b/sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/prerules_client_example_test.go new file mode 100644 index 000000000000..118cba83affd --- /dev/null +++ b/sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/prerules_client_example_test.go @@ -0,0 +1,629 @@ +//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. +// Code generated by Microsoft (R) AutoRest Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. +// DO NOT EDIT. + +package armpanngfw_test + +import ( + "context" + "log" + + "github.com/Azure/azure-sdk-for-go/sdk/azcore/to" + "github.com/Azure/azure-sdk-for-go/sdk/azidentity" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/paloaltonetworksngfw/armpanngfw" +) + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/PreRules_List_MaximumSet_Gen.json +func ExamplePreRulesClient_NewListPager_preRulesListMaximumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + pager := clientFactory.NewPreRulesClient().NewListPager("lrs1", nil) + for pager.More() { + page, err := pager.NextPage(ctx) + if err != nil { + log.Fatalf("failed to advance page: %v", err) + } + for _, v := range page.Value { + // You could use page here. We use blank identifier for just demo purposes. + _ = v + } + // If the HTTP response code is 200 as defined in example definition, your page structure would look as follows. Please pay attention that all the values in the output are fake values for just demo purposes. + // page.PreRulesResourceListResult = armpanngfw.PreRulesResourceListResult{ + // Value: []*armpanngfw.PreRulesResource{ + // { + // Name: to.Ptr("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"), + // Type: to.Ptr("aaaaaaaaaaaaaaaaaaaaaaaaaa"), + // ID: to.Ptr("aaaaaaaaaaaaaaaaaaaaaa"), + // SystemData: &armpanngfw.SystemData{ + // CreatedAt: to.Ptr(func() time.Time { t, _ := time.Parse(time.RFC3339Nano, "2022-09-09T05:08:24.229Z"); return t}()), + // CreatedBy: to.Ptr("praval"), + // CreatedByType: to.Ptr(armpanngfw.CreatedByTypeUser), + // LastModifiedAt: to.Ptr(func() time.Time { t, _ := time.Parse(time.RFC3339Nano, "2022-09-09T05:08:24.229Z"); return t}()), + // LastModifiedBy: to.Ptr("praval"), + // LastModifiedByType: to.Ptr(armpanngfw.CreatedByTypeUser), + // }, + // Properties: &armpanngfw.RuleEntry{ + // Description: to.Ptr("aaaaaaaaaaaaaaaaaaaaaaaaaaaa"), + // ActionType: to.Ptr(armpanngfw.ActionEnumAllow), + // Applications: []*string{ + // to.Ptr("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")}, + // AuditComment: to.Ptr("aaa"), + // Category: &armpanngfw.Category{ + // Feeds: []*string{ + // to.Ptr("aaaaaaaaaaaa")}, + // URLCustom: []*string{ + // to.Ptr("aaaaa")}, + // }, + // DecryptionRuleType: to.Ptr(armpanngfw.DecryptionRuleTypeEnumSSLOutboundInspection), + // Destination: &armpanngfw.DestinationAddr{ + // Cidrs: []*string{ + // to.Ptr("aaaaaaa")}, + // Countries: []*string{ + // to.Ptr("aaaaaaaaaaaaaa")}, + // Feeds: []*string{ + // to.Ptr("aaaaaaaaaaaaaaaaaaaaaaaaaa")}, + // FqdnLists: []*string{ + // to.Ptr("aaaaaaaaaaaaa")}, + // PrefixLists: []*string{ + // to.Ptr("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")}, + // }, + // EnableLogging: to.Ptr(armpanngfw.StateEnumDISABLED), + // Etag: to.Ptr("aaaaaaaaaaaaaaaaaaaa"), + // InboundInspectionCertificate: to.Ptr("aaaaaaaaaaaaaaaaaaaaaaaaaaa"), + // NegateDestination: to.Ptr(armpanngfw.BooleanEnumTRUE), + // NegateSource: to.Ptr(armpanngfw.BooleanEnumTRUE), + // Priority: to.Ptr[int32](24), + // ProtocolPortList: []*string{ + // to.Ptr("aaaaaaaaaaaa")}, + // ProvisioningState: to.Ptr(armpanngfw.ProvisioningStateSucceeded), + // RuleName: to.Ptr("aaaaaaaaaaaaaaaaaaaaaaaaa"), + // RuleState: to.Ptr(armpanngfw.StateEnumDISABLED), + // Source: &armpanngfw.SourceAddr{ + // Cidrs: []*string{ + // to.Ptr("aaa")}, + // Countries: []*string{ + // to.Ptr("aaaaa")}, + // Feeds: []*string{ + // to.Ptr("aaaaaaaaaaaaaaaaaaa")}, + // PrefixLists: []*string{ + // to.Ptr("aaaaaaaaaaaaaaaaaaaa")}, + // }, + // Tags: []*armpanngfw.TagInfo{ + // { + // Key: to.Ptr("keyName"), + // Value: to.Ptr("value"), + // }}, + // Protocol: to.Ptr("aaaa"), + // }, + // }}, + // } + } +} + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/PreRules_List_MinimumSet_Gen.json +func ExamplePreRulesClient_NewListPager_preRulesListMinimumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + pager := clientFactory.NewPreRulesClient().NewListPager("lrs1", nil) + for pager.More() { + page, err := pager.NextPage(ctx) + if err != nil { + log.Fatalf("failed to advance page: %v", err) + } + for _, v := range page.Value { + // You could use page here. We use blank identifier for just demo purposes. + _ = v + } + // If the HTTP response code is 200 as defined in example definition, your page structure would look as follows. Please pay attention that all the values in the output are fake values for just demo purposes. + // page.PreRulesResourceListResult = armpanngfw.PreRulesResourceListResult{ + // Value: []*armpanngfw.PreRulesResource{ + // { + // ID: to.Ptr("/providers/PaloAltoNetworks.Cloudngfw/globalRulestacks/lrs1/prerules/1"), + // Properties: &armpanngfw.RuleEntry{ + // RuleName: to.Ptr("aaaaaaaaaaaaaaaaaaaaaaaaa"), + // }, + // }}, + // } + } +} + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/PreRules_Get_MaximumSet_Gen.json +func ExamplePreRulesClient_Get_preRulesGetMaximumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + res, err := clientFactory.NewPreRulesClient().Get(ctx, "lrs1", "1", nil) + if err != nil { + log.Fatalf("failed to finish the request: %v", err) + } + // You could use response here. We use blank identifier for just demo purposes. + _ = res + // If the HTTP response code is 200 as defined in example definition, your response structure would look as follows. Please pay attention that all the values in the output are fake values for just demo purposes. + // res.PreRulesResource = armpanngfw.PreRulesResource{ + // Name: to.Ptr("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"), + // Type: to.Ptr("aaaaaaaaaaaaaaaaaaaaaaaaaa"), + // ID: to.Ptr("aaaaaaaaaaaaaaaaaaaaaa"), + // SystemData: &armpanngfw.SystemData{ + // CreatedAt: to.Ptr(func() time.Time { t, _ := time.Parse(time.RFC3339Nano, "2022-09-09T05:08:24.229Z"); return t}()), + // CreatedBy: to.Ptr("praval"), + // CreatedByType: to.Ptr(armpanngfw.CreatedByTypeUser), + // LastModifiedAt: to.Ptr(func() time.Time { t, _ := time.Parse(time.RFC3339Nano, "2022-09-09T05:08:24.229Z"); return t}()), + // LastModifiedBy: to.Ptr("praval"), + // LastModifiedByType: to.Ptr(armpanngfw.CreatedByTypeUser), + // }, + // Properties: &armpanngfw.RuleEntry{ + // Description: to.Ptr("aaaaaaaaaaaaaaaaaaaaaaaaaaaa"), + // ActionType: to.Ptr(armpanngfw.ActionEnumAllow), + // Applications: []*string{ + // to.Ptr("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")}, + // AuditComment: to.Ptr("aaa"), + // Category: &armpanngfw.Category{ + // Feeds: []*string{ + // to.Ptr("aaaaaaaaaaaa")}, + // URLCustom: []*string{ + // to.Ptr("aaaaa")}, + // }, + // DecryptionRuleType: to.Ptr(armpanngfw.DecryptionRuleTypeEnumSSLOutboundInspection), + // Destination: &armpanngfw.DestinationAddr{ + // Cidrs: []*string{ + // to.Ptr("aaaaaaa")}, + // Countries: []*string{ + // to.Ptr("aaaaaaaaaaaaaa")}, + // Feeds: []*string{ + // to.Ptr("aaaaaaaaaaaaaaaaaaaaaaaaaa")}, + // FqdnLists: []*string{ + // to.Ptr("aaaaaaaaaaaaa")}, + // PrefixLists: []*string{ + // to.Ptr("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")}, + // }, + // EnableLogging: to.Ptr(armpanngfw.StateEnumDISABLED), + // Etag: to.Ptr("aaaaaaaaaaaaaaaaaaaa"), + // InboundInspectionCertificate: to.Ptr("aaaaaaaaaaaaaaaaaaaaaaaaaaa"), + // NegateDestination: to.Ptr(armpanngfw.BooleanEnumTRUE), + // NegateSource: to.Ptr(armpanngfw.BooleanEnumTRUE), + // Priority: to.Ptr[int32](24), + // ProtocolPortList: []*string{ + // to.Ptr("aaaaaaaaaaaa")}, + // ProvisioningState: to.Ptr(armpanngfw.ProvisioningStateSucceeded), + // RuleName: to.Ptr("aaaaaaaaaaaaaaaaaaaaaaaaa"), + // RuleState: to.Ptr(armpanngfw.StateEnumDISABLED), + // Source: &armpanngfw.SourceAddr{ + // Cidrs: []*string{ + // to.Ptr("aaa")}, + // Countries: []*string{ + // to.Ptr("aaaaa")}, + // Feeds: []*string{ + // to.Ptr("aaaaaaaaaaaaaaaaaaa")}, + // PrefixLists: []*string{ + // to.Ptr("aaaaaaaaaaaaaaaaaaaa")}, + // }, + // Tags: []*armpanngfw.TagInfo{ + // { + // Key: to.Ptr("keyName"), + // Value: to.Ptr("value"), + // }}, + // Protocol: to.Ptr("aaaa"), + // }, + // } +} + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/PreRules_Get_MinimumSet_Gen.json +func ExamplePreRulesClient_Get_preRulesGetMinimumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + res, err := clientFactory.NewPreRulesClient().Get(ctx, "lrs1", "1", nil) + if err != nil { + log.Fatalf("failed to finish the request: %v", err) + } + // You could use response here. We use blank identifier for just demo purposes. + _ = res + // If the HTTP response code is 200 as defined in example definition, your response structure would look as follows. Please pay attention that all the values in the output are fake values for just demo purposes. + // res.PreRulesResource = armpanngfw.PreRulesResource{ + // ID: to.Ptr("/providers/PaloAltoNetworks.Cloudngfw/globalRulestacks/lrs1/prerules/1"), + // Properties: &armpanngfw.RuleEntry{ + // RuleName: to.Ptr("aaaaaaaaaaaaaaaaaaaaaaaaa"), + // }, + // } +} + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/PreRules_CreateOrUpdate_MaximumSet_Gen.json +func ExamplePreRulesClient_BeginCreateOrUpdate_preRulesCreateOrUpdateMaximumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + poller, err := clientFactory.NewPreRulesClient().BeginCreateOrUpdate(ctx, "lrs1", "1", armpanngfw.PreRulesResource{ + Properties: &armpanngfw.RuleEntry{ + Description: to.Ptr("description of pre rule"), + ActionType: to.Ptr(armpanngfw.ActionEnumAllow), + Applications: []*string{ + to.Ptr("app1")}, + AuditComment: to.Ptr("example comment"), + Category: &armpanngfw.Category{ + Feeds: []*string{ + to.Ptr("feed")}, + URLCustom: []*string{ + to.Ptr("https://microsoft.com")}, + }, + DecryptionRuleType: to.Ptr(armpanngfw.DecryptionRuleTypeEnumSSLOutboundInspection), + Destination: &armpanngfw.DestinationAddr{ + Cidrs: []*string{ + to.Ptr("1.0.0.1/10")}, + Countries: []*string{ + to.Ptr("India")}, + Feeds: []*string{ + to.Ptr("feed")}, + FqdnLists: []*string{ + to.Ptr("FQDN1")}, + PrefixLists: []*string{ + to.Ptr("PL1")}, + }, + EnableLogging: to.Ptr(armpanngfw.StateEnumDISABLED), + Etag: to.Ptr("c18e6eef-ba3e-49ee-8a85-2b36c863a9d0"), + InboundInspectionCertificate: to.Ptr("cert1"), + NegateDestination: to.Ptr(armpanngfw.BooleanEnumTRUE), + NegateSource: to.Ptr(armpanngfw.BooleanEnumTRUE), + ProtocolPortList: []*string{ + to.Ptr("80")}, + ProvisioningState: to.Ptr(armpanngfw.ProvisioningStateAccepted), + RuleName: to.Ptr("preRule1"), + RuleState: to.Ptr(armpanngfw.StateEnumDISABLED), + Source: &armpanngfw.SourceAddr{ + Cidrs: []*string{ + to.Ptr("1.0.0.1/10")}, + Countries: []*string{ + to.Ptr("India")}, + Feeds: []*string{ + to.Ptr("feed")}, + PrefixLists: []*string{ + to.Ptr("PL1")}, + }, + Tags: []*armpanngfw.TagInfo{ + { + Key: to.Ptr("keyName"), + Value: to.Ptr("value"), + }}, + Protocol: to.Ptr("HTTP"), + }, + }, nil) + if err != nil { + log.Fatalf("failed to finish the request: %v", err) + } + res, err := poller.PollUntilDone(ctx, nil) + if err != nil { + log.Fatalf("failed to pull the result: %v", err) + } + // You could use response here. We use blank identifier for just demo purposes. + _ = res + // If the HTTP response code is 200 as defined in example definition, your response structure would look as follows. Please pay attention that all the values in the output are fake values for just demo purposes. + // res.PreRulesResource = armpanngfw.PreRulesResource{ + // Name: to.Ptr("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"), + // Type: to.Ptr("aaaaaaaaaaaaaaaaaaaaaaaaaa"), + // ID: to.Ptr("aaaaaaaaaaaaaaaaaaaaaa"), + // SystemData: &armpanngfw.SystemData{ + // CreatedAt: to.Ptr(func() time.Time { t, _ := time.Parse(time.RFC3339Nano, "2022-09-09T05:08:24.229Z"); return t}()), + // CreatedBy: to.Ptr("praval"), + // CreatedByType: to.Ptr(armpanngfw.CreatedByTypeUser), + // LastModifiedAt: to.Ptr(func() time.Time { t, _ := time.Parse(time.RFC3339Nano, "2022-09-09T05:08:24.229Z"); return t}()), + // LastModifiedBy: to.Ptr("praval"), + // LastModifiedByType: to.Ptr(armpanngfw.CreatedByTypeUser), + // }, + // Properties: &armpanngfw.RuleEntry{ + // Description: to.Ptr("aaaaaaaaaaaaaaaaaaaaaaaaaaaa"), + // ActionType: to.Ptr(armpanngfw.ActionEnumAllow), + // Applications: []*string{ + // to.Ptr("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")}, + // AuditComment: to.Ptr("aaa"), + // Category: &armpanngfw.Category{ + // Feeds: []*string{ + // to.Ptr("aaaaaaaaaaaa")}, + // URLCustom: []*string{ + // to.Ptr("aaaaa")}, + // }, + // DecryptionRuleType: to.Ptr(armpanngfw.DecryptionRuleTypeEnumSSLOutboundInspection), + // Destination: &armpanngfw.DestinationAddr{ + // Cidrs: []*string{ + // to.Ptr("aaaaaaa")}, + // Countries: []*string{ + // to.Ptr("aaaaaaaaaaaaaa")}, + // Feeds: []*string{ + // to.Ptr("aaaaaaaaaaaaaaaaaaaaaaaaaa")}, + // FqdnLists: []*string{ + // to.Ptr("aaaaaaaaaaaaa")}, + // PrefixLists: []*string{ + // to.Ptr("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")}, + // }, + // EnableLogging: to.Ptr(armpanngfw.StateEnumDISABLED), + // Etag: to.Ptr("aaaaaaaaaaaaaaaaaaaa"), + // InboundInspectionCertificate: to.Ptr("aaaaaaaaaaaaaaaaaaaaaaaaaaa"), + // NegateDestination: to.Ptr(armpanngfw.BooleanEnumTRUE), + // NegateSource: to.Ptr(armpanngfw.BooleanEnumTRUE), + // Priority: to.Ptr[int32](24), + // ProtocolPortList: []*string{ + // to.Ptr("aaaaaaaaaaaa")}, + // ProvisioningState: to.Ptr(armpanngfw.ProvisioningStateSucceeded), + // RuleName: to.Ptr("aaaaaaaaaaaaaaaaaaaaaaaaa"), + // RuleState: to.Ptr(armpanngfw.StateEnumDISABLED), + // Source: &armpanngfw.SourceAddr{ + // Cidrs: []*string{ + // to.Ptr("aaa")}, + // Countries: []*string{ + // to.Ptr("aaaaa")}, + // Feeds: []*string{ + // to.Ptr("aaaaaaaaaaaaaaaaaaa")}, + // PrefixLists: []*string{ + // to.Ptr("aaaaaaaaaaaaaaaaaaaa")}, + // }, + // Tags: []*armpanngfw.TagInfo{ + // { + // Key: to.Ptr("keyName"), + // Value: to.Ptr("value"), + // }}, + // Protocol: to.Ptr("aaaa"), + // }, + // } +} + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/PreRules_CreateOrUpdate_MinimumSet_Gen.json +func ExamplePreRulesClient_BeginCreateOrUpdate_preRulesCreateOrUpdateMinimumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + poller, err := clientFactory.NewPreRulesClient().BeginCreateOrUpdate(ctx, "lrs1", "1", armpanngfw.PreRulesResource{ + Properties: &armpanngfw.RuleEntry{ + RuleName: to.Ptr("preRule1"), + }, + }, nil) + if err != nil { + log.Fatalf("failed to finish the request: %v", err) + } + res, err := poller.PollUntilDone(ctx, nil) + if err != nil { + log.Fatalf("failed to pull the result: %v", err) + } + // You could use response here. We use blank identifier for just demo purposes. + _ = res + // If the HTTP response code is 200 as defined in example definition, your response structure would look as follows. Please pay attention that all the values in the output are fake values for just demo purposes. + // res.PreRulesResource = armpanngfw.PreRulesResource{ + // ID: to.Ptr("/providers/PaloAltoNetworks.Cloudngfw/globalRulestacks/lrs1/prerules/1"), + // Properties: &armpanngfw.RuleEntry{ + // RuleName: to.Ptr("aaaaaaaaaaaaaaaaaaaaaaaaa"), + // }, + // } +} + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/PreRules_Delete_MaximumSet_Gen.json +func ExamplePreRulesClient_BeginDelete_preRulesDeleteMaximumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + poller, err := clientFactory.NewPreRulesClient().BeginDelete(ctx, "lrs1", "1", nil) + if err != nil { + log.Fatalf("failed to finish the request: %v", err) + } + _, err = poller.PollUntilDone(ctx, nil) + if err != nil { + log.Fatalf("failed to pull the result: %v", err) + } +} + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/PreRules_Delete_MinimumSet_Gen.json +func ExamplePreRulesClient_BeginDelete_preRulesDeleteMinimumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + poller, err := clientFactory.NewPreRulesClient().BeginDelete(ctx, "lrs1", "1", nil) + if err != nil { + log.Fatalf("failed to finish the request: %v", err) + } + _, err = poller.PollUntilDone(ctx, nil) + if err != nil { + log.Fatalf("failed to pull the result: %v", err) + } +} + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/PreRules_getCounters_MaximumSet_Gen.json +func ExamplePreRulesClient_GetCounters_preRulesGetCountersMaximumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + res, err := clientFactory.NewPreRulesClient().GetCounters(ctx, "lrs1", "1", &armpanngfw.PreRulesClientGetCountersOptions{FirewallName: to.Ptr("firewall1")}) + if err != nil { + log.Fatalf("failed to finish the request: %v", err) + } + // You could use response here. We use blank identifier for just demo purposes. + _ = res + // If the HTTP response code is 200 as defined in example definition, your response structure would look as follows. Please pay attention that all the values in the output are fake values for just demo purposes. + // res.RuleCounter = armpanngfw.RuleCounter{ + // AppSeen: &armpanngfw.AppSeenData{ + // AppSeenList: []*armpanngfw.AppSeenInfo{ + // { + // Category: to.Ptr("aaaaaaaaaaaaaaaaaaa"), + // Risk: to.Ptr("aaaaaaaaaaaaaaaaaaaaaaaaaa"), + // StandardPorts: to.Ptr("aaaaaaaaaaaaaaaaaa"), + // SubCategory: to.Ptr("aaaaaaaaaaaaaaaaa"), + // Tag: to.Ptr("aaaaaaaaaa"), + // Technology: to.Ptr("aaaaaaaaaaaaaaaaaaaa"), + // Title: to.Ptr("aaaaaaaaaaaaaaaaaaaaaaaaaaaa"), + // }}, + // Count: to.Ptr[int32](13), + // }, + // FirewallName: to.Ptr("aaaaaaaaaaaaaaaaaa"), + // HitCount: to.Ptr[int32](20), + // LastUpdatedTimestamp: to.Ptr(func() time.Time { t, _ := time.Parse(time.RFC3339Nano, "2022-09-09T05:08:24.229Z"); return t}()), + // Priority: to.Ptr("aaaaaaaaaaaaaaaaaaaa"), + // RequestTimestamp: to.Ptr(func() time.Time { t, _ := time.Parse(time.RFC3339Nano, "2022-09-09T05:08:24.229Z"); return t}()), + // RuleListName: to.Ptr("aaaaaaaaaaaaaaaaaaa"), + // RuleName: to.Ptr("aaaa"), + // RuleStackName: to.Ptr("aaaaaaaaaaaaaaaaa"), + // Timestamp: to.Ptr(func() time.Time { t, _ := time.Parse(time.RFC3339Nano, "2022-09-09T05:08:24.229Z"); return t}()), + // } +} + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/PreRules_getCounters_MinimumSet_Gen.json +func ExamplePreRulesClient_GetCounters_preRulesGetCountersMinimumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + res, err := clientFactory.NewPreRulesClient().GetCounters(ctx, "lrs1", "1", &armpanngfw.PreRulesClientGetCountersOptions{FirewallName: nil}) + if err != nil { + log.Fatalf("failed to finish the request: %v", err) + } + // You could use response here. We use blank identifier for just demo purposes. + _ = res + // If the HTTP response code is 200 as defined in example definition, your response structure would look as follows. Please pay attention that all the values in the output are fake values for just demo purposes. + // res.RuleCounter = armpanngfw.RuleCounter{ + // Priority: to.Ptr("aaaaaaaaaaaaaaaaaaaa"), + // RuleName: to.Ptr("aaaa"), + // } +} + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/PreRules_refreshCounters_MaximumSet_Gen.json +func ExamplePreRulesClient_RefreshCounters_preRulesRefreshCountersMaximumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + _, err = clientFactory.NewPreRulesClient().RefreshCounters(ctx, "lrs1", "1", &armpanngfw.PreRulesClientRefreshCountersOptions{FirewallName: to.Ptr("firewall1")}) + if err != nil { + log.Fatalf("failed to finish the request: %v", err) + } +} + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/PreRules_refreshCounters_MinimumSet_Gen.json +func ExamplePreRulesClient_RefreshCounters_preRulesRefreshCountersMinimumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + _, err = clientFactory.NewPreRulesClient().RefreshCounters(ctx, "lrs1", "1", &armpanngfw.PreRulesClientRefreshCountersOptions{FirewallName: nil}) + if err != nil { + log.Fatalf("failed to finish the request: %v", err) + } +} + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/PreRules_resetCounters_MaximumSet_Gen.json +func ExamplePreRulesClient_ResetCounters_preRulesResetCountersMaximumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + res, err := clientFactory.NewPreRulesClient().ResetCounters(ctx, "lrs1", "1", &armpanngfw.PreRulesClientResetCountersOptions{FirewallName: to.Ptr("firewall1")}) + if err != nil { + log.Fatalf("failed to finish the request: %v", err) + } + // You could use response here. We use blank identifier for just demo purposes. + _ = res + // If the HTTP response code is 200 as defined in example definition, your response structure would look as follows. Please pay attention that all the values in the output are fake values for just demo purposes. + // res.RuleCounterReset = armpanngfw.RuleCounterReset{ + // FirewallName: to.Ptr("aaaaaaaaaaaaaaaaaa"), + // Priority: to.Ptr("aaaaaaa"), + // RuleListName: to.Ptr("aaaaa"), + // RuleName: to.Ptr("aaaaa"), + // RuleStackName: to.Ptr("aa"), + // } +} + +// Generated from example definition: https://github.com/Azure/azure-rest-api-specs/blob/fdf43f2fdacf17bd78c0621df44a5c024b61db82/specification/paloaltonetworks/resource-manager/PaloAltoNetworks.Cloudngfw/preview/2022-08-29-preview/examples/PreRules_resetCounters_MinimumSet_Gen.json +func ExamplePreRulesClient_ResetCounters_preRulesResetCountersMinimumSetGen() { + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + log.Fatalf("failed to obtain a credential: %v", err) + } + ctx := context.Background() + clientFactory, err := armpanngfw.NewClientFactory("", cred, nil) + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + res, err := clientFactory.NewPreRulesClient().ResetCounters(ctx, "lrs1", "1", &armpanngfw.PreRulesClientResetCountersOptions{FirewallName: nil}) + if err != nil { + log.Fatalf("failed to finish the request: %v", err) + } + // You could use response here. We use blank identifier for just demo purposes. + _ = res + // If the HTTP response code is 200 as defined in example definition, your response structure would look as follows. Please pay attention that all the values in the output are fake values for just demo purposes. + // res.RuleCounterReset = armpanngfw.RuleCounterReset{ + // } +} diff --git a/sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/response_types.go b/sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/response_types.go new file mode 100644 index 000000000000..45565bcd1f6d --- /dev/null +++ b/sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/response_types.go @@ -0,0 +1,450 @@ +//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. +// Code generated by Microsoft (R) AutoRest Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. +// DO NOT EDIT. + +package armpanngfw + +// CertificateObjectGlobalRulestackClientCreateOrUpdateResponse contains the response from method CertificateObjectGlobalRulestackClient.BeginCreateOrUpdate. +type CertificateObjectGlobalRulestackClientCreateOrUpdateResponse struct { + CertificateObjectGlobalRulestackResource +} + +// CertificateObjectGlobalRulestackClientDeleteResponse contains the response from method CertificateObjectGlobalRulestackClient.BeginDelete. +type CertificateObjectGlobalRulestackClientDeleteResponse struct { + // placeholder for future response values +} + +// CertificateObjectGlobalRulestackClientGetResponse contains the response from method CertificateObjectGlobalRulestackClient.Get. +type CertificateObjectGlobalRulestackClientGetResponse struct { + CertificateObjectGlobalRulestackResource +} + +// CertificateObjectGlobalRulestackClientListResponse contains the response from method CertificateObjectGlobalRulestackClient.NewListPager. +type CertificateObjectGlobalRulestackClientListResponse struct { + CertificateObjectGlobalRulestackResourceListResult +} + +// CertificateObjectLocalRulestackClientCreateOrUpdateResponse contains the response from method CertificateObjectLocalRulestackClient.BeginCreateOrUpdate. +type CertificateObjectLocalRulestackClientCreateOrUpdateResponse struct { + CertificateObjectLocalRulestackResource +} + +// CertificateObjectLocalRulestackClientDeleteResponse contains the response from method CertificateObjectLocalRulestackClient.BeginDelete. +type CertificateObjectLocalRulestackClientDeleteResponse struct { + // placeholder for future response values +} + +// CertificateObjectLocalRulestackClientGetResponse contains the response from method CertificateObjectLocalRulestackClient.Get. +type CertificateObjectLocalRulestackClientGetResponse struct { + CertificateObjectLocalRulestackResource +} + +// CertificateObjectLocalRulestackClientListByLocalRulestacksResponse contains the response from method CertificateObjectLocalRulestackClient.NewListByLocalRulestacksPager. +type CertificateObjectLocalRulestackClientListByLocalRulestacksResponse struct { + CertificateObjectLocalRulestackResourceListResult +} + +// FirewallStatusClientGetResponse contains the response from method FirewallStatusClient.Get. +type FirewallStatusClientGetResponse struct { + FirewallStatusResource +} + +// FirewallStatusClientListByFirewallsResponse contains the response from method FirewallStatusClient.NewListByFirewallsPager. +type FirewallStatusClientListByFirewallsResponse struct { + FirewallStatusResourceListResult +} + +// FirewallsClientCreateOrUpdateResponse contains the response from method FirewallsClient.BeginCreateOrUpdate. +type FirewallsClientCreateOrUpdateResponse struct { + FirewallResource +} + +// FirewallsClientDeleteResponse contains the response from method FirewallsClient.BeginDelete. +type FirewallsClientDeleteResponse struct { + // placeholder for future response values +} + +// FirewallsClientGetGlobalRulestackResponse contains the response from method FirewallsClient.GetGlobalRulestack. +type FirewallsClientGetGlobalRulestackResponse struct { + GlobalRulestackInfo +} + +// FirewallsClientGetLogProfileResponse contains the response from method FirewallsClient.GetLogProfile. +type FirewallsClientGetLogProfileResponse struct { + LogSettings +} + +// FirewallsClientGetResponse contains the response from method FirewallsClient.Get. +type FirewallsClientGetResponse struct { + FirewallResource +} + +// FirewallsClientGetSupportInfoResponse contains the response from method FirewallsClient.GetSupportInfo. +type FirewallsClientGetSupportInfoResponse struct { + SupportInfo +} + +// FirewallsClientListByResourceGroupResponse contains the response from method FirewallsClient.NewListByResourceGroupPager. +type FirewallsClientListByResourceGroupResponse struct { + FirewallResourceListResult +} + +// FirewallsClientListBySubscriptionResponse contains the response from method FirewallsClient.NewListBySubscriptionPager. +type FirewallsClientListBySubscriptionResponse struct { + FirewallResourceListResult +} + +// FirewallsClientSaveLogProfileResponse contains the response from method FirewallsClient.SaveLogProfile. +type FirewallsClientSaveLogProfileResponse struct { + // placeholder for future response values +} + +// FirewallsClientUpdateResponse contains the response from method FirewallsClient.Update. +type FirewallsClientUpdateResponse struct { + FirewallResource +} + +// FqdnListGlobalRulestackClientCreateOrUpdateResponse contains the response from method FqdnListGlobalRulestackClient.BeginCreateOrUpdate. +type FqdnListGlobalRulestackClientCreateOrUpdateResponse struct { + FqdnListGlobalRulestackResource +} + +// FqdnListGlobalRulestackClientDeleteResponse contains the response from method FqdnListGlobalRulestackClient.BeginDelete. +type FqdnListGlobalRulestackClientDeleteResponse struct { + // placeholder for future response values +} + +// FqdnListGlobalRulestackClientGetResponse contains the response from method FqdnListGlobalRulestackClient.Get. +type FqdnListGlobalRulestackClientGetResponse struct { + FqdnListGlobalRulestackResource +} + +// FqdnListGlobalRulestackClientListResponse contains the response from method FqdnListGlobalRulestackClient.NewListPager. +type FqdnListGlobalRulestackClientListResponse struct { + FqdnListGlobalRulestackResourceListResult +} + +// FqdnListLocalRulestackClientCreateOrUpdateResponse contains the response from method FqdnListLocalRulestackClient.BeginCreateOrUpdate. +type FqdnListLocalRulestackClientCreateOrUpdateResponse struct { + FqdnListLocalRulestackResource +} + +// FqdnListLocalRulestackClientDeleteResponse contains the response from method FqdnListLocalRulestackClient.BeginDelete. +type FqdnListLocalRulestackClientDeleteResponse struct { + // placeholder for future response values +} + +// FqdnListLocalRulestackClientGetResponse contains the response from method FqdnListLocalRulestackClient.Get. +type FqdnListLocalRulestackClientGetResponse struct { + FqdnListLocalRulestackResource +} + +// FqdnListLocalRulestackClientListByLocalRulestacksResponse contains the response from method FqdnListLocalRulestackClient.NewListByLocalRulestacksPager. +type FqdnListLocalRulestackClientListByLocalRulestacksResponse struct { + FqdnListLocalRulestackResourceListResult +} + +// GlobalRulestackClientCommitResponse contains the response from method GlobalRulestackClient.BeginCommit. +type GlobalRulestackClientCommitResponse struct { + // placeholder for future response values +} + +// GlobalRulestackClientCreateOrUpdateResponse contains the response from method GlobalRulestackClient.BeginCreateOrUpdate. +type GlobalRulestackClientCreateOrUpdateResponse struct { + GlobalRulestackResource +} + +// GlobalRulestackClientDeleteResponse contains the response from method GlobalRulestackClient.BeginDelete. +type GlobalRulestackClientDeleteResponse struct { + // placeholder for future response values +} + +// GlobalRulestackClientGetChangeLogResponse contains the response from method GlobalRulestackClient.GetChangeLog. +type GlobalRulestackClientGetChangeLogResponse struct { + Changelog +} + +// GlobalRulestackClientGetResponse contains the response from method GlobalRulestackClient.Get. +type GlobalRulestackClientGetResponse struct { + GlobalRulestackResource +} + +// GlobalRulestackClientListAdvancedSecurityObjectsResponse contains the response from method GlobalRulestackClient.ListAdvancedSecurityObjects. +type GlobalRulestackClientListAdvancedSecurityObjectsResponse struct { + AdvSecurityObjectListResponse +} + +// GlobalRulestackClientListAppIDsResponse contains the response from method GlobalRulestackClient.ListAppIDs. +type GlobalRulestackClientListAppIDsResponse struct { + ListAppIDResponse +} + +// GlobalRulestackClientListCountriesResponse contains the response from method GlobalRulestackClient.ListCountries. +type GlobalRulestackClientListCountriesResponse struct { + CountriesResponse +} + +// GlobalRulestackClientListFirewallsResponse contains the response from method GlobalRulestackClient.ListFirewalls. +type GlobalRulestackClientListFirewallsResponse struct { + ListFirewallsResponse +} + +// GlobalRulestackClientListPredefinedURLCategoriesResponse contains the response from method GlobalRulestackClient.ListPredefinedURLCategories. +type GlobalRulestackClientListPredefinedURLCategoriesResponse struct { + PredefinedURLCategoriesResponse +} + +// GlobalRulestackClientListResponse contains the response from method GlobalRulestackClient.NewListPager. +type GlobalRulestackClientListResponse struct { + GlobalRulestackResourceListResult +} + +// GlobalRulestackClientListSecurityServicesResponse contains the response from method GlobalRulestackClient.ListSecurityServices. +type GlobalRulestackClientListSecurityServicesResponse struct { + SecurityServicesResponse +} + +// GlobalRulestackClientRevertResponse contains the response from method GlobalRulestackClient.Revert. +type GlobalRulestackClientRevertResponse struct { + // placeholder for future response values +} + +// GlobalRulestackClientUpdateResponse contains the response from method GlobalRulestackClient.Update. +type GlobalRulestackClientUpdateResponse struct { + GlobalRulestackResource +} + +// LocalRulesClientCreateOrUpdateResponse contains the response from method LocalRulesClient.BeginCreateOrUpdate. +type LocalRulesClientCreateOrUpdateResponse struct { + LocalRulesResource +} + +// LocalRulesClientDeleteResponse contains the response from method LocalRulesClient.BeginDelete. +type LocalRulesClientDeleteResponse struct { + // placeholder for future response values +} + +// LocalRulesClientGetCountersResponse contains the response from method LocalRulesClient.GetCounters. +type LocalRulesClientGetCountersResponse struct { + RuleCounter +} + +// LocalRulesClientGetResponse contains the response from method LocalRulesClient.Get. +type LocalRulesClientGetResponse struct { + LocalRulesResource +} + +// LocalRulesClientListByLocalRulestacksResponse contains the response from method LocalRulesClient.NewListByLocalRulestacksPager. +type LocalRulesClientListByLocalRulestacksResponse struct { + LocalRulesResourceListResult +} + +// LocalRulesClientRefreshCountersResponse contains the response from method LocalRulesClient.RefreshCounters. +type LocalRulesClientRefreshCountersResponse struct { + // placeholder for future response values +} + +// LocalRulesClientResetCountersResponse contains the response from method LocalRulesClient.ResetCounters. +type LocalRulesClientResetCountersResponse struct { + RuleCounterReset +} + +// LocalRulestacksClientCommitResponse contains the response from method LocalRulestacksClient.BeginCommit. +type LocalRulestacksClientCommitResponse struct { + // placeholder for future response values +} + +// LocalRulestacksClientCreateOrUpdateResponse contains the response from method LocalRulestacksClient.BeginCreateOrUpdate. +type LocalRulestacksClientCreateOrUpdateResponse struct { + LocalRulestackResource +} + +// LocalRulestacksClientDeleteResponse contains the response from method LocalRulestacksClient.BeginDelete. +type LocalRulestacksClientDeleteResponse struct { + // placeholder for future response values +} + +// LocalRulestacksClientGetChangeLogResponse contains the response from method LocalRulestacksClient.GetChangeLog. +type LocalRulestacksClientGetChangeLogResponse struct { + Changelog +} + +// LocalRulestacksClientGetResponse contains the response from method LocalRulestacksClient.Get. +type LocalRulestacksClientGetResponse struct { + LocalRulestackResource +} + +// LocalRulestacksClientGetSupportInfoResponse contains the response from method LocalRulestacksClient.GetSupportInfo. +type LocalRulestacksClientGetSupportInfoResponse struct { + SupportInfo +} + +// LocalRulestacksClientListAdvancedSecurityObjectsResponse contains the response from method LocalRulestacksClient.ListAdvancedSecurityObjects. +type LocalRulestacksClientListAdvancedSecurityObjectsResponse struct { + AdvSecurityObjectListResponse +} + +// LocalRulestacksClientListAppIDsResponse contains the response from method LocalRulestacksClient.ListAppIDs. +type LocalRulestacksClientListAppIDsResponse struct { + ListAppIDResponse +} + +// LocalRulestacksClientListByResourceGroupResponse contains the response from method LocalRulestacksClient.NewListByResourceGroupPager. +type LocalRulestacksClientListByResourceGroupResponse struct { + LocalRulestackResourceListResult +} + +// LocalRulestacksClientListBySubscriptionResponse contains the response from method LocalRulestacksClient.NewListBySubscriptionPager. +type LocalRulestacksClientListBySubscriptionResponse struct { + LocalRulestackResourceListResult +} + +// LocalRulestacksClientListCountriesResponse contains the response from method LocalRulestacksClient.ListCountries. +type LocalRulestacksClientListCountriesResponse struct { + CountriesResponse +} + +// LocalRulestacksClientListFirewallsResponse contains the response from method LocalRulestacksClient.ListFirewalls. +type LocalRulestacksClientListFirewallsResponse struct { + ListFirewallsResponse +} + +// LocalRulestacksClientListPredefinedURLCategoriesResponse contains the response from method LocalRulestacksClient.ListPredefinedURLCategories. +type LocalRulestacksClientListPredefinedURLCategoriesResponse struct { + PredefinedURLCategoriesResponse +} + +// LocalRulestacksClientListSecurityServicesResponse contains the response from method LocalRulestacksClient.ListSecurityServices. +type LocalRulestacksClientListSecurityServicesResponse struct { + SecurityServicesResponse +} + +// LocalRulestacksClientRevertResponse contains the response from method LocalRulestacksClient.Revert. +type LocalRulestacksClientRevertResponse struct { + // placeholder for future response values +} + +// LocalRulestacksClientUpdateResponse contains the response from method LocalRulestacksClient.Update. +type LocalRulestacksClientUpdateResponse struct { + LocalRulestackResource +} + +// OperationsClientListResponse contains the response from method OperationsClient.NewListPager. +type OperationsClientListResponse struct { + OperationListResult +} + +// PostRulesClientCreateOrUpdateResponse contains the response from method PostRulesClient.BeginCreateOrUpdate. +type PostRulesClientCreateOrUpdateResponse struct { + PostRulesResource +} + +// PostRulesClientDeleteResponse contains the response from method PostRulesClient.BeginDelete. +type PostRulesClientDeleteResponse struct { + // placeholder for future response values +} + +// PostRulesClientGetCountersResponse contains the response from method PostRulesClient.GetCounters. +type PostRulesClientGetCountersResponse struct { + RuleCounter +} + +// PostRulesClientGetResponse contains the response from method PostRulesClient.Get. +type PostRulesClientGetResponse struct { + PostRulesResource +} + +// PostRulesClientListResponse contains the response from method PostRulesClient.NewListPager. +type PostRulesClientListResponse struct { + PostRulesResourceListResult +} + +// PostRulesClientRefreshCountersResponse contains the response from method PostRulesClient.RefreshCounters. +type PostRulesClientRefreshCountersResponse struct { + // placeholder for future response values +} + +// PostRulesClientResetCountersResponse contains the response from method PostRulesClient.ResetCounters. +type PostRulesClientResetCountersResponse struct { + RuleCounterReset +} + +// PreRulesClientCreateOrUpdateResponse contains the response from method PreRulesClient.BeginCreateOrUpdate. +type PreRulesClientCreateOrUpdateResponse struct { + PreRulesResource +} + +// PreRulesClientDeleteResponse contains the response from method PreRulesClient.BeginDelete. +type PreRulesClientDeleteResponse struct { + // placeholder for future response values +} + +// PreRulesClientGetCountersResponse contains the response from method PreRulesClient.GetCounters. +type PreRulesClientGetCountersResponse struct { + RuleCounter +} + +// PreRulesClientGetResponse contains the response from method PreRulesClient.Get. +type PreRulesClientGetResponse struct { + PreRulesResource +} + +// PreRulesClientListResponse contains the response from method PreRulesClient.NewListPager. +type PreRulesClientListResponse struct { + PreRulesResourceListResult +} + +// PreRulesClientRefreshCountersResponse contains the response from method PreRulesClient.RefreshCounters. +type PreRulesClientRefreshCountersResponse struct { + // placeholder for future response values +} + +// PreRulesClientResetCountersResponse contains the response from method PreRulesClient.ResetCounters. +type PreRulesClientResetCountersResponse struct { + RuleCounterReset +} + +// PrefixListGlobalRulestackClientCreateOrUpdateResponse contains the response from method PrefixListGlobalRulestackClient.BeginCreateOrUpdate. +type PrefixListGlobalRulestackClientCreateOrUpdateResponse struct { + PrefixListGlobalRulestackResource +} + +// PrefixListGlobalRulestackClientDeleteResponse contains the response from method PrefixListGlobalRulestackClient.BeginDelete. +type PrefixListGlobalRulestackClientDeleteResponse struct { + // placeholder for future response values +} + +// PrefixListGlobalRulestackClientGetResponse contains the response from method PrefixListGlobalRulestackClient.Get. +type PrefixListGlobalRulestackClientGetResponse struct { + PrefixListGlobalRulestackResource +} + +// PrefixListGlobalRulestackClientListResponse contains the response from method PrefixListGlobalRulestackClient.NewListPager. +type PrefixListGlobalRulestackClientListResponse struct { + PrefixListGlobalRulestackResourceListResult +} + +// PrefixListLocalRulestackClientCreateOrUpdateResponse contains the response from method PrefixListLocalRulestackClient.BeginCreateOrUpdate. +type PrefixListLocalRulestackClientCreateOrUpdateResponse struct { + PrefixListResource +} + +// PrefixListLocalRulestackClientDeleteResponse contains the response from method PrefixListLocalRulestackClient.BeginDelete. +type PrefixListLocalRulestackClientDeleteResponse struct { + // placeholder for future response values +} + +// PrefixListLocalRulestackClientGetResponse contains the response from method PrefixListLocalRulestackClient.Get. +type PrefixListLocalRulestackClientGetResponse struct { + PrefixListResource +} + +// PrefixListLocalRulestackClientListByLocalRulestacksResponse contains the response from method PrefixListLocalRulestackClient.NewListByLocalRulestacksPager. +type PrefixListLocalRulestackClientListByLocalRulestacksResponse struct { + PrefixListResourceListResult +} diff --git a/sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/time_rfc3339.go b/sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/time_rfc3339.go new file mode 100644 index 000000000000..b37eb2234926 --- /dev/null +++ b/sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/time_rfc3339.go @@ -0,0 +1,87 @@ +//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. +// Code generated by Microsoft (R) AutoRest Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. +// DO NOT EDIT. + +package armpanngfw + +import ( + "encoding/json" + "fmt" + "github.com/Azure/azure-sdk-for-go/sdk/azcore" + "reflect" + "regexp" + "strings" + "time" +) + +const ( + utcLayoutJSON = `"2006-01-02T15:04:05.999999999"` + utcLayout = "2006-01-02T15:04:05.999999999" + rfc3339JSON = `"` + time.RFC3339Nano + `"` +) + +// Azure reports time in UTC but it doesn't include the 'Z' time zone suffix in some cases. +var tzOffsetRegex = regexp.MustCompile(`(Z|z|\+|-)(\d+:\d+)*"*$`) + +type timeRFC3339 time.Time + +func (t timeRFC3339) MarshalJSON() (json []byte, err error) { + tt := time.Time(t) + return tt.MarshalJSON() +} + +func (t timeRFC3339) MarshalText() (text []byte, err error) { + tt := time.Time(t) + return tt.MarshalText() +} + +func (t *timeRFC3339) UnmarshalJSON(data []byte) error { + layout := utcLayoutJSON + if tzOffsetRegex.Match(data) { + layout = rfc3339JSON + } + return t.Parse(layout, string(data)) +} + +func (t *timeRFC3339) UnmarshalText(data []byte) (err error) { + layout := utcLayout + if tzOffsetRegex.Match(data) { + layout = time.RFC3339Nano + } + return t.Parse(layout, string(data)) +} + +func (t *timeRFC3339) Parse(layout, value string) error { + p, err := time.Parse(layout, strings.ToUpper(value)) + *t = timeRFC3339(p) + return err +} + +func populateTimeRFC3339(m map[string]any, k string, t *time.Time) { + if t == nil { + return + } else if azcore.IsNullValue(t) { + m[k] = nil + return + } else if reflect.ValueOf(t).IsNil() { + return + } + m[k] = (*timeRFC3339)(t) +} + +func unpopulateTimeRFC3339(data json.RawMessage, fn string, t **time.Time) error { + if data == nil || strings.EqualFold(string(data), "null") { + return nil + } + var aux timeRFC3339 + if err := json.Unmarshal(data, &aux); err != nil { + return fmt.Errorf("struct field %s: %v", fn, err) + } + *t = (*time.Time)(&aux) + return nil +} diff --git a/sdk/resourcemanager/postgresql/armpostgresql/assets.json b/sdk/resourcemanager/postgresql/armpostgresql/assets.json index 0a673e5602dd..c7e1e87d6349 100644 --- a/sdk/resourcemanager/postgresql/armpostgresql/assets.json +++ b/sdk/resourcemanager/postgresql/armpostgresql/assets.json @@ -2,5 +2,5 @@ "AssetsRepo": "Azure/azure-sdk-assets", "AssetsRepoPrefixPath": "go", "TagPrefix": "go/resourcemanager/postgresql/armpostgresql", - "Tag": "go/resourcemanager/postgresql/armpostgresql_d9bc2d0da1" + "Tag": "go/resourcemanager/postgresql/armpostgresql_2a306718c0" } diff --git a/sdk/resourcemanager/postgresql/armpostgresql/postgresql_live_test.go b/sdk/resourcemanager/postgresql/armpostgresql/postgresql_live_test.go index 7bf657fd16b5..64c3c42c4a63 100644 --- a/sdk/resourcemanager/postgresql/armpostgresql/postgresql_live_test.go +++ b/sdk/resourcemanager/postgresql/armpostgresql/postgresql_live_test.go @@ -14,6 +14,7 @@ import ( "github.com/Azure/azure-sdk-for-go/sdk/azcore" "github.com/Azure/azure-sdk-for-go/sdk/azcore/arm" "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/resourcemanager/internal/testutil" "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/postgresql/armpostgresql" "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armresources" @@ -35,14 +36,14 @@ type PostgresqlTestSuite struct { func (testsuite *PostgresqlTestSuite) SetupSuite() { testutil.StartRecording(testsuite.T(), "sdk/resourcemanager/postgresql/armpostgresql/testdata") + testsuite.ctx = context.Background() testsuite.cred, testsuite.options = testutil.GetCredAndClientOptions(testsuite.T()) - testsuite.serverName = testutil.GenerateAlphaNumericID(testsuite.T(), "pgservers", 6) - testsuite.adminPassword = testutil.GetEnv("ADMIN_PASSWORD", "000000000000") - testsuite.location = testutil.GetEnv("LOCATION", "eastus") + testsuite.serverName, _ = recording.GenerateAlphaNumericID(testsuite.T(), "serverna", 14, true) + testsuite.adminPassword = testutil.GetEnv("ADMIN_PASSWORD", "") + testsuite.location = testutil.GetEnv("LOCATION", "westus") testsuite.resourceGroupName = testutil.GetEnv("RESOURCE_GROUP_NAME", "scenarioTestTempGroup") testsuite.subscriptionId = testutil.GetEnv("AZURE_SUBSCRIPTION_ID", "00000000-0000-0000-0000-000000000000") - resourceGroup, _, err := testutil.CreateResourceGroup(testsuite.ctx, testsuite.subscriptionId, testsuite.cred, testsuite.options, testsuite.location) testsuite.Require().NoError(err) testsuite.resourceGroupName = *resourceGroup.Name @@ -81,8 +82,8 @@ func (testsuite *PostgresqlTestSuite) Prepare() { AdministratorLoginPassword: to.Ptr(testsuite.adminPassword), }, SKU: &armpostgresql.SKU{ - Family: to.Ptr("Gen5"), Name: to.Ptr("GP_Gen5_8"), + Family: to.Ptr("Gen5"), Tier: to.Ptr(armpostgresql.SKUTierGeneralPurpose), }, Tags: map[string]*string{ @@ -94,7 +95,7 @@ func (testsuite *PostgresqlTestSuite) Prepare() { testsuite.Require().NoError(err) } -// Microsoft.DBforPostgreSQL/servers +// Microsoft.DBforPostgreSQL/servers/{serverName} func (testsuite *PostgresqlTestSuite) TestServers() { var err error // From step Servers_List @@ -143,23 +144,8 @@ func (testsuite *PostgresqlTestSuite) TestServers() { testsuite.Require().NoError(err) } -// Microsoft.DBforPostgreSQL/servers/replicas -func (testsuite *PostgresqlTestSuite) TestReplicas() { - var err error - // From step Replicas_ListByServer - fmt.Println("Call operation: Replicas_ListByServer") - replicasClient, err := armpostgresql.NewReplicasClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) - testsuite.Require().NoError(err) - replicasClientNewListByServerPager := replicasClient.NewListByServerPager(testsuite.resourceGroupName, testsuite.serverName, nil) - for replicasClientNewListByServerPager.More() { - _, err := replicasClientNewListByServerPager.NextPage(testsuite.ctx) - testsuite.Require().NoError(err) - break - } -} - -// Microsoft.DBforPostgreSQL/servers/firewallRules -func (testsuite *PostgresqlTestSuite) TestFirewallrules() { +// Microsoft.DBforPostgreSQL/servers/{serverName}/firewallRules/{firewallRuleName} +func (testsuite *PostgresqlTestSuite) TestFirewallRules() { var err error // From step FirewallRules_CreateOrUpdate fmt.Println("Call operation: FirewallRules_CreateOrUpdate") @@ -197,67 +183,63 @@ func (testsuite *PostgresqlTestSuite) TestFirewallrules() { testsuite.Require().NoError(err) } -// Microsoft.DBforPostgreSQL/servers/virtualNetworkRules -func (testsuite *PostgresqlTestSuite) TestVirtualnetworkrules() { +// Microsoft.DBforPostgreSQL/servers/{serverName}/virtualNetworkRules/{virtualNetworkRuleName} +func (testsuite *PostgresqlTestSuite) TestVirtualNetworkRules() { var subnetId string var err error // From step VirtualNetwork_Create - template := map[string]interface{}{ + template := map[string]any{ "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", "contentVersion": "1.0.0.0", - "outputs": map[string]interface{}{ - "subnetId": map[string]interface{}{ + "outputs": map[string]any{ + "subnetId": map[string]any{ "type": "string", "value": "[resourceId('Microsoft.Network/virtualNetworks/subnets', parameters('virtualNetworksName'), parameters('subnetName'))]", }, }, - "parameters": map[string]interface{}{ - "location": map[string]interface{}{ + "parameters": map[string]any{ + "location": map[string]any{ "type": "string", - "defaultValue": "$(location)", + "defaultValue": testsuite.location, }, - "subnetName": map[string]interface{}{ + "subnetName": map[string]any{ "type": "string", "defaultValue": "pgsubnet", }, - "virtualNetworksName": map[string]interface{}{ + "virtualNetworksName": map[string]any{ "type": "string", "defaultValue": "pgvnet", }, }, - "resources": []interface{}{ - map[string]interface{}{ + "resources": []any{ + map[string]any{ "name": "[parameters('virtualNetworksName')]", "type": "Microsoft.Network/virtualNetworks", "apiVersion": "2021-05-01", "location": "[parameters('location')]", - "properties": map[string]interface{}{ - "addressSpace": map[string]interface{}{ - "addressPrefixes": []interface{}{ + "properties": map[string]any{ + "addressSpace": map[string]any{ + "addressPrefixes": []any{ "10.0.0.0/16", }, }, - "subnets": []interface{}{ - map[string]interface{}{ + "subnets": []any{ + map[string]any{ "name": "[parameters('subnetName')]", - "properties": map[string]interface{}{ + "properties": map[string]any{ "addressPrefix": "10.0.0.0/24", }, }, }, }, - "tags": map[string]interface{}{}, + "tags": map[string]any{}, }, }, } - params := map[string]interface{}{ - "location": map[string]interface{}{"value": testsuite.location}, - } deployment := armresources.Deployment{ Properties: &armresources.DeploymentProperties{ - Template: template, - Parameters: params, - Mode: to.Ptr(armresources.DeploymentModeIncremental), + Template: template, + Mode: to.Ptr(armresources.DeploymentModeIncremental), }, } deploymentExtend, err := testutil.CreateDeployment(testsuite.ctx, testsuite.subscriptionId, testsuite.cred, testsuite.options, testsuite.resourceGroupName, "VirtualNetwork_Create", &deployment) @@ -300,7 +282,7 @@ func (testsuite *PostgresqlTestSuite) TestVirtualnetworkrules() { testsuite.Require().NoError(err) } -// Microsoft.DBforPostgreSQL/servers/databases +// Microsoft.DBforPostgreSQL/servers/{serverName}/databases/{databaseName} func (testsuite *PostgresqlTestSuite) TestDatabases() { var err error // From step Databases_CreateOrUpdate @@ -339,7 +321,7 @@ func (testsuite *PostgresqlTestSuite) TestDatabases() { testsuite.Require().NoError(err) } -// Microsoft.DBforPostgreSQL/servers/configurations +// Microsoft.DBforPostgreSQL/servers/{serverName}/configurations/{configurationName} func (testsuite *PostgresqlTestSuite) TestConfigurations() { var err error // From step Configurations_CreateOrUpdate @@ -371,8 +353,64 @@ func (testsuite *PostgresqlTestSuite) TestConfigurations() { testsuite.Require().NoError(err) } +// Microsoft.DBforPostgreSQL/servers/{serverName}/administrators/activeDirectory +func (testsuite *PostgresqlTestSuite) TestServerAdministrators() { + var err error + // From step ServerAdministrators_CreateOrUpdate + fmt.Println("Call operation: ServerAdministrators_CreateOrUpdate") + serverAdministratorsClient, err := armpostgresql.NewServerAdministratorsClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + serverAdministratorsClientCreateOrUpdateResponsePoller, err := serverAdministratorsClient.BeginCreateOrUpdate(testsuite.ctx, testsuite.resourceGroupName, testsuite.serverName, armpostgresql.ServerAdministratorResource{ + Properties: &armpostgresql.ServerAdministratorProperties{ + AdministratorType: to.Ptr("ActiveDirectory"), + Login: to.Ptr("bob@contoso.com"), + Sid: to.Ptr("c6b82b90-a647-49cb-8a62-0d2d3cb7ac7c"), + TenantID: to.Ptr("c6b82b90-a647-49cb-8a62-0d2d3cb7ac7c"), + }, + }, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, serverAdministratorsClientCreateOrUpdateResponsePoller) + testsuite.Require().NoError(err) + + // From step ServerAdministrators_List + fmt.Println("Call operation: ServerAdministrators_List") + serverAdministratorsClientNewListPager := serverAdministratorsClient.NewListPager(testsuite.resourceGroupName, testsuite.serverName, nil) + for serverAdministratorsClientNewListPager.More() { + _, err := serverAdministratorsClientNewListPager.NextPage(testsuite.ctx) + testsuite.Require().NoError(err) + break + } + + // From step ServerAdministrators_Get + fmt.Println("Call operation: ServerAdministrators_Get") + _, err = serverAdministratorsClient.Get(testsuite.ctx, testsuite.resourceGroupName, testsuite.serverName, nil) + testsuite.Require().NoError(err) + + // From step ServerAdministrators_Delete + fmt.Println("Call operation: ServerAdministrators_Delete") + serverAdministratorsClientDeleteResponsePoller, err := serverAdministratorsClient.BeginDelete(testsuite.ctx, testsuite.resourceGroupName, testsuite.serverName, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, serverAdministratorsClientDeleteResponsePoller) + testsuite.Require().NoError(err) +} + +// Microsoft.DBforPostgreSQL/servers/replicas +func (testsuite *PostgresqlTestSuite) TestReplicas() { + var err error + // From step Replicas_ListByServer + fmt.Println("Call operation: Replicas_ListByServer") + replicasClient, err := armpostgresql.NewReplicasClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + replicasClientNewListByServerPager := replicasClient.NewListByServerPager(testsuite.resourceGroupName, testsuite.serverName, nil) + for replicasClientNewListByServerPager.More() { + _, err := replicasClientNewListByServerPager.NextPage(testsuite.ctx) + testsuite.Require().NoError(err) + break + } +} + // Microsoft.DBforPostgreSQL/servers/updateConfigurations -func (testsuite *PostgresqlTestSuite) TestServerparameters() { +func (testsuite *PostgresqlTestSuite) TestServerParameters() { var err error // From step ServerParameters_ListUpdateConfigurations fmt.Println("Call operation: ServerParameters_ListUpdateConfigurations") @@ -399,7 +437,7 @@ func (testsuite *PostgresqlTestSuite) TestServerparameters() { } // Microsoft.DBforPostgreSQL/servers/logFiles -func (testsuite *PostgresqlTestSuite) TestLogfiles() { +func (testsuite *PostgresqlTestSuite) TestLogFiles() { var err error // From step LogFiles_ListByServer fmt.Println("Call operation: LogFiles_ListByServer") @@ -413,49 +451,8 @@ func (testsuite *PostgresqlTestSuite) TestLogfiles() { } } -// Microsoft.DBforPostgreSQL/servers/administrators/activeDirectory -func (testsuite *PostgresqlTestSuite) TestServeradministrators() { - var err error - // From step ServerAdministrators_CreateOrUpdate - fmt.Println("Call operation: ServerAdministrators_CreateOrUpdate") - serverAdministratorsClient, err := armpostgresql.NewServerAdministratorsClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) - testsuite.Require().NoError(err) - serverAdministratorsClientCreateOrUpdateResponsePoller, err := serverAdministratorsClient.BeginCreateOrUpdate(testsuite.ctx, testsuite.resourceGroupName, testsuite.serverName, armpostgresql.ServerAdministratorResource{ - Properties: &armpostgresql.ServerAdministratorProperties{ - AdministratorType: to.Ptr("ActiveDirectory"), - Login: to.Ptr("bob@contoso.com"), - Sid: to.Ptr("c6b82b90-a647-49cb-8a62-0d2d3cb7ac7c"), - TenantID: to.Ptr("c6b82b90-a647-49cb-8a62-0d2d3cb7ac7c"), - }, - }, nil) - testsuite.Require().NoError(err) - _, err = testutil.PollForTest(testsuite.ctx, serverAdministratorsClientCreateOrUpdateResponsePoller) - testsuite.Require().NoError(err) - - // From step ServerAdministrators_List - fmt.Println("Call operation: ServerAdministrators_List") - serverAdministratorsClientNewListPager := serverAdministratorsClient.NewListPager(testsuite.resourceGroupName, testsuite.serverName, nil) - for serverAdministratorsClientNewListPager.More() { - _, err := serverAdministratorsClientNewListPager.NextPage(testsuite.ctx) - testsuite.Require().NoError(err) - break - } - - // From step ServerAdministrators_Get - fmt.Println("Call operation: ServerAdministrators_Get") - _, err = serverAdministratorsClient.Get(testsuite.ctx, testsuite.resourceGroupName, testsuite.serverName, nil) - testsuite.Require().NoError(err) - - // From step ServerAdministrators_Delete - fmt.Println("Call operation: ServerAdministrators_Delete") - serverAdministratorsClientDeleteResponsePoller, err := serverAdministratorsClient.BeginDelete(testsuite.ctx, testsuite.resourceGroupName, testsuite.serverName, nil) - testsuite.Require().NoError(err) - _, err = testutil.PollForTest(testsuite.ctx, serverAdministratorsClientDeleteResponsePoller) - testsuite.Require().NoError(err) -} - // Microsoft.DBforPostgreSQL/servers/recoverableServers -func (testsuite *PostgresqlTestSuite) TestRecoverableservers() { +func (testsuite *PostgresqlTestSuite) TestRecoverableServers() { var err error // From step RecoverableServers_Get fmt.Println("Call operation: RecoverableServers_Get") @@ -466,7 +463,7 @@ func (testsuite *PostgresqlTestSuite) TestRecoverableservers() { } // Microsoft.DBforPostgreSQL/servers/performanceTiers -func (testsuite *PostgresqlTestSuite) TestServerbasedperformancetier() { +func (testsuite *PostgresqlTestSuite) TestServerBasedPerformanceTier() { var err error // From step ServerBasedPerformanceTier_List fmt.Println("Call operation: ServerBasedPerformanceTier_List") @@ -481,7 +478,7 @@ func (testsuite *PostgresqlTestSuite) TestServerbasedperformancetier() { } // Microsoft.DBforPostgreSQL/locations/performanceTiers -func (testsuite *PostgresqlTestSuite) TestLocationbasedperformancetier() { +func (testsuite *PostgresqlTestSuite) TestLocationBasedPerformanceTier() { var err error // From step LocationBasedPerformanceTier_List fmt.Println("Call operation: LocationBasedPerformanceTier_List") @@ -496,7 +493,7 @@ func (testsuite *PostgresqlTestSuite) TestLocationbasedperformancetier() { } // Microsoft.DBforPostgreSQL/checkNameAvailability -func (testsuite *PostgresqlTestSuite) TestChecknameavailability() { +func (testsuite *PostgresqlTestSuite) TestCheckNameAvailability() { var err error // From step CheckNameAvailability_Execute fmt.Println("Call operation: CheckNameAvailability_Execute") diff --git a/sdk/resourcemanager/postgresql/armpostgresql/privateendpointconnections_live_test.go b/sdk/resourcemanager/postgresql/armpostgresql/privateendpointconnections_live_test.go new file mode 100644 index 000000000000..ba1c718d40df --- /dev/null +++ b/sdk/resourcemanager/postgresql/armpostgresql/privateendpointconnections_live_test.go @@ -0,0 +1,271 @@ +//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 armpostgresql_test + +import ( + "context" + "fmt" + "testing" + + "github.com/Azure/azure-sdk-for-go/sdk/azcore" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/arm" + "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/resourcemanager/internal/testutil" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/postgresql/armpostgresql" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armresources" + "github.com/stretchr/testify/suite" +) + +type PrivateEndpointConnectionsTestSuite struct { + suite.Suite + + ctx context.Context + cred azcore.TokenCredential + options *arm.ClientOptions + postgresqlserverId string + serverName string + adminPassword string + location string + resourceGroupName string + subscriptionId string +} + +func (testsuite *PrivateEndpointConnectionsTestSuite) SetupSuite() { + testutil.StartRecording(testsuite.T(), "sdk/resourcemanager/postgresql/armpostgresql/testdata") + + testsuite.ctx = context.Background() + testsuite.cred, testsuite.options = testutil.GetCredAndClientOptions(testsuite.T()) + testsuite.serverName, _ = recording.GenerateAlphaNumericID(testsuite.T(), "serverna", 14, true) + testsuite.adminPassword = testutil.GetEnv("ADMIN_PASSWORD", "") + testsuite.location = testutil.GetEnv("LOCATION", "westus") + testsuite.resourceGroupName = testutil.GetEnv("RESOURCE_GROUP_NAME", "scenarioTestTempGroup") + testsuite.subscriptionId = testutil.GetEnv("AZURE_SUBSCRIPTION_ID", "00000000-0000-0000-0000-000000000000") + resourceGroup, _, err := testutil.CreateResourceGroup(testsuite.ctx, testsuite.subscriptionId, testsuite.cred, testsuite.options, testsuite.location) + testsuite.Require().NoError(err) + testsuite.resourceGroupName = *resourceGroup.Name + testsuite.Prepare() +} + +func (testsuite *PrivateEndpointConnectionsTestSuite) TearDownSuite() { + _, err := testutil.DeleteResourceGroup(testsuite.ctx, testsuite.subscriptionId, testsuite.cred, testsuite.options, testsuite.resourceGroupName) + testsuite.Require().NoError(err) + testutil.StopRecording(testsuite.T()) +} + +func TestPrivateEndpointConnectionsTestSuite(t *testing.T) { + suite.Run(t, new(PrivateEndpointConnectionsTestSuite)) +} + +func (testsuite *PrivateEndpointConnectionsTestSuite) Prepare() { + var err error + // From step Servers_Create + fmt.Println("Call operation: Servers_Create") + serversClient, err := armpostgresql.NewServersClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + serversClientCreateResponsePoller, err := serversClient.BeginCreate(testsuite.ctx, testsuite.resourceGroupName, testsuite.serverName, armpostgresql.ServerForCreate{ + Location: to.Ptr(testsuite.location), + Properties: &armpostgresql.ServerPropertiesForDefaultCreate{ + CreateMode: to.Ptr(armpostgresql.CreateModeDefault), + MinimalTLSVersion: to.Ptr(armpostgresql.MinimalTLSVersionEnumTLS12), + SSLEnforcement: to.Ptr(armpostgresql.SSLEnforcementEnumEnabled), + StorageProfile: &armpostgresql.StorageProfile{ + BackupRetentionDays: to.Ptr[int32](7), + GeoRedundantBackup: to.Ptr(armpostgresql.GeoRedundantBackupDisabled), + StorageMB: to.Ptr[int32](128000), + }, + AdministratorLogin: to.Ptr("cloudsa"), + AdministratorLoginPassword: to.Ptr(testsuite.adminPassword), + }, + SKU: &armpostgresql.SKU{ + Name: to.Ptr("GP_Gen5_8"), + Family: to.Ptr("Gen5"), + Tier: to.Ptr(armpostgresql.SKUTierGeneralPurpose), + }, + Tags: map[string]*string{ + "ElasticServer": to.Ptr("1"), + }, + }, nil) + testsuite.Require().NoError(err) + var serversClientCreateResponse *armpostgresql.ServersClientCreateResponse + serversClientCreateResponse, err = testutil.PollForTest(testsuite.ctx, serversClientCreateResponsePoller) + testsuite.Require().NoError(err) + testsuite.postgresqlserverId = *serversClientCreateResponse.ID +} + +// Microsoft.DBforPostgreSQL/servers/{serverName}/privateEndpointConnections/{privateEndpointConnectionName} +func (testsuite *PrivateEndpointConnectionsTestSuite) TestPrivateEndpointConnections() { + var err error + // From step Create_PrivateEndpoint + template := map[string]any{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "parameters": map[string]any{ + "location": map[string]any{ + "type": "string", + "defaultValue": testsuite.location, + }, + "networkInterfaceName": map[string]any{ + "type": "string", + "defaultValue": "pepostgresql-nic", + }, + "postgresqlserverId": map[string]any{ + "type": "string", + "defaultValue": testsuite.postgresqlserverId, + }, + "privateEndpointName": map[string]any{ + "type": "string", + "defaultValue": "pepostgresql", + }, + "virtualNetworksName": map[string]any{ + "type": "string", + "defaultValue": "pepostgresqlvnet", + }, + }, + "resources": []any{ + map[string]any{ + "name": "[parameters('virtualNetworksName')]", + "type": "Microsoft.Network/virtualNetworks", + "apiVersion": "2020-11-01", + "location": "[parameters('location')]", + "properties": map[string]any{ + "addressSpace": map[string]any{ + "addressPrefixes": []any{ + "10.0.0.0/16", + }, + }, + "enableDdosProtection": false, + "subnets": []any{ + map[string]any{ + "name": "default", + "properties": map[string]any{ + "addressPrefix": "10.0.0.0/24", + "delegations": []any{}, + "privateEndpointNetworkPolicies": "Disabled", + "privateLinkServiceNetworkPolicies": "Enabled", + }, + }, + }, + "virtualNetworkPeerings": []any{}, + }, + }, + map[string]any{ + "name": "[parameters('networkInterfaceName')]", + "type": "Microsoft.Network/networkInterfaces", + "apiVersion": "2020-11-01", + "dependsOn": []any{ + "[resourceId('Microsoft.Network/virtualNetworks', parameters('virtualNetworksName'))]", + }, + "location": "[parameters('location')]", + "properties": map[string]any{ + "dnsSettings": map[string]any{ + "dnsServers": []any{}, + }, + "enableIPForwarding": false, + "ipConfigurations": []any{ + map[string]any{ + "name": "privateEndpointIpConfig", + "properties": map[string]any{ + "primary": true, + "privateIPAddress": "10.0.0.4", + "privateIPAddressVersion": "IPv4", + "privateIPAllocationMethod": "Dynamic", + "subnet": map[string]any{ + "id": "[resourceId('Microsoft.Network/virtualNetworks/subnets', parameters('virtualNetworksName'), 'default')]", + }, + }, + }, + }, + }, + }, + map[string]any{ + "name": "[parameters('privateEndpointName')]", + "type": "Microsoft.Network/privateEndpoints", + "apiVersion": "2020-11-01", + "dependsOn": []any{ + "[resourceId('Microsoft.Network/virtualNetworks', parameters('virtualNetworksName'))]", + }, + "location": "[parameters('location')]", + "properties": map[string]any{ + "customDnsConfigs": []any{}, + "manualPrivateLinkServiceConnections": []any{}, + "privateLinkServiceConnections": []any{ + map[string]any{ + "name": "[parameters('privateEndpointName')]", + "properties": map[string]any{ + "groupIds": []any{ + "postgresqlServer", + }, + "privateLinkServiceConnectionState": map[string]any{ + "description": "Auto-Approved", + "actionsRequired": "None", + "status": "Approved", + }, + "privateLinkServiceId": "[parameters('postgresqlserverId')]", + }, + }, + }, + "subnet": map[string]any{ + "id": "[resourceId('Microsoft.Network/virtualNetworks/subnets', parameters('virtualNetworksName'), 'default')]", + }, + }, + }, + }, + "variables": map[string]any{}, + } + deployment := armresources.Deployment{ + Properties: &armresources.DeploymentProperties{ + Template: template, + Mode: to.Ptr(armresources.DeploymentModeIncremental), + }, + } + _, err = testutil.CreateDeployment(testsuite.ctx, testsuite.subscriptionId, testsuite.cred, testsuite.options, testsuite.resourceGroupName, "Create_PrivateEndpoint", &deployment) + testsuite.Require().NoError(err) + + var privateEndpointConnectionName string + // From step PrivateEndpointConnections_ListByServer + fmt.Println("Call operation: PrivateEndpointConnections_ListByServer") + privateEndpointConnectionsClient, err := armpostgresql.NewPrivateEndpointConnectionsClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + privateEndpointConnectionsClientNewListByServerPager := privateEndpointConnectionsClient.NewListByServerPager(testsuite.resourceGroupName, testsuite.serverName, nil) + for privateEndpointConnectionsClientNewListByServerPager.More() { + result, err := privateEndpointConnectionsClientNewListByServerPager.NextPage(testsuite.ctx) + testsuite.Require().NoError(err) + privateEndpointConnectionName = *result.Value[0].Name + break + } + + // From step PrivateEndpointConnections_Get + fmt.Println("Call operation: PrivateEndpointConnections_Get") + _, err = privateEndpointConnectionsClient.Get(testsuite.ctx, testsuite.resourceGroupName, testsuite.serverName, privateEndpointConnectionName, nil) + testsuite.Require().NoError(err) + + var privateLinkResourceName string + // from step PrivateLinkResources_ListByServer + fmt.Println("Call operation: PrivateLinkResources_ListByServer") + privateLinkResourcesClient, err := armpostgresql.NewPrivateLinkResourcesClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + privateLinkResourcesClientNewListByServerPager := privateLinkResourcesClient.NewListByServerPager(testsuite.resourceGroupName, testsuite.serverName, nil) + for privateLinkResourcesClientNewListByServerPager.More() { + result, err := privateLinkResourcesClientNewListByServerPager.NextPage(testsuite.ctx) + testsuite.Require().NoError(err) + privateLinkResourceName = *result.Value[0].Name + break + } + + // From step PrivateLinkResources_Get + fmt.Println("Call operation: PrivateLinkResources_Get") + _, err = privateLinkResourcesClient.Get(testsuite.ctx, testsuite.resourceGroupName, testsuite.serverName, privateLinkResourceName, nil) + testsuite.Require().NoError(err) + + // From step PrivateEndpointConnections_Delete + fmt.Println("Call operation: PrivateEndpointConnections_Delete") + privateEndpointConnectionsClientDeleteResponsePoller, err := privateEndpointConnectionsClient.BeginDelete(testsuite.ctx, testsuite.resourceGroupName, testsuite.serverName, privateEndpointConnectionName, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, privateEndpointConnectionsClientDeleteResponsePoller) + testsuite.Require().NoError(err) +} diff --git a/sdk/resourcemanager/postgresql/armpostgresql/serversecurityalertpolicies_live_test.go b/sdk/resourcemanager/postgresql/armpostgresql/serversecurityalertpolicies_live_test.go new file mode 100644 index 000000000000..f8cecb98ac1c --- /dev/null +++ b/sdk/resourcemanager/postgresql/armpostgresql/serversecurityalertpolicies_live_test.go @@ -0,0 +1,126 @@ +//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 armpostgresql_test + +import ( + "context" + "fmt" + "testing" + + "github.com/Azure/azure-sdk-for-go/sdk/azcore" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/arm" + "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/resourcemanager/internal/testutil" + "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/postgresql/armpostgresql" + "github.com/stretchr/testify/suite" +) + +type ServerSecurityAlertPoliciesTestSuite struct { + suite.Suite + + ctx context.Context + cred azcore.TokenCredential + options *arm.ClientOptions + serverName string + adminPassword string + location string + resourceGroupName string + subscriptionId string +} + +func (testsuite *ServerSecurityAlertPoliciesTestSuite) SetupSuite() { + testutil.StartRecording(testsuite.T(), "sdk/resourcemanager/postgresql/armpostgresql/testdata") + + testsuite.ctx = context.Background() + testsuite.cred, testsuite.options = testutil.GetCredAndClientOptions(testsuite.T()) + testsuite.serverName, _ = recording.GenerateAlphaNumericID(testsuite.T(), "serverna", 14, true) + testsuite.adminPassword = testutil.GetEnv("ADMIN_PASSWORD", "") + testsuite.location = testutil.GetEnv("LOCATION", "westus") + testsuite.resourceGroupName = testutil.GetEnv("RESOURCE_GROUP_NAME", "scenarioTestTempGroup") + testsuite.subscriptionId = testutil.GetEnv("AZURE_SUBSCRIPTION_ID", "00000000-0000-0000-0000-000000000000") + resourceGroup, _, err := testutil.CreateResourceGroup(testsuite.ctx, testsuite.subscriptionId, testsuite.cred, testsuite.options, testsuite.location) + testsuite.Require().NoError(err) + testsuite.resourceGroupName = *resourceGroup.Name + testsuite.Prepare() +} + +func (testsuite *ServerSecurityAlertPoliciesTestSuite) TearDownSuite() { + _, err := testutil.DeleteResourceGroup(testsuite.ctx, testsuite.subscriptionId, testsuite.cred, testsuite.options, testsuite.resourceGroupName) + testsuite.Require().NoError(err) + testutil.StopRecording(testsuite.T()) +} + +func TestServerSecurityAlertPoliciesTestSuite(t *testing.T) { + suite.Run(t, new(ServerSecurityAlertPoliciesTestSuite)) +} + +func (testsuite *ServerSecurityAlertPoliciesTestSuite) Prepare() { + var err error + // From step Servers_Create + fmt.Println("Call operation: Servers_Create") + serversClient, err := armpostgresql.NewServersClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + serversClientCreateResponsePoller, err := serversClient.BeginCreate(testsuite.ctx, testsuite.resourceGroupName, testsuite.serverName, armpostgresql.ServerForCreate{ + Location: to.Ptr(testsuite.location), + Properties: &armpostgresql.ServerPropertiesForDefaultCreate{ + CreateMode: to.Ptr(armpostgresql.CreateModeDefault), + MinimalTLSVersion: to.Ptr(armpostgresql.MinimalTLSVersionEnumTLS12), + SSLEnforcement: to.Ptr(armpostgresql.SSLEnforcementEnumEnabled), + StorageProfile: &armpostgresql.StorageProfile{ + BackupRetentionDays: to.Ptr[int32](7), + GeoRedundantBackup: to.Ptr(armpostgresql.GeoRedundantBackupDisabled), + StorageMB: to.Ptr[int32](128000), + }, + AdministratorLogin: to.Ptr("cloudsa"), + AdministratorLoginPassword: to.Ptr(testsuite.adminPassword), + }, + SKU: &armpostgresql.SKU{ + Name: to.Ptr("GP_Gen5_8"), + Family: to.Ptr("Gen5"), + Tier: to.Ptr(armpostgresql.SKUTierGeneralPurpose), + }, + Tags: map[string]*string{ + "ElasticServer": to.Ptr("1"), + }, + }, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, serversClientCreateResponsePoller) + testsuite.Require().NoError(err) +} + +// Microsoft.DBforPostgreSQL/servers/{serverName}/securityAlertPolicies/{securityAlertPolicyName} +func (testsuite *ServerSecurityAlertPoliciesTestSuite) TestServerSecurityAlertPolicies() { + var err error + // From step ServerSecurityAlertPolicies_CreateOrUpdate + fmt.Println("Call operation: ServerSecurityAlertPolicies_CreateOrUpdate") + serverSecurityAlertPoliciesClient, err := armpostgresql.NewServerSecurityAlertPoliciesClient(testsuite.subscriptionId, testsuite.cred, testsuite.options) + testsuite.Require().NoError(err) + serverSecurityAlertPoliciesClientCreateOrUpdateResponsePoller, err := serverSecurityAlertPoliciesClient.BeginCreateOrUpdate(testsuite.ctx, testsuite.resourceGroupName, testsuite.serverName, armpostgresql.SecurityAlertPolicyNameDefault, armpostgresql.ServerSecurityAlertPolicy{ + Properties: &armpostgresql.SecurityAlertPolicyProperties{ + EmailAccountAdmins: to.Ptr(true), + State: to.Ptr(armpostgresql.ServerSecurityAlertPolicyStateDisabled), + }, + }, nil) + testsuite.Require().NoError(err) + _, err = testutil.PollForTest(testsuite.ctx, serverSecurityAlertPoliciesClientCreateOrUpdateResponsePoller) + testsuite.Require().NoError(err) + + // From step ServerSecurityAlertPolicies_ListByServer + fmt.Println("Call operation: ServerSecurityAlertPolicies_ListByServer") + serverSecurityAlertPoliciesClientNewListByServerPager := serverSecurityAlertPoliciesClient.NewListByServerPager(testsuite.resourceGroupName, testsuite.serverName, nil) + for serverSecurityAlertPoliciesClientNewListByServerPager.More() { + _, err := serverSecurityAlertPoliciesClientNewListByServerPager.NextPage(testsuite.ctx) + testsuite.Require().NoError(err) + break + } + + // From step ServerSecurityAlertPolicies_Get + fmt.Println("Call operation: ServerSecurityAlertPolicies_Get") + _, err = serverSecurityAlertPoliciesClient.Get(testsuite.ctx, testsuite.resourceGroupName, testsuite.serverName, armpostgresql.SecurityAlertPolicyNameDefault, nil) + testsuite.Require().NoError(err) +} diff --git a/sdk/security/keyvault/azadmin/CHANGELOG.md b/sdk/security/keyvault/azadmin/CHANGELOG.md index 9801ea4bf6d3..2ce73e268b87 100644 --- a/sdk/security/keyvault/azadmin/CHANGELOG.md +++ b/sdk/security/keyvault/azadmin/CHANGELOG.md @@ -1,14 +1,9 @@ ## Release History -### 0.2.1 (Unreleased) +## 1.0.0 (2023-05-11) -#### Features Added - -#### Breaking Changes - -#### Bugs Fixed - -#### Other Changes +### Other Changes +* Updated dependencies ### 0.2.0 (2023-04-13) diff --git a/sdk/security/keyvault/azadmin/go.mod b/sdk/security/keyvault/azadmin/go.mod index 0401754c0546..3d736680146e 100644 --- a/sdk/security/keyvault/azadmin/go.mod +++ b/sdk/security/keyvault/azadmin/go.mod @@ -3,8 +3,8 @@ module github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azadmin go 1.18 require ( - github.com/Azure/azure-sdk-for-go/sdk/azcore v1.4.0 - github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.2.1 + github.com/Azure/azure-sdk-for-go/sdk/azcore v1.6.0 + github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.3.0 github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0 github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azkeys v0.11.0 github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/internal v0.8.0 @@ -13,17 +13,17 @@ require ( ) require ( - github.com/AzureAD/microsoft-authentication-library-for-go v0.8.1 // indirect + github.com/AzureAD/microsoft-authentication-library-for-go v1.0.0 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/dnaeon/go-vcr v1.2.0 // indirect - github.com/golang-jwt/jwt/v4 v4.4.3 // indirect + github.com/golang-jwt/jwt/v4 v4.5.0 // indirect github.com/kylelemons/godebug v1.1.0 // indirect github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - golang.org/x/crypto v0.6.0 // indirect - golang.org/x/net v0.8.0 // indirect - golang.org/x/sys v0.6.0 // indirect - golang.org/x/text v0.8.0 // indirect + golang.org/x/crypto v0.9.0 // indirect + golang.org/x/net v0.10.0 // indirect + golang.org/x/sys v0.8.0 // indirect + golang.org/x/text v0.9.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/sdk/security/keyvault/azadmin/go.sum b/sdk/security/keyvault/azadmin/go.sum index eda99c5307f2..d443d38dbf8c 100644 --- a/sdk/security/keyvault/azadmin/go.sum +++ b/sdk/security/keyvault/azadmin/go.sum @@ -1,22 +1,22 @@ -github.com/Azure/azure-sdk-for-go/sdk/azcore v1.4.0 h1:rTnT/Jrcm+figWlYz4Ixzt0SJVR2cMC8lvZcimipiEY= -github.com/Azure/azure-sdk-for-go/sdk/azcore v1.4.0/go.mod h1:ON4tFdPTwRcgWEaVDrN3584Ef+b7GgSJaXxe5fW9t4M= -github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.2.1 h1:T8quHYlUGyb/oqtSTwqlCr1ilJHrDv+ZtpSfo+hm1BU= -github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.2.1/go.mod h1:gLa1CL2RNE4s7M3yopJ/p0iq5DdY6Yv5ZUt9MTRZOQM= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.6.0 h1:8kDqDngH+DmVBiCtIjCFTGa7MBnsIOkF9IccInFEbjk= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.6.0/go.mod h1:bjGvMhVMb+EEm3VRNQawDMUyMMjo+S5ewNjflkep/0Q= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.3.0 h1:vcYCAze6p19qBW7MhZybIsqD8sMV8js0NyQM8JDnVtg= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.3.0/go.mod h1:OQeznEEkTZ9OrhHJoDD8ZDq51FHgXjqtP9z6bEwBq9U= github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0 h1:sXr+ck84g/ZlZUOZiNELInmMgOsuGwdjjVkEIde0OtY= github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0/go.mod h1:okt5dMMTOFjX/aovMlrjvvXoPMBVSPzk9185BT0+eZM= github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azkeys v0.11.0 h1:efdSCWUBtk2FUUIlEfZhRQyVIM3Ts8lA3vaF18amnwo= github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azkeys v0.11.0/go.mod h1:LLJYu/UhJ8GpH5PtJc06RmJ1gJ5mPCSc1PiDMW17MHM= github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/internal v0.8.0 h1:T028gtTPiYt/RMUfs8nVsAL7FDQrfLlrm/NnRG/zcC4= github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/internal v0.8.0/go.mod h1:cw4zVQgBby0Z5f2v0itn6se2dDP17nTjbZFXW5uPyHA= -github.com/AzureAD/microsoft-authentication-library-for-go v0.8.1 h1:oPdPEZFSbl7oSPEAIPMPBMUmiL+mqgzBJwM/9qYcwNg= -github.com/AzureAD/microsoft-authentication-library-for-go v0.8.1/go.mod h1:4qFor3D/HDsvBME35Xy9rwW9DecL+M2sNw1ybjPtwA0= +github.com/AzureAD/microsoft-authentication-library-for-go v1.0.0 h1:OBhqkivkhkMqLPymWEppkm7vgPQY2XsHoEkaMQ0AdZY= +github.com/AzureAD/microsoft-authentication-library-for-go v1.0.0/go.mod h1:kgDmCTgBzIEPFElEF+FK0SdjAor06dRq2Go927dnQ6o= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/dnaeon/go-vcr v1.2.0 h1:zHCHvJYTMh1N7xnV7zf1m1GPBF9Ad0Jk/whtQ1663qI= github.com/dnaeon/go-vcr v1.2.0/go.mod h1:R4UdLID7HZT3taECzJs4YgbbH6PIGXB6W/sc5OLb6RQ= -github.com/golang-jwt/jwt/v4 v4.4.3 h1:Hxl6lhQFj4AnOX6MLrsCb/+7tCj7DxP7VA+2rDIq5AU= -github.com/golang-jwt/jwt/v4 v4.4.3/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= +github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg= +github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= @@ -33,15 +33,15 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -golang.org/x/crypto v0.6.0 h1:qfktjS5LUO+fFKeJXZ+ikTRijMmljikvG68fpMMruSc= -golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58= -golang.org/x/net v0.8.0 h1:Zrh2ngAOFYneWTAIAPethzeaQLuHwhuBkuV6ZiRnUaQ= -golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= +golang.org/x/crypto v0.9.0 h1:LF6fAI+IutBocDJ2OT0Q1g8plpYljMZ4+lty+dsqw3g= +golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0= +golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M= +golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/sys v0.0.0-20210616045830-e2b7044e8c71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.6.0 h1:MVltZSvRTcU2ljQOhs94SXPftV6DCNnZViHeQps87pQ= -golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/text v0.8.0 h1:57P1ETyNKtuIjB4SRd15iJxuhj8Gc416Y78H3qgMh68= -golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU= +golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE= +golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/sdk/security/keyvault/azadmin/internal/version.go b/sdk/security/keyvault/azadmin/internal/version.go index a247ad64aa14..3476033e8db1 100644 --- a/sdk/security/keyvault/azadmin/internal/version.go +++ b/sdk/security/keyvault/azadmin/internal/version.go @@ -8,5 +8,5 @@ package internal const ( ModuleName = "azadmin" - Version = "v0.2.1" + Version = "v1.0.0" ) diff --git a/sdk/security/keyvault/azadmin/settings/client_test.go b/sdk/security/keyvault/azadmin/settings/client_test.go index 932444a5595c..d638eb6dad5e 100644 --- a/sdk/security/keyvault/azadmin/settings/client_test.go +++ b/sdk/security/keyvault/azadmin/settings/client_test.go @@ -8,10 +8,13 @@ package settings_test import ( "context" + "errors" "testing" + "time" "github.com/Azure/azure-sdk-for-go/sdk/azcore" "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/security/keyvault/azadmin/settings" "github.com/stretchr/testify/require" ) @@ -103,7 +106,16 @@ func TestUpdateSetting_InvalidSettingName(t *testing.T) { require.Nil(t, res.Type) require.Nil(t, res.Value) - res, err = client.UpdateSetting(context.Background(), "invalid name", settings.UpdateSettingRequest{Value: to.Ptr("true")}, nil) + for i := 0; i < 4; i++ { + res, err = client.UpdateSetting(context.Background(), "invalid name", settings.UpdateSettingRequest{Value: to.Ptr("true")}, nil) + var httpErr *azcore.ResponseError + // if correct error is returned, break from the loop and check for correctness + if errors.As(err, &httpErr) && httpErr.StatusCode == 400 { + break + } + // else sleep for 30 seconds and try again + recording.Sleep(30 * time.Second) + } require.Error(t, err) require.Nil(t, res.Name) require.Nil(t, res.Type) diff --git a/sdk/security/keyvault/azcertificates/CHANGELOG.md b/sdk/security/keyvault/azcertificates/CHANGELOG.md index 21b91691dd46..f78a18bc4269 100644 --- a/sdk/security/keyvault/azcertificates/CHANGELOG.md +++ b/sdk/security/keyvault/azcertificates/CHANGELOG.md @@ -1,14 +1,9 @@ # Release History -## 0.10.1 (Unreleased) - -### Features Added - -### Breaking Changes - -### Bugs Fixed +## 1.0.0 (2023-05-11) ### Other Changes +* Updated dependencies ## 0.10.0 (2023-04-13) diff --git a/sdk/security/keyvault/azcertificates/go.mod b/sdk/security/keyvault/azcertificates/go.mod index 518df8ee4700..bc7cc5e9b251 100644 --- a/sdk/security/keyvault/azcertificates/go.mod +++ b/sdk/security/keyvault/azcertificates/go.mod @@ -3,26 +3,26 @@ module github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azcertificates go 1.18 require ( - github.com/Azure/azure-sdk-for-go/sdk/azcore v1.4.0 - github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.1.0 - github.com/Azure/azure-sdk-for-go/sdk/internal v1.2.0 + github.com/Azure/azure-sdk-for-go/sdk/azcore v1.6.0 + github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.3.0 + github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0 github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/internal v0.8.0 github.com/stretchr/testify v1.8.2 ) require ( - github.com/AzureAD/microsoft-authentication-library-for-go v0.5.1 // indirect + github.com/AzureAD/microsoft-authentication-library-for-go v1.0.0 // indirect github.com/davecgh/go-spew v1.1.1 // indirect - github.com/dnaeon/go-vcr v1.1.0 // indirect - github.com/golang-jwt/jwt v3.2.1+incompatible // indirect - github.com/google/uuid v1.1.1 // indirect + github.com/dnaeon/go-vcr v1.2.0 // indirect + github.com/golang-jwt/jwt/v4 v4.5.0 // indirect + github.com/google/uuid v1.3.0 // indirect github.com/kylelemons/godebug v1.1.0 // indirect - github.com/pkg/browser v0.0.0-20210115035449-ce105d075bb4 // indirect + github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - golang.org/x/crypto v0.0.0-20220511200225-c6db032c6c88 // indirect - golang.org/x/net v0.7.0 // indirect - golang.org/x/sys v0.5.0 // indirect - golang.org/x/text v0.7.0 // indirect + golang.org/x/crypto v0.9.0 // indirect + golang.org/x/net v0.10.0 // indirect + golang.org/x/sys v0.8.0 // indirect + golang.org/x/text v0.9.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/sdk/security/keyvault/azcertificates/go.sum b/sdk/security/keyvault/azcertificates/go.sum index 020402e414b9..51e117ba2909 100644 --- a/sdk/security/keyvault/azcertificates/go.sum +++ b/sdk/security/keyvault/azcertificates/go.sum @@ -1,29 +1,27 @@ -github.com/Azure/azure-sdk-for-go/sdk/azcore v1.4.0 h1:rTnT/Jrcm+figWlYz4Ixzt0SJVR2cMC8lvZcimipiEY= -github.com/Azure/azure-sdk-for-go/sdk/azcore v1.4.0/go.mod h1:ON4tFdPTwRcgWEaVDrN3584Ef+b7GgSJaXxe5fW9t4M= -github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.1.0 h1:QkAcEIAKbNL4KoFr4SathZPhDhF4mVwpBMFlYjyAqy8= -github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.1.0/go.mod h1:bhXu1AjYL+wutSL/kpSq6s7733q2Rb0yuot9Zgfqa/0= -github.com/Azure/azure-sdk-for-go/sdk/internal v1.2.0 h1:leh5DwKv6Ihwi+h60uHtn6UWAxBbZ0q8DwQVMzf61zw= -github.com/Azure/azure-sdk-for-go/sdk/internal v1.2.0/go.mod h1:eWRD7oawr1Mu1sLCawqVc0CUiF43ia3qQMxLscsKQ9w= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.6.0 h1:8kDqDngH+DmVBiCtIjCFTGa7MBnsIOkF9IccInFEbjk= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.6.0/go.mod h1:bjGvMhVMb+EEm3VRNQawDMUyMMjo+S5ewNjflkep/0Q= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.3.0 h1:vcYCAze6p19qBW7MhZybIsqD8sMV8js0NyQM8JDnVtg= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.3.0/go.mod h1:OQeznEEkTZ9OrhHJoDD8ZDq51FHgXjqtP9z6bEwBq9U= +github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0 h1:sXr+ck84g/ZlZUOZiNELInmMgOsuGwdjjVkEIde0OtY= +github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0/go.mod h1:okt5dMMTOFjX/aovMlrjvvXoPMBVSPzk9185BT0+eZM= github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/internal v0.8.0 h1:T028gtTPiYt/RMUfs8nVsAL7FDQrfLlrm/NnRG/zcC4= github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/internal v0.8.0/go.mod h1:cw4zVQgBby0Z5f2v0itn6se2dDP17nTjbZFXW5uPyHA= -github.com/AzureAD/microsoft-authentication-library-for-go v0.5.1 h1:BWe8a+f/t+7KY7zH2mqygeUD0t8hNFXe08p1Pb3/jKE= -github.com/AzureAD/microsoft-authentication-library-for-go v0.5.1/go.mod h1:Vt9sXTKwMyGcOxSmLDMnGPgqsUg7m8pe215qMLrDXw4= +github.com/AzureAD/microsoft-authentication-library-for-go v1.0.0 h1:OBhqkivkhkMqLPymWEppkm7vgPQY2XsHoEkaMQ0AdZY= +github.com/AzureAD/microsoft-authentication-library-for-go v1.0.0/go.mod h1:kgDmCTgBzIEPFElEF+FK0SdjAor06dRq2Go927dnQ6o= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/dnaeon/go-vcr v1.1.0 h1:ReYa/UBrRyQdant9B4fNHGoCNKw6qh6P0fsdGmZpR7c= -github.com/dnaeon/go-vcr v1.1.0/go.mod h1:M7tiix8f0r6mKKJ3Yq/kqU1OYf3MnfmBWVbPx/yU9ko= -github.com/golang-jwt/jwt v3.2.1+incompatible h1:73Z+4BJcrTC+KczS6WvTPvRGOp1WmfEP4Q1lOd9Z/+c= -github.com/golang-jwt/jwt v3.2.1+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I= -github.com/golang-jwt/jwt/v4 v4.2.0 h1:besgBTC8w8HjP6NzQdxwKH9Z5oQMZ24ThTrHp3cZ8eU= -github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY= -github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/dnaeon/go-vcr v1.2.0 h1:zHCHvJYTMh1N7xnV7zf1m1GPBF9Ad0Jk/whtQ1663qI= +github.com/dnaeon/go-vcr v1.2.0/go.mod h1:R4UdLID7HZT3taECzJs4YgbbH6PIGXB6W/sc5OLb6RQ= +github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg= +github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= +github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= +github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= github.com/modocache/gover v0.0.0-20171022184752-b58185e213c5/go.mod h1:caMODM3PzxT8aQXRPkAt8xlV/e7d7w8GM5g0fa5F0D8= -github.com/montanaflynn/stats v0.6.6/go.mod h1:etXPPgVO6n31NxCd9KQUMvCM+ve0ruNzt6R8Bnaayow= -github.com/pkg/browser v0.0.0-20210115035449-ce105d075bb4 h1:Qj1ukM4GlMWXNdMBuXcXfz/Kw9s1qm0CLY32QxuSImI= -github.com/pkg/browser v0.0.0-20210115035449-ce105d075bb4/go.mod h1:N6UoU20jOqggOuDwUaBQpluzLNDqif3kq9z2wpdYEfQ= +github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 h1:KoWmjvw+nsYOo29YJK9vDA65RGE3NrOnUtO7a+RF9HU= +github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8/go.mod h1:HKlIX3XHQyzLZPlr7++PzdhaXEj94dEiJgZDTsxEqUI= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= @@ -33,18 +31,18 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -golang.org/x/crypto v0.0.0-20220511200225-c6db032c6c88 h1:Tgea0cVUD0ivh5ADBX4WwuI12DUd2to3nCYe2eayMIw= -golang.org/x/crypto v0.0.0-20220511200225-c6db032c6c88/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/net v0.7.0 h1:rJrUqqhjsgNp7KqAIc25s9pZnjU7TUcSY7HcVZjdn1g= -golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= -golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU= -golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/text v0.7.0 h1:4BRB4x83lYWy72KwLD/qYDuTu7q9PjSagHvijDw7cLo= -golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/crypto v0.9.0 h1:LF6fAI+IutBocDJ2OT0Q1g8plpYljMZ4+lty+dsqw3g= +golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0= +golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M= +golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= +golang.org/x/sys v0.0.0-20210616045830-e2b7044e8c71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU= +golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE= +golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/sdk/security/keyvault/azcertificates/testdata/perf/go.mod b/sdk/security/keyvault/azcertificates/testdata/perf/go.mod index a9463126402d..c729f56244b1 100644 --- a/sdk/security/keyvault/azcertificates/testdata/perf/go.mod +++ b/sdk/security/keyvault/azcertificates/testdata/perf/go.mod @@ -5,22 +5,21 @@ go 1.18 replace github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azcertificates => ../.. require ( - github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.2.2 - github.com/Azure/azure-sdk-for-go/sdk/internal v1.2.0 - github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azcertificates v0.3.0 + github.com/Azure/azure-sdk-for-go/sdk/azcore v1.6.0 + github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.3.0 + github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0 + github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azcertificates v0.10.0 ) require ( - github.com/Azure/azure-sdk-for-go/sdk/azcore v1.4.0 // indirect github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/internal v0.8.0 // indirect - github.com/AzureAD/microsoft-authentication-library-for-go v0.9.0 // indirect - github.com/golang-jwt/jwt v3.2.1+incompatible // indirect + github.com/AzureAD/microsoft-authentication-library-for-go v1.0.0 // indirect github.com/golang-jwt/jwt/v4 v4.5.0 // indirect github.com/google/uuid v1.3.0 // indirect github.com/kylelemons/godebug v1.1.0 // indirect github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 // indirect - golang.org/x/crypto v0.6.0 // indirect - golang.org/x/net v0.7.0 // indirect - golang.org/x/sys v0.5.0 // indirect - golang.org/x/text v0.7.0 // indirect + golang.org/x/crypto v0.9.0 // indirect + golang.org/x/net v0.10.0 // indirect + golang.org/x/sys v0.8.0 // indirect + golang.org/x/text v0.9.0 // indirect ) diff --git a/sdk/security/keyvault/azcertificates/testdata/perf/go.sum b/sdk/security/keyvault/azcertificates/testdata/perf/go.sum index 7a20a947a37e..9e3409f5ceb6 100644 --- a/sdk/security/keyvault/azcertificates/testdata/perf/go.sum +++ b/sdk/security/keyvault/azcertificates/testdata/perf/go.sum @@ -1,81 +1,33 @@ -github.com/Azure/azure-sdk-for-go/sdk/azcore v0.23.0 h1:D7l5jspkc4kwBYRWoZE4DQnu6LVpLwDsMZjBKS4wZLQ= -github.com/Azure/azure-sdk-for-go/sdk/azcore v0.23.0/go.mod h1:w5pDIZuawUmY3Bj4tVx3Xb8KS96ToB0j315w9rqpAg0= -github.com/Azure/azure-sdk-for-go/sdk/azcore v1.4.0 h1:rTnT/Jrcm+figWlYz4Ixzt0SJVR2cMC8lvZcimipiEY= -github.com/Azure/azure-sdk-for-go/sdk/azcore v1.4.0/go.mod h1:ON4tFdPTwRcgWEaVDrN3584Ef+b7GgSJaXxe5fW9t4M= -github.com/Azure/azure-sdk-for-go/sdk/azidentity v0.14.0 h1:NVS/4LOQfkBpk+B1VopIzv1ptmYeEskA8w/3K/w7vjo= -github.com/Azure/azure-sdk-for-go/sdk/azidentity v0.14.0/go.mod h1:RG0cZndeZM17StwohYclmcXSr4oOJ8b1I5hB8llIc6Y= -github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.1.0/go.mod h1:bhXu1AjYL+wutSL/kpSq6s7733q2Rb0yuot9Zgfqa/0= -github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.2.2 h1:uqM+VoHjVH6zdlkLF2b6O0ZANcHoj3rO0PoQ3jglUJA= -github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.2.2/go.mod h1:twTKAa1E6hLmSDjLhaCkbTMQKc7p/rNLU40rLxGEOCI= -github.com/Azure/azure-sdk-for-go/sdk/internal v0.9.2 h1:Px2KVERcYEg2Lv25AqC2hVr0xUWaq94wuEObLIkYzmA= -github.com/Azure/azure-sdk-for-go/sdk/internal v0.9.2/go.mod h1:CdSJQNNzZhCkwDaV27XV1w48ZBPtxe7mlrZAsPNxD5g= -github.com/Azure/azure-sdk-for-go/sdk/internal v1.2.0 h1:leh5DwKv6Ihwi+h60uHtn6UWAxBbZ0q8DwQVMzf61zw= -github.com/Azure/azure-sdk-for-go/sdk/internal v1.2.0/go.mod h1:eWRD7oawr1Mu1sLCawqVc0CUiF43ia3qQMxLscsKQ9w= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.6.0 h1:8kDqDngH+DmVBiCtIjCFTGa7MBnsIOkF9IccInFEbjk= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.6.0/go.mod h1:bjGvMhVMb+EEm3VRNQawDMUyMMjo+S5ewNjflkep/0Q= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.3.0 h1:vcYCAze6p19qBW7MhZybIsqD8sMV8js0NyQM8JDnVtg= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.3.0/go.mod h1:OQeznEEkTZ9OrhHJoDD8ZDq51FHgXjqtP9z6bEwBq9U= +github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0 h1:sXr+ck84g/ZlZUOZiNELInmMgOsuGwdjjVkEIde0OtY= +github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0/go.mod h1:okt5dMMTOFjX/aovMlrjvvXoPMBVSPzk9185BT0+eZM= github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/internal v0.8.0 h1:T028gtTPiYt/RMUfs8nVsAL7FDQrfLlrm/NnRG/zcC4= github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/internal v0.8.0/go.mod h1:cw4zVQgBby0Z5f2v0itn6se2dDP17nTjbZFXW5uPyHA= -github.com/AzureAD/microsoft-authentication-library-for-go v0.4.0 h1:WVsrXCnHlDDX8ls+tootqRE87/hL9S/g4ewig9RsD/c= -github.com/AzureAD/microsoft-authentication-library-for-go v0.4.0/go.mod h1:Vt9sXTKwMyGcOxSmLDMnGPgqsUg7m8pe215qMLrDXw4= -github.com/AzureAD/microsoft-authentication-library-for-go v0.5.1/go.mod h1:Vt9sXTKwMyGcOxSmLDMnGPgqsUg7m8pe215qMLrDXw4= -github.com/AzureAD/microsoft-authentication-library-for-go v0.9.0 h1:UE9n9rkJF62ArLb1F3DEjRt8O3jLwMWdSoypKV4f3MU= -github.com/AzureAD/microsoft-authentication-library-for-go v0.9.0/go.mod h1:kgDmCTgBzIEPFElEF+FK0SdjAor06dRq2Go927dnQ6o= -github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/AzureAD/microsoft-authentication-library-for-go v1.0.0 h1:OBhqkivkhkMqLPymWEppkm7vgPQY2XsHoEkaMQ0AdZY= +github.com/AzureAD/microsoft-authentication-library-for-go v1.0.0/go.mod h1:kgDmCTgBzIEPFElEF+FK0SdjAor06dRq2Go927dnQ6o= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= -github.com/dnaeon/go-vcr v1.1.0 h1:ReYa/UBrRyQdant9B4fNHGoCNKw6qh6P0fsdGmZpR7c= -github.com/dnaeon/go-vcr v1.1.0/go.mod h1:M7tiix8f0r6mKKJ3Yq/kqU1OYf3MnfmBWVbPx/yU9ko= -github.com/golang-jwt/jwt v3.2.1+incompatible h1:73Z+4BJcrTC+KczS6WvTPvRGOp1WmfEP4Q1lOd9Z/+c= -github.com/golang-jwt/jwt v3.2.1+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I= -github.com/golang-jwt/jwt/v4 v4.2.0 h1:besgBTC8w8HjP6NzQdxwKH9Z5oQMZ24ThTrHp3cZ8eU= +github.com/dnaeon/go-vcr v1.2.0 h1:zHCHvJYTMh1N7xnV7zf1m1GPBF9Ad0Jk/whtQ1663qI= github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg= github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= -github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY= -github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= -github.com/modocache/gover v0.0.0-20171022184752-b58185e213c5/go.mod h1:caMODM3PzxT8aQXRPkAt8xlV/e7d7w8GM5g0fa5F0D8= -github.com/montanaflynn/stats v0.6.6/go.mod h1:etXPPgVO6n31NxCd9KQUMvCM+ve0ruNzt6R8Bnaayow= -github.com/pkg/browser v0.0.0-20210115035449-ce105d075bb4 h1:Qj1ukM4GlMWXNdMBuXcXfz/Kw9s1qm0CLY32QxuSImI= -github.com/pkg/browser v0.0.0-20210115035449-ce105d075bb4/go.mod h1:N6UoU20jOqggOuDwUaBQpluzLNDqif3kq9z2wpdYEfQ= github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 h1:KoWmjvw+nsYOo29YJK9vDA65RGE3NrOnUtO7a+RF9HU= github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8/go.mod h1:HKlIX3XHQyzLZPlr7++PzdhaXEj94dEiJgZDTsxEqUI= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= -github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= -github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897 h1:pLI5jrR7OSLijeIDcmRxNmw2api+jEfxLoykJVice/E= -golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20220511200225-c6db032c6c88/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.6.0 h1:qfktjS5LUO+fFKeJXZ+ikTRijMmljikvG68fpMMruSc= -golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58= -golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20201010224723-4f7140c49acb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f h1:OfiFi4JbukWwe3lzw+xunroH1mnC1e2Gy5cxNJApiSY= -golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.7.0 h1:rJrUqqhjsgNp7KqAIc25s9pZnjU7TUcSY7HcVZjdn1g= -golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= -golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= +golang.org/x/crypto v0.9.0 h1:LF6fAI+IutBocDJ2OT0Q1g8plpYljMZ4+lty+dsqw3g= +golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0= +golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M= +golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/sys v0.0.0-20210616045830-e2b7044e8c71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211019181941-9d821ace8654 h1:id054HUawV2/6IGm2IV8KZQjqtwAOo2CYlOToYqa0d0= -golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU= -golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= -golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.7.0 h1:4BRB4x83lYWy72KwLD/qYDuTu7q9PjSagHvijDw7cLo= -golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU= +golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE= +golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= -gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= diff --git a/sdk/security/keyvault/azcertificates/version.go b/sdk/security/keyvault/azcertificates/version.go index fcd766917ec2..b3d53e37bc29 100644 --- a/sdk/security/keyvault/azcertificates/version.go +++ b/sdk/security/keyvault/azcertificates/version.go @@ -8,5 +8,5 @@ package azcertificates const ( moduleName = "azcertificates" - version = "v0.10.1" + version = "v1.0.0" ) diff --git a/sdk/security/keyvault/azkeys/CHANGELOG.md b/sdk/security/keyvault/azkeys/CHANGELOG.md index 83a4f8a1d69a..1bf58ce5eb8d 100644 --- a/sdk/security/keyvault/azkeys/CHANGELOG.md +++ b/sdk/security/keyvault/azkeys/CHANGELOG.md @@ -1,14 +1,9 @@ # Release History -## 0.11.1 (Unreleased) - -### Features Added - -### Breaking Changes - -### Bugs Fixed +## 1.0.0 (2023-05-11) ### Other Changes +* Updated dependencies ## 0.11.0 (2023-04-13) diff --git a/sdk/security/keyvault/azkeys/go.mod b/sdk/security/keyvault/azkeys/go.mod index db3f1705323f..06b59e94fcbc 100644 --- a/sdk/security/keyvault/azkeys/go.mod +++ b/sdk/security/keyvault/azkeys/go.mod @@ -3,26 +3,26 @@ module github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azkeys go 1.18 require ( - github.com/Azure/azure-sdk-for-go/sdk/azcore v1.4.0 - github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.1.0 - github.com/Azure/azure-sdk-for-go/sdk/internal v1.2.0 + github.com/Azure/azure-sdk-for-go/sdk/azcore v1.6.0 + github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.3.0 + github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0 github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/internal v0.8.0 github.com/stretchr/testify v1.8.2 ) require ( - github.com/AzureAD/microsoft-authentication-library-for-go v0.5.1 // indirect + github.com/AzureAD/microsoft-authentication-library-for-go v1.0.0 // indirect github.com/davecgh/go-spew v1.1.1 // indirect - github.com/dnaeon/go-vcr v1.1.0 // indirect - github.com/golang-jwt/jwt v3.2.1+incompatible // indirect - github.com/google/uuid v1.1.1 // indirect + github.com/dnaeon/go-vcr v1.2.0 // indirect + github.com/golang-jwt/jwt/v4 v4.5.0 // indirect + github.com/google/uuid v1.3.0 // indirect github.com/kylelemons/godebug v1.1.0 // indirect - github.com/pkg/browser v0.0.0-20210115035449-ce105d075bb4 // indirect + github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - golang.org/x/crypto v0.0.0-20220511200225-c6db032c6c88 // indirect - golang.org/x/net v0.8.0 // indirect - golang.org/x/sys v0.6.0 // indirect - golang.org/x/text v0.8.0 // indirect + golang.org/x/crypto v0.9.0 // indirect + golang.org/x/net v0.10.0 // indirect + golang.org/x/sys v0.8.0 // indirect + golang.org/x/text v0.9.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/sdk/security/keyvault/azkeys/go.sum b/sdk/security/keyvault/azkeys/go.sum index f4c11a230c77..51e117ba2909 100644 --- a/sdk/security/keyvault/azkeys/go.sum +++ b/sdk/security/keyvault/azkeys/go.sum @@ -1,29 +1,27 @@ -github.com/Azure/azure-sdk-for-go/sdk/azcore v1.4.0 h1:rTnT/Jrcm+figWlYz4Ixzt0SJVR2cMC8lvZcimipiEY= -github.com/Azure/azure-sdk-for-go/sdk/azcore v1.4.0/go.mod h1:ON4tFdPTwRcgWEaVDrN3584Ef+b7GgSJaXxe5fW9t4M= -github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.1.0 h1:QkAcEIAKbNL4KoFr4SathZPhDhF4mVwpBMFlYjyAqy8= -github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.1.0/go.mod h1:bhXu1AjYL+wutSL/kpSq6s7733q2Rb0yuot9Zgfqa/0= -github.com/Azure/azure-sdk-for-go/sdk/internal v1.2.0 h1:leh5DwKv6Ihwi+h60uHtn6UWAxBbZ0q8DwQVMzf61zw= -github.com/Azure/azure-sdk-for-go/sdk/internal v1.2.0/go.mod h1:eWRD7oawr1Mu1sLCawqVc0CUiF43ia3qQMxLscsKQ9w= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.6.0 h1:8kDqDngH+DmVBiCtIjCFTGa7MBnsIOkF9IccInFEbjk= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.6.0/go.mod h1:bjGvMhVMb+EEm3VRNQawDMUyMMjo+S5ewNjflkep/0Q= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.3.0 h1:vcYCAze6p19qBW7MhZybIsqD8sMV8js0NyQM8JDnVtg= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.3.0/go.mod h1:OQeznEEkTZ9OrhHJoDD8ZDq51FHgXjqtP9z6bEwBq9U= +github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0 h1:sXr+ck84g/ZlZUOZiNELInmMgOsuGwdjjVkEIde0OtY= +github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0/go.mod h1:okt5dMMTOFjX/aovMlrjvvXoPMBVSPzk9185BT0+eZM= github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/internal v0.8.0 h1:T028gtTPiYt/RMUfs8nVsAL7FDQrfLlrm/NnRG/zcC4= github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/internal v0.8.0/go.mod h1:cw4zVQgBby0Z5f2v0itn6se2dDP17nTjbZFXW5uPyHA= -github.com/AzureAD/microsoft-authentication-library-for-go v0.5.1 h1:BWe8a+f/t+7KY7zH2mqygeUD0t8hNFXe08p1Pb3/jKE= -github.com/AzureAD/microsoft-authentication-library-for-go v0.5.1/go.mod h1:Vt9sXTKwMyGcOxSmLDMnGPgqsUg7m8pe215qMLrDXw4= +github.com/AzureAD/microsoft-authentication-library-for-go v1.0.0 h1:OBhqkivkhkMqLPymWEppkm7vgPQY2XsHoEkaMQ0AdZY= +github.com/AzureAD/microsoft-authentication-library-for-go v1.0.0/go.mod h1:kgDmCTgBzIEPFElEF+FK0SdjAor06dRq2Go927dnQ6o= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/dnaeon/go-vcr v1.1.0 h1:ReYa/UBrRyQdant9B4fNHGoCNKw6qh6P0fsdGmZpR7c= -github.com/dnaeon/go-vcr v1.1.0/go.mod h1:M7tiix8f0r6mKKJ3Yq/kqU1OYf3MnfmBWVbPx/yU9ko= -github.com/golang-jwt/jwt v3.2.1+incompatible h1:73Z+4BJcrTC+KczS6WvTPvRGOp1WmfEP4Q1lOd9Z/+c= -github.com/golang-jwt/jwt v3.2.1+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I= -github.com/golang-jwt/jwt/v4 v4.2.0 h1:besgBTC8w8HjP6NzQdxwKH9Z5oQMZ24ThTrHp3cZ8eU= -github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY= -github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/dnaeon/go-vcr v1.2.0 h1:zHCHvJYTMh1N7xnV7zf1m1GPBF9Ad0Jk/whtQ1663qI= +github.com/dnaeon/go-vcr v1.2.0/go.mod h1:R4UdLID7HZT3taECzJs4YgbbH6PIGXB6W/sc5OLb6RQ= +github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg= +github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= +github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= +github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= github.com/modocache/gover v0.0.0-20171022184752-b58185e213c5/go.mod h1:caMODM3PzxT8aQXRPkAt8xlV/e7d7w8GM5g0fa5F0D8= -github.com/montanaflynn/stats v0.6.6/go.mod h1:etXPPgVO6n31NxCd9KQUMvCM+ve0ruNzt6R8Bnaayow= -github.com/pkg/browser v0.0.0-20210115035449-ce105d075bb4 h1:Qj1ukM4GlMWXNdMBuXcXfz/Kw9s1qm0CLY32QxuSImI= -github.com/pkg/browser v0.0.0-20210115035449-ce105d075bb4/go.mod h1:N6UoU20jOqggOuDwUaBQpluzLNDqif3kq9z2wpdYEfQ= +github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 h1:KoWmjvw+nsYOo29YJK9vDA65RGE3NrOnUtO7a+RF9HU= +github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8/go.mod h1:HKlIX3XHQyzLZPlr7++PzdhaXEj94dEiJgZDTsxEqUI= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= @@ -33,18 +31,18 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -golang.org/x/crypto v0.0.0-20220511200225-c6db032c6c88 h1:Tgea0cVUD0ivh5ADBX4WwuI12DUd2to3nCYe2eayMIw= -golang.org/x/crypto v0.0.0-20220511200225-c6db032c6c88/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/net v0.8.0 h1:Zrh2ngAOFYneWTAIAPethzeaQLuHwhuBkuV6ZiRnUaQ= -golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= -golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.6.0 h1:MVltZSvRTcU2ljQOhs94SXPftV6DCNnZViHeQps87pQ= -golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/text v0.8.0 h1:57P1ETyNKtuIjB4SRd15iJxuhj8Gc416Y78H3qgMh68= -golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/crypto v0.9.0 h1:LF6fAI+IutBocDJ2OT0Q1g8plpYljMZ4+lty+dsqw3g= +golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0= +golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M= +golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= +golang.org/x/sys v0.0.0-20210616045830-e2b7044e8c71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU= +golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE= +golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/sdk/security/keyvault/azkeys/testdata/perf/go.mod b/sdk/security/keyvault/azkeys/testdata/perf/go.mod index cd071a65aae0..e146d87a3b81 100644 --- a/sdk/security/keyvault/azkeys/testdata/perf/go.mod +++ b/sdk/security/keyvault/azkeys/testdata/perf/go.mod @@ -5,22 +5,21 @@ go 1.18 replace github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azkeys => ../.. require ( - github.com/Azure/azure-sdk-for-go/sdk/azcore v1.4.0 - github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.2.2 - github.com/Azure/azure-sdk-for-go/sdk/internal v1.2.0 - github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azkeys v0.5.0 + github.com/Azure/azure-sdk-for-go/sdk/azcore v1.6.0 + github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.3.0 + github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0 + github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azkeys v0.11.0 ) require ( github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/internal v0.8.0 // indirect - github.com/AzureAD/microsoft-authentication-library-for-go v0.9.0 // indirect - github.com/golang-jwt/jwt v3.2.1+incompatible // indirect + github.com/AzureAD/microsoft-authentication-library-for-go v1.0.0 // indirect github.com/golang-jwt/jwt/v4 v4.5.0 // indirect github.com/google/uuid v1.3.0 // indirect github.com/kylelemons/godebug v1.1.0 // indirect github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 // indirect - golang.org/x/crypto v0.6.0 // indirect - golang.org/x/net v0.8.0 // indirect - golang.org/x/sys v0.6.0 // indirect - golang.org/x/text v0.8.0 // indirect + golang.org/x/crypto v0.9.0 // indirect + golang.org/x/net v0.10.0 // indirect + golang.org/x/sys v0.8.0 // indirect + golang.org/x/text v0.9.0 // indirect ) diff --git a/sdk/security/keyvault/azkeys/testdata/perf/go.sum b/sdk/security/keyvault/azkeys/testdata/perf/go.sum index 1c8487835094..9e3409f5ceb6 100644 --- a/sdk/security/keyvault/azkeys/testdata/perf/go.sum +++ b/sdk/security/keyvault/azkeys/testdata/perf/go.sum @@ -1,81 +1,33 @@ -github.com/Azure/azure-sdk-for-go/sdk/azcore v0.23.0 h1:D7l5jspkc4kwBYRWoZE4DQnu6LVpLwDsMZjBKS4wZLQ= -github.com/Azure/azure-sdk-for-go/sdk/azcore v0.23.0/go.mod h1:w5pDIZuawUmY3Bj4tVx3Xb8KS96ToB0j315w9rqpAg0= -github.com/Azure/azure-sdk-for-go/sdk/azcore v1.4.0 h1:rTnT/Jrcm+figWlYz4Ixzt0SJVR2cMC8lvZcimipiEY= -github.com/Azure/azure-sdk-for-go/sdk/azcore v1.4.0/go.mod h1:ON4tFdPTwRcgWEaVDrN3584Ef+b7GgSJaXxe5fW9t4M= -github.com/Azure/azure-sdk-for-go/sdk/azidentity v0.14.0 h1:NVS/4LOQfkBpk+B1VopIzv1ptmYeEskA8w/3K/w7vjo= -github.com/Azure/azure-sdk-for-go/sdk/azidentity v0.14.0/go.mod h1:RG0cZndeZM17StwohYclmcXSr4oOJ8b1I5hB8llIc6Y= -github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.1.0/go.mod h1:bhXu1AjYL+wutSL/kpSq6s7733q2Rb0yuot9Zgfqa/0= -github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.2.2 h1:uqM+VoHjVH6zdlkLF2b6O0ZANcHoj3rO0PoQ3jglUJA= -github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.2.2/go.mod h1:twTKAa1E6hLmSDjLhaCkbTMQKc7p/rNLU40rLxGEOCI= -github.com/Azure/azure-sdk-for-go/sdk/internal v0.9.2 h1:Px2KVERcYEg2Lv25AqC2hVr0xUWaq94wuEObLIkYzmA= -github.com/Azure/azure-sdk-for-go/sdk/internal v0.9.2/go.mod h1:CdSJQNNzZhCkwDaV27XV1w48ZBPtxe7mlrZAsPNxD5g= -github.com/Azure/azure-sdk-for-go/sdk/internal v1.2.0 h1:leh5DwKv6Ihwi+h60uHtn6UWAxBbZ0q8DwQVMzf61zw= -github.com/Azure/azure-sdk-for-go/sdk/internal v1.2.0/go.mod h1:eWRD7oawr1Mu1sLCawqVc0CUiF43ia3qQMxLscsKQ9w= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.6.0 h1:8kDqDngH+DmVBiCtIjCFTGa7MBnsIOkF9IccInFEbjk= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.6.0/go.mod h1:bjGvMhVMb+EEm3VRNQawDMUyMMjo+S5ewNjflkep/0Q= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.3.0 h1:vcYCAze6p19qBW7MhZybIsqD8sMV8js0NyQM8JDnVtg= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.3.0/go.mod h1:OQeznEEkTZ9OrhHJoDD8ZDq51FHgXjqtP9z6bEwBq9U= +github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0 h1:sXr+ck84g/ZlZUOZiNELInmMgOsuGwdjjVkEIde0OtY= +github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0/go.mod h1:okt5dMMTOFjX/aovMlrjvvXoPMBVSPzk9185BT0+eZM= github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/internal v0.8.0 h1:T028gtTPiYt/RMUfs8nVsAL7FDQrfLlrm/NnRG/zcC4= github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/internal v0.8.0/go.mod h1:cw4zVQgBby0Z5f2v0itn6se2dDP17nTjbZFXW5uPyHA= -github.com/AzureAD/microsoft-authentication-library-for-go v0.4.0 h1:WVsrXCnHlDDX8ls+tootqRE87/hL9S/g4ewig9RsD/c= -github.com/AzureAD/microsoft-authentication-library-for-go v0.4.0/go.mod h1:Vt9sXTKwMyGcOxSmLDMnGPgqsUg7m8pe215qMLrDXw4= -github.com/AzureAD/microsoft-authentication-library-for-go v0.5.1/go.mod h1:Vt9sXTKwMyGcOxSmLDMnGPgqsUg7m8pe215qMLrDXw4= -github.com/AzureAD/microsoft-authentication-library-for-go v0.9.0 h1:UE9n9rkJF62ArLb1F3DEjRt8O3jLwMWdSoypKV4f3MU= -github.com/AzureAD/microsoft-authentication-library-for-go v0.9.0/go.mod h1:kgDmCTgBzIEPFElEF+FK0SdjAor06dRq2Go927dnQ6o= -github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/AzureAD/microsoft-authentication-library-for-go v1.0.0 h1:OBhqkivkhkMqLPymWEppkm7vgPQY2XsHoEkaMQ0AdZY= +github.com/AzureAD/microsoft-authentication-library-for-go v1.0.0/go.mod h1:kgDmCTgBzIEPFElEF+FK0SdjAor06dRq2Go927dnQ6o= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= -github.com/dnaeon/go-vcr v1.1.0 h1:ReYa/UBrRyQdant9B4fNHGoCNKw6qh6P0fsdGmZpR7c= -github.com/dnaeon/go-vcr v1.1.0/go.mod h1:M7tiix8f0r6mKKJ3Yq/kqU1OYf3MnfmBWVbPx/yU9ko= -github.com/golang-jwt/jwt v3.2.1+incompatible h1:73Z+4BJcrTC+KczS6WvTPvRGOp1WmfEP4Q1lOd9Z/+c= -github.com/golang-jwt/jwt v3.2.1+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I= -github.com/golang-jwt/jwt/v4 v4.2.0 h1:besgBTC8w8HjP6NzQdxwKH9Z5oQMZ24ThTrHp3cZ8eU= +github.com/dnaeon/go-vcr v1.2.0 h1:zHCHvJYTMh1N7xnV7zf1m1GPBF9Ad0Jk/whtQ1663qI= github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg= github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= -github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY= -github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= -github.com/modocache/gover v0.0.0-20171022184752-b58185e213c5/go.mod h1:caMODM3PzxT8aQXRPkAt8xlV/e7d7w8GM5g0fa5F0D8= -github.com/montanaflynn/stats v0.6.6/go.mod h1:etXPPgVO6n31NxCd9KQUMvCM+ve0ruNzt6R8Bnaayow= -github.com/pkg/browser v0.0.0-20210115035449-ce105d075bb4 h1:Qj1ukM4GlMWXNdMBuXcXfz/Kw9s1qm0CLY32QxuSImI= -github.com/pkg/browser v0.0.0-20210115035449-ce105d075bb4/go.mod h1:N6UoU20jOqggOuDwUaBQpluzLNDqif3kq9z2wpdYEfQ= github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 h1:KoWmjvw+nsYOo29YJK9vDA65RGE3NrOnUtO7a+RF9HU= github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8/go.mod h1:HKlIX3XHQyzLZPlr7++PzdhaXEj94dEiJgZDTsxEqUI= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= -github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= -github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897 h1:pLI5jrR7OSLijeIDcmRxNmw2api+jEfxLoykJVice/E= -golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20220511200225-c6db032c6c88/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.6.0 h1:qfktjS5LUO+fFKeJXZ+ikTRijMmljikvG68fpMMruSc= -golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58= -golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20201010224723-4f7140c49acb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f h1:OfiFi4JbukWwe3lzw+xunroH1mnC1e2Gy5cxNJApiSY= -golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.8.0 h1:Zrh2ngAOFYneWTAIAPethzeaQLuHwhuBkuV6ZiRnUaQ= -golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= -golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= +golang.org/x/crypto v0.9.0 h1:LF6fAI+IutBocDJ2OT0Q1g8plpYljMZ4+lty+dsqw3g= +golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0= +golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M= +golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/sys v0.0.0-20210616045830-e2b7044e8c71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211019181941-9d821ace8654 h1:id054HUawV2/6IGm2IV8KZQjqtwAOo2CYlOToYqa0d0= -golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.6.0 h1:MVltZSvRTcU2ljQOhs94SXPftV6DCNnZViHeQps87pQ= -golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= -golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.8.0 h1:57P1ETyNKtuIjB4SRd15iJxuhj8Gc416Y78H3qgMh68= -golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= -golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU= +golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE= +golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= -gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= diff --git a/sdk/security/keyvault/azkeys/version.go b/sdk/security/keyvault/azkeys/version.go index e43ed94345f2..d38632ecc25a 100644 --- a/sdk/security/keyvault/azkeys/version.go +++ b/sdk/security/keyvault/azkeys/version.go @@ -8,5 +8,5 @@ package azkeys const ( moduleName = "azkeys" - version = "v0.11.1" + version = "v1.0.0" ) diff --git a/sdk/security/keyvault/azsecrets/CHANGELOG.md b/sdk/security/keyvault/azsecrets/CHANGELOG.md index 3219c8bfe2fe..6336429cfa50 100644 --- a/sdk/security/keyvault/azsecrets/CHANGELOG.md +++ b/sdk/security/keyvault/azsecrets/CHANGELOG.md @@ -1,14 +1,9 @@ # Release History -## 0.13.1 (Unreleased) - -### Features Added - -### Breaking Changes - -### Bugs Fixed +## 1.0.0 (2023-05-11) ### Other Changes +* Updated dependencies ## 0.13.0 (2023-04-13) diff --git a/sdk/security/keyvault/azsecrets/go.mod b/sdk/security/keyvault/azsecrets/go.mod index 48c9dc66a6f3..6d224d94bb44 100644 --- a/sdk/security/keyvault/azsecrets/go.mod +++ b/sdk/security/keyvault/azsecrets/go.mod @@ -3,26 +3,26 @@ module github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azsecrets go 1.18 require ( - github.com/Azure/azure-sdk-for-go/sdk/azcore v1.4.0 - github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.1.0 - github.com/Azure/azure-sdk-for-go/sdk/internal v1.2.0 + github.com/Azure/azure-sdk-for-go/sdk/azcore v1.6.0 + github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.3.0 + github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0 github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/internal v0.8.0 github.com/stretchr/testify v1.8.2 ) require ( - github.com/AzureAD/microsoft-authentication-library-for-go v0.5.1 // indirect + github.com/AzureAD/microsoft-authentication-library-for-go v1.0.0 // indirect github.com/davecgh/go-spew v1.1.1 // indirect - github.com/dnaeon/go-vcr v1.1.0 // indirect - github.com/golang-jwt/jwt v3.2.1+incompatible // indirect - github.com/google/uuid v1.1.1 // indirect + github.com/dnaeon/go-vcr v1.2.0 // indirect + github.com/golang-jwt/jwt/v4 v4.5.0 // indirect + github.com/google/uuid v1.3.0 // indirect github.com/kylelemons/godebug v1.1.0 // indirect - github.com/pkg/browser v0.0.0-20210115035449-ce105d075bb4 // indirect + github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - golang.org/x/crypto v0.0.0-20220511200225-c6db032c6c88 // indirect - golang.org/x/net v0.8.0 // indirect - golang.org/x/sys v0.6.0 // indirect - golang.org/x/text v0.8.0 // indirect + golang.org/x/crypto v0.9.0 // indirect + golang.org/x/net v0.10.0 // indirect + golang.org/x/sys v0.8.0 // indirect + golang.org/x/text v0.9.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/sdk/security/keyvault/azsecrets/go.sum b/sdk/security/keyvault/azsecrets/go.sum index f4c11a230c77..51e117ba2909 100644 --- a/sdk/security/keyvault/azsecrets/go.sum +++ b/sdk/security/keyvault/azsecrets/go.sum @@ -1,29 +1,27 @@ -github.com/Azure/azure-sdk-for-go/sdk/azcore v1.4.0 h1:rTnT/Jrcm+figWlYz4Ixzt0SJVR2cMC8lvZcimipiEY= -github.com/Azure/azure-sdk-for-go/sdk/azcore v1.4.0/go.mod h1:ON4tFdPTwRcgWEaVDrN3584Ef+b7GgSJaXxe5fW9t4M= -github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.1.0 h1:QkAcEIAKbNL4KoFr4SathZPhDhF4mVwpBMFlYjyAqy8= -github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.1.0/go.mod h1:bhXu1AjYL+wutSL/kpSq6s7733q2Rb0yuot9Zgfqa/0= -github.com/Azure/azure-sdk-for-go/sdk/internal v1.2.0 h1:leh5DwKv6Ihwi+h60uHtn6UWAxBbZ0q8DwQVMzf61zw= -github.com/Azure/azure-sdk-for-go/sdk/internal v1.2.0/go.mod h1:eWRD7oawr1Mu1sLCawqVc0CUiF43ia3qQMxLscsKQ9w= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.6.0 h1:8kDqDngH+DmVBiCtIjCFTGa7MBnsIOkF9IccInFEbjk= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.6.0/go.mod h1:bjGvMhVMb+EEm3VRNQawDMUyMMjo+S5ewNjflkep/0Q= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.3.0 h1:vcYCAze6p19qBW7MhZybIsqD8sMV8js0NyQM8JDnVtg= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.3.0/go.mod h1:OQeznEEkTZ9OrhHJoDD8ZDq51FHgXjqtP9z6bEwBq9U= +github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0 h1:sXr+ck84g/ZlZUOZiNELInmMgOsuGwdjjVkEIde0OtY= +github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0/go.mod h1:okt5dMMTOFjX/aovMlrjvvXoPMBVSPzk9185BT0+eZM= github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/internal v0.8.0 h1:T028gtTPiYt/RMUfs8nVsAL7FDQrfLlrm/NnRG/zcC4= github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/internal v0.8.0/go.mod h1:cw4zVQgBby0Z5f2v0itn6se2dDP17nTjbZFXW5uPyHA= -github.com/AzureAD/microsoft-authentication-library-for-go v0.5.1 h1:BWe8a+f/t+7KY7zH2mqygeUD0t8hNFXe08p1Pb3/jKE= -github.com/AzureAD/microsoft-authentication-library-for-go v0.5.1/go.mod h1:Vt9sXTKwMyGcOxSmLDMnGPgqsUg7m8pe215qMLrDXw4= +github.com/AzureAD/microsoft-authentication-library-for-go v1.0.0 h1:OBhqkivkhkMqLPymWEppkm7vgPQY2XsHoEkaMQ0AdZY= +github.com/AzureAD/microsoft-authentication-library-for-go v1.0.0/go.mod h1:kgDmCTgBzIEPFElEF+FK0SdjAor06dRq2Go927dnQ6o= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/dnaeon/go-vcr v1.1.0 h1:ReYa/UBrRyQdant9B4fNHGoCNKw6qh6P0fsdGmZpR7c= -github.com/dnaeon/go-vcr v1.1.0/go.mod h1:M7tiix8f0r6mKKJ3Yq/kqU1OYf3MnfmBWVbPx/yU9ko= -github.com/golang-jwt/jwt v3.2.1+incompatible h1:73Z+4BJcrTC+KczS6WvTPvRGOp1WmfEP4Q1lOd9Z/+c= -github.com/golang-jwt/jwt v3.2.1+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I= -github.com/golang-jwt/jwt/v4 v4.2.0 h1:besgBTC8w8HjP6NzQdxwKH9Z5oQMZ24ThTrHp3cZ8eU= -github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY= -github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/dnaeon/go-vcr v1.2.0 h1:zHCHvJYTMh1N7xnV7zf1m1GPBF9Ad0Jk/whtQ1663qI= +github.com/dnaeon/go-vcr v1.2.0/go.mod h1:R4UdLID7HZT3taECzJs4YgbbH6PIGXB6W/sc5OLb6RQ= +github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg= +github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= +github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= +github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= github.com/modocache/gover v0.0.0-20171022184752-b58185e213c5/go.mod h1:caMODM3PzxT8aQXRPkAt8xlV/e7d7w8GM5g0fa5F0D8= -github.com/montanaflynn/stats v0.6.6/go.mod h1:etXPPgVO6n31NxCd9KQUMvCM+ve0ruNzt6R8Bnaayow= -github.com/pkg/browser v0.0.0-20210115035449-ce105d075bb4 h1:Qj1ukM4GlMWXNdMBuXcXfz/Kw9s1qm0CLY32QxuSImI= -github.com/pkg/browser v0.0.0-20210115035449-ce105d075bb4/go.mod h1:N6UoU20jOqggOuDwUaBQpluzLNDqif3kq9z2wpdYEfQ= +github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 h1:KoWmjvw+nsYOo29YJK9vDA65RGE3NrOnUtO7a+RF9HU= +github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8/go.mod h1:HKlIX3XHQyzLZPlr7++PzdhaXEj94dEiJgZDTsxEqUI= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= @@ -33,18 +31,18 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -golang.org/x/crypto v0.0.0-20220511200225-c6db032c6c88 h1:Tgea0cVUD0ivh5ADBX4WwuI12DUd2to3nCYe2eayMIw= -golang.org/x/crypto v0.0.0-20220511200225-c6db032c6c88/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/net v0.8.0 h1:Zrh2ngAOFYneWTAIAPethzeaQLuHwhuBkuV6ZiRnUaQ= -golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= -golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.6.0 h1:MVltZSvRTcU2ljQOhs94SXPftV6DCNnZViHeQps87pQ= -golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/text v0.8.0 h1:57P1ETyNKtuIjB4SRd15iJxuhj8Gc416Y78H3qgMh68= -golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/crypto v0.9.0 h1:LF6fAI+IutBocDJ2OT0Q1g8plpYljMZ4+lty+dsqw3g= +golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0= +golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M= +golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= +golang.org/x/sys v0.0.0-20210616045830-e2b7044e8c71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU= +golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE= +golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/sdk/security/keyvault/azsecrets/testdata/perf/go.mod b/sdk/security/keyvault/azsecrets/testdata/perf/go.mod index ae9a57f86f2f..90e8e662fed8 100644 --- a/sdk/security/keyvault/azsecrets/testdata/perf/go.mod +++ b/sdk/security/keyvault/azsecrets/testdata/perf/go.mod @@ -5,22 +5,21 @@ go 1.18 replace github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azsecrets => ../.. require ( - github.com/Azure/azure-sdk-for-go/sdk/azcore v1.4.0 - github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.2.2 - github.com/Azure/azure-sdk-for-go/sdk/internal v1.2.0 - github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azsecrets v0.7.0 + github.com/Azure/azure-sdk-for-go/sdk/azcore v1.6.0 + github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.3.0 + github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0 + github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azsecrets v0.13.0 ) require ( github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/internal v0.8.0 // indirect - github.com/AzureAD/microsoft-authentication-library-for-go v0.9.0 // indirect - github.com/golang-jwt/jwt v3.2.1+incompatible // indirect + github.com/AzureAD/microsoft-authentication-library-for-go v1.0.0 // indirect github.com/golang-jwt/jwt/v4 v4.5.0 // indirect github.com/google/uuid v1.3.0 // indirect github.com/kylelemons/godebug v1.1.0 // indirect github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 // indirect - golang.org/x/crypto v0.6.0 // indirect - golang.org/x/net v0.8.0 // indirect - golang.org/x/sys v0.6.0 // indirect - golang.org/x/text v0.8.0 // indirect + golang.org/x/crypto v0.9.0 // indirect + golang.org/x/net v0.10.0 // indirect + golang.org/x/sys v0.8.0 // indirect + golang.org/x/text v0.9.0 // indirect ) diff --git a/sdk/security/keyvault/azsecrets/testdata/perf/go.sum b/sdk/security/keyvault/azsecrets/testdata/perf/go.sum index 8f4b16fb9eaf..9e3409f5ceb6 100644 --- a/sdk/security/keyvault/azsecrets/testdata/perf/go.sum +++ b/sdk/security/keyvault/azsecrets/testdata/perf/go.sum @@ -1,48 +1,33 @@ -github.com/Azure/azure-sdk-for-go/sdk/azcore v1.4.0 h1:rTnT/Jrcm+figWlYz4Ixzt0SJVR2cMC8lvZcimipiEY= -github.com/Azure/azure-sdk-for-go/sdk/azcore v1.4.0/go.mod h1:ON4tFdPTwRcgWEaVDrN3584Ef+b7GgSJaXxe5fW9t4M= -github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.1.0 h1:QkAcEIAKbNL4KoFr4SathZPhDhF4mVwpBMFlYjyAqy8= -github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.1.0/go.mod h1:bhXu1AjYL+wutSL/kpSq6s7733q2Rb0yuot9Zgfqa/0= -github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.2.2 h1:uqM+VoHjVH6zdlkLF2b6O0ZANcHoj3rO0PoQ3jglUJA= -github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.2.2/go.mod h1:twTKAa1E6hLmSDjLhaCkbTMQKc7p/rNLU40rLxGEOCI= -github.com/Azure/azure-sdk-for-go/sdk/internal v1.2.0 h1:leh5DwKv6Ihwi+h60uHtn6UWAxBbZ0q8DwQVMzf61zw= -github.com/Azure/azure-sdk-for-go/sdk/internal v1.2.0/go.mod h1:eWRD7oawr1Mu1sLCawqVc0CUiF43ia3qQMxLscsKQ9w= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.6.0 h1:8kDqDngH+DmVBiCtIjCFTGa7MBnsIOkF9IccInFEbjk= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.6.0/go.mod h1:bjGvMhVMb+EEm3VRNQawDMUyMMjo+S5ewNjflkep/0Q= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.3.0 h1:vcYCAze6p19qBW7MhZybIsqD8sMV8js0NyQM8JDnVtg= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.3.0/go.mod h1:OQeznEEkTZ9OrhHJoDD8ZDq51FHgXjqtP9z6bEwBq9U= +github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0 h1:sXr+ck84g/ZlZUOZiNELInmMgOsuGwdjjVkEIde0OtY= +github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0/go.mod h1:okt5dMMTOFjX/aovMlrjvvXoPMBVSPzk9185BT0+eZM= github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/internal v0.8.0 h1:T028gtTPiYt/RMUfs8nVsAL7FDQrfLlrm/NnRG/zcC4= github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/internal v0.8.0/go.mod h1:cw4zVQgBby0Z5f2v0itn6se2dDP17nTjbZFXW5uPyHA= -github.com/AzureAD/microsoft-authentication-library-for-go v0.5.1 h1:BWe8a+f/t+7KY7zH2mqygeUD0t8hNFXe08p1Pb3/jKE= -github.com/AzureAD/microsoft-authentication-library-for-go v0.5.1/go.mod h1:Vt9sXTKwMyGcOxSmLDMnGPgqsUg7m8pe215qMLrDXw4= -github.com/AzureAD/microsoft-authentication-library-for-go v0.9.0 h1:UE9n9rkJF62ArLb1F3DEjRt8O3jLwMWdSoypKV4f3MU= -github.com/AzureAD/microsoft-authentication-library-for-go v0.9.0/go.mod h1:kgDmCTgBzIEPFElEF+FK0SdjAor06dRq2Go927dnQ6o= +github.com/AzureAD/microsoft-authentication-library-for-go v1.0.0 h1:OBhqkivkhkMqLPymWEppkm7vgPQY2XsHoEkaMQ0AdZY= +github.com/AzureAD/microsoft-authentication-library-for-go v1.0.0/go.mod h1:kgDmCTgBzIEPFElEF+FK0SdjAor06dRq2Go927dnQ6o= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= -github.com/dnaeon/go-vcr v1.1.0 h1:ReYa/UBrRyQdant9B4fNHGoCNKw6qh6P0fsdGmZpR7c= -github.com/golang-jwt/jwt v3.2.1+incompatible h1:73Z+4BJcrTC+KczS6WvTPvRGOp1WmfEP4Q1lOd9Z/+c= -github.com/golang-jwt/jwt v3.2.1+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I= -github.com/golang-jwt/jwt/v4 v4.2.0 h1:besgBTC8w8HjP6NzQdxwKH9Z5oQMZ24ThTrHp3cZ8eU= +github.com/dnaeon/go-vcr v1.2.0 h1:zHCHvJYTMh1N7xnV7zf1m1GPBF9Ad0Jk/whtQ1663qI= github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg= github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= -github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY= -github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= -github.com/montanaflynn/stats v0.6.6/go.mod h1:etXPPgVO6n31NxCd9KQUMvCM+ve0ruNzt6R8Bnaayow= -github.com/pkg/browser v0.0.0-20210115035449-ce105d075bb4 h1:Qj1ukM4GlMWXNdMBuXcXfz/Kw9s1qm0CLY32QxuSImI= -github.com/pkg/browser v0.0.0-20210115035449-ce105d075bb4/go.mod h1:N6UoU20jOqggOuDwUaBQpluzLNDqif3kq9z2wpdYEfQ= github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 h1:KoWmjvw+nsYOo29YJK9vDA65RGE3NrOnUtO7a+RF9HU= github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8/go.mod h1:HKlIX3XHQyzLZPlr7++PzdhaXEj94dEiJgZDTsxEqUI= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= -golang.org/x/crypto v0.0.0-20220511200225-c6db032c6c88 h1:Tgea0cVUD0ivh5ADBX4WwuI12DUd2to3nCYe2eayMIw= -golang.org/x/crypto v0.0.0-20220511200225-c6db032c6c88/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.6.0 h1:qfktjS5LUO+fFKeJXZ+ikTRijMmljikvG68fpMMruSc= -golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58= -golang.org/x/net v0.8.0 h1:Zrh2ngAOFYneWTAIAPethzeaQLuHwhuBkuV6ZiRnUaQ= -golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= -golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/crypto v0.9.0 h1:LF6fAI+IutBocDJ2OT0Q1g8plpYljMZ4+lty+dsqw3g= +golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0= +golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M= +golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/sys v0.0.0-20210616045830-e2b7044e8c71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.6.0 h1:MVltZSvRTcU2ljQOhs94SXPftV6DCNnZViHeQps87pQ= -golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/text v0.8.0 h1:57P1ETyNKtuIjB4SRd15iJxuhj8Gc416Y78H3qgMh68= -golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU= +golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE= +golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= diff --git a/sdk/security/keyvault/azsecrets/version.go b/sdk/security/keyvault/azsecrets/version.go index 1a195cdc8507..936e7274d409 100644 --- a/sdk/security/keyvault/azsecrets/version.go +++ b/sdk/security/keyvault/azsecrets/version.go @@ -8,5 +8,5 @@ package azsecrets const ( moduleName = "azsecrets" - version = "v0.13.1" + version = "v1.0.0" ) diff --git a/sdk/storage/azblob/CHANGELOG.md b/sdk/storage/azblob/CHANGELOG.md index 26b05273b1c5..786f837b0870 100644 --- a/sdk/storage/azblob/CHANGELOG.md +++ b/sdk/storage/azblob/CHANGELOG.md @@ -1,6 +1,6 @@ # Release History -## 1.0.1 (Unreleased) +## 1.1.0-beta.1 (2023-05-09) ### Features Added @@ -11,15 +11,11 @@ * Added support for CopySourceAuthorization to appendblob.AppendBlockFromURL * Added support for tag permission in Container SAS. -### Breaking Changes - ### Bugs Fixed * Fixed time formatting for the conditional request headers. Fixes [#20475](https://github.com/Azure/azure-sdk-for-go/issues/20475). * Fixed an issue where passing a blob tags map of length 0 would result in the x-ms-tags header to be sent to the service with an empty string as value. -### Other Changes - ## 1.0.0 (2023-02-07) ### Features Added diff --git a/sdk/storage/azblob/blockblob/mmf_windows.go b/sdk/storage/azblob/blockblob/mmf_windows.go index 2acef3a72f17..3f966d65b887 100644 --- a/sdk/storage/azblob/blockblob/mmf_windows.go +++ b/sdk/storage/azblob/blockblob/mmf_windows.go @@ -26,7 +26,9 @@ func newMMB(size int64) (mmb, error) { if err != nil { return nil, os.NewSyscallError("CreateFileMapping", err) } - defer syscall.CloseHandle(hMMF) + defer func() { + _ = syscall.CloseHandle(hMMF) + }() addr, err := syscall.MapViewOfFile(hMMF, access, 0, 0, uintptr(size)) if err != nil { diff --git a/sdk/storage/azblob/internal/exported/version.go b/sdk/storage/azblob/internal/exported/version.go index 19c92b607d90..7954108e6d27 100644 --- a/sdk/storage/azblob/internal/exported/version.go +++ b/sdk/storage/azblob/internal/exported/version.go @@ -8,5 +8,5 @@ package exported const ( ModuleName = "azblob" - ModuleVersion = "v1.0.1" + ModuleVersion = "v1.1.0-beta.1" ) diff --git a/sdk/storage/azblob/service/client_test.go b/sdk/storage/azblob/service/client_test.go index 7fb06d12d6c8..7d9c77090956 100644 --- a/sdk/storage/azblob/service/client_test.go +++ b/sdk/storage/azblob/service/client_test.go @@ -985,13 +985,11 @@ func (s *ServiceUnrecordedTestsSuite) TestServiceSASUploadDownload() { }.SignWithSharedKey(credential) _require.Nil(err) - sasURL := svcClient.URL() - if len(sasURL) > 0 && sasURL[len(sasURL)-1:] != "/" { - sasURL += "/" - } - sasURL += "?" + sasQueryParams.Encode() + srcBlobParts, _ := blob.ParseURL(svcClient.URL()) + srcBlobParts.SAS = sasQueryParams + srcBlobURLWithSAS := srcBlobParts.String() - azClient, err := azblob.NewClientWithNoCredential(sasURL, nil) + azClient, err := azblob.NewClientWithNoCredential(srcBlobURLWithSAS, nil) _require.Nil(err) const blobData = "test data" diff --git a/sdk/storage/azfile/CHANGELOG.md b/sdk/storage/azfile/CHANGELOG.md new file mode 100644 index 000000000000..0ae008e2971f --- /dev/null +++ b/sdk/storage/azfile/CHANGELOG.md @@ -0,0 +1,17 @@ +# Release History + +## 0.1.1 (Unreleased) + +### Features Added + +### Breaking Changes + +### Bugs Fixed + +### Other Changes + +## 0.1.0 (2023-05-09) + +### Features Added + +* This is the initial preview release of the `azfile` library diff --git a/sdk/messaging/azeventhubs/internal/go-amqp/LICENSE b/sdk/storage/azfile/LICENSE.txt similarity index 91% rename from sdk/messaging/azeventhubs/internal/go-amqp/LICENSE rename to sdk/storage/azfile/LICENSE.txt index 387b3e7e0f3b..d1ca00f20a89 100644 --- a/sdk/messaging/azeventhubs/internal/go-amqp/LICENSE +++ b/sdk/storage/azfile/LICENSE.txt @@ -1,7 +1,6 @@ MIT License - Copyright (C) 2017 Kale Blankenship - Portions Copyright (C) Microsoft Corporation + Copyright (c) Microsoft Corporation. All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -19,4 +18,4 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE + SOFTWARE \ No newline at end of file diff --git a/sdk/storage/azfile/README.md b/sdk/storage/azfile/README.md new file mode 100644 index 000000000000..2b6ba2b9a02e --- /dev/null +++ b/sdk/storage/azfile/README.md @@ -0,0 +1,266 @@ +# Azure File Storage SDK for Go + +> Service Version: 2020-10-02 + +Azure File Shares offers fully managed file shares in the cloud that are accessible via the industry standard +[Server Message Block (SMB) protocol](https://docs.microsoft.com/windows/desktop/FileIO/microsoft-smb-protocol-and-cifs-protocol-overview). +Azure file shares can be mounted concurrently by cloud or on-premises deployments of Windows, Linux, and macOS. +Additionally, Azure file shares can be cached on Windows Servers with Azure File Sync for fast access near where the data is being used. + +[Source code][source] | [API reference documentation][docs] | [REST API documentation][rest_docs] | [Product documentation][product_docs] + +## Getting started + +### Install the package + +Install the Azure File Storage SDK for Go with [go get][goget]: + +```Powershell +go get github.com/Azure/azure-sdk-for-go/sdk/storage/azfile +``` + +### Prerequisites + +A supported [Go][godevdl] version (the Azure SDK supports the two most recent Go releases). + +You need an [Azure subscription][azure_sub] and a +[Storage Account][storage_account_docs] to use this package. + +To create a new Storage Account, you can use the [Azure Portal][storage_account_create_portal], +[Azure PowerShell][storage_account_create_ps], or the [Azure CLI][storage_account_create_cli]. +Here's an example using the Azure CLI: + +```Powershell +az storage account create --name MyStorageAccount --resource-group MyResourceGroup --location westus --sku Standard_LRS +``` + +### Authenticate the client + +The Azure File Storage SDK for Go allows you to interact with four types of resources: the storage +account itself, file shares, directories, and files. Interaction with these resources starts with an instance of a +client. To create a client object, you will need the storage account's file service URL and a +credential that allows you to access the storage account: + +```go +// create a credential for authenticating using shared key +cred, err := service.NewSharedKeyCredential("", "") +// TODO: handle err + +// create service.Client for the specified storage account that uses the above credential +client, err := service.NewClientWithSharedKeyCredential("https://.file.core.windows.net/", cred, nil) +// TODO: handle err +``` + +## Key concepts + +Azure file shares can be used to: + +- Completely replace or supplement traditional on-premises file servers or NAS devices. +- "Lift and shift" applications to the cloud that expect a file share to store file application or user data. +- Simplify new cloud development projects with shared application settings, diagnostic shares, and Dev/Test/Debug tool file shares. + +### Goroutine safety +We guarantee that all client instance methods are goroutine-safe and independent of each other ([guideline](https://azure.github.io/azure-sdk/golang_introduction.html#thread-safety)). This ensures that the recommendation of reusing client instances is always safe, even across goroutines. + +### Additional concepts + +[Client options](https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/azcore/policy#ClientOptions) | +[Accessing the response](https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime#WithCaptureResponse) | +[Handling failures](https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/azcore#ResponseError) | +[Logging](https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/azcore/log) + + +## Examples + +### Create a share and upload a file + +```go +const ( +shareName = "sample-share" +dirName = "sample-dir" +fileName = "sample-file" +) + +// Get a connection string to our Azure Storage account. You can +// obtain your connection string from the Azure Portal (click +// Access Keys under Settings in the Portal Storage account blade) +// or using the Azure CLI with: +// +// az storage account show-connection-string --name --resource-group +// +// And you can provide the connection string to your application +// using an environment variable. +connectionString := "" + +// Path to the local file to upload +localFilePath := "" + +// Get reference to a share and create it +shareClient, err := share.NewClientFromConnectionString(connectionString, shareName, nil) +// TODO: handle error +_, err = shareClient.Create(context.TODO(), nil) +// TODO: handle error + +// Get reference to a directory and create it +dirClient := shareClient.NewDirectoryClient(dirName) +_, err = dirClient.Create(context.TODO(), nil) +// TODO: handle error + +// open the file for reading +file, err := os.OpenFile(localFilePath, os.O_RDONLY, 0) +// TODO: handle error +defer file.Close() + +// get the size of file +fInfo, err := file.Stat() +// TODO: handle error +fSize := fInfo.Size() + +// create the file +fClient := dirClient.NewFileClient(fileName) +_, err = fClient.Create(context.TODO(), fSize, nil) +// TODO: handle error + +// upload the file +err = fClient.UploadFile(context.TODO(), file, nil) +// TODO: handle error +``` + +### Download a file + +```go +const ( +shareName = "sample-share" +dirName = "sample-dir" +fileName = "sample-file" +) + +connectionString := "" + +// Path to the save the downloaded file +localFilePath := "" + +// Get reference to the share +shareClient, err := share.NewClientFromConnectionString(connectionString, shareName, nil) +// TODO: handle error + +// Get reference to the directory +dirClient := shareClient.NewDirectoryClient(dirName) + +// Get reference to the file +fClient := dirClient.NewFileClient(fileName) + +// create or open a local file where we can download the Azure File +file, err := os.Create(localFilePath) +// TODO: handle error +defer file.Close() + +// Download the file +_, err = fClient.DownloadFile(context.TODO(), file, nil) +// TODO: handle error +``` + +### Traverse a share + +```go +const shareName = "sample-share" + +connectionString := "" + +// Get reference to the share +shareClient, err := share.NewClientFromConnectionString(connectionString, shareName, nil) +// TODO: handle error + +// Track the remaining directories to walk, starting from the root +var dirs []*directory.Client +dirs = append(dirs, shareClient.NewRootDirectoryClient()) +for len(dirs) > 0 { + dirClient := dirs[0] + dirs = dirs[1:] + + // Get all the next directory's files and subdirectories + pager := dirClient.NewListFilesAndDirectoriesPager(nil) + for pager.More() { + resp, err := pager.NextPage(context.TODO()) + // TODO: handle error + + for _, d := range resp.Segment.Directories { + fmt.Println(*d.Name) + // Keep walking down directories + dirs = append(dirs, dirClient.NewSubdirectoryClient(*d.Name)) + } + + for _, f := range resp.Segment.Files { + fmt.Println(*f.Name) + } + } +} +``` + +## Troubleshooting + +All File service operations will return an +[*azcore.ResponseError][azcore_response_error] on failure with a +populated `ErrorCode` field. Many of these errors are recoverable. +The [fileerror][file_error] package provides the possible Storage error codes +along with various helper facilities for error handling. + +```go +const ( + connectionString = "" + shareName = "sample-share" +) + +// create a client with the provided connection string +client, err := service.NewClientFromConnectionString(connectionString, nil) +// TODO: handle error + +// try to delete the share, avoiding any potential race conditions with an in-progress or completed deletion +_, err = client.DeleteShare(context.TODO(), shareName, nil) + +if fileerror.HasCode(err, fileerror.ShareBeingDeleted, fileerror.ShareNotFound) { + // ignore any errors if the share is being deleted or already has been deleted +} else if err != nil { + // TODO: some other error +} +``` + +## Next steps + +Get started with our [File samples][samples]. They contain complete examples of the above snippets and more. + +## Contributing + +See the [Storage CONTRIBUTING.md][storage_contrib] for details on building, +testing, and contributing to this library. + +This project welcomes contributions and suggestions. Most contributions require +you to agree to a Contributor License Agreement (CLA) declaring that you have +the right to, and actually do, grant us the rights to use your contribution. For +details, visit [cla.microsoft.com][cla]. + +This project has adopted the [Microsoft Open Source Code of Conduct][coc]. +For more information see the [Code of Conduct FAQ][coc_faq] +or contact [opencode@microsoft.com][coc_contact] with any +additional questions or comments. + + +[source]: https://github.com/Azure/azure-sdk-for-go/tree/main/sdk/storage/azfile +[docs]: https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/storage/azfile +[rest_docs]: https://docs.microsoft.com/rest/api/storageservices/file-service-rest-api +[product_docs]: https://docs.microsoft.com/azure/storage/files/storage-files-introduction +[godevdl]: https://go.dev/dl/ +[goget]: https://pkg.go.dev/cmd/go#hdr-Add_dependencies_to_current_module_and_install_them +[storage_account_docs]: https://docs.microsoft.com/azure/storage/common/storage-account-overview +[storage_account_create_ps]: https://docs.microsoft.com/azure/storage/common/storage-quickstart-create-account?tabs=azure-powershell +[storage_account_create_cli]: https://docs.microsoft.com/azure/storage/common/storage-quickstart-create-account?tabs=azure-cli +[storage_account_create_portal]: https://docs.microsoft.com/azure/storage/common/storage-quickstart-create-account?tabs=azure-portal +[azure_sub]: https://azure.microsoft.com/free/ +[azcore_response_error]: https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/azcore#ResponseError +[file_error]: https://github.com/Azure/azure-sdk-for-go/tree/main/sdk/storage/azfile/fileerror/error_codes.go +[samples]: https://github.com/Azure/azure-sdk-for-go/blob/main/sdk/storage/azfile/file/examples_test.go +[storage_contrib]: https://github.com/Azure/azure-sdk-for-go/blob/main/CONTRIBUTING.md +[cla]: https://cla.microsoft.com +[coc]: https://opensource.microsoft.com/codeofconduct/ +[coc_faq]: https://opensource.microsoft.com/codeofconduct/faq/ +[coc_contact]: mailto:opencode@microsoft.com diff --git a/sdk/storage/azfile/assets.json b/sdk/storage/azfile/assets.json new file mode 100644 index 000000000000..47d08f9c3faa --- /dev/null +++ b/sdk/storage/azfile/assets.json @@ -0,0 +1,6 @@ +{ + "AssetsRepo": "Azure/azure-sdk-assets", + "AssetsRepoPrefixPath": "go", + "TagPrefix": "go/storage/azfile", + "Tag": "go/storage/azfile_f1e8c5b99b" +} diff --git a/sdk/storage/azfile/ci.yml b/sdk/storage/azfile/ci.yml new file mode 100644 index 000000000000..4978a37820df --- /dev/null +++ b/sdk/storage/azfile/ci.yml @@ -0,0 +1,33 @@ +trigger: + branches: + include: + - main + - feature/* + - hotfix/* + - release/* + paths: + include: + - sdk/storage/azfile + +pr: + branches: + include: + - main + - feature/* + - hotfix/* + - release/* + paths: + include: + - sdk/storage/azfile + + +stages: + - template: /eng/pipelines/templates/jobs/archetype-sdk-client.yml + parameters: + ServiceDirectory: 'storage/azfile' + RunLiveTests: true + EnvVars: + AZURE_CLIENT_ID: $(AZFILE_CLIENT_ID) + AZURE_TENANT_ID: $(AZFILE_TENANT_ID) + AZURE_CLIENT_SECRET: $(AZFILE_CLIENT_SECRET) + AZURE_SUBSCRIPTION_ID: $(AZFILE_SUBSCRIPTION_ID) diff --git a/sdk/storage/azfile/directory/client.go b/sdk/storage/azfile/directory/client.go new file mode 100644 index 000000000000..6ea9713d0f20 --- /dev/null +++ b/sdk/storage/azfile/directory/client.go @@ -0,0 +1,205 @@ +//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 + +import ( + "context" + "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/azfile/file" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azfile/internal/base" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azfile/internal/exported" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azfile/internal/generated" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azfile/internal/shared" + "net/http" + "net/url" + "strings" +) + +// ClientOptions contains the optional parameters when creating a Client. +type ClientOptions base.ClientOptions + +// Client represents a URL to the Azure Storage directory allowing you to manipulate its directories and files. +type Client base.Client[generated.DirectoryClient] + +// NewClientWithNoCredential creates an instance of Client with the specified values. +// This is used to anonymously access a directory or with a shared access signature (SAS) token. +// - directoryURL - the URL of the directory e.g. https://.file.core.windows.net/share/directory? +// - options - client options; pass nil to accept the default values +func NewClientWithNoCredential(directoryURL string, options *ClientOptions) (*Client, error) { + conOptions := shared.GetClientOptions(options) + pl := runtime.NewPipeline(exported.ModuleName, exported.ModuleVersion, runtime.PipelineOptions{}, &conOptions.ClientOptions) + + return (*Client)(base.NewDirectoryClient(directoryURL, pl, nil)), nil +} + +// NewClientWithSharedKeyCredential creates an instance of Client with the specified values. +// - directoryURL - the URL of the directory e.g. https://.file.core.windows.net/share/directory +// - cred - a SharedKeyCredential created with the matching directory's storage account and access key +// - options - client options; pass nil to accept the default values +func NewClientWithSharedKeyCredential(directoryURL string, cred *SharedKeyCredential, options *ClientOptions) (*Client, error) { + authPolicy := exported.NewSharedKeyCredPolicy(cred) + conOptions := shared.GetClientOptions(options) + conOptions.PerRetryPolicies = append(conOptions.PerRetryPolicies, authPolicy) + pl := runtime.NewPipeline(exported.ModuleName, exported.ModuleVersion, runtime.PipelineOptions{}, &conOptions.ClientOptions) + + return (*Client)(base.NewDirectoryClient(directoryURL, pl, cred)), nil +} + +// NewClientFromConnectionString creates an instance of Client with the specified values. +// - connectionString - a connection string for the desired storage account +// - shareName - the name of the share within the storage account +// - directoryPath - the path of the directory within the share +// - options - client options; pass nil to accept the default values +func NewClientFromConnectionString(connectionString string, shareName string, directoryPath string, options *ClientOptions) (*Client, error) { + parsed, err := shared.ParseConnectionString(connectionString) + if err != nil { + return nil, err + } + + directoryPath = strings.ReplaceAll(directoryPath, "\\", "/") + parsed.ServiceURL = runtime.JoinPaths(parsed.ServiceURL, shareName, directoryPath) + + if parsed.AccountKey != "" && parsed.AccountName != "" { + credential, err := exported.NewSharedKeyCredential(parsed.AccountName, parsed.AccountKey) + if err != nil { + return nil, err + } + return NewClientWithSharedKeyCredential(parsed.ServiceURL, credential, options) + } + + return NewClientWithNoCredential(parsed.ServiceURL, options) +} + +func (d *Client) generated() *generated.DirectoryClient { + return base.InnerClient((*base.Client[generated.DirectoryClient])(d)) +} + +func (d *Client) sharedKey() *SharedKeyCredential { + return base.SharedKey((*base.Client[generated.DirectoryClient])(d)) +} + +// URL returns the URL endpoint used by the Client object. +func (d *Client) URL() string { + return d.generated().Endpoint() +} + +// NewSubdirectoryClient creates a new Client object by concatenating subDirectoryName to the end of this Client's URL. +// The new subdirectory Client uses the same request policy pipeline as the parent directory Client. +func (d *Client) NewSubdirectoryClient(subDirectoryName string) *Client { + subDirectoryName = url.PathEscape(subDirectoryName) + subDirectoryURL := runtime.JoinPaths(d.URL(), subDirectoryName) + return (*Client)(base.NewDirectoryClient(subDirectoryURL, d.generated().Pipeline(), d.sharedKey())) +} + +// NewFileClient creates a new file.Client object by concatenating fileName to the end of this Client's URL. +// The new file.Client uses the same request policy pipeline as the Client. +func (d *Client) NewFileClient(fileName string) *file.Client { + fileName = url.PathEscape(fileName) + fileURL := runtime.JoinPaths(d.URL(), fileName) + return (*file.Client)(base.NewFileClient(fileURL, d.generated().Pipeline(), d.sharedKey())) +} + +// Create operation creates a new directory under the specified share or parent directory. +// For more information, see https://learn.microsoft.com/en-us/rest/api/storageservices/create-directory. +func (d *Client) Create(ctx context.Context, options *CreateOptions) (CreateResponse, error) { + fileAttributes, fileCreationTime, fileLastWriteTime, opts := options.format() + resp, err := d.generated().Create(ctx, fileAttributes, fileCreationTime, fileLastWriteTime, opts) + return resp, err +} + +// Delete operation removes the specified empty directory. Note that the directory must be empty before it can be deleted. +// Deleting directories that aren't empty returns error 409 (Directory Not Empty). +// For more information, see https://learn.microsoft.com/en-us/rest/api/storageservices/delete-directory. +func (d *Client) Delete(ctx context.Context, options *DeleteOptions) (DeleteResponse, error) { + opts := options.format() + resp, err := d.generated().Delete(ctx, opts) + return resp, err +} + +// GetProperties operation returns all system properties for the specified directory, and it can also be used to check the existence of a directory. +// For more information, see https://learn.microsoft.com/en-us/rest/api/storageservices/get-directory-properties. +func (d *Client) GetProperties(ctx context.Context, options *GetPropertiesOptions) (GetPropertiesResponse, error) { + opts := options.format() + resp, err := d.generated().GetProperties(ctx, opts) + return resp, err +} + +// SetProperties operation sets system properties for the specified directory. +// For more information, see https://learn.microsoft.com/en-us/rest/api/storageservices/set-directory-properties. +func (d *Client) SetProperties(ctx context.Context, options *SetPropertiesOptions) (SetPropertiesResponse, error) { + fileAttributes, fileCreationTime, fileLastWriteTime, opts := options.format() + resp, err := d.generated().SetProperties(ctx, fileAttributes, fileCreationTime, fileLastWriteTime, opts) + return resp, err +} + +// SetMetadata operation sets user-defined metadata for the specified directory. +// For more information, see https://learn.microsoft.com/en-us/rest/api/storageservices/set-directory-metadata. +func (d *Client) SetMetadata(ctx context.Context, options *SetMetadataOptions) (SetMetadataResponse, error) { + opts := options.format() + resp, err := d.generated().SetMetadata(ctx, opts) + return resp, err +} + +// ForceCloseHandles operation closes a handle or handles opened on a directory. +// - handleID - Specifies the handle ID to be closed. Use an asterisk (*) as a wildcard string to specify all handles. +// +// For more information, see https://learn.microsoft.com/en-us/rest/api/storageservices/force-close-handles. +func (d *Client) ForceCloseHandles(ctx context.Context, handleID string, options *ForceCloseHandlesOptions) (ForceCloseHandlesResponse, error) { + opts := options.format() + resp, err := d.generated().ForceCloseHandles(ctx, handleID, opts) + return resp, err +} + +// ListHandles operation returns a list of open handles on a directory. +// For more information, see https://learn.microsoft.com/en-us/rest/api/storageservices/list-handles. +func (d *Client) ListHandles(ctx context.Context, options *ListHandlesOptions) (ListHandlesResponse, error) { + opts := options.format() + resp, err := d.generated().ListHandles(ctx, opts) + return resp, err +} + +// NewListFilesAndDirectoriesPager operation returns a pager for the files and directories starting from the specified Marker. +// For more information, see https://learn.microsoft.com/en-us/rest/api/storageservices/list-directories-and-files. +func (d *Client) NewListFilesAndDirectoriesPager(options *ListFilesAndDirectoriesOptions) *runtime.Pager[ListFilesAndDirectoriesResponse] { + listOptions := generated.DirectoryClientListFilesAndDirectoriesSegmentOptions{} + if options != nil { + listOptions.Include = options.Include.format() + listOptions.IncludeExtendedInfo = options.IncludeExtendedInfo + listOptions.Marker = options.Marker + listOptions.Maxresults = options.MaxResults + listOptions.Prefix = options.Prefix + listOptions.Sharesnapshot = options.ShareSnapshot + } + + return runtime.NewPager(runtime.PagingHandler[ListFilesAndDirectoriesResponse]{ + More: func(page ListFilesAndDirectoriesResponse) bool { + return page.NextMarker != nil && len(*page.NextMarker) > 0 + }, + Fetcher: func(ctx context.Context, page *ListFilesAndDirectoriesResponse) (ListFilesAndDirectoriesResponse, error) { + var req *policy.Request + var err error + if page == nil { + req, err = d.generated().ListFilesAndDirectoriesSegmentCreateRequest(ctx, &listOptions) + } else { + listOptions.Marker = page.NextMarker + req, err = d.generated().ListFilesAndDirectoriesSegmentCreateRequest(ctx, &listOptions) + } + if err != nil { + return ListFilesAndDirectoriesResponse{}, err + } + resp, err := d.generated().Pipeline().Do(req) + if err != nil { + return ListFilesAndDirectoriesResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusOK) { + return ListFilesAndDirectoriesResponse{}, runtime.NewResponseError(resp) + } + return d.generated().ListFilesAndDirectoriesSegmentHandleResponse(resp) + }, + }) +} diff --git a/sdk/storage/azfile/directory/client_test.go b/sdk/storage/azfile/directory/client_test.go new file mode 100644 index 000000000000..4e91138e9aad --- /dev/null +++ b/sdk/storage/azfile/directory/client_test.go @@ -0,0 +1,1117 @@ +//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" + "fmt" + "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/azfile/directory" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azfile/file" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azfile/fileerror" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azfile/internal/testcommon" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azfile/share" + "github.com/stretchr/testify/require" + "github.com/stretchr/testify/suite" + "testing" + "time" +) + +func Test(t *testing.T) { + recordMode := recording.GetRecordMode() + t.Logf("Running directory Tests in %s mode\n", recordMode) + if recordMode == recording.LiveMode { + suite.Run(t, &DirectoryRecordedTestsSuite{}) + suite.Run(t, &DirectoryUnrecordedTestsSuite{}) + } else if recordMode == recording.PlaybackMode { + suite.Run(t, &DirectoryRecordedTestsSuite{}) + } else if recordMode == recording.RecordingMode { + suite.Run(t, &DirectoryRecordedTestsSuite{}) + } +} + +func (d *DirectoryRecordedTestsSuite) BeforeTest(suite string, test string) { + testcommon.BeforeTest(d.T(), suite, test) +} + +func (d *DirectoryRecordedTestsSuite) AfterTest(suite string, test string) { + testcommon.AfterTest(d.T(), suite, test) +} + +func (d *DirectoryUnrecordedTestsSuite) BeforeTest(suite string, test string) { + +} + +func (d *DirectoryUnrecordedTestsSuite) AfterTest(suite string, test string) { + +} + +type DirectoryRecordedTestsSuite struct { + suite.Suite +} + +type DirectoryUnrecordedTestsSuite struct { + suite.Suite +} + +func (d *DirectoryRecordedTestsSuite) TestDirNewDirectoryClient() { + _require := require.New(d.T()) + testName := d.T().Name() + + accountName, _ := testcommon.GetGenericAccountInfo(testcommon.TestAccountDefault) + _require.Greater(len(accountName), 0) + + svcClient, err := testcommon.GetServiceClient(d.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + shareName := testcommon.GenerateShareName(testName) + shareClient := svcClient.NewShareClient(shareName) + + dirName := testcommon.GenerateDirectoryName(testName) + dirClient := shareClient.NewDirectoryClient(dirName) + + subDirName := "inner" + dirName + subDirClient := dirClient.NewSubdirectoryClient(subDirName) + + correctURL := "https://" + accountName + ".file.core.windows.net/" + shareName + "/" + dirName + "/" + subDirName + _require.Equal(subDirClient.URL(), correctURL) +} + +func (d *DirectoryRecordedTestsSuite) TestDirCreateFileURL() { + _require := require.New(d.T()) + testName := d.T().Name() + + accountName, _ := testcommon.GetGenericAccountInfo(testcommon.TestAccountDefault) + _require.Greater(len(accountName), 0) + + svcClient, err := testcommon.GetServiceClient(d.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + shareName := testcommon.GenerateShareName(testName) + shareClient := svcClient.NewShareClient(shareName) + + dirName := testcommon.GenerateDirectoryName(testName) + dirClient := shareClient.NewDirectoryClient(dirName) + + fileName := testcommon.GenerateFileName(testName) + fileClient := dirClient.NewFileClient(fileName) + + correctURL := "https://" + accountName + ".file.core.windows.net/" + shareName + "/" + dirName + "/" + fileName + _require.Equal(fileClient.URL(), correctURL) +} + +func (d *DirectoryRecordedTestsSuite) TestDirectoryCreateUsingSharedKey() { + _require := require.New(d.T()) + testName := d.T().Name() + + cred, err := testcommon.GetGenericSharedKeyCredential(testcommon.TestAccountDefault) + _require.NoError(err) + + svcClient, err := testcommon.GetServiceClient(d.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + shareName := testcommon.GenerateShareName(testName) + shareClient := testcommon.CreateNewShare(context.Background(), _require, shareName, svcClient) + defer testcommon.DeleteShare(context.Background(), _require, shareClient) + + dirName := testcommon.GenerateDirectoryName(testName) + dirURL := "https://" + cred.AccountName() + ".file.core.windows.net/" + shareName + "/" + dirName + + options := &directory.ClientOptions{} + testcommon.SetClientOptions(d.T(), &options.ClientOptions) + dirClient, err := directory.NewClientWithSharedKeyCredential(dirURL, cred, options) + _require.NoError(err) + + resp, err := dirClient.Create(context.Background(), nil) + _require.NoError(err) + _require.NotNil(resp.ETag) + _require.NotNil(resp.RequestID) + _require.Equal(resp.LastModified.IsZero(), false) + _require.Equal(resp.FileCreationTime.IsZero(), false) + _require.Equal(resp.FileLastWriteTime.IsZero(), false) + _require.Equal(resp.FileChangeTime.IsZero(), false) +} + +func (d *DirectoryRecordedTestsSuite) TestDirectoryCreateUsingConnectionString() { + _require := require.New(d.T()) + testName := d.T().Name() + + connString, err := testcommon.GetGenericConnectionString(testcommon.TestAccountDefault) + _require.NoError(err) + + svcClient, err := testcommon.GetServiceClient(d.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + shareName := testcommon.GenerateShareName(testName) + shareClient := testcommon.CreateNewShare(context.Background(), _require, shareName, svcClient) + defer testcommon.DeleteShare(context.Background(), _require, shareClient) + + dirName := testcommon.GenerateDirectoryName(testName) + options := &directory.ClientOptions{} + testcommon.SetClientOptions(d.T(), &options.ClientOptions) + dirClient, err := directory.NewClientFromConnectionString(*connString, shareName, dirName, options) + _require.NoError(err) + + resp, err := dirClient.Create(context.Background(), nil) + _require.NoError(err) + _require.NotNil(resp.ETag) + _require.NotNil(resp.RequestID) + _require.Equal(resp.LastModified.IsZero(), false) + _require.Equal(resp.FileCreationTime.IsZero(), false) + _require.Equal(resp.FileLastWriteTime.IsZero(), false) + _require.Equal(resp.FileChangeTime.IsZero(), false) + + innerDirName1 := "innerdir1" + dirPath := dirName + "/" + innerDirName1 + dirClient1, err := directory.NewClientFromConnectionString(*connString, shareName, dirPath, options) + _require.NoError(err) + + resp, err = dirClient1.Create(context.Background(), nil) + _require.NoError(err) + _require.NotNil(resp.RequestID) + _require.Equal(resp.LastModified.IsZero(), false) + _require.Equal(resp.FileCreationTime.IsZero(), false) + + innerDirName2 := "innerdir2" + // using '\' as path separator between directories + dirPath = dirName + "\\" + innerDirName1 + "\\" + innerDirName2 + dirClient2, err := directory.NewClientFromConnectionString(*connString, shareName, dirPath, options) + _require.NoError(err) + + resp, err = dirClient2.Create(context.Background(), nil) + _require.NoError(err) + _require.NotNil(resp.RequestID) + _require.Equal(resp.LastModified.IsZero(), false) + _require.Equal(resp.FileCreationTime.IsZero(), false) +} + +func (d *DirectoryRecordedTestsSuite) TestDirectoryCreateNegativeMultiLevel() { + _require := require.New(d.T()) + testName := d.T().Name() + + connString, err := testcommon.GetGenericConnectionString(testcommon.TestAccountDefault) + _require.NoError(err) + + svcClient, err := testcommon.GetServiceClient(d.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + shareName := testcommon.GenerateShareName(testName) + shareClient := testcommon.CreateNewShare(context.Background(), _require, shareName, svcClient) + defer testcommon.DeleteShare(context.Background(), _require, shareClient) + + dirName := testcommon.GenerateDirectoryName(testName) + // dirPath where parent dir does not exist + dirPath := "a/b/c/d/" + dirName + options := &directory.ClientOptions{} + testcommon.SetClientOptions(d.T(), &options.ClientOptions) + dirClient, err := directory.NewClientFromConnectionString(*connString, shareName, dirPath, options) + _require.NoError(err) + + resp, err := dirClient.Create(context.Background(), nil) + _require.Error(err) + _require.Nil(resp.RequestID) + testcommon.ValidateFileErrorCode(_require, err, fileerror.ParentNotFound) +} + +func (d *DirectoryRecordedTestsSuite) TestDirCreateDeleteDefault() { + _require := require.New(d.T()) + testName := d.T().Name() + svcClient, err := testcommon.GetServiceClient(d.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + shareName := testcommon.GenerateShareName(testName) + shareClient := testcommon.CreateNewShare(context.Background(), _require, shareName, svcClient) + defer testcommon.DeleteShare(context.Background(), _require, shareClient) + + dirName := testcommon.GenerateDirectoryName(testName) + dirClient := shareClient.NewDirectoryClient(dirName) + _require.NoError(err) + + cResp, err := dirClient.Create(context.Background(), nil) + _require.NoError(err) + _require.NotNil(cResp.RequestID) + _require.NotNil(cResp.ETag) + _require.Equal(cResp.Date.IsZero(), false) + _require.Equal(cResp.LastModified.IsZero(), false) + _require.Equal(cResp.FileCreationTime.IsZero(), false) + _require.Equal(cResp.FileLastWriteTime.IsZero(), false) + _require.Equal(cResp.FileChangeTime.IsZero(), false) + + gResp, err := dirClient.GetProperties(context.Background(), nil) + _require.NoError(err) + _require.NotNil(gResp.RequestID) + _require.NotNil(gResp.ETag) + _require.Equal(gResp.Date.IsZero(), false) + _require.Equal(gResp.LastModified.IsZero(), false) + _require.Equal(gResp.FileCreationTime.IsZero(), false) + _require.Equal(gResp.FileLastWriteTime.IsZero(), false) + _require.Equal(gResp.FileChangeTime.IsZero(), false) +} + +func (d *DirectoryRecordedTestsSuite) TestDirSetPropertiesDefault() { + _require := require.New(d.T()) + testName := d.T().Name() + svcClient, err := testcommon.GetServiceClient(d.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + shareName := testcommon.GenerateShareName(testName) + shareClient := testcommon.CreateNewShare(context.Background(), _require, shareName, svcClient) + defer testcommon.DeleteShare(context.Background(), _require, shareClient) + + dirName := testcommon.GenerateDirectoryName(testName) + dirClient := testcommon.GetDirectoryClient(dirName, shareClient) + + cResp, err := dirClient.Create(context.Background(), nil) + _require.NoError(err) + _require.NotNil(cResp.FilePermissionKey) + + // Set the custom permissions + sResp, err := dirClient.SetProperties(context.Background(), nil) + _require.NoError(err) + _require.NotNil(sResp.FileCreationTime) + _require.NotNil(sResp.FileLastWriteTime) + _require.NotNil(sResp.FilePermissionKey) + _require.Equal(*sResp.FilePermissionKey, *cResp.FilePermissionKey) + + gResp, err := dirClient.GetProperties(context.Background(), nil) + _require.NoError(err) + _require.NotNil(gResp.FileCreationTime) + _require.NotNil(gResp.FileLastWriteTime) + _require.NotNil(gResp.FilePermissionKey) + _require.Equal(*gResp.FilePermissionKey, *sResp.FilePermissionKey) + _require.Equal(*gResp.FileCreationTime, *sResp.FileCreationTime) + _require.Equal(*gResp.FileLastWriteTime, *sResp.FileLastWriteTime) + _require.Equal(*gResp.FileAttributes, *sResp.FileAttributes) +} + +func (d *DirectoryRecordedTestsSuite) TestDirSetPropertiesNonDefault() { + _require := require.New(d.T()) + testName := d.T().Name() + svcClient, err := testcommon.GetServiceClient(d.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + shareName := testcommon.GenerateShareName(testName) + shareClient := testcommon.CreateNewShare(context.Background(), _require, shareName, svcClient) + defer testcommon.DeleteShare(context.Background(), _require, shareClient) + + dirName := testcommon.GenerateDirectoryName(testName) + dirClient := testcommon.GetDirectoryClient(dirName, shareClient) + + cResp, err := dirClient.Create(context.Background(), nil) + _require.NoError(err) + _require.NotNil(cResp.FilePermissionKey) + + currTime, err := time.Parse(time.UnixDate, "Fri Mar 31 21:00:00 GMT 2023") + _require.NoError(err) + creationTime := currTime.Add(5 * time.Minute).Round(time.Microsecond) + lastWriteTime := currTime.Add(10 * time.Minute).Round(time.Millisecond) + + // Set the custom permissions + sResp, err := dirClient.SetProperties(context.Background(), &directory.SetPropertiesOptions{ + FileSMBProperties: &file.SMBProperties{ + Attributes: &file.NTFSFileAttributes{ + ReadOnly: true, + System: true, + }, + CreationTime: &creationTime, + LastWriteTime: &lastWriteTime, + }, + FilePermissions: &file.Permissions{ + Permission: &testcommon.SampleSDDL, + }, + }) + _require.NoError(err) + _require.NotNil(sResp.FileCreationTime) + _require.NotNil(sResp.FileLastWriteTime) + _require.NotNil(sResp.FilePermissionKey) + _require.NotEqual(*sResp.FilePermissionKey, *cResp.FilePermissionKey) + _require.Equal(*sResp.FileCreationTime, creationTime.UTC()) + _require.Equal(*sResp.FileLastWriteTime, lastWriteTime.UTC()) + + gResp, err := dirClient.GetProperties(context.Background(), nil) + _require.NoError(err) + _require.NotNil(gResp.FileCreationTime) + _require.NotNil(gResp.FileLastWriteTime) + _require.NotNil(gResp.FilePermissionKey) + _require.Equal(*gResp.FilePermissionKey, *sResp.FilePermissionKey) + _require.Equal(*gResp.FileCreationTime, *sResp.FileCreationTime) + _require.Equal(*gResp.FileLastWriteTime, *sResp.FileLastWriteTime) + _require.Equal(*gResp.FileAttributes, *sResp.FileAttributes) +} + +func (d *DirectoryUnrecordedTestsSuite) TestDirCreateDeleteNonDefault() { + _require := require.New(d.T()) + testName := d.T().Name() + svcClient, err := testcommon.GetServiceClient(d.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + shareName := testcommon.GenerateShareName(testName) + shareClient := testcommon.CreateNewShare(context.Background(), _require, shareName, svcClient) + defer testcommon.DeleteShare(context.Background(), _require, shareClient) + + dirName := testcommon.GenerateDirectoryName(testName) + dirClient := testcommon.GetDirectoryClient(dirName, shareClient) + + md := map[string]*string{ + "Foo": to.Ptr("FooValuE"), + "Bar": to.Ptr("bArvaLue"), + } + + cResp, err := dirClient.Create(context.Background(), &directory.CreateOptions{ + Metadata: md, + FileSMBProperties: &file.SMBProperties{ + Attributes: &file.NTFSFileAttributes{None: true}, + CreationTime: to.Ptr(time.Now().Add(5 * time.Minute)), + LastWriteTime: to.Ptr(time.Now().Add(10 * time.Minute)), + }, + FilePermissions: &file.Permissions{ + Permission: &testcommon.SampleSDDL, + }, + }) + _require.NoError(err) + _require.NotNil(cResp.FilePermissionKey) + _require.Equal(cResp.Date.IsZero(), false) + _require.NotNil(cResp.ETag) + _require.Equal(cResp.LastModified.IsZero(), false) + _require.NotNil(cResp.RequestID) + + gResp, err := dirClient.GetProperties(context.Background(), nil) + _require.NoError(err) + _require.Equal(*gResp.FilePermissionKey, *cResp.FilePermissionKey) + _require.EqualValues(gResp.Metadata, md) + + // Creating again will result in 409 and ResourceAlreadyExists. + _, err = dirClient.Create(context.Background(), &directory.CreateOptions{Metadata: md}) + _require.Error(err) + testcommon.ValidateFileErrorCode(_require, err, fileerror.ResourceAlreadyExists) + + dResp, err := dirClient.Delete(context.Background(), nil) + _require.NoError(err) + _require.Equal(dResp.Date.IsZero(), false) + _require.NotNil(dResp.RequestID) + _require.NotNil(dResp.Version) + + _, err = dirClient.GetProperties(context.Background(), nil) + _require.Error(err) + testcommon.ValidateFileErrorCode(_require, err, fileerror.ResourceNotFound) +} + +func (d *DirectoryRecordedTestsSuite) TestDirCreateNegativePermissions() { + _require := require.New(d.T()) + testName := d.T().Name() + svcClient, err := testcommon.GetServiceClient(d.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + shareName := testcommon.GenerateShareName(testName) + shareClient := testcommon.CreateNewShare(context.Background(), _require, shareName, svcClient) + defer testcommon.DeleteShare(context.Background(), _require, shareClient) + + dirName := testcommon.GenerateDirectoryName(testName) + dirClient := testcommon.GetDirectoryClient(dirName, shareClient) + subDirClient := dirClient.NewSubdirectoryClient("subdir" + dirName) + + cResp, err := dirClient.Create(context.Background(), nil) + _require.NoError(err) + _require.NotNil(cResp.FilePermissionKey) + + // having both Permission and PermissionKey set returns error + _, err = subDirClient.Create(context.Background(), &directory.CreateOptions{ + FileSMBProperties: &file.SMBProperties{ + Attributes: &file.NTFSFileAttributes{None: true}, + }, + FilePermissions: &file.Permissions{ + Permission: &testcommon.SampleSDDL, + PermissionKey: cResp.FilePermissionKey, + }, + }) + _require.Error(err) +} + +func (d *DirectoryRecordedTestsSuite) TestDirCreateNegativeAttributes() { + _require := require.New(d.T()) + testName := d.T().Name() + svcClient, err := testcommon.GetServiceClient(d.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + shareName := testcommon.GenerateShareName(testName) + shareClient := testcommon.CreateNewShare(context.Background(), _require, shareName, svcClient) + defer testcommon.DeleteShare(context.Background(), _require, shareClient) + + dirClient := testcommon.GetDirectoryClient(testcommon.GenerateDirectoryName(testName), shareClient) + + // None attribute must be used alone. + _, err = dirClient.Create(context.Background(), &directory.CreateOptions{ + FileSMBProperties: &file.SMBProperties{ + Attributes: &file.NTFSFileAttributes{None: true, ReadOnly: true}, + }, + }) + _require.Error(err) + testcommon.ValidateFileErrorCode(_require, err, fileerror.InvalidHeaderValue) +} + +func (d *DirectoryRecordedTestsSuite) TestDirCreateDeleteNegativeMultiLevelDir() { + _require := require.New(d.T()) + testName := d.T().Name() + svcClient, err := testcommon.GetServiceClient(d.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + shareName := testcommon.GenerateShareName(testName) + shareClient := testcommon.CreateNewShare(context.Background(), _require, shareName, svcClient) + defer testcommon.DeleteShare(context.Background(), _require, shareClient) + + parentDirName := "parent" + testcommon.GenerateDirectoryName(testName) + parentDirClient := shareClient.NewDirectoryClient(parentDirName) + + subDirName := "subdir" + testcommon.GenerateDirectoryName(testName) + subDirClient := parentDirClient.NewSubdirectoryClient(subDirName) + + // Directory create with subDirClient + _, err = subDirClient.Create(context.Background(), nil) + _require.Error(err) + testcommon.ValidateFileErrorCode(_require, err, fileerror.ParentNotFound) + + _, err = parentDirClient.Create(context.Background(), nil) + _require.NoError(err) + + _, err = subDirClient.Create(context.Background(), nil) + _require.NoError(err) + + _, err = subDirClient.GetProperties(context.Background(), nil) + _require.NoError(err) + + // Delete level by level + // Delete Non-empty directory should fail + _, err = parentDirClient.Delete(context.Background(), nil) + _require.Error(err) + testcommon.ValidateFileErrorCode(_require, err, fileerror.DirectoryNotEmpty) + + _, err = subDirClient.Delete(context.Background(), nil) + _require.NoError(err) + + _, err = parentDirClient.Delete(context.Background(), nil) + _require.NoError(err) +} + +func (d *DirectoryRecordedTestsSuite) TestDirCreateEndWithSlash() { + _require := require.New(d.T()) + testName := d.T().Name() + svcClient, err := testcommon.GetServiceClient(d.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + shareName := testcommon.GenerateShareName(testName) + shareClient := testcommon.CreateNewShare(context.Background(), _require, shareName, svcClient) + defer testcommon.DeleteShare(context.Background(), _require, shareClient) + + dirName := testcommon.GenerateDirectoryName(testName) + "/" + dirClient := testcommon.GetDirectoryClient(dirName, shareClient) + + cResp, err := dirClient.Create(context.Background(), nil) + _require.NoError(err) + _require.Equal(cResp.Date.IsZero(), false) + _require.NotNil(cResp.ETag) + _require.Equal(cResp.LastModified.IsZero(), false) + _require.NotNil(cResp.RequestID) + _require.NotNil(cResp.Version) + + _, err = dirClient.GetProperties(context.Background(), nil) + _require.NoError(err) +} + +func (d *DirectoryRecordedTestsSuite) TestDirGetSetMetadataDefault() { + _require := require.New(d.T()) + testName := d.T().Name() + svcClient, err := testcommon.GetServiceClient(d.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + shareName := testcommon.GenerateShareName(testName) + shareClient := testcommon.CreateNewShare(context.Background(), _require, shareName, svcClient) + defer testcommon.DeleteShare(context.Background(), _require, shareClient) + + dirName := testcommon.GenerateDirectoryName(testName) + dirClient := testcommon.CreateNewDirectory(context.Background(), _require, dirName, shareClient) + defer testcommon.DeleteDirectory(context.Background(), _require, dirClient) + + sResp, err := dirClient.SetMetadata(context.Background(), nil) + _require.NoError(err) + _require.Equal(sResp.Date.IsZero(), false) + _require.NotNil(sResp.ETag) + _require.NotNil(sResp.RequestID) + _require.NotNil(sResp.Version) + _require.NotNil(sResp.IsServerEncrypted) + + gResp, err := dirClient.GetProperties(context.Background(), nil) + _require.NoError(err) + _require.Equal(gResp.Date.IsZero(), false) + _require.NotNil(gResp.ETag) + _require.Equal(gResp.LastModified.IsZero(), false) + _require.NotNil(gResp.RequestID) + _require.NotNil(gResp.Version) + _require.NotNil(gResp.IsServerEncrypted) + _require.Len(gResp.Metadata, 0) +} + +func (d *DirectoryRecordedTestsSuite) TestDirGetSetMetadataNonDefault() { + _require := require.New(d.T()) + testName := d.T().Name() + svcClient, err := testcommon.GetServiceClient(d.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + shareName := testcommon.GenerateShareName(testName) + shareClient := testcommon.CreateNewShare(context.Background(), _require, shareName, svcClient) + defer testcommon.DeleteShare(context.Background(), _require, shareClient) + + dirName := testcommon.GenerateDirectoryName(testName) + dirClient := testcommon.CreateNewDirectory(context.Background(), _require, dirName, shareClient) + defer testcommon.DeleteDirectory(context.Background(), _require, dirClient) + + md := map[string]*string{ + "Foo": to.Ptr("FooValuE"), + "Bar": to.Ptr("bArvaLue"), + } + + sResp, err := dirClient.SetMetadata(context.Background(), &directory.SetMetadataOptions{ + Metadata: md, + }) + _require.NoError(err) + _require.Equal(sResp.Date.IsZero(), false) + _require.NotNil(sResp.ETag) + _require.NotNil(sResp.RequestID) + _require.NotNil(sResp.Version) + _require.NotNil(sResp.IsServerEncrypted) + + gResp, err := dirClient.GetProperties(context.Background(), nil) + _require.NoError(err) + _require.Equal(gResp.Date.IsZero(), false) + _require.NotNil(gResp.ETag) + _require.Equal(gResp.LastModified.IsZero(), false) + _require.NotNil(gResp.RequestID) + _require.NotNil(gResp.Version) + _require.NotNil(gResp.IsServerEncrypted) + _require.EqualValues(gResp.Metadata, md) +} + +func (d *DirectoryRecordedTestsSuite) TestDirSetMetadataNegative() { + _require := require.New(d.T()) + testName := d.T().Name() + svcClient, err := testcommon.GetServiceClient(d.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + shareName := testcommon.GenerateShareName(testName) + shareClient := testcommon.CreateNewShare(context.Background(), _require, shareName, svcClient) + defer testcommon.DeleteShare(context.Background(), _require, shareClient) + + dirName := testcommon.GenerateDirectoryName(testName) + dirClient := testcommon.CreateNewDirectory(context.Background(), _require, dirName, shareClient) + defer testcommon.DeleteDirectory(context.Background(), _require, dirClient) + + md := map[string]*string{ + "!@#$%^&*()": to.Ptr("!@#$%^&*()"), + } + + _, err = dirClient.SetMetadata(context.Background(), &directory.SetMetadataOptions{ + Metadata: md, + }) + _require.Error(err) +} + +func (d *DirectoryRecordedTestsSuite) TestDirGetPropertiesNegative() { + _require := require.New(d.T()) + testName := d.T().Name() + svcClient, err := testcommon.GetServiceClient(d.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + shareName := testcommon.GenerateShareName(testName) + shareClient := testcommon.CreateNewShare(context.Background(), _require, shareName, svcClient) + defer testcommon.DeleteShare(context.Background(), _require, shareClient) + + dirName := testcommon.GenerateDirectoryName(testName) + dirClient := testcommon.GetDirectoryClient(dirName, shareClient) + + _, err = dirClient.GetProperties(context.Background(), nil) + _require.Error(err) + testcommon.ValidateFileErrorCode(_require, err, fileerror.ResourceNotFound) +} + +func (d *DirectoryRecordedTestsSuite) TestDirGetPropertiesWithBaseDirectory() { + _require := require.New(d.T()) + testName := d.T().Name() + svcClient, err := testcommon.GetServiceClient(d.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + shareName := testcommon.GenerateShareName(testName) + shareClient := testcommon.CreateNewShare(context.Background(), _require, shareName, svcClient) + defer testcommon.DeleteShare(context.Background(), _require, shareClient) + + dirClient := shareClient.NewRootDirectoryClient() + + gResp, err := dirClient.GetProperties(context.Background(), nil) + _require.NoError(err) + _require.NotNil(gResp.ETag) + _require.Equal(gResp.LastModified.IsZero(), false) + _require.NotNil(gResp.RequestID) + _require.NotNil(gResp.Version) + _require.Equal(gResp.Date.IsZero(), false) + _require.Equal(gResp.FileCreationTime.IsZero(), false) + _require.Equal(gResp.FileLastWriteTime.IsZero(), false) + _require.Equal(gResp.FileChangeTime.IsZero(), false) + _require.NotNil(gResp.IsServerEncrypted) +} + +func (d *DirectoryRecordedTestsSuite) TestDirGetSetMetadataMergeAndReplace() { + _require := require.New(d.T()) + testName := d.T().Name() + svcClient, err := testcommon.GetServiceClient(d.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + shareName := testcommon.GenerateShareName(testName) + shareClient := testcommon.CreateNewShare(context.Background(), _require, shareName, svcClient) + defer testcommon.DeleteShare(context.Background(), _require, shareClient) + + dirName := testcommon.GenerateDirectoryName(testName) + dirClient := testcommon.CreateNewDirectory(context.Background(), _require, dirName, shareClient) + defer testcommon.DeleteDirectory(context.Background(), _require, dirClient) + + md := map[string]*string{ + "Color": to.Ptr("RED"), + } + + sResp, err := dirClient.SetMetadata(context.Background(), &directory.SetMetadataOptions{ + Metadata: md, + }) + _require.NoError(err) + _require.NotNil(sResp.RequestID) + _require.NotNil(sResp.IsServerEncrypted) + + gResp, err := dirClient.GetProperties(context.Background(), nil) + _require.NoError(err) + _require.Equal(gResp.Date.IsZero(), false) + _require.NotNil(gResp.ETag) + _require.Equal(gResp.LastModified.IsZero(), false) + _require.NotNil(gResp.RequestID) + _require.NotNil(gResp.Version) + _require.NotNil(gResp.IsServerEncrypted) + _require.EqualValues(gResp.Metadata, md) + + md2 := map[string]*string{ + "Color": to.Ptr("WHITE"), + } + + sResp, err = dirClient.SetMetadata(context.Background(), &directory.SetMetadataOptions{ + Metadata: md2, + }) + _require.NoError(err) + _require.NotNil(sResp.RequestID) + _require.NotNil(sResp.IsServerEncrypted) + + gResp, err = dirClient.GetProperties(context.Background(), nil) + _require.NoError(err) + _require.Equal(gResp.Date.IsZero(), false) + _require.NotNil(gResp.ETag) + _require.Equal(gResp.LastModified.IsZero(), false) + _require.NotNil(gResp.RequestID) + _require.NotNil(gResp.Version) + _require.NotNil(gResp.IsServerEncrypted) + _require.EqualValues(gResp.Metadata, md2) +} + +func (d *DirectoryRecordedTestsSuite) TestDirListFilesAndDirsDefault() { + _require := require.New(d.T()) + testName := d.T().Name() + + svcClient, err := testcommon.GetServiceClient(d.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + shareClient := testcommon.CreateNewShare(context.Background(), _require, testcommon.GenerateShareName(testName), svcClient) + defer testcommon.DeleteShare(context.Background(), _require, shareClient) + + dirName := testcommon.GenerateDirectoryName(testName) + fileName := testcommon.GenerateFileName(testName) + + for i := 0; i < 10; i++ { + _ = testcommon.CreateNewDirectory(context.Background(), _require, dirName+fmt.Sprintf("%v", i), shareClient) + } + + for i := 0; i < 5; i++ { + _ = testcommon.CreateNewFileFromShare(context.Background(), _require, fileName+fmt.Sprintf("%v", i), 2048, shareClient) + } + + dirCtr, fileCtr := 0, 0 + pager := shareClient.NewRootDirectoryClient().NewListFilesAndDirectoriesPager(nil) + for pager.More() { + resp, err := pager.NextPage(context.Background()) + _require.NoError(err) + dirCtr += len(resp.Segment.Directories) + fileCtr += len(resp.Segment.Files) + for _, dir := range resp.Segment.Directories { + _require.NotNil(dir.Name) + _require.NotNil(dir.ID) + _require.Nil(dir.Attributes) + _require.Nil(dir.PermissionKey) + _require.Nil(dir.Properties.ETag) + _require.Nil(dir.Properties.ChangeTime) + _require.Nil(dir.Properties.CreationTime) + _require.Nil(dir.Properties.ContentLength) + } + for _, f := range resp.Segment.Files { + _require.NotNil(f.Name) + _require.NotNil(f.ID) + _require.Nil(f.Attributes) + _require.Nil(f.PermissionKey) + _require.Nil(f.Properties.ETag) + _require.Nil(f.Properties.ChangeTime) + _require.Nil(f.Properties.CreationTime) + _require.NotNil(f.Properties.ContentLength) + _require.Equal(*f.Properties.ContentLength, int64(2048)) + } + } + _require.Equal(dirCtr, 10) + _require.Equal(fileCtr, 5) +} + +func (d *DirectoryRecordedTestsSuite) TestDirListFilesAndDirsInclude() { + _require := require.New(d.T()) + testName := d.T().Name() + + svcClient, err := testcommon.GetServiceClient(d.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + shareClient := testcommon.CreateNewShare(context.Background(), _require, testcommon.GenerateShareName(testName), svcClient) + defer testcommon.DeleteShare(context.Background(), _require, shareClient) + + dirName := testcommon.GenerateDirectoryName(testName) + fileName := testcommon.GenerateFileName(testName) + + for i := 0; i < 10; i++ { + _ = testcommon.CreateNewDirectory(context.Background(), _require, dirName+fmt.Sprintf("%v", i), shareClient) + } + + for i := 0; i < 5; i++ { + _ = testcommon.CreateNewFileFromShare(context.Background(), _require, fileName+fmt.Sprintf("%v", i), 2048, shareClient) + } + + dirCtr, fileCtr := 0, 0 + pager := shareClient.NewRootDirectoryClient().NewListFilesAndDirectoriesPager(&directory.ListFilesAndDirectoriesOptions{ + Include: directory.ListFilesInclude{Timestamps: true, ETag: true, Attributes: true, PermissionKey: true}, + IncludeExtendedInfo: to.Ptr(true), + }) + for pager.More() { + resp, err := pager.NextPage(context.Background()) + _require.NoError(err) + dirCtr += len(resp.Segment.Directories) + fileCtr += len(resp.Segment.Files) + for _, dir := range resp.Segment.Directories { + _require.NotNil(dir.Name) + _require.NotNil(dir.ID) + _require.NotNil(dir.Attributes) + _require.NotNil(dir.PermissionKey) + _require.NotNil(dir.Properties.ETag) + _require.NotNil(dir.Properties.ChangeTime) + _require.NotNil(dir.Properties.CreationTime) + _require.Nil(dir.Properties.ContentLength) + } + for _, f := range resp.Segment.Files { + _require.NotNil(f.Name) + _require.NotNil(f.ID) + _require.NotNil(f.Attributes) + _require.NotNil(f.PermissionKey) + _require.NotNil(f.Properties.ETag) + _require.NotNil(f.Properties.ChangeTime) + _require.NotNil(f.Properties.CreationTime) + _require.NotNil(f.Properties.ContentLength) + _require.Equal(*f.Properties.ContentLength, int64(2048)) + } + } + _require.Equal(dirCtr, 10) + _require.Equal(fileCtr, 5) +} + +func (d *DirectoryRecordedTestsSuite) TestDirListFilesAndDirsMaxResultsAndMarker() { + _require := require.New(d.T()) + testName := d.T().Name() + + svcClient, err := testcommon.GetServiceClient(d.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + shareClient := testcommon.CreateNewShare(context.Background(), _require, testcommon.GenerateShareName(testName), svcClient) + defer testcommon.DeleteShare(context.Background(), _require, shareClient) + + dirName := testcommon.GenerateDirectoryName(testName) + fileName := testcommon.GenerateFileName(testName) + + for i := 0; i < 10; i++ { + _ = testcommon.CreateNewDirectory(context.Background(), _require, dirName+fmt.Sprintf("%v", i), shareClient) + } + + for i := 0; i < 5; i++ { + _ = testcommon.CreateNewFileFromShare(context.Background(), _require, fileName+fmt.Sprintf("%v", i), 2048, shareClient) + } + + dirCtr, fileCtr := 0, 0 + pager := shareClient.NewRootDirectoryClient().NewListFilesAndDirectoriesPager(&directory.ListFilesAndDirectoriesOptions{ + MaxResults: to.Ptr(int32(2)), + }) + resp, err := pager.NextPage(context.Background()) + _require.NoError(err) + dirCtr += len(resp.Segment.Directories) + fileCtr += len(resp.Segment.Files) + _require.Equal(dirCtr+fileCtr, 2) + + pager = shareClient.NewRootDirectoryClient().NewListFilesAndDirectoriesPager(&directory.ListFilesAndDirectoriesOptions{ + Marker: resp.NextMarker, + MaxResults: to.Ptr(int32(5)), + }) + for pager.More() { + resp, err := pager.NextPage(context.Background()) + _require.NoError(err) + dirCtr += len(resp.Segment.Directories) + fileCtr += len(resp.Segment.Files) + } + _require.Equal(dirCtr, 10) + _require.Equal(fileCtr, 5) +} + +func (d *DirectoryRecordedTestsSuite) TestDirListFilesAndDirsWithPrefix() { + _require := require.New(d.T()) + testName := d.T().Name() + + svcClient, err := testcommon.GetServiceClient(d.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + shareClient := testcommon.CreateNewShare(context.Background(), _require, testcommon.GenerateShareName(testName), svcClient) + defer testcommon.DeleteShare(context.Background(), _require, shareClient) + + dirName := testcommon.GenerateDirectoryName(testName) + fileName := testcommon.GenerateFileName(testName) + + for i := 0; i < 10; i++ { + _ = testcommon.CreateNewDirectory(context.Background(), _require, fmt.Sprintf("%v", i)+dirName, shareClient) + } + + for i := 0; i < 5; i++ { + _ = testcommon.CreateNewFileFromShare(context.Background(), _require, fmt.Sprintf("%v", i)+fileName, 2048, shareClient) + } + + dirCtr, fileCtr := 0, 0 + pager := shareClient.NewRootDirectoryClient().NewListFilesAndDirectoriesPager(&directory.ListFilesAndDirectoriesOptions{ + Prefix: to.Ptr("1"), + }) + for pager.More() { + resp, err := pager.NextPage(context.Background()) + _require.NoError(err) + dirCtr += len(resp.Segment.Directories) + fileCtr += len(resp.Segment.Files) + if len(resp.Segment.Directories) > 0 { + _require.NotNil(resp.Segment.Directories[0].Name) + _require.Equal(*resp.Segment.Directories[0].Name, "1"+dirName) + } + if len(resp.Segment.Files) > 0 { + _require.NotNil(resp.Segment.Files[0].Name) + _require.Equal(*resp.Segment.Files[0].Name, "1"+fileName) + } + } + _require.Equal(dirCtr, 1) + _require.Equal(fileCtr, 1) +} + +func (d *DirectoryRecordedTestsSuite) TestDirListFilesAndDirsMaxResultsNegative() { + _require := require.New(d.T()) + testName := d.T().Name() + + svcClient, err := testcommon.GetServiceClient(d.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + shareClient := testcommon.CreateNewShare(context.Background(), _require, testcommon.GenerateShareName(testName), svcClient) + defer testcommon.DeleteShare(context.Background(), _require, shareClient) + + dirName := testcommon.GenerateDirectoryName(testName) + fileName := testcommon.GenerateFileName(testName) + + for i := 0; i < 2; i++ { + _ = testcommon.CreateNewDirectory(context.Background(), _require, dirName+fmt.Sprintf("%v", i), shareClient) + } + + for i := 0; i < 2; i++ { + _ = testcommon.CreateNewFileFromShare(context.Background(), _require, fileName+fmt.Sprintf("%v", i), 2048, shareClient) + } + + pager := shareClient.NewRootDirectoryClient().NewListFilesAndDirectoriesPager(&directory.ListFilesAndDirectoriesOptions{ + MaxResults: to.Ptr(int32(-1)), + }) + _, err = pager.NextPage(context.Background()) + _require.Error(err) + testcommon.ValidateFileErrorCode(_require, err, fileerror.OutOfRangeQueryParameterValue) +} + +func (d *DirectoryRecordedTestsSuite) TestDirListFilesAndDirsSnapshot() { + _require := require.New(d.T()) + testName := d.T().Name() + + svcClient, err := testcommon.GetServiceClient(d.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + shareClient := testcommon.CreateNewShare(context.Background(), _require, testcommon.GenerateShareName(testName), svcClient) + defer func() { + _, err := shareClient.Delete(context.Background(), &share.DeleteOptions{DeleteSnapshots: to.Ptr(share.DeleteSnapshotsOptionTypeInclude)}) + _require.NoError(err) + }() + + dirName := testcommon.GenerateDirectoryName(testName) + fileName := testcommon.GenerateFileName(testName) + + for i := 0; i < 10; i++ { + _ = testcommon.CreateNewDirectory(context.Background(), _require, dirName+fmt.Sprintf("%v", i), shareClient) + } + + for i := 0; i < 5; i++ { + _ = testcommon.CreateNewFileFromShare(context.Background(), _require, fileName+fmt.Sprintf("%v", i), 2048, shareClient) + } + + snapResp, err := shareClient.CreateSnapshot(context.Background(), nil) + _require.NoError(err) + _require.NotNil(snapResp.Snapshot) + + _, err = shareClient.NewRootDirectoryClient().GetProperties(context.Background(), &directory.GetPropertiesOptions{ShareSnapshot: snapResp.Snapshot}) + _require.NoError(err) + + dirCtr, fileCtr := 0, 0 + pager := shareClient.NewRootDirectoryClient().NewListFilesAndDirectoriesPager(&directory.ListFilesAndDirectoriesOptions{ + ShareSnapshot: snapResp.Snapshot, + }) + for pager.More() { + resp, err := pager.NextPage(context.Background()) + _require.NoError(err) + dirCtr += len(resp.Segment.Directories) + fileCtr += len(resp.Segment.Files) + } + _require.Equal(dirCtr, 10) + _require.Equal(fileCtr, 5) +} + +func (d *DirectoryRecordedTestsSuite) TestDirListFilesAndDirsInsideDir() { + _require := require.New(d.T()) + testName := d.T().Name() + + svcClient, err := testcommon.GetServiceClient(d.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + shareClient := testcommon.CreateNewShare(context.Background(), _require, testcommon.GenerateShareName(testName), svcClient) + defer testcommon.DeleteShare(context.Background(), _require, shareClient) + + dirName := testcommon.GenerateDirectoryName(testName) + fileName := testcommon.GenerateFileName(testName) + + dirClient := testcommon.CreateNewDirectory(context.Background(), _require, dirName, shareClient) + + for i := 0; i < 5; i++ { + _, err = dirClient.NewSubdirectoryClient("subdir"+fmt.Sprintf("%v", i)).Create(context.Background(), nil) + _require.NoError(err) + } + + for i := 0; i < 5; i++ { + _, err = dirClient.NewFileClient(fileName+fmt.Sprintf("%v", i)).Create(context.Background(), 0, nil) + _require.NoError(err) + } + + dirCtr, fileCtr := 0, 0 + pager := dirClient.NewListFilesAndDirectoriesPager(&directory.ListFilesAndDirectoriesOptions{ + Include: directory.ListFilesInclude{Timestamps: true, ETag: true, Attributes: true, PermissionKey: true}, + }) + for pager.More() { + resp, err := pager.NextPage(context.Background()) + _require.NoError(err) + dirCtr += len(resp.Segment.Directories) + fileCtr += len(resp.Segment.Files) + for _, dir := range resp.Segment.Directories { + _require.NotNil(dir.Name) + _require.NotNil(dir.ID) + _require.NotNil(dir.Attributes) + _require.NotNil(dir.PermissionKey) + _require.NotNil(dir.Properties.ETag) + _require.NotNil(dir.Properties.ChangeTime) + _require.NotNil(dir.Properties.CreationTime) + _require.Nil(dir.Properties.ContentLength) + } + for _, f := range resp.Segment.Files { + _require.NotNil(f.Name) + _require.NotNil(f.ID) + _require.NotNil(f.Attributes) + _require.NotNil(f.PermissionKey) + _require.NotNil(f.Properties.ETag) + _require.NotNil(f.Properties.ChangeTime) + _require.NotNil(f.Properties.CreationTime) + _require.NotNil(f.Properties.ContentLength) + _require.Equal(*f.Properties.ContentLength, int64(0)) + } + } + _require.Equal(dirCtr, 5) + _require.Equal(fileCtr, 5) +} + +func (d *DirectoryRecordedTestsSuite) TestDirListHandlesDefault() { + _require := require.New(d.T()) + testName := d.T().Name() + + svcClient, err := testcommon.GetServiceClient(d.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + shareClient := testcommon.CreateNewShare(context.Background(), _require, testcommon.GenerateShareName(testName), svcClient) + defer testcommon.DeleteShare(context.Background(), _require, shareClient) + + dirClient := testcommon.CreateNewDirectory(context.Background(), _require, testcommon.GenerateDirectoryName(testName), shareClient) + + resp, err := dirClient.ListHandles(context.Background(), nil) + _require.NoError(err) + _require.Len(resp.Handles, 0) + _require.NotNil(resp.NextMarker) + _require.Equal(*resp.NextMarker, "") +} + +func (d *DirectoryRecordedTestsSuite) TestDirForceCloseHandlesDefault() { + _require := require.New(d.T()) + testName := d.T().Name() + + svcClient, err := testcommon.GetServiceClient(d.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + shareClient := testcommon.CreateNewShare(context.Background(), _require, testcommon.GenerateShareName(testName), svcClient) + defer testcommon.DeleteShare(context.Background(), _require, shareClient) + + dirClient := testcommon.CreateNewDirectory(context.Background(), _require, testcommon.GenerateDirectoryName(testName), shareClient) + + resp, err := dirClient.ForceCloseHandles(context.Background(), "*", nil) + _require.NoError(err) + _require.EqualValues(*resp.NumberOfHandlesClosed, 0) + _require.EqualValues(*resp.NumberOfHandlesFailedToClose, 0) + _require.Nil(resp.Marker) +} + +func (d *DirectoryRecordedTestsSuite) TestDirectoryCreateNegativeWithoutSAS() { + _require := require.New(d.T()) + testName := d.T().Name() + + accountName, _ := testcommon.GetGenericAccountInfo(testcommon.TestAccountDefault) + _require.Greater(len(accountName), 0) + + svcClient, err := testcommon.GetServiceClient(d.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + shareName := testcommon.GenerateShareName(testName) + shareClient := testcommon.CreateNewShare(context.Background(), _require, shareName, svcClient) + defer testcommon.DeleteShare(context.Background(), _require, shareClient) + + dirName := testcommon.GenerateDirectoryName(testName) + dirURL := "https://" + accountName + ".file.core.windows.net/" + shareName + "/" + dirName + + options := &directory.ClientOptions{} + testcommon.SetClientOptions(d.T(), &options.ClientOptions) + dirClient, err := directory.NewClientWithNoCredential(dirURL, nil) + _require.NoError(err) + + _, err = dirClient.Create(context.Background(), nil) + _require.Error(err) +} diff --git a/sdk/storage/azfile/directory/constants.go b/sdk/storage/azfile/directory/constants.go new file mode 100644 index 000000000000..2b16931bbc56 --- /dev/null +++ b/sdk/storage/azfile/directory/constants.go @@ -0,0 +1,24 @@ +//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 + +import "github.com/Azure/azure-sdk-for-go/sdk/storage/azfile/internal/generated" + +// ListFilesIncludeType defines values for ListFilesIncludeType +type ListFilesIncludeType = generated.ListFilesIncludeType + +const ( + ListFilesIncludeTypeTimestamps ListFilesIncludeType = generated.ListFilesIncludeTypeTimestamps + ListFilesIncludeTypeETag ListFilesIncludeType = generated.ListFilesIncludeTypeEtag + ListFilesIncludeTypeAttributes ListFilesIncludeType = generated.ListFilesIncludeTypeAttributes + ListFilesIncludeTypePermissionKey ListFilesIncludeType = generated.ListFilesIncludeTypePermissionKey +) + +// PossibleListFilesIncludeTypeValues returns the possible values for the ListFilesIncludeType const type. +func PossibleListFilesIncludeTypeValues() []ListFilesIncludeType { + return generated.PossibleListFilesIncludeTypeValues() +} diff --git a/sdk/storage/azfile/directory/examples_test.go b/sdk/storage/azfile/directory/examples_test.go new file mode 100644 index 000000000000..0d355ff82191 --- /dev/null +++ b/sdk/storage/azfile/directory/examples_test.go @@ -0,0 +1,193 @@ +//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" + "fmt" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/to" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azfile/directory" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azfile/file" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azfile/internal/testcommon" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azfile/service" + "log" + "os" + "time" +) + +func handleError(err error) { + if err != nil { + log.Fatal(err.Error()) + } +} + +func Example_client_NewClient() { + accountName, ok := os.LookupEnv("AZURE_STORAGE_ACCOUNT_NAME") + if !ok { + panic("AZURE_STORAGE_ACCOUNT_NAME could not be found") + } + accountKey, ok := os.LookupEnv("AZURE_STORAGE_ACCOUNT_KEY") + if !ok { + panic("AZURE_STORAGE_ACCOUNT_KEY could not be found") + } + + serviceURL := fmt.Sprintf("https://%s.file.core.windows.net/", accountName) + + cred, err := service.NewSharedKeyCredential(accountName, accountKey) + handleError(err) + + client, err := service.NewClientWithSharedKeyCredential(serviceURL, cred, nil) + handleError(err) + + shareClient := client.NewShareClient("testShare") + + dirClient := shareClient.NewDirectoryClient("testDir") + fmt.Println(dirClient.URL()) + +} + +func Example_directory_NewClientFromConnectionString() { + // Your connection string can be obtained from the Azure Portal. + connectionString, ok := os.LookupEnv("AZURE_STORAGE_CONNECTION_STRING") + if !ok { + log.Fatal("the environment variable 'AZURE_STORAGE_CONNECTION_STRING' could not be found") + } + shareName := "testShare" + dirName := "testDirectory" + dirClient, err := directory.NewClientFromConnectionString(connectionString, shareName, dirName, nil) + handleError(err) + fmt.Println(dirClient.URL()) +} + +func Example_directoryClient_Create() { + // Your connection string can be obtained from the Azure Portal. + connectionString, ok := os.LookupEnv("AZURE_STORAGE_CONNECTION_STRING") + if !ok { + log.Fatal("the environment variable 'AZURE_STORAGE_CONNECTION_STRING' could not be found") + } + shareName := "testShare" + dirName := "testDirectory" + dirClient, err := directory.NewClientFromConnectionString(connectionString, shareName, dirName, nil) + handleError(err) + _, err = dirClient.Create(context.Background(), nil) + handleError(err) + fmt.Println("Directory created") + + _, err = dirClient.Delete(context.Background(), nil) + handleError(err) + fmt.Println("Directory deleted") +} + +func Example_directoryClient_SetProperties() { + // Your connection string can be obtained from the Azure Portal. + connectionString, ok := os.LookupEnv("AZURE_STORAGE_CONNECTION_STRING") + if !ok { + log.Fatal("the environment variable 'AZURE_STORAGE_CONNECTION_STRING' could not be found") + } + shareName := "testShare" + dirName := "testDirectory" + dirClient, err := directory.NewClientFromConnectionString(connectionString, shareName, dirName, nil) + handleError(err) + _, err = dirClient.Create(context.Background(), nil) + handleError(err) + fmt.Println("Directory created") + + creationTime := time.Now().Add(5 * time.Minute).Round(time.Microsecond) + lastWriteTime := time.Now().Add(10 * time.Minute).Round(time.Millisecond) + + // Set the custom permissions + _, err = dirClient.SetProperties(context.Background(), &directory.SetPropertiesOptions{ + FileSMBProperties: &file.SMBProperties{ + Attributes: &file.NTFSFileAttributes{ + ReadOnly: true, + System: true, + }, + CreationTime: &creationTime, + LastWriteTime: &lastWriteTime, + }, + FilePermissions: &file.Permissions{ + Permission: &testcommon.SampleSDDL, + }, + }) + handleError(err) + fmt.Println("Directory properties set") + + _, err = dirClient.GetProperties(context.Background(), nil) + handleError(err) + fmt.Println("Directory properties retrieved") + + _, err = dirClient.Delete(context.Background(), nil) + handleError(err) + fmt.Println("Directory deleted") +} + +func Example_directoryClient_ListFilesAndDirectoriesSegment() { + connectionString, ok := os.LookupEnv("AZURE_STORAGE_CONNECTION_STRING") + if !ok { + log.Fatal("the environment variable 'AZURE_STORAGE_CONNECTION_STRING' could not be found") + } + shareName := "testShare" + parentDirName := "testParentDirectory" + childDirName := "testChildDirectory" + parentDirClient, err := directory.NewClientFromConnectionString(connectionString, shareName, parentDirName, nil) + handleError(err) + _, err = parentDirClient.Create(context.Background(), nil) + handleError(err) + fmt.Println("Parent directory created") + + childDirClient := parentDirClient.NewSubdirectoryClient(childDirName) + _, err = childDirClient.Create(context.Background(), nil) + handleError(err) + fmt.Println("Child directory created") + + pager := parentDirClient.NewListFilesAndDirectoriesPager(nil) + for pager.More() { + resp, err := pager.NextPage(context.Background()) + handleError(err) // if err is not nil, break the loop. + for _, _dir := range resp.Segment.Directories { + fmt.Printf("%v", _dir) + } + } + + _, err = childDirClient.Delete(context.Background(), nil) + handleError(err) + fmt.Println("Child directory deleted") + + _, err = parentDirClient.Delete(context.Background(), nil) + handleError(err) + fmt.Println("Parent directory deleted") +} + +func Example_directoryClient_SetMetadata() { + // Your connection string can be obtained from the Azure Portal. + connectionString, ok := os.LookupEnv("AZURE_STORAGE_CONNECTION_STRING") + if !ok { + log.Fatal("the environment variable 'AZURE_STORAGE_CONNECTION_STRING' could not be found") + } + shareName := "testShare" + dirName := "testDirectory" + dirClient, err := directory.NewClientFromConnectionString(connectionString, shareName, dirName, nil) + handleError(err) + _, err = dirClient.Create(context.Background(), nil) + handleError(err) + fmt.Println("Directory created") + + md := map[string]*string{ + "Foo": to.Ptr("FooValuE"), + "Bar": to.Ptr("bArvaLue"), + } + + _, err = dirClient.SetMetadata(context.Background(), &directory.SetMetadataOptions{ + Metadata: md, + }) + handleError(err) + fmt.Println("Directory metadata set") + + _, err = dirClient.Delete(context.Background(), nil) + handleError(err) + fmt.Println("Directory deleted") +} diff --git a/sdk/storage/azfile/directory/models.go b/sdk/storage/azfile/directory/models.go new file mode 100644 index 000000000000..950cf1a91d63 --- /dev/null +++ b/sdk/storage/azfile/directory/models.go @@ -0,0 +1,255 @@ +//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 + +import ( + "github.com/Azure/azure-sdk-for-go/sdk/azcore/to" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azfile/file" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azfile/internal/exported" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azfile/internal/generated" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azfile/internal/shared" + "reflect" +) + +// SharedKeyCredential contains an account's name and its primary or secondary key. +type SharedKeyCredential = exported.SharedKeyCredential + +// NewSharedKeyCredential creates an immutable SharedKeyCredential containing the +// storage account's name and either its primary or secondary key. +func NewSharedKeyCredential(accountName, accountKey string) (*SharedKeyCredential, error) { + return exported.NewSharedKeyCredential(accountName, accountKey) +} + +// --------------------------------------------------------------------------------------------------------------------- + +// CreateOptions contains the optional parameters for the Client.Create method. +type CreateOptions struct { + // The default value is 'Directory' for Attributes and 'now' for CreationTime and LastWriteTime fields in file.SMBProperties. + FileSMBProperties *file.SMBProperties + // The default value is 'inherit' for Permission field in file.Permissions. + FilePermissions *file.Permissions + // A name-value pair to associate with a file storage object. + Metadata map[string]*string +} + +func (o *CreateOptions) format() (fileAttributes string, fileCreationTime string, fileLastWriteTime string, createOptions *generated.DirectoryClientCreateOptions) { + if o == nil { + return shared.FileAttributesDirectory, shared.DefaultCurrentTimeString, shared.DefaultCurrentTimeString, &generated.DirectoryClientCreateOptions{ + FilePermission: to.Ptr(shared.DefaultFilePermissionString), + } + } + + fileAttributes, fileCreationTime, fileLastWriteTime = o.FileSMBProperties.Format(true, shared.FileAttributesDirectory, shared.DefaultCurrentTimeString) + + permission, permissionKey := o.FilePermissions.Format(shared.DefaultFilePermissionString) + + createOptions = &generated.DirectoryClientCreateOptions{ + FilePermission: permission, + FilePermissionKey: permissionKey, + Metadata: o.Metadata, + } + + return +} + +// --------------------------------------------------------------------------------------------------------------------- + +// DeleteOptions contains the optional parameters for the Client.Delete method. +type DeleteOptions struct { + // placeholder for future options +} + +func (o *DeleteOptions) format() *generated.DirectoryClientDeleteOptions { + return nil +} + +// --------------------------------------------------------------------------------------------------------------------- + +// GetPropertiesOptions contains the optional parameters for the Client.GetProperties method. +type GetPropertiesOptions struct { + // ShareSnapshot parameter is an opaque DateTime value that, when present, specifies the share snapshot to query for the directory properties. + ShareSnapshot *string +} + +func (o *GetPropertiesOptions) format() *generated.DirectoryClientGetPropertiesOptions { + if o == nil { + return nil + } + + return &generated.DirectoryClientGetPropertiesOptions{ + Sharesnapshot: o.ShareSnapshot, + } +} + +// --------------------------------------------------------------------------------------------------------------------- + +// SetPropertiesOptions contains the optional parameters for the Client.SetProperties method. +type SetPropertiesOptions struct { + // The default value is 'preserve' for Attributes, CreationTime and LastWriteTime fields in file.SMBProperties. + FileSMBProperties *file.SMBProperties + // The default value is 'preserve' for Permission field in file.Permissions. + FilePermissions *file.Permissions +} + +func (o *SetPropertiesOptions) format() (fileAttributes string, fileCreationTime string, fileLastWriteTime string, setPropertiesOptions *generated.DirectoryClientSetPropertiesOptions) { + if o == nil { + return shared.DefaultPreserveString, shared.DefaultPreserveString, shared.DefaultPreserveString, &generated.DirectoryClientSetPropertiesOptions{ + FilePermission: to.Ptr(shared.DefaultPreserveString), + } + } + + fileAttributes, fileCreationTime, fileLastWriteTime = o.FileSMBProperties.Format(true, shared.DefaultPreserveString, shared.DefaultPreserveString) + + permission, permissionKey := o.FilePermissions.Format(shared.DefaultPreserveString) + + setPropertiesOptions = &generated.DirectoryClientSetPropertiesOptions{ + FilePermission: permission, + FilePermissionKey: permissionKey, + } + return +} + +// --------------------------------------------------------------------------------------------------------------------- + +// SetMetadataOptions contains the optional parameters for the Client.SetMetadata method. +type SetMetadataOptions struct { + // A name-value pair to associate with a file storage object. + Metadata map[string]*string +} + +func (o *SetMetadataOptions) format() *generated.DirectoryClientSetMetadataOptions { + if o == nil { + return nil + } + + return &generated.DirectoryClientSetMetadataOptions{ + Metadata: o.Metadata, + } +} + +// --------------------------------------------------------------------------------------------------------------------- + +// ListFilesAndDirectoriesOptions contains the optional parameters for the Client.NewListFilesAndDirectoriesPager method. +type ListFilesAndDirectoriesOptions struct { + // Include this parameter to specify one or more datasets to include in the response. + Include ListFilesInclude + // Include extended information. + IncludeExtendedInfo *bool + // A string value that identifies the portion of the list to be returned with the next list operation. The operation returns + // a marker value within the response body if the list returned was not complete. + // The marker value may then be used in a subsequent call to request the next set of list items. The marker value is opaque + // to the client. + Marker *string + // Specifies the maximum number of entries to return. If the request does not specify maxresults, or specifies a value greater + // than 5,000, the server will return up to 5,000 items. + MaxResults *int32 + // Filters the results to return only entries whose name begins with the specified prefix. + Prefix *string + // The snapshot parameter is an opaque DateTime value that, when present, specifies the share snapshot to query for the list of files and directories. + ShareSnapshot *string +} + +// ListFilesInclude specifies one or more datasets to include in the response. +type ListFilesInclude struct { + Timestamps, ETag, Attributes, PermissionKey bool +} + +func (l ListFilesInclude) format() []generated.ListFilesIncludeType { + if reflect.ValueOf(l).IsZero() { + return nil + } + + var include []generated.ListFilesIncludeType + + if l.Timestamps { + include = append(include, ListFilesIncludeTypeTimestamps) + } + if l.ETag { + include = append(include, ListFilesIncludeTypeETag) + } + if l.Attributes { + include = append(include, ListFilesIncludeTypeAttributes) + } + if l.PermissionKey { + include = append(include, ListFilesIncludeTypePermissionKey) + } + + return include +} + +// FilesAndDirectoriesListSegment - Abstract for entries that can be listed from directory. +type FilesAndDirectoriesListSegment = generated.FilesAndDirectoriesListSegment + +// Directory - A listed directory item. +type Directory = generated.Directory + +// File - A listed file item. +type File = generated.File + +// FileProperty - File properties. +type FileProperty = generated.FileProperty + +// --------------------------------------------------------------------------------------------------------------------- + +// ListHandlesOptions contains the optional parameters for the Client.ListHandles method. +type ListHandlesOptions struct { + // A string value that identifies the portion of the list to be returned with the next list operation. The operation returns + // a marker value within the response body if the list returned was not complete. + // The marker value may then be used in a subsequent call to request the next set of list items. The marker value is opaque + // to the client. + Marker *string + // Specifies the maximum number of entries to return. If the request does not specify maxresults, or specifies a value greater + // than 5,000, the server will return up to 5,000 items. + MaxResults *int32 + // Specifies operation should apply to the directory specified in the URI, its files, its subdirectories and their files. + Recursive *bool + // The snapshot parameter is an opaque DateTime value that, when present, specifies the share snapshot to query. + ShareSnapshot *string +} + +func (o *ListHandlesOptions) format() *generated.DirectoryClientListHandlesOptions { + if o == nil { + return nil + } + + return &generated.DirectoryClientListHandlesOptions{ + Marker: o.Marker, + Maxresults: o.MaxResults, + Recursive: o.Recursive, + Sharesnapshot: o.ShareSnapshot, + } +} + +// Handle - A listed Azure Storage handle item. +type Handle = generated.Handle + +// --------------------------------------------------------------------------------------------------------------------- + +// ForceCloseHandlesOptions contains the optional parameters for the Client.ForceCloseHandles method. +type ForceCloseHandlesOptions struct { + // A string value that identifies the portion of the list to be returned with the next list operation. The operation returns + // a marker value within the response body if the list returned was not complete. + // The marker value may then be used in a subsequent call to request the next set of list items. The marker value is opaque + // to the client. + Marker *string + // Specifies operation should apply to the directory specified in the URI, its files, its subdirectories and their files. + Recursive *bool + // The snapshot parameter is an opaque DateTime value that, when present, specifies the share snapshot to query. + ShareSnapshot *string +} + +func (o *ForceCloseHandlesOptions) format() *generated.DirectoryClientForceCloseHandlesOptions { + if o == nil { + return nil + } + + return &generated.DirectoryClientForceCloseHandlesOptions{ + Marker: o.Marker, + Recursive: o.Recursive, + Sharesnapshot: o.ShareSnapshot, + } +} diff --git a/sdk/storage/azfile/directory/responses.go b/sdk/storage/azfile/directory/responses.go new file mode 100644 index 000000000000..28f2470b10ba --- /dev/null +++ b/sdk/storage/azfile/directory/responses.go @@ -0,0 +1,39 @@ +//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 + +import "github.com/Azure/azure-sdk-for-go/sdk/storage/azfile/internal/generated" + +// CreateResponse contains the response from method Client.Create. +type CreateResponse = generated.DirectoryClientCreateResponse + +// DeleteResponse contains the response from method Client.Delete. +type DeleteResponse = generated.DirectoryClientDeleteResponse + +// GetPropertiesResponse contains the response from method Client.GetProperties. +type GetPropertiesResponse = generated.DirectoryClientGetPropertiesResponse + +// SetPropertiesResponse contains the response from method Client.SetProperties. +type SetPropertiesResponse = generated.DirectoryClientSetPropertiesResponse + +// SetMetadataResponse contains the response from method Client.SetMetadata. +type SetMetadataResponse = generated.DirectoryClientSetMetadataResponse + +// ListFilesAndDirectoriesResponse contains the response from method Client.NewListFilesAndDirectoriesPager. +type ListFilesAndDirectoriesResponse = generated.DirectoryClientListFilesAndDirectoriesSegmentResponse + +// ListFilesAndDirectoriesSegmentResponse - An enumeration of directories and files. +type ListFilesAndDirectoriesSegmentResponse = generated.ListFilesAndDirectoriesSegmentResponse + +// ListHandlesResponse contains the response from method Client.ListHandles. +type ListHandlesResponse = generated.DirectoryClientListHandlesResponse + +// ListHandlesSegmentResponse - An enumeration of handles. +type ListHandlesSegmentResponse = generated.ListHandlesResponse + +// ForceCloseHandlesResponse contains the response from method Client.ForceCloseHandles. +type ForceCloseHandlesResponse = generated.DirectoryClientForceCloseHandlesResponse diff --git a/sdk/storage/azfile/doc.go b/sdk/storage/azfile/doc.go new file mode 100644 index 000000000000..51d645839165 --- /dev/null +++ b/sdk/storage/azfile/doc.go @@ -0,0 +1,229 @@ +//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 azfile provides access to Azure File Storage. +For more information please see https://learn.microsoft.com/rest/api/storageservices/file-service-rest-api + +The azfile package is capable of :- + - Creating, deleting, and querying shares in an account + - Creating, deleting, and querying directories in a share + - Creating, deleting, and querying files in a share or directory + - Creating Shared Access Signature for authentication + +Types of Resources + +The azfile package allows you to interact with four types of resources :- + +* Azure storage accounts. +* Shares within those storage accounts. +* Directories within those shares. +* Files within those shares or directories. + +The Azure File Storage (azfile) client library for Go allows you to interact with each of these components through the use of a dedicated client object. +To create a client object, you will need the account's file service endpoint URL and a credential that allows you to access the account. + +Types of Credentials + +The clients support different forms of authentication. +The azfile library supports authorization via a shared key, Connection String, +or with a Shared Access Signature token. + +Using a Shared Key + +To use an account shared key (aka account key or access key), provide the key as a string. +This can be found in your storage account in the Azure Portal under the "Access Keys" section. + +Use the key as the credential parameter to authenticate the client: + + accountName, ok := os.LookupEnv("AZURE_STORAGE_ACCOUNT_NAME") + if !ok { + panic("AZURE_STORAGE_ACCOUNT_NAME could not be found") + } + accountKey, ok := os.LookupEnv("AZURE_STORAGE_ACCOUNT_KEY") + if !ok { + panic("AZURE_STORAGE_ACCOUNT_KEY could not be found") + } + + serviceURL := fmt.Sprintf("https://%s.file.core.windows.net/", accountName) + + cred, err := service.NewSharedKeyCredential(accountName, accountKey) + handle(err) + + serviceClient, err := service.NewClientWithSharedKeyCredential(serviceURL, cred, nil) + handle(err) + + fmt.Println(serviceClient.URL()) + +Using a Connection String + +Depending on your use case and authorization method, you may prefer to initialize a client instance with a connection string instead of providing the account URL and credential separately. +To do this, pass the connection string to the service client's `NewClientFromConnectionString` method. +The connection string can be found in your storage account in the Azure Portal under the "Access Keys" section. + + connStr := "DefaultEndpointsProtocol=https;AccountName=;AccountKey=;EndpointSuffix=core.windows.net" + serviceClient, err := azfile.NewServiceClientFromConnectionString(connStr, nil) + handle(err) + +Using a Shared Access Signature (SAS) Token + +To use a shared access signature (SAS) token, provide the token at the end of your service URL. +You can generate a SAS token from the Azure Portal under Shared Access Signature or use the service.Client.GetSASURL() functions. + + accountName, ok := os.LookupEnv("AZURE_STORAGE_ACCOUNT_NAME") + if !ok { + panic("AZURE_STORAGE_ACCOUNT_NAME could not be found") + } + accountKey, ok := os.LookupEnv("AZURE_STORAGE_ACCOUNT_KEY") + if !ok { + panic("AZURE_STORAGE_ACCOUNT_KEY could not be found") + } + serviceURL := fmt.Sprintf("https://%s.file.core.windows.net/", accountName) + + cred, err := service.NewSharedKeyCredential(accountName, accountKey) + handle(err) + serviceClient, err := service.NewClientWithSharedKeyCredential(serviceURL, cred, nil) + handle(err) + fmt.Println(serviceClient.URL()) + + // Alternatively, you can create SAS on the fly + + resources := sas.AccountResourceTypes{Service: true} + permission := sas.AccountPermissions{Read: true} + start := time.Now() + expiry := start.AddDate(0, 0, 1) + serviceURLWithSAS, err := serviceClient.GetSASURL(resources, permission, expiry, &service.GetSASURLOptions{StartTime: &start}) + handle(err) + + serviceClientWithSAS, err := service.NewClientWithNoCredential(serviceURLWithSAS, nil) + handle(err) + + fmt.Println(serviceClientWithSAS.URL()) + +Types of Clients + +There are four different clients provided to interact with the various components of the File Service: + +1. **`ServiceClient`** + * Get and set account settings. + * Query, create, delete and restore shares within the account. + +2. **`ShareClient`** + * Get and set share access settings, properties, and metadata. + * Create, delete, and query directories and files within the share. + * `lease.ShareClient` to support share lease management. + +3. **`DirectoryClient`** + * Create or delete operations on a given directory. + * Get and set directory properties. + * List sub-directories and files within the given directory. + +3. **`FileClient`** + * Get and set file properties. + * Perform CRUD operations on a given file. + * `FileLeaseClient` to support file lease management. + +Examples + + // Your account name and key can be obtained from the Azure Portal. + accountName, ok := os.LookupEnv("AZURE_STORAGE_ACCOUNT_NAME") + if !ok { + panic("AZURE_STORAGE_ACCOUNT_NAME could not be found") + } + + accountKey, ok := os.LookupEnv("AZURE_STORAGE_ACCOUNT_KEY") + if !ok { + panic("AZURE_STORAGE_ACCOUNT_KEY could not be found") + } + + cred, err := service.NewSharedKeyCredential(accountName, accountKey) + handle(err) + + // The service URL for file endpoints is usually in the form: http(s)://.file.core.windows.net/ + serviceClient, err := service.NewClientWithSharedKeyCredential(fmt.Sprintf("https://%s.file.core.windows.net/", accountName), cred, nil) + handle(err) + + // ===== 1. Create a share ===== + + // First, create a share client, and use the Create method to create a new share in your account + shareClient := serviceClient.NewShareClient("testshare") + handle(err) + + // All APIs have an options' bag struct as a parameter. + // The options' bag struct allows you to specify optional parameters such as metadata, quota, etc. + // If you want to use the default options, pass in nil. + _, err = shareClient.Create(context.TODO(), nil) + handle(err) + + // ===== 2. Create a directory ===== + + // First, create a directory client, and use the Create method to create a new directory in the share + dirClient := shareClient.NewDirectoryClient("testdir") + _, err = dirClient.Create(context.TODO(), nil) + + // ===== 3. Upload and Download a file ===== + uploadData := "Hello world!" + + // First, create a file client, and use the Create method to create a new file in the directory + fileClient := dirClient.NewFileClient("HelloWorld.txt") + _, err = fileClient.Create(context.TODO(), int64(len(uploadData)), nil) + handle(err) + + // Upload data to the file + _, err = fileClient.UploadRange(context.TODO(), 0, streaming.NopCloser(strings.NewReader(uploadData)), nil) + handle(err) + + // Download the file's contents and ensure that the download worked properly + fileDownloadResponse, err := fileClient.DownloadStream(context.TODO(), nil) + handle(err) + + // Use io.readAll to read the downloaded data. + // RetryReaderOptions has a lot of in-depth tuning abilities, but for the sake of simplicity, we'll omit those here. + reader := fileDownloadResponse.Body + downloadData, err := io.ReadAll(reader) + handle(err) + if string(downloadData) != uploadData { + handle(errors.New("uploaded data should be same as downloaded data")) + } + + if err = reader.Close(); err != nil { + handle(err) + return + } + + // ===== 3. List directories and files in a share ===== + // List methods returns a pager object which can be used to iterate over the results of a paging operation. + // To iterate over a page use the NextPage(context.Context) to fetch the next page of results. + // PageResponse() can be used to iterate over the results of the specific page. + // Always check the Err() method after paging to see if an error was returned by the pager. A pager will return either an error or the page of results. + // The below code lists the contents only for a single level of the directory hierarchy. + rootDirClient := shareClient.NewRootDirectoryClient() + pager := rootDirClient.NewListFilesAndDirectoriesPager(nil) + for pager.More() { + resp, err := pager.NextPage(context.TODO()) + handle(err) + for _, d := range resp.Segment.Directories { + fmt.Println(*d.Name) + } + for _, f := range resp.Segment.Files { + fmt.Println(*f.Name) + } + } + + // Delete the file. + _, err = fileClient.Delete(context.TODO(), nil) + handle(err) + + // Delete the directory. + _, err = dirClient.Delete(context.TODO(), nil) + handle(err) + + // Delete the share. + _, err = shareClient.Delete(context.TODO(), nil) + handle(err) +*/ + +package azfile diff --git a/sdk/storage/azfile/file/chunkwriting.go b/sdk/storage/azfile/file/chunkwriting.go new file mode 100644 index 000000000000..21070c19bcad --- /dev/null +++ b/sdk/storage/azfile/file/chunkwriting.go @@ -0,0 +1,189 @@ +//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 file + +import ( + "bytes" + "context" + "errors" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/streaming" + "io" + "sync" +) + +// chunkWriter provides methods to upload chunks that represent a file to a server. +// This allows us to provide a local implementation that fakes the server for hermetic testing. +type chunkWriter interface { + UploadRange(context.Context, int64, io.ReadSeekCloser, *UploadRangeOptions) (UploadRangeResponse, error) +} + +// bufferManager provides an abstraction for the management of buffers. +// this is mostly for testing purposes, but does allow for different implementations without changing the algorithm. +type bufferManager[T ~[]byte] interface { + // Acquire returns the channel that contains the pool of buffers. + Acquire() <-chan T + + // Release releases the buffer back to the pool for reuse/cleanup. + Release(T) + + // Grow grows the number of buffers, up to the predefined max. + // It returns the total number of buffers or an error. + // No error is returned if the number of buffers has reached max. + // This is called only from the reading goroutine. + Grow() (int, error) + + // Free cleans up all buffers. + Free() +} + +// copyFromReader copies a source io.Reader to file storage using concurrent uploads. +func copyFromReader[T ~[]byte](ctx context.Context, src io.Reader, dst chunkWriter, options UploadStreamOptions, getBufferManager func(maxBuffers int, bufferSize int64) bufferManager[T]) error { + options.setDefaults() + + wg := sync.WaitGroup{} // Used to know when all outgoing chunks have finished processing + errCh := make(chan error, 1) // contains the first error encountered during processing + var err error + + buffers := getBufferManager(options.Concurrency, options.ChunkSize) + defer buffers.Free() + + // this controls the lifetime of the uploading goroutines. + // if an error is encountered, cancel() is called which will terminate all uploads. + // NOTE: the ordering is important here. cancel MUST execute before + // cleaning up the buffers so that any uploading goroutines exit first, + // releasing their buffers back to the pool for cleanup. + ctx, cancel := context.WithCancel(ctx) + defer cancel() + + // This goroutine grabs a buffer, reads from the stream into the buffer, + // then creates a goroutine to upload/stage the chunk. + for chunkNum := uint32(0); true; chunkNum++ { + var buffer T + select { + case buffer = <-buffers.Acquire(): + // got a buffer + default: + // no buffer available; allocate a new buffer if possible + if _, err := buffers.Grow(); err != nil { + return err + } + + // either grab the newly allocated buffer or wait for one to become available + buffer = <-buffers.Acquire() + } + + var n int + n, err = io.ReadFull(src, buffer) + + if n > 0 { + // some data was read, upload it + wg.Add(1) // We're posting a buffer to be sent + + // NOTE: we must pass chunkNum as an arg to our goroutine else + // it's captured by reference and can change underneath us! + go func(chunkNum uint32) { + // Upload the outgoing chunk, matching the number of bytes read + offset := int64(chunkNum) * options.ChunkSize + uploadRangeOptions := options.getUploadRangeOptions() + _, err := dst.UploadRange(ctx, offset, streaming.NopCloser(bytes.NewReader(buffer[:n])), uploadRangeOptions) + if err != nil { + select { + case errCh <- err: + // error was set + default: + // some other error is already set + } + cancel() + } + buffers.Release(buffer) // The goroutine reading from the stream can reuse this buffer now + + // signal that the chunk has been staged. + // we MUST do this after attempting to write to errCh + // to avoid it racing with the reading goroutine. + wg.Done() + }(chunkNum) + } else { + // nothing was read so the buffer is empty, send it back for reuse/clean-up. + buffers.Release(buffer) + } + + if err != nil { // The reader is done, no more outgoing buffers + if errors.Is(err, io.EOF) || errors.Is(err, io.ErrUnexpectedEOF) { + // these are expected errors, we don't surface those + err = nil + } else { + // some other error happened, terminate any outstanding uploads + cancel() + } + break + } + } + + wg.Wait() // Wait for all outgoing chunks to complete + + if err != nil { + // there was an error reading from src, favor this error over any error during staging + return err + } + + select { + case err = <-errCh: + // there was an error during staging + return err + default: + // no error was encountered + } + + // All chunks uploaded, return nil error + return nil +} + +// mmbPool implements the bufferManager interface. +// it uses anonymous memory mapped files for buffers. +// don't use this type directly, use newMMBPool() instead. +type mmbPool struct { + buffers chan mmb + count int + max int + size int64 +} + +func newMMBPool(maxBuffers int, bufferSize int64) bufferManager[mmb] { + return &mmbPool{ + buffers: make(chan mmb, maxBuffers), + max: maxBuffers, + size: bufferSize, + } +} + +func (pool *mmbPool) Acquire() <-chan mmb { + return pool.buffers +} + +func (pool *mmbPool) Grow() (int, error) { + if pool.count < pool.max { + buffer, err := newMMB(pool.size) + if err != nil { + return 0, err + } + pool.buffers <- buffer + pool.count++ + } + return pool.count, nil +} + +func (pool *mmbPool) Release(buffer mmb) { + pool.buffers <- buffer +} + +func (pool *mmbPool) Free() { + for i := 0; i < pool.count; i++ { + buffer := <-pool.buffers + buffer.delete() + } + pool.count = 0 +} diff --git a/sdk/storage/azfile/file/client.go b/sdk/storage/azfile/file/client.go new file mode 100644 index 000000000000..432f8ae379a1 --- /dev/null +++ b/sdk/storage/azfile/file/client.go @@ -0,0 +1,505 @@ +//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 file + +import ( + "bytes" + "context" + "errors" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/streaming" + "github.com/Azure/azure-sdk-for-go/sdk/internal/log" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azfile/fileerror" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azfile/internal/base" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azfile/internal/exported" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azfile/internal/generated" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azfile/internal/shared" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azfile/sas" + "io" + "os" + "strings" + "sync" + "time" +) + +// ClientOptions contains the optional parameters when creating a Client. +type ClientOptions base.ClientOptions + +// Client represents a URL to the Azure Storage file. +type Client base.Client[generated.FileClient] + +// NewClientWithNoCredential creates an instance of Client with the specified values. +// This is used to anonymously access a file or with a shared access signature (SAS) token. +// - fileURL - the URL of the file e.g. https://.file.core.windows.net/share/directoryPath/file? +// - options - client options; pass nil to accept the default values +// +// The directoryPath is optional in the fileURL. If omitted, it points to file within the specified share. +func NewClientWithNoCredential(fileURL string, options *ClientOptions) (*Client, error) { + conOptions := shared.GetClientOptions(options) + pl := runtime.NewPipeline(exported.ModuleName, exported.ModuleVersion, runtime.PipelineOptions{}, &conOptions.ClientOptions) + + return (*Client)(base.NewFileClient(fileURL, pl, nil)), nil +} + +// NewClientWithSharedKeyCredential creates an instance of Client with the specified values. +// - fileURL - the URL of the file e.g. https://.file.core.windows.net/share/directoryPath/file +// - cred - a SharedKeyCredential created with the matching file's storage account and access key +// - options - client options; pass nil to accept the default values +// +// The directoryPath is optional in the fileURL. If omitted, it points to file within the specified share. +func NewClientWithSharedKeyCredential(fileURL string, cred *SharedKeyCredential, options *ClientOptions) (*Client, error) { + authPolicy := exported.NewSharedKeyCredPolicy(cred) + conOptions := shared.GetClientOptions(options) + conOptions.PerRetryPolicies = append(conOptions.PerRetryPolicies, authPolicy) + pl := runtime.NewPipeline(exported.ModuleName, exported.ModuleVersion, runtime.PipelineOptions{}, &conOptions.ClientOptions) + + return (*Client)(base.NewFileClient(fileURL, pl, cred)), nil +} + +// NewClientFromConnectionString creates an instance of Client with the specified values. +// - connectionString - a connection string for the desired storage account +// - shareName - the name of the share within the storage account +// - filePath - the path of the file within the share +// - options - client options; pass nil to accept the default values +func NewClientFromConnectionString(connectionString string, shareName string, filePath string, options *ClientOptions) (*Client, error) { + parsed, err := shared.ParseConnectionString(connectionString) + if err != nil { + return nil, err + } + + filePath = strings.ReplaceAll(filePath, "\\", "/") + parsed.ServiceURL = runtime.JoinPaths(parsed.ServiceURL, shareName, filePath) + + if parsed.AccountKey != "" && parsed.AccountName != "" { + credential, err := exported.NewSharedKeyCredential(parsed.AccountName, parsed.AccountKey) + if err != nil { + return nil, err + } + return NewClientWithSharedKeyCredential(parsed.ServiceURL, credential, options) + } + + return NewClientWithNoCredential(parsed.ServiceURL, options) +} + +func (f *Client) generated() *generated.FileClient { + return base.InnerClient((*base.Client[generated.FileClient])(f)) +} + +func (f *Client) sharedKey() *SharedKeyCredential { + return base.SharedKey((*base.Client[generated.FileClient])(f)) +} + +// URL returns the URL endpoint used by the Client object. +func (f *Client) URL() string { + return f.generated().Endpoint() +} + +// Create operation creates a new file or replaces a file. Note it only initializes the file with no content. +// - fileContentLength: Specifies the maximum size for the file in bytes, up to 4 TB. +// +// For more information, see https://learn.microsoft.com/en-us/rest/api/storageservices/create-file. +func (f *Client) Create(ctx context.Context, fileContentLength int64, options *CreateOptions) (CreateResponse, error) { + fileAttributes, fileCreationTime, fileLastWriteTime, fileCreateOptions, fileHTTPHeaders, leaseAccessConditions := options.format() + resp, err := f.generated().Create(ctx, fileContentLength, fileAttributes, fileCreationTime, fileLastWriteTime, fileCreateOptions, fileHTTPHeaders, leaseAccessConditions) + return resp, err +} + +// Delete operation removes the file from the storage account. +// For more information, see https://learn.microsoft.com/en-us/rest/api/storageservices/delete-file2. +func (f *Client) Delete(ctx context.Context, options *DeleteOptions) (DeleteResponse, error) { + opts, leaseAccessConditions := options.format() + resp, err := f.generated().Delete(ctx, opts, leaseAccessConditions) + return resp, err +} + +// GetProperties operation returns all user-defined metadata, standard HTTP properties, and system properties for the file. +// For more information, see https://learn.microsoft.com/en-us/rest/api/storageservices/get-file-properties. +func (f *Client) GetProperties(ctx context.Context, options *GetPropertiesOptions) (GetPropertiesResponse, error) { + opts, leaseAccessConditions := options.format() + resp, err := f.generated().GetProperties(ctx, opts, leaseAccessConditions) + return resp, err +} + +// SetHTTPHeaders operation sets HTTP headers on the file. +// For more information, see https://learn.microsoft.com/en-us/rest/api/storageservices/set-file-properties. +func (f *Client) SetHTTPHeaders(ctx context.Context, options *SetHTTPHeadersOptions) (SetHTTPHeadersResponse, error) { + fileAttributes, fileCreationTime, fileLastWriteTime, opts, fileHTTPHeaders, leaseAccessConditions := options.format() + resp, err := f.generated().SetHTTPHeaders(ctx, fileAttributes, fileCreationTime, fileLastWriteTime, opts, fileHTTPHeaders, leaseAccessConditions) + return resp, err +} + +// SetMetadata operation sets user-defined metadata for the specified file. +// For more information, see https://learn.microsoft.com/en-us/rest/api/storageservices/set-file-metadata. +func (f *Client) SetMetadata(ctx context.Context, options *SetMetadataOptions) (SetMetadataResponse, error) { + opts, leaseAccessConditions := options.format() + resp, err := f.generated().SetMetadata(ctx, opts, leaseAccessConditions) + return resp, err +} + +// StartCopyFromURL operation copies the data at the source URL to a file. +// - copySource: specifies the URL of the source file or blob, up to 2KiB in length. +// +// For more information, see https://learn.microsoft.com/en-us/rest/api/storageservices/copy-file. +func (f *Client) StartCopyFromURL(ctx context.Context, copySource string, options *StartCopyFromURLOptions) (StartCopyFromURLResponse, error) { + opts, copyFileSmbInfo, leaseAccessConditions := options.format() + resp, err := f.generated().StartCopy(ctx, copySource, opts, copyFileSmbInfo, leaseAccessConditions) + return resp, err +} + +// AbortCopy operation cancels a pending Copy File operation, and leaves a destination file with zero length and full metadata. +// - copyID: the copy identifier provided in the x-ms-copy-id header of the original Copy File operation. +// +// For more information, see https://learn.microsoft.com/en-us/rest/api/storageservices/abort-copy-file. +func (f *Client) AbortCopy(ctx context.Context, copyID string, options *AbortCopyOptions) (AbortCopyResponse, error) { + opts, leaseAccessConditions := options.format() + resp, err := f.generated().AbortCopy(ctx, copyID, opts, leaseAccessConditions) + return resp, err +} + +// Resize operation resizes the file to the specified size. +// For more information, see https://learn.microsoft.com/en-us/rest/api/storageservices/set-file-properties. +func (f *Client) Resize(ctx context.Context, size int64, options *ResizeOptions) (ResizeResponse, error) { + fileAttributes, fileCreationTime, fileLastWriteTime, opts, leaseAccessConditions := options.format(size) + resp, err := f.generated().SetHTTPHeaders(ctx, fileAttributes, fileCreationTime, fileLastWriteTime, opts, nil, leaseAccessConditions) + return resp, err +} + +// UploadRange operation uploads a range of bytes to a file. +// - offset: Specifies the start byte at which the range of bytes is to be written. +// - body: Specifies the data to be uploaded. +// +// For more information, see https://learn.microsoft.com/en-us/rest/api/storageservices/put-range. +func (f *Client) UploadRange(ctx context.Context, offset int64, body io.ReadSeekCloser, options *UploadRangeOptions) (UploadRangeResponse, error) { + rangeParam, contentLength, uploadRangeOptions, leaseAccessConditions, err := options.format(offset, body) + if err != nil { + return UploadRangeResponse{}, err + } + + resp, err := f.generated().UploadRange(ctx, rangeParam, RangeWriteTypeUpdate, contentLength, body, uploadRangeOptions, leaseAccessConditions) + return resp, err +} + +// ClearRange operation clears the specified range and releases the space used in storage for that range. +// - contentRange: Specifies the range of bytes to be cleared. +// +// For more information, see https://learn.microsoft.com/en-us/rest/api/storageservices/put-range. +func (f *Client) ClearRange(ctx context.Context, contentRange HTTPRange, options *ClearRangeOptions) (ClearRangeResponse, error) { + rangeParam, leaseAccessConditions, err := options.format(contentRange) + if err != nil { + return ClearRangeResponse{}, err + } + + resp, err := f.generated().UploadRange(ctx, rangeParam, RangeWriteTypeClear, 0, nil, nil, leaseAccessConditions) + return resp, err +} + +// UploadRangeFromURL operation uploads a range of bytes to a file where the contents are read from a URL. +// - copySource: Specifies the URL of the source file or blob, up to 2 KB in length. +// - destinationRange: Specifies the range of bytes in the file to be written. +// - sourceRange: Bytes of source data in the specified range. +// +// For more information, see https://learn.microsoft.com/en-us/rest/api/storageservices/put-range-from-url. +func (f *Client) UploadRangeFromURL(ctx context.Context, copySource string, sourceOffset int64, destinationOffset int64, count int64, options *UploadRangeFromURLOptions) (UploadRangeFromURLResponse, error) { + destRange, opts, sourceModifiedAccessConditions, leaseAccessConditions, err := options.format(sourceOffset, destinationOffset, count) + if err != nil { + return UploadRangeFromURLResponse{}, err + } + + resp, err := f.generated().UploadRangeFromURL(ctx, destRange, copySource, 0, opts, sourceModifiedAccessConditions, leaseAccessConditions) + return resp, err +} + +// GetRangeList operation returns the list of valid ranges for a file. +// For more information, see https://learn.microsoft.com/en-us/rest/api/storageservices/list-ranges. +func (f *Client) GetRangeList(ctx context.Context, options *GetRangeListOptions) (GetRangeListResponse, error) { + opts, leaseAccessConditions := options.format() + resp, err := f.generated().GetRangeList(ctx, opts, leaseAccessConditions) + return resp, err +} + +// ForceCloseHandles operation closes a handle or handles opened on a file. +// - handleID - Specifies the handle ID to be closed. Use an asterisk (*) as a wildcard string to specify all handles. +// +// For more information, see https://learn.microsoft.com/en-us/rest/api/storageservices/force-close-handles. +func (f *Client) ForceCloseHandles(ctx context.Context, handleID string, options *ForceCloseHandlesOptions) (ForceCloseHandlesResponse, error) { + opts := options.format() + resp, err := f.generated().ForceCloseHandles(ctx, handleID, opts) + return resp, err +} + +// ListHandles operation returns a list of open handles on a file. +// For more information, see https://learn.microsoft.com/en-us/rest/api/storageservices/list-handles. +func (f *Client) ListHandles(ctx context.Context, options *ListHandlesOptions) (ListHandlesResponse, error) { + opts := options.format() + resp, err := f.generated().ListHandles(ctx, opts) + return resp, err +} + +// GetSASURL is a convenience method for generating a SAS token for the currently pointed at file. +// It can only be used if the credential supplied during creation was a SharedKeyCredential. +func (f *Client) GetSASURL(permissions sas.FilePermissions, expiry time.Time, o *GetSASURLOptions) (string, error) { + if f.sharedKey() == nil { + return "", fileerror.MissingSharedKeyCredential + } + st := o.format() + + urlParts, err := ParseURL(f.URL()) + if err != nil { + return "", err + } + + qps, err := sas.SignatureValues{ + Version: sas.Version, + Protocol: sas.ProtocolHTTPS, + ShareName: urlParts.ShareName, + FilePath: urlParts.DirectoryOrFilePath, + Permissions: permissions.String(), + StartTime: st, + ExpiryTime: expiry.UTC(), + }.SignWithSharedKey(f.sharedKey()) + if err != nil { + return "", err + } + + endpoint := f.URL() + "?" + qps.Encode() + + return endpoint, nil +} + +// Concurrent Upload Functions ----------------------------------------------------------------------------------------- + +// uploadFromReader uploads a buffer in chunks to an Azure file. +func (f *Client) uploadFromReader(ctx context.Context, reader io.ReaderAt, actualSize int64, o *uploadFromReaderOptions) error { + if actualSize > MaxFileSize { + return errors.New("buffer is too large to upload to a file") + } + if o.ChunkSize == 0 { + o.ChunkSize = MaxUpdateRangeBytes + } + + if log.Should(exported.EventUpload) { + urlParts, err := ParseURL(f.URL()) + if err == nil { + log.Writef(exported.EventUpload, "file name %s actual size %v chunk-size %v chunk-count %v", + urlParts.DirectoryOrFilePath, actualSize, o.ChunkSize, ((actualSize-1)/o.ChunkSize)+1) + } + } + + progress := int64(0) + progressLock := &sync.Mutex{} + + err := shared.DoBatchTransfer(ctx, &shared.BatchTransferOptions{ + OperationName: "uploadFromReader", + TransferSize: actualSize, + ChunkSize: o.ChunkSize, + Concurrency: o.Concurrency, + Operation: func(ctx context.Context, offset int64, chunkSize int64) error { + // This function is called once per file range. + // It is passed this file's offset within the buffer and its count of bytes + // Prepare to read the proper range/section of the buffer + if chunkSize < o.ChunkSize { + // this is the last file range. Its actual size might be less + // than the calculated size due to rounding up of the payload + // size to fit in a whole number of chunks. + chunkSize = actualSize - offset + } + var body io.ReadSeeker = io.NewSectionReader(reader, offset, chunkSize) + if o.Progress != nil { + chunkProgress := int64(0) + body = streaming.NewRequestProgress(streaming.NopCloser(body), + func(bytesTransferred int64) { + diff := bytesTransferred - chunkProgress + chunkProgress = bytesTransferred + progressLock.Lock() // 1 goroutine at a time gets progress report + progress += diff + o.Progress(progress) + progressLock.Unlock() + }) + } + + uploadRangeOptions := o.getUploadRangeOptions() + _, err := f.UploadRange(ctx, offset, streaming.NopCloser(body), uploadRangeOptions) + return err + }, + }) + return err +} + +// UploadBuffer uploads a buffer in chunks to an Azure file. +func (f *Client) UploadBuffer(ctx context.Context, buffer []byte, options *UploadBufferOptions) error { + uploadOptions := uploadFromReaderOptions{} + if options != nil { + uploadOptions = *options + } + return f.uploadFromReader(ctx, bytes.NewReader(buffer), int64(len(buffer)), &uploadOptions) +} + +// UploadFile uploads a file in chunks to an Azure file. +func (f *Client) UploadFile(ctx context.Context, file *os.File, options *UploadFileOptions) error { + stat, err := file.Stat() + if err != nil { + return err + } + uploadOptions := uploadFromReaderOptions{} + if options != nil { + uploadOptions = *options + } + return f.uploadFromReader(ctx, file, stat.Size(), &uploadOptions) +} + +// UploadStream copies the file held in io.Reader to the file at fileClient. +// A Context deadline or cancellation will cause this to error. +func (f *Client) UploadStream(ctx context.Context, body io.Reader, options *UploadStreamOptions) error { + if options == nil { + options = &UploadStreamOptions{} + } + + err := copyFromReader(ctx, body, f, *options, newMMBPool) + return err +} + +// Concurrent Download Functions ----------------------------------------------------------------------------------------- + +// download method downloads an Azure file to a WriterAt in parallel. +func (f *Client) download(ctx context.Context, writer io.WriterAt, o downloadOptions) (int64, error) { + if o.ChunkSize == 0 { + o.ChunkSize = DefaultDownloadChunkSize + } + + count := o.Range.Count + if count == CountToEnd { // If size not specified, calculate it + // If we don't have the length at all, get it + getFilePropertiesOptions := o.getFilePropertiesOptions() + gr, err := f.GetProperties(ctx, getFilePropertiesOptions) + if err != nil { + return 0, err + } + count = *gr.ContentLength - o.Range.Offset + } + + if count <= 0 { + // The file is empty, there is nothing to download. + return 0, nil + } + + // Prepare and do parallel download. + progress := int64(0) + progressLock := &sync.Mutex{} + + err := shared.DoBatchTransfer(ctx, &shared.BatchTransferOptions{ + OperationName: "downloadFileToWriterAt", + TransferSize: count, + ChunkSize: o.ChunkSize, + Concurrency: o.Concurrency, + Operation: func(ctx context.Context, chunkStart int64, count int64) error { + downloadFileOptions := o.getDownloadFileOptions(HTTPRange{ + Offset: chunkStart + o.Range.Offset, + Count: count, + }) + dr, err := f.DownloadStream(ctx, downloadFileOptions) + if err != nil { + return err + } + var body io.ReadCloser = dr.NewRetryReader(ctx, &o.RetryReaderOptionsPerChunk) + if o.Progress != nil { + rangeProgress := int64(0) + body = streaming.NewResponseProgress( + body, + func(bytesTransferred int64) { + diff := bytesTransferred - rangeProgress + rangeProgress = bytesTransferred + progressLock.Lock() + progress += diff + o.Progress(progress) + progressLock.Unlock() + }) + } + _, err = io.Copy(shared.NewSectionWriter(writer, chunkStart, count), body) + if err != nil { + return err + } + err = body.Close() + return err + }, + }) + if err != nil { + return 0, err + } + return count, nil +} + +// DownloadStream operation reads or downloads a file from the system, including its metadata and properties. +// For more information, see https://learn.microsoft.com/en-us/rest/api/storageservices/get-file. +func (f *Client) DownloadStream(ctx context.Context, options *DownloadStreamOptions) (DownloadStreamResponse, error) { + opts, leaseAccessConditions := options.format() + if options == nil { + options = &DownloadStreamOptions{} + } + + resp, err := f.generated().Download(ctx, opts, leaseAccessConditions) + if err != nil { + return DownloadStreamResponse{}, err + } + + return DownloadStreamResponse{ + DownloadResponse: resp, + client: f, + getInfo: httpGetterInfo{Range: options.Range}, + leaseAccessConditions: options.LeaseAccessConditions, + }, err +} + +// DownloadBuffer downloads an Azure file to a buffer with parallel. +func (f *Client) DownloadBuffer(ctx context.Context, buffer []byte, o *DownloadBufferOptions) (int64, error) { + if o == nil { + o = &DownloadBufferOptions{} + } + + return f.download(ctx, shared.NewBytesWriter(buffer), (downloadOptions)(*o)) +} + +// DownloadFile downloads an Azure file to a local file. +// The file would be truncated if the size doesn't match. +func (f *Client) DownloadFile(ctx context.Context, file *os.File, o *DownloadFileOptions) (int64, error) { + if o == nil { + o = &DownloadFileOptions{} + } + do := (*downloadOptions)(o) + + // 1. Calculate the size of the destination file + var size int64 + + count := do.Range.Count + if count == CountToEnd { + // Try to get Azure file's size + getFilePropertiesOptions := do.getFilePropertiesOptions() + props, err := f.GetProperties(ctx, getFilePropertiesOptions) + if err != nil { + return 0, err + } + size = *props.ContentLength - do.Range.Offset + } else { + size = count + } + + // 2. Compare and try to resize local file's size if it doesn't match Azure file's size. + stat, err := file.Stat() + if err != nil { + return 0, err + } + if stat.Size() != size { + if err = file.Truncate(size); err != nil { + return 0, err + } + } + + if size > 0 { + return f.download(ctx, file, *do) + } else { // if the file's size is 0, there is no need in downloading it + return 0, nil + } +} diff --git a/sdk/storage/azfile/file/client_test.go b/sdk/storage/azfile/file/client_test.go new file mode 100644 index 000000000000..094b660b9d7b --- /dev/null +++ b/sdk/storage/azfile/file/client_test.go @@ -0,0 +1,3119 @@ +//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 file_test + +import ( + "bytes" + "context" + "crypto/md5" + "crypto/rand" + "encoding/binary" + "fmt" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/policy" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/streaming" + "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/azblob" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azfile/file" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azfile/fileerror" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azfile/internal/shared" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azfile/internal/testcommon" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azfile/sas" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azfile/share" + "github.com/stretchr/testify/require" + "github.com/stretchr/testify/suite" + "hash/crc64" + "io" + "io/ioutil" + "net/http" + "os" + "strings" + "testing" + "time" +) + +func Test(t *testing.T) { + recordMode := recording.GetRecordMode() + t.Logf("Running file Tests in %s mode\n", recordMode) + if recordMode == recording.LiveMode { + suite.Run(t, &FileRecordedTestsSuite{}) + suite.Run(t, &FileUnrecordedTestsSuite{}) + } else if recordMode == recording.PlaybackMode { + suite.Run(t, &FileRecordedTestsSuite{}) + } else if recordMode == recording.RecordingMode { + suite.Run(t, &FileRecordedTestsSuite{}) + } +} + +func (f *FileRecordedTestsSuite) BeforeTest(suite string, test string) { + testcommon.BeforeTest(f.T(), suite, test) +} + +func (f *FileRecordedTestsSuite) AfterTest(suite string, test string) { + testcommon.AfterTest(f.T(), suite, test) +} + +func (f *FileUnrecordedTestsSuite) BeforeTest(suite string, test string) { + +} + +func (f *FileUnrecordedTestsSuite) AfterTest(suite string, test string) { + +} + +type FileRecordedTestsSuite struct { + suite.Suite +} + +type FileUnrecordedTestsSuite struct { + suite.Suite +} + +func (f *FileRecordedTestsSuite) TestFileNewFileClient() { + _require := require.New(f.T()) + testName := f.T().Name() + + accountName, _ := testcommon.GetGenericAccountInfo(testcommon.TestAccountDefault) + _require.Greater(len(accountName), 0) + + svcClient, err := testcommon.GetServiceClient(f.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + shareName := testcommon.GenerateShareName(testName) + shareClient := svcClient.NewShareClient(shareName) + + dirName := testcommon.GenerateDirectoryName(testName) + dirClient := shareClient.NewDirectoryClient(dirName) + + fileName := testcommon.GenerateFileName(testName) + fileClient := dirClient.NewFileClient(fileName) + + correctURL := "https://" + accountName + ".file.core.windows.net/" + shareName + "/" + dirName + "/" + fileName + _require.Equal(fileClient.URL(), correctURL) + + rootFileClient := shareClient.NewRootDirectoryClient().NewFileClient(fileName) + + correctURL = "https://" + accountName + ".file.core.windows.net/" + shareName + "/" + fileName + _require.Equal(rootFileClient.URL(), correctURL) +} + +func (f *FileRecordedTestsSuite) TestFileCreateUsingSharedKey() { + _require := require.New(f.T()) + testName := f.T().Name() + + cred, err := testcommon.GetGenericSharedKeyCredential(testcommon.TestAccountDefault) + _require.NoError(err) + + svcClient, err := testcommon.GetServiceClient(f.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + shareName := testcommon.GenerateShareName(testName) + shareClient := testcommon.CreateNewShare(context.Background(), _require, shareName, svcClient) + defer testcommon.DeleteShare(context.Background(), _require, shareClient) + + dirName := testcommon.GenerateDirectoryName(testName) + fileName := testcommon.GenerateFileName(testName) + fileURL := "https://" + cred.AccountName() + ".file.core.windows.net/" + shareName + "/" + dirName + "/" + fileName + + options := &file.ClientOptions{} + testcommon.SetClientOptions(f.T(), &options.ClientOptions) + fileClient, err := file.NewClientWithSharedKeyCredential(fileURL, cred, options) + _require.NoError(err) + + // creating file where directory does not exist gives ParentNotFound error + _, err = fileClient.Create(context.Background(), 1024, nil) + _require.Error(err) + testcommon.ValidateFileErrorCode(_require, err, fileerror.ParentNotFound) + + testcommon.CreateNewDirectory(context.Background(), _require, dirName, shareClient) + + resp, err := fileClient.Create(context.Background(), 1024, nil) + _require.NoError(err) + _require.NotNil(resp.ETag) + _require.NotNil(resp.RequestID) + _require.Equal(resp.LastModified.IsZero(), false) + _require.Equal(resp.FileCreationTime.IsZero(), false) + _require.Equal(resp.FileLastWriteTime.IsZero(), false) + _require.Equal(resp.FileChangeTime.IsZero(), false) +} + +func (f *FileRecordedTestsSuite) TestFileCreateUsingConnectionString() { + _require := require.New(f.T()) + testName := f.T().Name() + + connString, err := testcommon.GetGenericConnectionString(testcommon.TestAccountDefault) + _require.NoError(err) + + svcClient, err := testcommon.GetServiceClient(f.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + shareName := testcommon.GenerateShareName(testName) + shareClient := testcommon.CreateNewShare(context.Background(), _require, shareName, svcClient) + defer testcommon.DeleteShare(context.Background(), _require, shareClient) + + dirName := testcommon.GenerateDirectoryName(testName) + fileName := testcommon.GenerateFileName(testName) + options := &file.ClientOptions{} + testcommon.SetClientOptions(f.T(), &options.ClientOptions) + fileClient1, err := file.NewClientFromConnectionString(*connString, shareName, fileName, options) + _require.NoError(err) + + resp, err := fileClient1.Create(context.Background(), 1024, nil) + _require.NoError(err) + _require.NotNil(resp.ETag) + _require.NotNil(resp.RequestID) + _require.Equal(resp.LastModified.IsZero(), false) + _require.Equal(resp.FileCreationTime.IsZero(), false) + _require.Equal(resp.FileLastWriteTime.IsZero(), false) + _require.Equal(resp.FileChangeTime.IsZero(), false) + + filePath := dirName + "/" + fileName + fileClient2, err := file.NewClientFromConnectionString(*connString, shareName, filePath, options) + _require.NoError(err) + + _, err = fileClient2.Create(context.Background(), 1024, nil) + _require.Error(err) + testcommon.ValidateFileErrorCode(_require, err, fileerror.ParentNotFound) + + testcommon.CreateNewDirectory(context.Background(), _require, dirName, shareClient) + + // using '\' as path separator + filePath = dirName + "\\" + fileName + fileClient3, err := file.NewClientFromConnectionString(*connString, shareName, filePath, options) + _require.NoError(err) + + resp, err = fileClient3.Create(context.Background(), 1024, nil) + _require.NoError(err) + _require.NotNil(resp.RequestID) + _require.Equal(resp.LastModified.IsZero(), false) + _require.Equal(resp.FileCreationTime.IsZero(), false) +} + +func (f *FileUnrecordedTestsSuite) TestFileClientUsingSAS() { + _require := require.New(f.T()) + testName := f.T().Name() + + svcClient, err := testcommon.GetServiceClient(f.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + shareName := testcommon.GenerateShareName(testName) + shareClient := testcommon.CreateNewShare(context.Background(), _require, shareName, svcClient) + defer testcommon.DeleteShare(context.Background(), _require, shareClient) + + dirName := testcommon.GenerateDirectoryName(testName) + dirClient := testcommon.CreateNewDirectory(context.Background(), _require, dirName, shareClient) + + fileName := testcommon.GenerateFileName(testName) + fileClient := dirClient.NewFileClient(fileName) + + permissions := sas.FilePermissions{ + Read: true, + Write: true, + Delete: true, + Create: true, + } + expiry := time.Now().Add(time.Hour) + + fileSASURL, err := fileClient.GetSASURL(permissions, expiry, nil) + _require.NoError(err) + + fileSASClient, err := file.NewClientWithNoCredential(fileSASURL, nil) + _require.NoError(err) + + _, err = fileSASClient.GetProperties(context.Background(), nil) + _require.Error(err) + testcommon.ValidateFileErrorCode(_require, err, fileerror.ResourceNotFound) + + _, err = fileSASClient.Create(context.Background(), 1024, nil) + _require.NoError(err) + + resp, err := fileSASClient.GetProperties(context.Background(), nil) + _require.NoError(err) + _require.NotNil(resp.RequestID) + _require.Equal(resp.LastModified.IsZero(), false) + _require.Equal(resp.FileCreationTime.IsZero(), false) +} + +func (f *FileRecordedTestsSuite) TestFileCreateDeleteDefault() { + _require := require.New(f.T()) + testName := f.T().Name() + + svcClient, err := testcommon.GetServiceClient(f.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + shareName := testcommon.GenerateShareName(testName) + shareClient := testcommon.CreateNewShare(context.Background(), _require, shareName, svcClient) + defer testcommon.DeleteShare(context.Background(), _require, shareClient) + + fileName := testcommon.GenerateFileName(testName) + rootDirClient := shareClient.NewRootDirectoryClient() + _require.NoError(err) + + fClient := rootDirClient.NewFileClient(fileName) + + // Create and delete file in root directory. + cResp, err := fClient.Create(context.Background(), 1024, nil) + _require.NoError(err) + _require.NotNil(cResp.ETag) + _require.Equal(cResp.LastModified.IsZero(), false) + _require.NotNil(cResp.RequestID) + _require.NotNil(cResp.Version) + _require.Equal(cResp.Date.IsZero(), false) + _require.NotNil(cResp.IsServerEncrypted) + + delResp, err := fClient.Delete(context.Background(), nil) + _require.NoError(err) + _require.NotNil(delResp.RequestID) + _require.NotNil(delResp.Version) + _require.Equal(delResp.Date.IsZero(), false) + + dirClient := testcommon.CreateNewDirectory(context.Background(), _require, testcommon.GenerateDirectoryName(testName), shareClient) + + // Create and delete file in named directory. + afClient := dirClient.NewFileClient(fileName) + + cResp, err = afClient.Create(context.Background(), 1024, nil) + _require.NoError(err) + _require.NotNil(cResp.ETag) + _require.Equal(cResp.LastModified.IsZero(), false) + _require.NotNil(cResp.RequestID) + _require.NotNil(cResp.Version) + _require.Equal(cResp.Date.IsZero(), false) + _require.NotNil(cResp.IsServerEncrypted) + + delResp, err = afClient.Delete(context.Background(), nil) + _require.NoError(err) + _require.NotNil(delResp.RequestID) + _require.NotNil(delResp.Version) + _require.Equal(delResp.Date.IsZero(), false) +} + +func (f *FileRecordedTestsSuite) TestFileCreateNonDefaultMetadataNonEmpty() { + _require := require.New(f.T()) + testName := f.T().Name() + + svcClient, err := testcommon.GetServiceClient(f.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + shareClient := testcommon.CreateNewShare(context.Background(), _require, testcommon.GenerateShareName(testName), svcClient) + defer testcommon.DeleteShare(context.Background(), _require, shareClient) + + fClient := shareClient.NewRootDirectoryClient().NewFileClient(testcommon.GenerateFileName(testName)) + + _, err = fClient.Create(context.Background(), 1024, &file.CreateOptions{ + Metadata: testcommon.BasicMetadata, + }) + _require.NoError(err) + + resp, err := fClient.GetProperties(context.Background(), nil) + _require.NoError(err) + _require.Len(resp.Metadata, len(testcommon.BasicMetadata)) + for k, v := range resp.Metadata { + val := testcommon.BasicMetadata[strings.ToLower(k)] + _require.NotNil(val) + _require.Equal(*v, *val) + } +} + +func (f *FileRecordedTestsSuite) TestFileCreateNonDefaultHTTPHeaders() { + _require := require.New(f.T()) + testName := f.T().Name() + svcClient, err := testcommon.GetServiceClient(f.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + shareClient := testcommon.CreateNewShare(context.Background(), _require, testcommon.GenerateShareName(testName), svcClient) + defer testcommon.DeleteShare(context.Background(), _require, shareClient) + + fClient := shareClient.NewRootDirectoryClient().NewFileClient(testcommon.GenerateFileName(testName)) + + httpHeaders := file.HTTPHeaders{ + ContentType: to.Ptr("my_type"), + ContentDisposition: to.Ptr("my_disposition"), + CacheControl: to.Ptr("control"), + ContentMD5: nil, + ContentLanguage: to.Ptr("my_language"), + ContentEncoding: to.Ptr("my_encoding"), + } + + _, err = fClient.Create(context.Background(), 1024, &file.CreateOptions{ + HTTPHeaders: &httpHeaders, + }) + _require.NoError(err) + + resp, err := fClient.GetProperties(context.Background(), nil) + _require.NoError(err) + _require.EqualValues(resp.ContentType, httpHeaders.ContentType) + _require.EqualValues(resp.ContentDisposition, httpHeaders.ContentDisposition) + _require.EqualValues(resp.CacheControl, httpHeaders.CacheControl) + _require.EqualValues(resp.ContentLanguage, httpHeaders.ContentLanguage) + _require.EqualValues(resp.ContentEncoding, httpHeaders.ContentEncoding) + _require.Nil(resp.ContentMD5) +} + +func (f *FileRecordedTestsSuite) TestFileCreateNegativeMetadataInvalid() { + _require := require.New(f.T()) + testName := f.T().Name() + + svcClient, err := testcommon.GetServiceClient(f.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + shareClient := testcommon.CreateNewShare(context.Background(), _require, testcommon.GenerateShareName(testName), svcClient) + defer testcommon.DeleteShare(context.Background(), _require, shareClient) + + fClient := shareClient.NewRootDirectoryClient().NewFileClient(testcommon.GenerateFileName(testName)) + + _, err = fClient.Create(context.Background(), 1024, &file.CreateOptions{ + Metadata: map[string]*string{"!@#$%^&*()": to.Ptr("!@#$%^&*()")}, + HTTPHeaders: &file.HTTPHeaders{}, + }) + _require.Error(err) +} + +func (f *FileUnrecordedTestsSuite) TestFileGetSetPropertiesNonDefault() { + _require := require.New(f.T()) + testName := f.T().Name() + svcClient, err := testcommon.GetServiceClient(f.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + shareClient := testcommon.CreateNewShare(context.Background(), _require, testcommon.GenerateShareName(testName), svcClient) + defer testcommon.DeleteShare(context.Background(), _require, shareClient) + + fClient := shareClient.NewRootDirectoryClient().NewFileClient(testcommon.GenerateFileName(testName)) + _, err = fClient.Create(context.Background(), 0, nil) + _require.NoError(err) + + md5Str := "MDAwMDAwMDA=" + testMd5 := []byte(md5Str) + + creationTime := time.Now().Add(-time.Hour) + lastWriteTime := time.Now().Add(-time.Minute * 15) + + options := &file.SetHTTPHeadersOptions{ + Permissions: &file.Permissions{Permission: &testcommon.SampleSDDL}, + SMBProperties: &file.SMBProperties{ + Attributes: &file.NTFSFileAttributes{Hidden: true}, + CreationTime: &creationTime, + LastWriteTime: &lastWriteTime, + }, + HTTPHeaders: &file.HTTPHeaders{ + ContentType: to.Ptr("text/html"), + ContentEncoding: to.Ptr("gzip"), + ContentLanguage: to.Ptr("en"), + ContentMD5: testMd5, + CacheControl: to.Ptr("no-transform"), + ContentDisposition: to.Ptr("attachment"), + }, + } + setResp, err := fClient.SetHTTPHeaders(context.Background(), options) + _require.NoError(err) + _require.NotNil(setResp.ETag) + _require.Equal(setResp.LastModified.IsZero(), false) + _require.NotNil(setResp.RequestID) + _require.NotNil(setResp.Version) + _require.Equal(setResp.Date.IsZero(), false) + _require.NotNil(setResp.IsServerEncrypted) + + getResp, err := fClient.GetProperties(context.Background(), nil) + _require.NoError(err) + _require.Equal(setResp.LastModified.IsZero(), false) + _require.Equal(*getResp.FileType, "File") + + _require.EqualValues(getResp.ContentType, options.HTTPHeaders.ContentType) + _require.EqualValues(getResp.ContentEncoding, options.HTTPHeaders.ContentEncoding) + _require.EqualValues(getResp.ContentLanguage, options.HTTPHeaders.ContentLanguage) + _require.EqualValues(getResp.ContentMD5, options.HTTPHeaders.ContentMD5) + _require.EqualValues(getResp.CacheControl, options.HTTPHeaders.CacheControl) + _require.EqualValues(getResp.ContentDisposition, options.HTTPHeaders.ContentDisposition) + _require.Equal(*getResp.ContentLength, int64(0)) + // We'll just ensure a permission exists, no need to test overlapping functionality. + _require.NotEqual(getResp.FilePermissionKey, "") + _require.Equal(*getResp.FileAttributes, options.SMBProperties.Attributes.String()) + + _require.EqualValues((*getResp.FileCreationTime).Format(testcommon.ISO8601), creationTime.UTC().Format(testcommon.ISO8601)) + _require.EqualValues((*getResp.FileLastWriteTime).Format(testcommon.ISO8601), lastWriteTime.UTC().Format(testcommon.ISO8601)) + + _require.NotNil(getResp.ETag) + _require.NotNil(getResp.RequestID) + _require.NotNil(getResp.Version) + _require.Equal(getResp.Date.IsZero(), false) + _require.NotNil(getResp.IsServerEncrypted) +} + +func (f *FileRecordedTestsSuite) TestFileGetSetPropertiesDefault() { + _require := require.New(f.T()) + testName := f.T().Name() + + svcClient, err := testcommon.GetServiceClient(f.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + shareClient := testcommon.CreateNewShare(context.Background(), _require, testcommon.GenerateShareName(testName), svcClient) + defer testcommon.DeleteShare(context.Background(), _require, shareClient) + + fClient := testcommon.CreateNewFileFromShare(context.Background(), _require, testcommon.GenerateFileName(testName), 0, shareClient) + + setResp, err := fClient.SetHTTPHeaders(context.Background(), nil) + _require.NoError(err) + _require.NotEqual(*setResp.ETag, "") + _require.Equal(setResp.LastModified.IsZero(), false) + _require.NotEqual(setResp.RequestID, "") + _require.NotEqual(setResp.Version, "") + _require.Equal(setResp.Date.IsZero(), false) + _require.NotNil(setResp.IsServerEncrypted) + + metadata := map[string]*string{ + "Foo": to.Ptr("Foovalue"), + "Bar": to.Ptr("Barvalue"), + } + _, err = fClient.SetMetadata(context.Background(), &file.SetMetadataOptions{ + Metadata: metadata, + }) + _require.NoError(err) + + // get properties on the share snapshot + getResp, err := fClient.GetProperties(context.Background(), nil) + _require.NoError(err) + _require.Equal(setResp.LastModified.IsZero(), false) + _require.Equal(*getResp.FileType, "File") + + _require.Nil(getResp.ContentType) + _require.Nil(getResp.ContentEncoding) + _require.Nil(getResp.ContentLanguage) + _require.Nil(getResp.ContentMD5) + _require.Nil(getResp.CacheControl) + _require.Nil(getResp.ContentDisposition) + _require.Equal(*getResp.ContentLength, int64(0)) + + _require.NotNil(getResp.ETag) + _require.NotNil(getResp.RequestID) + _require.NotNil(getResp.Version) + _require.Equal(getResp.Date.IsZero(), false) + _require.NotNil(getResp.IsServerEncrypted) + _require.EqualValues(getResp.Metadata, metadata) +} + +func (f *FileRecordedTestsSuite) TestFilePreservePermissions() { + _require := require.New(f.T()) + testName := f.T().Name() + + svcClient, err := testcommon.GetServiceClient(f.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + shareClient := testcommon.CreateNewShare(context.Background(), _require, testcommon.GenerateShareName(testName), svcClient) + defer testcommon.DeleteShare(context.Background(), _require, shareClient) + + fClient := shareClient.NewRootDirectoryClient().NewFileClient(testcommon.GenerateFileName(testName)) + _, err = fClient.Create(context.Background(), 0, &file.CreateOptions{ + Permissions: &file.Permissions{ + Permission: &testcommon.SampleSDDL, + }, + }) + _require.NoError(err) + + // Grab the original perm key before we set file headers. + getResp, err := fClient.GetProperties(context.Background(), nil) + _require.NoError(err) + + pKey := getResp.FilePermissionKey + cTime := getResp.FileCreationTime + lwTime := getResp.FileLastWriteTime + attribs := getResp.FileAttributes + + md5Str := "MDAwMDAwMDA=" + testMd5 := []byte(md5Str) + + properties := file.SetHTTPHeadersOptions{ + HTTPHeaders: &file.HTTPHeaders{ + ContentType: to.Ptr("text/html"), + ContentEncoding: to.Ptr("gzip"), + ContentLanguage: to.Ptr("en"), + ContentMD5: testMd5, + CacheControl: to.Ptr("no-transform"), + ContentDisposition: to.Ptr("attachment"), + }, + // SMBProperties, when options are left nil, leads to preserving. + SMBProperties: &file.SMBProperties{}, + } + + setResp, err := fClient.SetHTTPHeaders(context.Background(), &properties) + _require.NoError(err) + _require.NotNil(setResp.ETag) + _require.NotNil(setResp.RequestID) + _require.NotNil(setResp.LastModified) + _require.Equal(setResp.LastModified.IsZero(), false) + _require.NotNil(setResp.Version) + _require.Equal(setResp.Date.IsZero(), false) + + getResp, err = fClient.GetProperties(context.Background(), nil) + _require.NoError(err) + _require.NotNil(setResp.LastModified) + _require.Equal(setResp.LastModified.IsZero(), false) + _require.Equal(*getResp.FileType, "File") + + _require.EqualValues(getResp.ContentType, properties.HTTPHeaders.ContentType) + _require.EqualValues(getResp.ContentEncoding, properties.HTTPHeaders.ContentEncoding) + _require.EqualValues(getResp.ContentLanguage, properties.HTTPHeaders.ContentLanguage) + _require.EqualValues(getResp.ContentMD5, properties.HTTPHeaders.ContentMD5) + _require.EqualValues(getResp.CacheControl, properties.HTTPHeaders.CacheControl) + _require.EqualValues(getResp.ContentDisposition, properties.HTTPHeaders.ContentDisposition) + _require.Equal(*getResp.ContentLength, int64(0)) + // Ensure that the permission key gets preserved + _require.EqualValues(getResp.FilePermissionKey, pKey) + _require.EqualValues(cTime, getResp.FileCreationTime) + _require.EqualValues(lwTime, getResp.FileLastWriteTime) + _require.EqualValues(attribs, getResp.FileAttributes) + + _require.NotNil(getResp.ETag) + _require.NotNil(getResp.RequestID) + _require.NotNil(getResp.Version) + _require.Equal(getResp.Date.IsZero(), false) + _require.NotNil(getResp.IsServerEncrypted) +} + +func (f *FileRecordedTestsSuite) TestFileGetSetPropertiesSnapshot() { + _require := require.New(f.T()) + testName := f.T().Name() + + svcClient, err := testcommon.GetServiceClient(f.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + shareClient := testcommon.CreateNewShare(context.Background(), _require, testcommon.GenerateShareName(testName), svcClient) + defer func() { + _, err := shareClient.Delete(context.Background(), &share.DeleteOptions{DeleteSnapshots: to.Ptr(share.DeleteSnapshotsOptionTypeInclude)}) + _require.NoError(err) + }() + + fClient := shareClient.NewRootDirectoryClient().NewFileClient(testcommon.GenerateFileName(testName)) + _, err = fClient.Create(context.Background(), 0, nil) + _require.NoError(err) + + md5Str := "MDAwMDAwMDA=" + testMd5 := []byte(md5Str) + + fileSetHTTPHeadersOptions := file.SetHTTPHeadersOptions{ + HTTPHeaders: &file.HTTPHeaders{ + ContentType: to.Ptr("text/html"), + ContentEncoding: to.Ptr("gzip"), + ContentLanguage: to.Ptr("en"), + ContentMD5: testMd5, + CacheControl: to.Ptr("no-transform"), + ContentDisposition: to.Ptr("attachment"), + }, + } + setResp, err := fClient.SetHTTPHeaders(context.Background(), &fileSetHTTPHeadersOptions) + _require.NoError(err) + _require.NotEqual(*setResp.ETag, "") + _require.Equal(setResp.LastModified.IsZero(), false) + _require.NotEqual(setResp.RequestID, "") + _require.NotEqual(setResp.Version, "") + _require.Equal(setResp.Date.IsZero(), false) + _require.NotNil(setResp.IsServerEncrypted) + + metadata := map[string]*string{ + "Foo": to.Ptr("Foovalue"), + "Bar": to.Ptr("Barvalue"), + } + _, err = fClient.SetMetadata(context.Background(), &file.SetMetadataOptions{ + Metadata: metadata, + }) + _require.NoError(err) + + resp, err := shareClient.CreateSnapshot(context.Background(), &share.CreateSnapshotOptions{Metadata: map[string]*string{}}) + _require.NoError(err) + _require.NotNil(resp.Snapshot) + + // get properties on the share snapshot + getResp, err := fClient.GetProperties(context.Background(), &file.GetPropertiesOptions{ + ShareSnapshot: resp.Snapshot, + }) + _require.NoError(err) + _require.Equal(setResp.LastModified.IsZero(), false) + _require.Equal(*getResp.FileType, "File") + + _require.EqualValues(getResp.ContentType, fileSetHTTPHeadersOptions.HTTPHeaders.ContentType) + _require.EqualValues(getResp.ContentEncoding, fileSetHTTPHeadersOptions.HTTPHeaders.ContentEncoding) + _require.EqualValues(getResp.ContentLanguage, fileSetHTTPHeadersOptions.HTTPHeaders.ContentLanguage) + _require.EqualValues(getResp.ContentMD5, fileSetHTTPHeadersOptions.HTTPHeaders.ContentMD5) + _require.EqualValues(getResp.CacheControl, fileSetHTTPHeadersOptions.HTTPHeaders.CacheControl) + _require.EqualValues(getResp.ContentDisposition, fileSetHTTPHeadersOptions.HTTPHeaders.ContentDisposition) + _require.Equal(*getResp.ContentLength, int64(0)) + + _require.NotNil(getResp.ETag) + _require.NotNil(getResp.RequestID) + _require.NotNil(getResp.Version) + _require.Equal(getResp.Date.IsZero(), false) + _require.NotNil(getResp.IsServerEncrypted) + _require.EqualValues(getResp.Metadata, metadata) +} + +func (f *FileRecordedTestsSuite) TestGetSetMetadataNonDefault() { + _require := require.New(f.T()) + testName := f.T().Name() + + svcClient, err := testcommon.GetServiceClient(f.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + shareClient := testcommon.CreateNewShare(context.Background(), _require, testcommon.GenerateShareName(testName), svcClient) + defer testcommon.DeleteShare(context.Background(), _require, shareClient) + + fClient := shareClient.NewRootDirectoryClient().NewFileClient(testcommon.GenerateFileName(testName)) + _, err = fClient.Create(context.Background(), 0, nil) + _require.NoError(err) + + metadata := map[string]*string{ + "Foo": to.Ptr("Foovalue"), + "Bar": to.Ptr("Barvalue"), + } + setResp, err := fClient.SetMetadata(context.Background(), &file.SetMetadataOptions{ + Metadata: metadata, + }) + _require.NoError(err) + _require.NotNil(setResp.ETag) + _require.NotNil(setResp.RequestID) + _require.NotNil(setResp.Version) + _require.Equal(setResp.Date.IsZero(), false) + _require.NotNil(setResp.IsServerEncrypted) + + getResp, err := fClient.GetProperties(context.Background(), nil) + _require.NoError(err) + _require.NotNil(getResp.ETag) + _require.NotNil(getResp.RequestID) + _require.NotNil(getResp.Version) + _require.Equal(getResp.Date.IsZero(), false) + _require.NotNil(getResp.IsServerEncrypted) + _require.EqualValues(getResp.Metadata, metadata) +} + +func (f *FileRecordedTestsSuite) TestFileSetMetadataNil() { + _require := require.New(f.T()) + testName := f.T().Name() + + svcClient, err := testcommon.GetServiceClient(f.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + shareClient := testcommon.CreateNewShare(context.Background(), _require, testcommon.GenerateShareName(testName), svcClient) + defer testcommon.DeleteShare(context.Background(), _require, shareClient) + + fClient := shareClient.NewRootDirectoryClient().NewFileClient(testcommon.GenerateFileName(testName)) + _, err = fClient.Create(context.Background(), 0, nil) + _require.NoError(err) + + md := map[string]*string{"Not": to.Ptr("nil")} + + _, err = fClient.SetMetadata(context.Background(), &file.SetMetadataOptions{ + Metadata: md, + }) + _require.NoError(err) + + resp1, err := fClient.GetProperties(context.Background(), nil) + _require.NoError(err) + _require.EqualValues(resp1.Metadata, md) + + _, err = fClient.SetMetadata(context.Background(), nil) + _require.NoError(err) + + resp2, err := fClient.GetProperties(context.Background(), nil) + _require.NoError(err) + _require.Len(resp2.Metadata, 0) +} + +func (f *FileRecordedTestsSuite) TestFileSetMetadataDefaultEmpty() { + _require := require.New(f.T()) + testName := f.T().Name() + + svcClient, err := testcommon.GetServiceClient(f.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + shareClient := testcommon.CreateNewShare(context.Background(), _require, testcommon.GenerateShareName(testName), svcClient) + defer testcommon.DeleteShare(context.Background(), _require, shareClient) + + fClient := shareClient.NewRootDirectoryClient().NewFileClient(testcommon.GenerateFileName(testName)) + _, err = fClient.Create(context.Background(), 0, nil) + _require.NoError(err) + + md := map[string]*string{"Not": to.Ptr("nil")} + + _, err = fClient.SetMetadata(context.Background(), &file.SetMetadataOptions{ + Metadata: md, + }) + _require.NoError(err) + + resp1, err := fClient.GetProperties(context.Background(), nil) + _require.NoError(err) + _require.EqualValues(resp1.Metadata, md) + + _, err = fClient.SetMetadata(context.Background(), &file.SetMetadataOptions{ + Metadata: map[string]*string{}, + }) + _require.NoError(err) + + resp2, err := fClient.GetProperties(context.Background(), nil) + _require.NoError(err) + _require.Len(resp2.Metadata, 0) +} + +func (f *FileRecordedTestsSuite) TestFileSetMetadataInvalidField() { + _require := require.New(f.T()) + testName := f.T().Name() + + svcClient, err := testcommon.GetServiceClient(f.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + shareClient := testcommon.CreateNewShare(context.Background(), _require, testcommon.GenerateShareName(testName), svcClient) + defer testcommon.DeleteShare(context.Background(), _require, shareClient) + + fClient := shareClient.NewRootDirectoryClient().NewFileClient(testcommon.GenerateFileName(testName)) + _, err = fClient.Create(context.Background(), 0, nil) + _require.NoError(err) + + _, err = fClient.SetMetadata(context.Background(), &file.SetMetadataOptions{ + Metadata: map[string]*string{"!@#$%^&*()": to.Ptr("!@#$%^&*()")}, + }) + _require.Error(err) +} + +func (f *FileRecordedTestsSuite) TestStartCopyDefault() { + _require := require.New(f.T()) + testName := f.T().Name() + + svcClient, err := testcommon.GetServiceClient(f.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + shareClient := testcommon.CreateNewShare(context.Background(), _require, testcommon.GenerateShareName(testName), svcClient) + defer testcommon.DeleteShare(context.Background(), _require, shareClient) + + srcFile := shareClient.NewRootDirectoryClient().NewFileClient("src" + testcommon.GenerateFileName(testName)) + destFile := shareClient.NewRootDirectoryClient().NewFileClient("dest" + testcommon.GenerateFileName(testName)) + + fileSize := int64(2048) + _, err = srcFile.Create(context.Background(), fileSize, nil) + _require.NoError(err) + + contentR, srcContent := testcommon.GenerateData(int(fileSize)) + srcContentMD5 := md5.Sum(srcContent) + + _, err = srcFile.UploadRange(context.Background(), 0, contentR, nil) + _require.NoError(err) + + copyResp, err := destFile.StartCopyFromURL(context.Background(), srcFile.URL(), nil) + _require.NoError(err) + _require.NotNil(copyResp.ETag) + _require.Equal(copyResp.LastModified.IsZero(), false) + _require.NotNil(copyResp.RequestID) + _require.NotNil(copyResp.Version) + _require.Equal(copyResp.Date.IsZero(), false) + _require.NotEqual(copyResp.CopyStatus, "") + + time.Sleep(time.Duration(5) * time.Second) + + getResp, err := destFile.GetProperties(context.Background(), nil) + _require.NoError(err) + _require.EqualValues(getResp.CopyID, copyResp.CopyID) + _require.NotEqual(*getResp.CopyStatus, "") + _require.Equal(*getResp.CopySource, srcFile.URL()) + _require.Equal(*getResp.CopyStatus, file.CopyStatusTypeSuccess) + + // Abort will fail after copy finished + _, err = destFile.AbortCopy(context.Background(), *copyResp.CopyID, nil) + _require.Error(err) + testcommon.ValidateHTTPErrorCode(_require, err, http.StatusConflict) + + // validate data copied + dResp, err := destFile.DownloadStream(context.Background(), &file.DownloadStreamOptions{ + Range: file.HTTPRange{Offset: 0, Count: fileSize}, + RangeGetContentMD5: to.Ptr(true), + }) + _require.NoError(err) + + destContent, err := io.ReadAll(dResp.Body) + _require.NoError(err) + _require.EqualValues(srcContent, destContent) + _require.Equal(dResp.ContentMD5, srcContentMD5[:]) +} + +func (f *FileRecordedTestsSuite) TestFileStartCopyDestEmpty() { + _require := require.New(f.T()) + testName := f.T().Name() + + svcClient, err := testcommon.GetServiceClient(f.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + shareClient := testcommon.CreateNewShare(context.Background(), _require, testcommon.GenerateShareName(testName), svcClient) + defer testcommon.DeleteShare(context.Background(), _require, shareClient) + + fClient := testcommon.CreateNewFileFromShareWithData(context.Background(), _require, "src"+testcommon.GenerateFileName(testName), shareClient) + copyFClient := testcommon.GetFileClientFromShare("dest"+testcommon.GenerateFileName(testName), shareClient) + + _, err = copyFClient.StartCopyFromURL(context.Background(), fClient.URL(), nil) + _require.NoError(err) + + time.Sleep(4 * time.Second) + + resp, err := copyFClient.DownloadStream(context.Background(), nil) + _require.NoError(err) + + // Read the file data to verify the copy + data, err := ioutil.ReadAll(resp.Body) + defer func() { + err = resp.Body.Close() + _require.NoError(err) + }() + + _require.NoError(err) + _require.Equal(*resp.ContentLength, int64(len(testcommon.FileDefaultData))) + _require.Equal(string(data), testcommon.FileDefaultData) +} + +func (f *FileRecordedTestsSuite) TestFileStartCopyMetadata() { + _require := require.New(f.T()) + testName := f.T().Name() + + svcClient, err := testcommon.GetServiceClient(f.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + shareClient := testcommon.CreateNewShare(context.Background(), _require, testcommon.GenerateShareName(testName), svcClient) + defer testcommon.DeleteShare(context.Background(), _require, shareClient) + + fClient := shareClient.NewRootDirectoryClient().NewFileClient("src" + testcommon.GenerateFileName(testName)) + copyFClient := shareClient.NewRootDirectoryClient().NewFileClient("dst" + testcommon.GenerateFileName(testName)) + + _, err = fClient.Create(context.Background(), 0, nil) + _require.NoError(err) + + basicMetadata := map[string]*string{ + "Foo": to.Ptr("Foovalue"), + "Bar": to.Ptr("Barvalue"), + } + _, err = copyFClient.StartCopyFromURL(context.Background(), fClient.URL(), &file.StartCopyFromURLOptions{Metadata: basicMetadata}) + _require.NoError(err) + + time.Sleep(4 * time.Second) + + resp2, err := copyFClient.GetProperties(context.Background(), nil) + _require.NoError(err) + _require.EqualValues(resp2.Metadata, basicMetadata) +} + +func (f *FileRecordedTestsSuite) TestFileStartCopyMetadataNil() { + _require := require.New(f.T()) + testName := f.T().Name() + + svcClient, err := testcommon.GetServiceClient(f.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + shareClient := testcommon.CreateNewShare(context.Background(), _require, testcommon.GenerateShareName(testName), svcClient) + defer testcommon.DeleteShare(context.Background(), _require, shareClient) + + fClient := shareClient.NewRootDirectoryClient().NewFileClient("src" + testcommon.GenerateFileName(testName)) + copyFClient := shareClient.NewRootDirectoryClient().NewFileClient("dst" + testcommon.GenerateFileName(testName)) + + _, err = fClient.Create(context.Background(), 0, nil) + _require.NoError(err) + + basicMetadata := map[string]*string{ + "Foo": to.Ptr("Foovalue"), + "Bar": to.Ptr("Barvalue"), + } + + // Have the destination start with metadata so we ensure the nil metadata passed later takes effect + _, err = copyFClient.Create(context.Background(), 0, &file.CreateOptions{Metadata: basicMetadata}) + _require.NoError(err) + + gResp, err := copyFClient.GetProperties(context.Background(), nil) + _require.NoError(err) + _require.EqualValues(gResp.Metadata, basicMetadata) + + _, err = copyFClient.StartCopyFromURL(context.Background(), fClient.URL(), nil) + _require.NoError(err) + + time.Sleep(4 * time.Second) + + resp2, err := copyFClient.GetProperties(context.Background(), nil) + _require.NoError(err) + _require.Len(resp2.Metadata, 0) +} + +func (f *FileRecordedTestsSuite) TestFileStartCopyMetadataEmpty() { + _require := require.New(f.T()) + testName := f.T().Name() + + svcClient, err := testcommon.GetServiceClient(f.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + shareClient := testcommon.CreateNewShare(context.Background(), _require, testcommon.GenerateShareName(testName), svcClient) + defer testcommon.DeleteShare(context.Background(), _require, shareClient) + + fClient := shareClient.NewRootDirectoryClient().NewFileClient("src" + testcommon.GenerateFileName(testName)) + copyFClient := shareClient.NewRootDirectoryClient().NewFileClient("dst" + testcommon.GenerateFileName(testName)) + + _, err = fClient.Create(context.Background(), 0, nil) + _require.NoError(err) + + basicMetadata := map[string]*string{ + "Foo": to.Ptr("Foovalue"), + "Bar": to.Ptr("Barvalue"), + } + + // Have the destination start with metadata so we ensure the nil metadata passed later takes effect + _, err = copyFClient.Create(context.Background(), 0, &file.CreateOptions{Metadata: basicMetadata}) + _require.NoError(err) + + gResp, err := copyFClient.GetProperties(context.Background(), nil) + _require.NoError(err) + _require.EqualValues(gResp.Metadata, basicMetadata) + + _, err = copyFClient.StartCopyFromURL(context.Background(), fClient.URL(), &file.StartCopyFromURLOptions{Metadata: map[string]*string{}}) + _require.NoError(err) + + time.Sleep(4 * time.Second) + + resp2, err := copyFClient.GetProperties(context.Background(), nil) + _require.NoError(err) + _require.Len(resp2.Metadata, 0) +} + +func (f *FileRecordedTestsSuite) TestFileStartCopyNegativeMetadataInvalidField() { + _require := require.New(f.T()) + testName := f.T().Name() + + svcClient, err := testcommon.GetServiceClient(f.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + shareClient := testcommon.CreateNewShare(context.Background(), _require, testcommon.GenerateShareName(testName), svcClient) + defer testcommon.DeleteShare(context.Background(), _require, shareClient) + + fClient := shareClient.NewRootDirectoryClient().NewFileClient("src" + testcommon.GenerateFileName(testName)) + copyFClient := shareClient.NewRootDirectoryClient().NewFileClient("dst" + testcommon.GenerateFileName(testName)) + + _, err = fClient.Create(context.Background(), 0, nil) + _require.NoError(err) + + _, err = copyFClient.StartCopyFromURL(context.Background(), fClient.URL(), &file.StartCopyFromURLOptions{ + Metadata: map[string]*string{"!@#$%^&*()": to.Ptr("!@#$%^&*()")}, + }) + _require.Error(err) +} + +func (f *FileRecordedTestsSuite) TestFileStartCopySourceCreationTime() { + _require := require.New(f.T()) + testName := f.T().Name() + + svcClient, err := testcommon.GetServiceClient(f.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + shareClient := testcommon.CreateNewShare(context.Background(), _require, testcommon.GenerateShareName(testName), svcClient) + defer testcommon.DeleteShare(context.Background(), _require, shareClient) + + fClient := shareClient.NewRootDirectoryClient().NewFileClient("src" + testcommon.GenerateFileName(testName)) + copyFClient := shareClient.NewRootDirectoryClient().NewFileClient("dst" + testcommon.GenerateFileName(testName)) + + currTime, err := time.Parse(time.UnixDate, "Fri Mar 31 21:00:00 GMT 2023") + _require.NoError(err) + + cResp, err := fClient.Create(context.Background(), 0, &file.CreateOptions{ + SMBProperties: &file.SMBProperties{ + Attributes: &file.NTFSFileAttributes{ReadOnly: true, Hidden: true}, + CreationTime: to.Ptr(currTime.Add(5 * time.Minute)), + LastWriteTime: to.Ptr(currTime.Add(2 * time.Minute)), + }, + }) + _require.NoError(err) + _require.NotNil(cResp.FileCreationTime) + _require.NotNil(cResp.FileLastWriteTime) + _require.NotNil(cResp.FileAttributes) + _require.NotNil(cResp.FilePermissionKey) + + _, err = copyFClient.StartCopyFromURL(context.Background(), fClient.URL(), &file.StartCopyFromURLOptions{ + CopyFileSMBInfo: &file.CopyFileSMBInfo{ + CreationTime: file.SourceCopyFileCreationTime{}, + }, + }) + _require.NoError(err) + + time.Sleep(4 * time.Second) + + resp2, err := copyFClient.GetProperties(context.Background(), nil) + _require.NoError(err) + _require.EqualValues(resp2.FileCreationTime, cResp.FileCreationTime) + _require.NotEqualValues(resp2.FileLastWriteTime, cResp.FileLastWriteTime) + _require.NotEqualValues(resp2.FileAttributes, cResp.FileAttributes) +} + +func (f *FileRecordedTestsSuite) TestFileStartCopySourceProperties() { + _require := require.New(f.T()) + testName := f.T().Name() + + svcClient, err := testcommon.GetServiceClient(f.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + shareClient := testcommon.CreateNewShare(context.Background(), _require, testcommon.GenerateShareName(testName), svcClient) + defer testcommon.DeleteShare(context.Background(), _require, shareClient) + + fClient := shareClient.NewRootDirectoryClient().NewFileClient("src" + testcommon.GenerateFileName(testName)) + copyFClient := shareClient.NewRootDirectoryClient().NewFileClient("dst" + testcommon.GenerateFileName(testName)) + + currTime, err := time.Parse(time.UnixDate, "Fri Mar 31 20:00:00 GMT 2023") + _require.NoError(err) + + cResp, err := fClient.Create(context.Background(), 0, &file.CreateOptions{ + SMBProperties: &file.SMBProperties{ + Attributes: &file.NTFSFileAttributes{System: true}, + CreationTime: to.Ptr(currTime.Add(1 * time.Minute)), + LastWriteTime: to.Ptr(currTime.Add(2 * time.Minute)), + }, + }) + _require.NoError(err) + _require.NotNil(cResp.FileCreationTime) + _require.NotNil(cResp.FileLastWriteTime) + _require.NotNil(cResp.FileAttributes) + _require.NotNil(cResp.FilePermissionKey) + + _, err = copyFClient.StartCopyFromURL(context.Background(), fClient.URL(), &file.StartCopyFromURLOptions{ + CopyFileSMBInfo: &file.CopyFileSMBInfo{ + CreationTime: file.SourceCopyFileCreationTime{}, + LastWriteTime: file.SourceCopyFileLastWriteTime{}, + Attributes: file.SourceCopyFileAttributes{}, + PermissionCopyMode: to.Ptr(file.PermissionCopyModeTypeSource), + }, + }) + _require.NoError(err) + + time.Sleep(4 * time.Second) + + resp2, err := copyFClient.GetProperties(context.Background(), nil) + _require.NoError(err) + _require.EqualValues(resp2.FileCreationTime, cResp.FileCreationTime) + _require.EqualValues(resp2.FileLastWriteTime, cResp.FileLastWriteTime) + _require.EqualValues(resp2.FileAttributes, cResp.FileAttributes) + _require.EqualValues(resp2.FilePermissionKey, cResp.FilePermissionKey) +} + +func (f *FileRecordedTestsSuite) TestFileStartCopyDifferentProperties() { + _require := require.New(f.T()) + testName := f.T().Name() + + svcClient, err := testcommon.GetServiceClient(f.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + shareClient := testcommon.CreateNewShare(context.Background(), _require, testcommon.GenerateShareName(testName), svcClient) + defer testcommon.DeleteShare(context.Background(), _require, shareClient) + + fClient := shareClient.NewRootDirectoryClient().NewFileClient("src" + testcommon.GenerateFileName(testName)) + copyFClient := shareClient.NewRootDirectoryClient().NewFileClient("dst" + testcommon.GenerateFileName(testName)) + + currTime, err := time.Parse(time.UnixDate, "Fri Mar 31 20:00:00 GMT 2023") + _require.NoError(err) + + cResp, err := fClient.Create(context.Background(), 0, &file.CreateOptions{ + SMBProperties: &file.SMBProperties{ + Attributes: &file.NTFSFileAttributes{System: true}, + CreationTime: to.Ptr(currTime.Add(1 * time.Minute)), + LastWriteTime: to.Ptr(currTime.Add(2 * time.Minute)), + }, + }) + _require.NoError(err) + _require.NotNil(cResp.FileCreationTime) + _require.NotNil(cResp.FileLastWriteTime) + _require.NotNil(cResp.FileAttributes) + _require.NotNil(cResp.FilePermissionKey) + + destCreationTime := currTime.Add(5 * time.Minute) + destLastWriteTIme := currTime.Add(6 * time.Minute) + _, err = copyFClient.StartCopyFromURL(context.Background(), fClient.URL(), &file.StartCopyFromURLOptions{ + CopyFileSMBInfo: &file.CopyFileSMBInfo{ + CreationTime: file.DestinationCopyFileCreationTime(destCreationTime), + LastWriteTime: file.DestinationCopyFileLastWriteTime(destLastWriteTIme), + Attributes: file.DestinationCopyFileAttributes{ReadOnly: true}, + }, + }) + _require.NoError(err) + + time.Sleep(4 * time.Second) + + resp2, err := copyFClient.GetProperties(context.Background(), nil) + _require.NoError(err) + _require.NotEqualValues(resp2.FileCreationTime, cResp.FileCreationTime) + _require.EqualValues(*resp2.FileCreationTime, destCreationTime.UTC()) + _require.NotEqualValues(resp2.FileLastWriteTime, cResp.FileLastWriteTime) + _require.EqualValues(*resp2.FileLastWriteTime, destLastWriteTIme.UTC()) + _require.NotEqualValues(resp2.FileAttributes, cResp.FileAttributes) + _require.EqualValues(resp2.FilePermissionKey, cResp.FilePermissionKey) +} + +func (f *FileRecordedTestsSuite) TestFileStartCopyOverrideMode() { + _require := require.New(f.T()) + testName := f.T().Name() + + svcClient, err := testcommon.GetServiceClient(f.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + shareClient := testcommon.CreateNewShare(context.Background(), _require, testcommon.GenerateShareName(testName), svcClient) + defer testcommon.DeleteShare(context.Background(), _require, shareClient) + + fClient := shareClient.NewRootDirectoryClient().NewFileClient("src" + testcommon.GenerateFileName(testName)) + copyFClient := shareClient.NewRootDirectoryClient().NewFileClient("dst" + testcommon.GenerateFileName(testName)) + + cResp, err := fClient.Create(context.Background(), 0, nil) + _require.NoError(err) + _require.NotNil(cResp.FileCreationTime) + _require.NotNil(cResp.FileLastWriteTime) + _require.NotNil(cResp.FileAttributes) + _require.NotNil(cResp.FilePermissionKey) + + _, err = copyFClient.StartCopyFromURL(context.Background(), fClient.URL(), &file.StartCopyFromURLOptions{ + Permissions: &file.Permissions{ + Permission: to.Ptr(testcommon.SampleSDDL), + }, + CopyFileSMBInfo: &file.CopyFileSMBInfo{ + PermissionCopyMode: to.Ptr(file.PermissionCopyModeTypeOverride), + }, + }) + _require.NoError(err) + + time.Sleep(4 * time.Second) + + resp2, err := copyFClient.GetProperties(context.Background(), nil) + _require.NoError(err) + _require.NotEqualValues(resp2.FileCreationTime, cResp.FileCreationTime) + _require.NotEqualValues(resp2.FileLastWriteTime, cResp.FileLastWriteTime) + _require.NotEqualValues(resp2.FilePermissionKey, cResp.FilePermissionKey) +} + +func (f *FileRecordedTestsSuite) TestNegativeFileStartCopyOverrideMode() { + _require := require.New(f.T()) + testName := f.T().Name() + + svcClient, err := testcommon.GetServiceClient(f.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + shareClient := testcommon.CreateNewShare(context.Background(), _require, testcommon.GenerateShareName(testName), svcClient) + defer testcommon.DeleteShare(context.Background(), _require, shareClient) + + fClient := shareClient.NewRootDirectoryClient().NewFileClient("src" + testcommon.GenerateFileName(testName)) + copyFClient := shareClient.NewRootDirectoryClient().NewFileClient("dst" + testcommon.GenerateFileName(testName)) + + cResp, err := fClient.Create(context.Background(), 0, nil) + _require.NoError(err) + _require.NotNil(cResp.FileCreationTime) + _require.NotNil(cResp.FileLastWriteTime) + _require.NotNil(cResp.FileAttributes) + _require.NotNil(cResp.FilePermissionKey) + + // permission or permission key is required when the PermissionCopyMode is override. + _, err = copyFClient.StartCopyFromURL(context.Background(), fClient.URL(), &file.StartCopyFromURLOptions{ + CopyFileSMBInfo: &file.CopyFileSMBInfo{ + PermissionCopyMode: to.Ptr(file.PermissionCopyModeTypeOverride), + }, + }) + _require.Error(err) + testcommon.ValidateFileErrorCode(_require, err, fileerror.MissingRequiredHeader) +} + +func (f *FileRecordedTestsSuite) TestFileStartCopySetArchiveAttributeTrue() { + _require := require.New(f.T()) + testName := f.T().Name() + + svcClient, err := testcommon.GetServiceClient(f.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + shareClient := testcommon.CreateNewShare(context.Background(), _require, testcommon.GenerateShareName(testName), svcClient) + defer testcommon.DeleteShare(context.Background(), _require, shareClient) + + fClient := shareClient.NewRootDirectoryClient().NewFileClient("src" + testcommon.GenerateFileName(testName)) + copyFClient := shareClient.NewRootDirectoryClient().NewFileClient("dst" + testcommon.GenerateFileName(testName)) + + cResp, err := fClient.Create(context.Background(), 0, &file.CreateOptions{ + SMBProperties: &file.SMBProperties{ + Attributes: &file.NTFSFileAttributes{ReadOnly: true, Hidden: true}, + }, + }) + _require.NoError(err) + _require.NotNil(cResp.FileCreationTime) + _require.NotNil(cResp.FileLastWriteTime) + _require.NotNil(cResp.FileAttributes) + _require.NotNil(cResp.FilePermissionKey) + + _, err = copyFClient.StartCopyFromURL(context.Background(), fClient.URL(), &file.StartCopyFromURLOptions{ + CopyFileSMBInfo: &file.CopyFileSMBInfo{ + Attributes: file.DestinationCopyFileAttributes{System: true, ReadOnly: true}, + SetArchiveAttribute: to.Ptr(true), + }, + }) + _require.NoError(err) + + time.Sleep(4 * time.Second) + + resp2, err := copyFClient.GetProperties(context.Background(), nil) + _require.NoError(err) + _require.NotEqualValues(resp2.FileCreationTime, cResp.FileCreationTime) + _require.NotEqualValues(resp2.FileLastWriteTime, cResp.FileLastWriteTime) + _require.Contains(*resp2.FileAttributes, "Archive") +} + +func (f *FileRecordedTestsSuite) TestFileStartCopySetArchiveAttributeFalse() { + _require := require.New(f.T()) + testName := f.T().Name() + + svcClient, err := testcommon.GetServiceClient(f.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + shareClient := testcommon.CreateNewShare(context.Background(), _require, testcommon.GenerateShareName(testName), svcClient) + defer testcommon.DeleteShare(context.Background(), _require, shareClient) + + fClient := shareClient.NewRootDirectoryClient().NewFileClient("src" + testcommon.GenerateFileName(testName)) + copyFClient := shareClient.NewRootDirectoryClient().NewFileClient("dst" + testcommon.GenerateFileName(testName)) + + cResp, err := fClient.Create(context.Background(), 0, &file.CreateOptions{ + SMBProperties: &file.SMBProperties{ + Attributes: &file.NTFSFileAttributes{ReadOnly: true, Hidden: true}, + }, + }) + _require.NoError(err) + _require.NotNil(cResp.FileCreationTime) + _require.NotNil(cResp.FileLastWriteTime) + _require.NotNil(cResp.FileAttributes) + _require.NotNil(cResp.FilePermissionKey) + + _, err = copyFClient.StartCopyFromURL(context.Background(), fClient.URL(), &file.StartCopyFromURLOptions{ + CopyFileSMBInfo: &file.CopyFileSMBInfo{ + Attributes: file.DestinationCopyFileAttributes{System: true, ReadOnly: true}, + SetArchiveAttribute: to.Ptr(false), + }, + }) + _require.NoError(err) + + time.Sleep(4 * time.Second) + + resp2, err := copyFClient.GetProperties(context.Background(), nil) + _require.NoError(err) + _require.NotEqualValues(resp2.FileCreationTime, cResp.FileCreationTime) + _require.NotEqualValues(resp2.FileLastWriteTime, cResp.FileLastWriteTime) + _require.NotContains(*resp2.FileAttributes, "Archive") +} + +func (f *FileRecordedTestsSuite) TestFileStartCopyDestReadOnly() { + _require := require.New(f.T()) + testName := f.T().Name() + + svcClient, err := testcommon.GetServiceClient(f.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + shareClient := testcommon.CreateNewShare(context.Background(), _require, testcommon.GenerateShareName(testName), svcClient) + defer testcommon.DeleteShare(context.Background(), _require, shareClient) + + fClient := shareClient.NewRootDirectoryClient().NewFileClient("src" + testcommon.GenerateFileName(testName)) + copyFClient := shareClient.NewRootDirectoryClient().NewFileClient("dst" + testcommon.GenerateFileName(testName)) + + cResp, err := fClient.Create(context.Background(), 0, nil) + _require.NoError(err) + _require.NotNil(cResp.FileCreationTime) + _require.NotNil(cResp.FileLastWriteTime) + _require.NotNil(cResp.FileAttributes) + _require.NotNil(cResp.FilePermissionKey) + + _, err = copyFClient.Create(context.Background(), 0, &file.CreateOptions{ + SMBProperties: &file.SMBProperties{ + Attributes: &file.NTFSFileAttributes{ReadOnly: true}, + }, + }) + _require.NoError(err) + + _, err = copyFClient.StartCopyFromURL(context.Background(), fClient.URL(), &file.StartCopyFromURLOptions{ + CopyFileSMBInfo: &file.CopyFileSMBInfo{ + IgnoreReadOnly: to.Ptr(true), + }, + }) + _require.NoError(err) + + time.Sleep(4 * time.Second) + + resp2, err := copyFClient.GetProperties(context.Background(), nil) + _require.NoError(err) + _require.NotEqualValues(resp2.FileCreationTime, cResp.FileCreationTime) + _require.NotEqualValues(resp2.FileLastWriteTime, cResp.FileLastWriteTime) +} + +func (f *FileRecordedTestsSuite) TestNegativeFileStartCopyDestReadOnly() { + _require := require.New(f.T()) + testName := f.T().Name() + + svcClient, err := testcommon.GetServiceClient(f.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + shareClient := testcommon.CreateNewShare(context.Background(), _require, testcommon.GenerateShareName(testName), svcClient) + defer testcommon.DeleteShare(context.Background(), _require, shareClient) + + fClient := shareClient.NewRootDirectoryClient().NewFileClient("src" + testcommon.GenerateFileName(testName)) + copyFClient := shareClient.NewRootDirectoryClient().NewFileClient("dst" + testcommon.GenerateFileName(testName)) + + cResp, err := fClient.Create(context.Background(), 0, nil) + _require.NoError(err) + _require.NotNil(cResp.FileCreationTime) + _require.NotNil(cResp.FileLastWriteTime) + _require.NotNil(cResp.FileAttributes) + _require.NotNil(cResp.FilePermissionKey) + + _, err = copyFClient.Create(context.Background(), 0, &file.CreateOptions{ + SMBProperties: &file.SMBProperties{ + Attributes: &file.NTFSFileAttributes{ReadOnly: true}, + }, + }) + _require.NoError(err) + + _, err = copyFClient.StartCopyFromURL(context.Background(), fClient.URL(), nil) + _require.Error(err) + testcommon.ValidateFileErrorCode(_require, err, fileerror.ReadOnlyAttribute) +} + +func (f *FileRecordedTestsSuite) TestFileStartCopySourceNonExistent() { + _require := require.New(f.T()) + testName := f.T().Name() + + svcClient, err := testcommon.GetServiceClient(f.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + shareClient := testcommon.CreateNewShare(context.Background(), _require, testcommon.GenerateShareName(testName), svcClient) + defer testcommon.DeleteShare(context.Background(), _require, shareClient) + + fClient := shareClient.NewRootDirectoryClient().NewFileClient("src" + testcommon.GenerateFileName(testName)) + copyFClient := shareClient.NewRootDirectoryClient().NewFileClient("dst" + testcommon.GenerateFileName(testName)) + + _, err = copyFClient.StartCopyFromURL(context.Background(), fClient.URL(), nil) + testcommon.ValidateFileErrorCode(_require, err, fileerror.ResourceNotFound) +} + +func (f *FileUnrecordedTestsSuite) TestFileStartCopyUsingSASSrc() { + _require := require.New(f.T()) + testName := f.T().Name() + + svcClient, err := testcommon.GetServiceClient(f.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + shareName := testcommon.GenerateShareName(testName) + shareClient := testcommon.CreateNewShare(context.Background(), _require, "src"+shareName, svcClient) + defer testcommon.DeleteShare(context.Background(), _require, shareClient) + + fileName := testcommon.GenerateFileName(testName) + fClient := testcommon.CreateNewFileFromShareWithData(context.Background(), _require, "src"+fileName, shareClient) + + fileURLWithSAS, err := fClient.GetSASURL(sas.FilePermissions{Read: true, Write: true, Create: true, Delete: true}, time.Now().Add(5*time.Minute).UTC(), nil) + _require.NoError(err) + + // Create a new share for the destination + copyShareClient := testcommon.CreateNewShare(context.Background(), _require, "dest"+shareName, svcClient) + defer testcommon.DeleteShare(context.Background(), _require, copyShareClient) + + copyFileClient := testcommon.GetFileClientFromShare("dst"+fileName, copyShareClient) + + _, err = copyFileClient.StartCopyFromURL(context.Background(), fileURLWithSAS, nil) + _require.NoError(err) + + time.Sleep(4 * time.Second) + + dResp, err := copyFileClient.DownloadStream(context.Background(), nil) + _require.NoError(err) + + data, err := ioutil.ReadAll(dResp.Body) + defer func() { + err = dResp.Body.Close() + _require.NoError(err) + }() + + _require.NoError(err) + _require.Equal(*dResp.ContentLength, int64(len(testcommon.FileDefaultData))) + _require.Equal(string(data), testcommon.FileDefaultData) +} + +func (f *FileRecordedTestsSuite) TestFileAbortCopyNoCopyStarted() { + _require := require.New(f.T()) + testName := f.T().Name() + + svcClient, err := testcommon.GetServiceClient(f.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + shareClient := testcommon.CreateNewShare(context.Background(), _require, testcommon.GenerateShareName(testName), svcClient) + defer testcommon.DeleteShare(context.Background(), _require, shareClient) + + copyFClient := shareClient.NewRootDirectoryClient().NewFileClient(testcommon.GenerateFileName(testName)) + _, err = copyFClient.AbortCopy(context.Background(), "copynotstarted", nil) + _require.Error(err) + testcommon.ValidateFileErrorCode(_require, err, fileerror.InvalidQueryParameterValue) +} + +func (f *FileRecordedTestsSuite) TestResizeFile() { + _require := require.New(f.T()) + testName := f.T().Name() + + svcClient, err := testcommon.GetServiceClient(f.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + shareClient := testcommon.CreateNewShare(context.Background(), _require, testcommon.GenerateShareName(testName), svcClient) + defer testcommon.DeleteShare(context.Background(), _require, shareClient) + + fClient := shareClient.NewRootDirectoryClient().NewFileClient("src" + testcommon.GenerateFileName(testName)) + _, err = fClient.Create(context.Background(), 1234, nil) + _require.NoError(err) + + gResp, err := fClient.GetProperties(context.Background(), nil) + _require.NoError(err) + _require.Equal(*gResp.ContentLength, int64(1234)) + + _, err = fClient.Resize(context.Background(), 4096, nil) + _require.NoError(err) + + gResp, err = fClient.GetProperties(context.Background(), nil) + _require.NoError(err) + _require.Equal(*gResp.ContentLength, int64(4096)) +} + +func (f *FileRecordedTestsSuite) TestFileResizeZero() { + _require := require.New(f.T()) + testName := f.T().Name() + + svcClient, err := testcommon.GetServiceClient(f.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + shareClient := testcommon.CreateNewShare(context.Background(), _require, testcommon.GenerateShareName(testName), svcClient) + defer testcommon.DeleteShare(context.Background(), _require, shareClient) + + fClient := shareClient.NewRootDirectoryClient().NewFileClient("src" + testcommon.GenerateFileName(testName)) + _, err = fClient.Create(context.Background(), 10, nil) + _require.NoError(err) + + _, err = fClient.Resize(context.Background(), 0, nil) + _require.NoError(err) + + resp, err := fClient.GetProperties(context.Background(), nil) + _require.NoError(err) + _require.Equal(*resp.ContentLength, int64(0)) +} + +func (f *FileRecordedTestsSuite) TestFileResizeInvalidSizeNegative() { + _require := require.New(f.T()) + testName := f.T().Name() + + svcClient, err := testcommon.GetServiceClient(f.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + shareClient := testcommon.CreateNewShare(context.Background(), _require, testcommon.GenerateShareName(testName), svcClient) + defer testcommon.DeleteShare(context.Background(), _require, shareClient) + + fClient := shareClient.NewRootDirectoryClient().NewFileClient("src" + testcommon.GenerateFileName(testName)) + _, err = fClient.Create(context.Background(), 0, nil) + _require.NoError(err) + + _, err = fClient.Resize(context.Background(), -4, nil) + _require.Error(err) + testcommon.ValidateFileErrorCode(_require, err, fileerror.OutOfRangeInput) +} + +func (f *FileRecordedTestsSuite) TestNegativeFileSizeMoreThanShareQuota() { + _require := require.New(f.T()) + testName := f.T().Name() + svcClient, err := testcommon.GetServiceClient(f.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + var fileShareMaxQuota int32 = 1024 // share size in GiB which is 1TiB + var fileMaxAllowedSizeInBytes int64 = 4398046511104 // file size in bytes which is 4 TiB + + shareClient := testcommon.GetShareClient(testcommon.GenerateShareName(testName), svcClient) + _, err = shareClient.Create(context.Background(), &share.CreateOptions{ + Quota: &fileShareMaxQuota, + }) + _require.NoError(err) + defer testcommon.DeleteShare(context.Background(), _require, shareClient) + + fClient := shareClient.NewRootDirectoryClient().NewFileClient(testcommon.GenerateFileName(testName)) + _, err = fClient.Create(context.Background(), fileMaxAllowedSizeInBytes, &file.CreateOptions{ + HTTPHeaders: &file.HTTPHeaders{}, + }) + _require.Error(err) +} + +func (f *FileRecordedTestsSuite) TestCreateMaximumSizeFileShare() { + _require := require.New(f.T()) + testName := f.T().Name() + svcClient, err := testcommon.GetServiceClient(f.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + var fileShareMaxQuota int32 = 5120 // share size in GiB which is 5TiB + var fileMaxAllowedSizeInBytes int64 = 4398046511104 // file size in bytes which is 4 TiB + + shareClient := testcommon.GetShareClient(testcommon.GenerateShareName(testName), svcClient) + _, err = shareClient.Create(context.Background(), &share.CreateOptions{ + Quota: &fileShareMaxQuota, + }) + _require.NoError(err) + defer testcommon.DeleteShare(context.Background(), _require, shareClient) + + fClient := shareClient.NewRootDirectoryClient().NewFileClient(testcommon.GenerateFileName(testName)) + _, err = fClient.Create(context.Background(), fileMaxAllowedSizeInBytes, &file.CreateOptions{ + HTTPHeaders: &file.HTTPHeaders{}, + }) + _require.NoError(err) +} + +func (f *FileRecordedTestsSuite) TestSASFileClientNoKey() { + _require := require.New(f.T()) + accountName, _ := testcommon.GetGenericAccountInfo(testcommon.TestAccountDefault) + _require.Greater(len(accountName), 0) + + testName := f.T().Name() + shareName := testcommon.GenerateShareName(testName) + fileName := testcommon.GenerateFileName(testName) + fileClient, err := file.NewClientWithNoCredential(fmt.Sprintf("https://%s.file.core.windows.net/%v/%v", accountName, shareName, fileName), nil) + _require.NoError(err) + + permissions := sas.FilePermissions{ + Read: true, + Write: true, + Delete: true, + Create: true, + } + expiry := time.Now().Add(time.Hour) + + _, err = fileClient.GetSASURL(permissions, expiry, nil) + _require.Equal(err, fileerror.MissingSharedKeyCredential) +} + +func (f *FileRecordedTestsSuite) TestSASFileClientSignNegative() { + _require := require.New(f.T()) + accountName, accountKey := testcommon.GetGenericAccountInfo(testcommon.TestAccountDefault) + _require.Greater(len(accountName), 0) + _require.Greater(len(accountKey), 0) + + cred, err := file.NewSharedKeyCredential(accountName, accountKey) + _require.NoError(err) + + testName := f.T().Name() + shareName := testcommon.GenerateShareName(testName) + fileName := testcommon.GenerateFileName(testName) + fileClient, err := file.NewClientWithSharedKeyCredential(fmt.Sprintf("https://%s.file.core.windows.net/%v%v", accountName, shareName, fileName), cred, nil) + _require.NoError(err) + + permissions := sas.FilePermissions{ + Read: true, + Write: true, + Delete: true, + Create: true, + } + expiry := time.Time{} + + // zero expiry time + _, err = fileClient.GetSASURL(permissions, expiry, &file.GetSASURLOptions{StartTime: to.Ptr(time.Now())}) + _require.Equal(err.Error(), "service SAS is missing at least one of these: ExpiryTime or Permissions") + + // zero start and expiry time + _, err = fileClient.GetSASURL(permissions, expiry, &file.GetSASURLOptions{}) + _require.Equal(err.Error(), "service SAS is missing at least one of these: ExpiryTime or Permissions") + + // empty permissions + _, err = fileClient.GetSASURL(sas.FilePermissions{}, expiry, nil) + _require.Equal(err.Error(), "service SAS is missing at least one of these: ExpiryTime or Permissions") +} + +func (f *FileRecordedTestsSuite) TestFileUploadClearListRange() { + _require := require.New(f.T()) + testName := f.T().Name() + + svcClient, err := testcommon.GetServiceClient(f.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + shareClient := testcommon.CreateNewShare(context.Background(), _require, testcommon.GenerateShareName(testName), svcClient) + defer testcommon.DeleteShare(context.Background(), _require, shareClient) + + var fileSize int64 = 1024 * 10 + fClient := shareClient.NewRootDirectoryClient().NewFileClient(testcommon.GenerateFileName(testName)) + _, err = fClient.Create(context.Background(), fileSize, nil) + _require.NoError(err) + + gResp, err := fClient.GetProperties(context.Background(), nil) + _require.NoError(err) + _require.Equal(*gResp.ContentLength, fileSize) + + contentSize := 1024 * 2 // 2KB + contentR, contentD := testcommon.GenerateData(contentSize) + md5Value := md5.Sum(contentD) + contentMD5 := md5Value[:] + + uResp, err := fClient.UploadRange(context.Background(), 0, contentR, &file.UploadRangeOptions{ + TransactionalValidation: file.TransferValidationTypeMD5(contentMD5), + }) + _require.NoError(err) + _require.NotNil(uResp.ContentMD5) + _require.EqualValues(uResp.ContentMD5, contentMD5) + + rangeList, err := fClient.GetRangeList(context.Background(), nil) + _require.NoError(err) + _require.Len(rangeList.Ranges, 1) + _require.EqualValues(*rangeList.Ranges[0], file.ShareFileRange{Start: to.Ptr(int64(0)), End: to.Ptr(int64(contentSize - 1))}) + + cResp, err := fClient.ClearRange(context.Background(), file.HTTPRange{Offset: 0, Count: int64(contentSize)}, nil) + _require.NoError(err) + _require.Nil(cResp.ContentMD5) + + rangeList2, err := fClient.GetRangeList(context.Background(), nil) + _require.NoError(err) + _require.Len(rangeList2.Ranges, 0) +} + +func (f *FileUnrecordedTestsSuite) TestFileUploadRangeFromURL() { + _require := require.New(f.T()) + testName := f.T().Name() + + cred, err := testcommon.GetGenericSharedKeyCredential(testcommon.TestAccountDefault) + _require.NoError(err) + + svcClient, err := testcommon.GetServiceClient(f.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + shareName := testcommon.GenerateShareName(testName) + shareClient := testcommon.CreateNewShare(context.Background(), _require, shareName, svcClient) + defer testcommon.DeleteShare(context.Background(), _require, shareClient) + + var fileSize int64 = 1024 * 20 + srcFileName := "src" + testcommon.GenerateFileName(testName) + srcFClient := shareClient.NewRootDirectoryClient().NewFileClient(srcFileName) + _, err = srcFClient.Create(context.Background(), fileSize, nil) + _require.NoError(err) + + gResp, err := srcFClient.GetProperties(context.Background(), nil) + _require.NoError(err) + _require.Equal(*gResp.ContentLength, fileSize) + + contentSize := 1024 * 8 // 8KB + content := make([]byte, contentSize) + body := bytes.NewReader(content) + rsc := streaming.NopCloser(body) + contentCRC64 := crc64.Checksum(content, shared.CRC64Table) + + _, err = srcFClient.UploadRange(context.Background(), 0, rsc, nil) + _require.NoError(err) + + perms := sas.FilePermissions{Read: true, Write: true} + sasQueryParams, err := sas.SignatureValues{ + Protocol: sas.ProtocolHTTPS, // Users MUST use HTTPS (not HTTP) + ExpiryTime: time.Now().UTC().Add(48 * time.Hour), // 48-hours before expiration + ShareName: shareName, + FilePath: srcFileName, + Permissions: perms.String(), + }.SignWithSharedKey(cred) + _require.NoError(err) + + srcFileSAS := srcFClient.URL() + "?" + sasQueryParams.Encode() + + destFClient := shareClient.NewRootDirectoryClient().NewFileClient("dest" + testcommon.GenerateFileName(testName)) + _, err = destFClient.Create(context.Background(), fileSize, nil) + _require.NoError(err) + + uResp, err := destFClient.UploadRangeFromURL(context.Background(), srcFileSAS, 0, 0, int64(contentSize), &file.UploadRangeFromURLOptions{ + SourceContentCRC64: contentCRC64, + }) + _require.NoError(err) + _require.NotNil(uResp.XMSContentCRC64) + _require.EqualValues(binary.LittleEndian.Uint64(uResp.XMSContentCRC64), contentCRC64) + + rangeList, err := destFClient.GetRangeList(context.Background(), nil) + _require.NoError(err) + _require.Len(rangeList.Ranges, 1) + _require.Equal(*rangeList.Ranges[0].Start, int64(0)) + _require.Equal(*rangeList.Ranges[0].End, int64(contentSize-1)) + + cResp, err := destFClient.ClearRange(context.Background(), file.HTTPRange{Offset: 0, Count: int64(contentSize)}, nil) + _require.NoError(err) + _require.Nil(cResp.ContentMD5) + + rangeList2, err := destFClient.GetRangeList(context.Background(), nil) + _require.NoError(err) + _require.Len(rangeList2.Ranges, 0) +} + +func (f *FileRecordedTestsSuite) TestFileUploadRangeFromURLNegative() { + _require := require.New(f.T()) + testName := f.T().Name() + + svcClient, err := testcommon.GetServiceClient(f.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + shareName := testcommon.GenerateShareName(testName) + shareClient := testcommon.CreateNewShare(context.Background(), _require, shareName, svcClient) + defer testcommon.DeleteShare(context.Background(), _require, shareClient) + + var fileSize int64 = 1024 * 20 + srcFileName := "src" + testcommon.GenerateFileName(testName) + srcFClient := testcommon.CreateNewFileFromShare(context.Background(), _require, srcFileName, fileSize, shareClient) + + gResp, err := srcFClient.GetProperties(context.Background(), nil) + _require.NoError(err) + _require.Equal(*gResp.ContentLength, fileSize) + + contentSize := 1024 * 8 // 8KB + rsc, content := testcommon.GenerateData(contentSize) + contentCRC64 := crc64.Checksum(content, shared.CRC64Table) + + _, err = srcFClient.UploadRange(context.Background(), 0, rsc, nil) + _require.NoError(err) + + destFClient := testcommon.CreateNewFileFromShare(context.Background(), _require, "dest"+testcommon.GenerateFileName(testName), fileSize, shareClient) + + _, err = destFClient.UploadRangeFromURL(context.Background(), srcFClient.URL(), 0, 0, int64(contentSize), &file.UploadRangeFromURLOptions{ + SourceContentCRC64: contentCRC64, + }) + _require.Error(err) +} + +func (f *FileRecordedTestsSuite) TestFileUploadRangeFromURLOffsetNegative() { + _require := require.New(f.T()) + testName := f.T().Name() + + svcClient, err := testcommon.GetServiceClient(f.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + shareName := testcommon.GenerateShareName(testName) + shareClient := testcommon.CreateNewShare(context.Background(), _require, shareName, svcClient) + defer testcommon.DeleteShare(context.Background(), _require, shareClient) + + var fileSize int64 = 1024 * 20 + srcFileName := "src" + testcommon.GenerateFileName(testName) + srcFClient := testcommon.CreateNewFileFromShare(context.Background(), _require, srcFileName, fileSize, shareClient) + + gResp, err := srcFClient.GetProperties(context.Background(), nil) + _require.NoError(err) + _require.Equal(*gResp.ContentLength, fileSize) + + contentSize := 1024 * 8 // 8KB + destFClient := testcommon.CreateNewFileFromShare(context.Background(), _require, "dest"+testcommon.GenerateFileName(testName), fileSize, shareClient) + + // error is returned when source offset is negative + _, err = destFClient.UploadRangeFromURL(context.Background(), srcFClient.URL(), -1, 0, int64(contentSize), nil) + _require.Error(err) + _require.Equal(err.Error(), "invalid argument: source and destination offsets must be >= 0") +} + +func (f *FileUnrecordedTestsSuite) TestFileUploadRangeFromURLCopySourceAuthBlob() { + _require := require.New(f.T()) + testName := f.T().Name() + + accountName, _ := testcommon.GetGenericAccountInfo(testcommon.TestAccountDefault) + _require.Greater(len(accountName), 0) + + cred, err := testcommon.GetGenericTokenCredential() + _require.NoError(err) + + // Getting token + accessToken, err := cred.GetToken(context.Background(), policy.TokenRequestOptions{Scopes: []string{"https://storage.azure.com/.default"}}) + _require.NoError(err) + + svcClient, err := testcommon.GetServiceClient(f.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + shareName := testcommon.GenerateShareName(testName) + shareClient := testcommon.CreateNewShare(context.Background(), _require, shareName, svcClient) + defer testcommon.DeleteShare(context.Background(), _require, shareClient) + + var fileSize int64 = 1024 * 10 + contentSize := 1024 * 8 // 8KB + _, content := testcommon.GenerateData(contentSize) + contentCRC64 := crc64.Checksum(content, shared.CRC64Table) + + // create source block blob + blobClient, err := azblob.NewClient("https://"+accountName+".blob.core.windows.net/", cred, nil) + _require.NoError(err) + + containerName := "goc" + testcommon.GenerateEntityName(testName) + blobName := "blob" + testcommon.GenerateEntityName(testName) + _, err = blobClient.CreateContainer(context.Background(), containerName, nil) + _require.NoError(err) + defer func() { + _, err := blobClient.DeleteContainer(context.Background(), containerName, nil) + _require.NoError(err) + }() + + _, err = blobClient.UploadBuffer(context.Background(), containerName, blobName, content, nil) + _require.NoError(err) + + destFClient := shareClient.NewRootDirectoryClient().NewFileClient("dest" + testcommon.GenerateFileName(testName)) + _, err = destFClient.Create(context.Background(), fileSize, nil) + _require.NoError(err) + + blobURL := blobClient.ServiceClient().NewContainerClient(containerName).NewBlockBlobClient(blobName).URL() + uResp, err := destFClient.UploadRangeFromURL(context.Background(), blobURL, 0, 0, int64(contentSize), &file.UploadRangeFromURLOptions{ + SourceContentCRC64: contentCRC64, + CopySourceAuthorization: to.Ptr("Bearer " + accessToken.Token), + }) + _require.NoError(err) + _require.NotNil(uResp.XMSContentCRC64) + _require.EqualValues(binary.LittleEndian.Uint64(uResp.XMSContentCRC64), contentCRC64) + + // validate the content uploaded + dResp, err := destFClient.DownloadStream(context.Background(), &file.DownloadStreamOptions{ + Range: file.HTTPRange{Offset: 0, Count: int64(contentSize)}, + }) + _require.NoError(err) + + data, err := ioutil.ReadAll(dResp.Body) + defer func() { + err = dResp.Body.Close() + _require.NoError(err) + }() + + _require.EqualValues(data, content) +} + +func (f *FileUnrecordedTestsSuite) TestFileUploadBuffer() { + _require := require.New(f.T()) + testName := f.T().Name() + + svcClient, err := testcommon.GetServiceClient(f.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + shareClient := testcommon.CreateNewShare(context.Background(), _require, testcommon.GenerateShareName(testName), svcClient) + defer testcommon.DeleteShare(context.Background(), _require, shareClient) + + var fileSize int64 = 100 * 1024 * 1024 + fClient := shareClient.NewRootDirectoryClient().NewFileClient(testcommon.GenerateFileName(testName)) + _, err = fClient.Create(context.Background(), fileSize, nil) + _require.NoError(err) + + gResp, err := fClient.GetProperties(context.Background(), nil) + _require.NoError(err) + _require.Equal(*gResp.ContentLength, fileSize) + + content := make([]byte, fileSize) + _, err = rand.Read(content) + _require.NoError(err) + md5Value := md5.Sum(content) + contentMD5 := md5Value[:] + + err = fClient.UploadBuffer(context.Background(), content, &file.UploadBufferOptions{ + Concurrency: 5, + ChunkSize: 4 * 1024 * 1024, + }) + _require.NoError(err) + + dResp, err := fClient.DownloadStream(context.Background(), nil) + _require.NoError(err) + + data, err := io.ReadAll(dResp.Body) + _require.NoError(err) + + downloadedMD5Value := md5.Sum(data) + downloadedContentMD5 := downloadedMD5Value[:] + + _require.EqualValues(downloadedContentMD5, contentMD5) + + gResp2, err := fClient.GetProperties(context.Background(), nil) + _require.NoError(err) + _require.Equal(*gResp2.ContentLength, fileSize) + + rangeList, err := fClient.GetRangeList(context.Background(), nil) + _require.NoError(err) + _require.Len(rangeList.Ranges, 1) + _require.Equal(*rangeList.Ranges[0].Start, int64(0)) + _require.Equal(*rangeList.Ranges[0].End, fileSize-1) +} + +func (f *FileUnrecordedTestsSuite) TestFileUploadFile() { + _require := require.New(f.T()) + testName := f.T().Name() + + svcClient, err := testcommon.GetServiceClient(f.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + shareClient := testcommon.CreateNewShare(context.Background(), _require, testcommon.GenerateShareName(testName), svcClient) + defer testcommon.DeleteShare(context.Background(), _require, shareClient) + + var fileSize int64 = 200 * 1024 * 1024 + fClient := shareClient.NewRootDirectoryClient().NewFileClient(testcommon.GenerateFileName(testName)) + _, err = fClient.Create(context.Background(), fileSize, nil) + _require.NoError(err) + + gResp, err := fClient.GetProperties(context.Background(), nil) + _require.NoError(err) + _require.Equal(*gResp.ContentLength, fileSize) + + // create local file + content := make([]byte, fileSize) + _, err = rand.Read(content) + _require.NoError(err) + err = ioutil.WriteFile("testFile", content, 0644) + _require.NoError(err) + + defer func() { + err = os.Remove("testFile") + _require.NoError(err) + }() + + fh, err := os.Open("testFile") + _require.NoError(err) + + defer func(fh *os.File) { + err := fh.Close() + _require.NoError(err) + }(fh) + + hash := md5.New() + _, err = io.Copy(hash, fh) + _require.NoError(err) + contentMD5 := hash.Sum(nil) + + err = fClient.UploadFile(context.Background(), fh, &file.UploadFileOptions{ + Concurrency: 5, + ChunkSize: 4 * 1024 * 1024, + }) + _require.NoError(err) + + dResp, err := fClient.DownloadStream(context.Background(), nil) + _require.NoError(err) + + data, err := io.ReadAll(dResp.Body) + _require.NoError(err) + + downloadedMD5Value := md5.Sum(data) + downloadedContentMD5 := downloadedMD5Value[:] + + _require.EqualValues(downloadedContentMD5, contentMD5) + + gResp2, err := fClient.GetProperties(context.Background(), nil) + _require.NoError(err) + _require.Equal(*gResp2.ContentLength, fileSize) + + rangeList, err := fClient.GetRangeList(context.Background(), nil) + _require.NoError(err) + _require.Len(rangeList.Ranges, 1) + _require.Equal(*rangeList.Ranges[0].Start, int64(0)) + _require.Equal(*rangeList.Ranges[0].End, fileSize-1) +} + +func (f *FileUnrecordedTestsSuite) TestFileUploadStream() { + _require := require.New(f.T()) + testName := f.T().Name() + + svcClient, err := testcommon.GetServiceClient(f.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + shareClient := testcommon.CreateNewShare(context.Background(), _require, testcommon.GenerateShareName(testName), svcClient) + defer testcommon.DeleteShare(context.Background(), _require, shareClient) + + var fileSize int64 = 100 * 1024 * 1024 + fClient := shareClient.NewRootDirectoryClient().NewFileClient(testcommon.GenerateFileName(testName)) + _, err = fClient.Create(context.Background(), fileSize, nil) + _require.NoError(err) + + gResp, err := fClient.GetProperties(context.Background(), nil) + _require.NoError(err) + _require.Equal(*gResp.ContentLength, fileSize) + + content := make([]byte, fileSize) + _, err = rand.Read(content) + _require.NoError(err) + md5Value := md5.Sum(content) + contentMD5 := md5Value[:] + + err = fClient.UploadStream(context.Background(), streaming.NopCloser(bytes.NewReader(content)), &file.UploadStreamOptions{ + Concurrency: 5, + ChunkSize: 4 * 1024 * 1024, + }) + _require.NoError(err) + + dResp, err := fClient.DownloadStream(context.Background(), nil) + _require.NoError(err) + + data, err := io.ReadAll(dResp.Body) + _require.NoError(err) + + downloadedMD5Value := md5.Sum(data) + downloadedContentMD5 := downloadedMD5Value[:] + + _require.EqualValues(downloadedContentMD5, contentMD5) + + gResp2, err := fClient.GetProperties(context.Background(), nil) + _require.NoError(err) + _require.Equal(*gResp2.ContentLength, fileSize) + + rangeList, err := fClient.GetRangeList(context.Background(), nil) + _require.NoError(err) + _require.Len(rangeList.Ranges, 1) + _require.Equal(*rangeList.Ranges[0].Start, int64(0)) + _require.Equal(*rangeList.Ranges[0].End, fileSize-1) +} + +func (f *FileUnrecordedTestsSuite) TestFileDownloadBuffer() { + _require := require.New(f.T()) + testName := f.T().Name() + + svcClient, err := testcommon.GetServiceClient(f.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + shareClient := testcommon.CreateNewShare(context.Background(), _require, testcommon.GenerateShareName(testName), svcClient) + defer testcommon.DeleteShare(context.Background(), _require, shareClient) + + var fileSize int64 = 100 * 1024 * 1024 + fClient := shareClient.NewRootDirectoryClient().NewFileClient(testcommon.GenerateFileName(testName)) + _, err = fClient.Create(context.Background(), fileSize, nil) + _require.NoError(err) + + gResp, err := fClient.GetProperties(context.Background(), nil) + _require.NoError(err) + _require.Equal(*gResp.ContentLength, fileSize) + + content := make([]byte, fileSize) + _, err = rand.Read(content) + _require.NoError(err) + md5Value := md5.Sum(content) + contentMD5 := md5Value[:] + + err = fClient.UploadBuffer(context.Background(), content, &file.UploadBufferOptions{ + Concurrency: 5, + ChunkSize: 4 * 1024 * 1024, + }) + _require.NoError(err) + + destBuffer := make([]byte, fileSize) + cnt, err := fClient.DownloadBuffer(context.Background(), destBuffer, &file.DownloadBufferOptions{ + ChunkSize: 10 * 1024 * 1024, + Concurrency: 5, + }) + _require.NoError(err) + _require.Equal(cnt, fileSize) + + downloadedMD5Value := md5.Sum(destBuffer) + downloadedContentMD5 := downloadedMD5Value[:] + + _require.EqualValues(downloadedContentMD5, contentMD5) + + gResp2, err := fClient.GetProperties(context.Background(), nil) + _require.NoError(err) + _require.Equal(*gResp2.ContentLength, fileSize) + + rangeList, err := fClient.GetRangeList(context.Background(), nil) + _require.NoError(err) + _require.Len(rangeList.Ranges, 1) + _require.Equal(*rangeList.Ranges[0].Start, int64(0)) + _require.Equal(*rangeList.Ranges[0].End, fileSize-1) +} + +func (f *FileUnrecordedTestsSuite) TestFileDownloadFile() { + _require := require.New(f.T()) + testName := f.T().Name() + + svcClient, err := testcommon.GetServiceClient(f.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + shareClient := testcommon.CreateNewShare(context.Background(), _require, testcommon.GenerateShareName(testName), svcClient) + defer testcommon.DeleteShare(context.Background(), _require, shareClient) + + var fileSize int64 = 100 * 1024 * 1024 + fClient := shareClient.NewRootDirectoryClient().NewFileClient(testcommon.GenerateFileName(testName)) + _, err = fClient.Create(context.Background(), fileSize, nil) + _require.NoError(err) + + gResp, err := fClient.GetProperties(context.Background(), nil) + _require.NoError(err) + _require.Equal(*gResp.ContentLength, fileSize) + + content := make([]byte, fileSize) + _, err = rand.Read(content) + _require.NoError(err) + md5Value := md5.Sum(content) + contentMD5 := md5Value[:] + + err = fClient.UploadBuffer(context.Background(), content, &file.UploadBufferOptions{ + Concurrency: 5, + ChunkSize: 4 * 1024 * 1024, + }) + _require.NoError(err) + + destFileName := "BigFile-downloaded.bin" + destFile, err := os.Create(destFileName) + _require.NoError(err) + defer func(name string) { + err = os.Remove(name) + _require.NoError(err) + }(destFileName) + defer func(destFile *os.File) { + err = destFile.Close() + _require.NoError(err) + }(destFile) + + cnt, err := fClient.DownloadFile(context.Background(), destFile, &file.DownloadFileOptions{ + ChunkSize: 10 * 1024 * 1024, + Concurrency: 5, + }) + _require.NoError(err) + _require.Equal(cnt, fileSize) + + hash := md5.New() + _, err = io.Copy(hash, destFile) + _require.NoError(err) + downloadedContentMD5 := hash.Sum(nil) + + _require.EqualValues(downloadedContentMD5, contentMD5) + + gResp2, err := fClient.GetProperties(context.Background(), nil) + _require.NoError(err) + _require.Equal(*gResp2.ContentLength, fileSize) + + rangeList, err := fClient.GetRangeList(context.Background(), nil) + _require.NoError(err) + _require.Len(rangeList.Ranges, 1) + _require.Equal(*rangeList.Ranges[0].Start, int64(0)) + _require.Equal(*rangeList.Ranges[0].End, fileSize-1) +} + +func (f *FileRecordedTestsSuite) TestUploadDownloadDefaultNonDefaultMD5() { + _require := require.New(f.T()) + testName := f.T().Name() + + svcClient, err := testcommon.GetServiceClient(f.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + shareClient := testcommon.CreateNewShare(context.Background(), _require, testcommon.GenerateShareName(testName), svcClient) + defer testcommon.DeleteShare(context.Background(), _require, shareClient) + + fClient := testcommon.CreateNewFileFromShare(context.Background(), _require, "src"+testcommon.GenerateFileName(testName), 2048, shareClient) + defer testcommon.DeleteFile(context.Background(), _require, fClient) + + contentR, contentD := testcommon.GenerateData(2048) + + pResp, err := fClient.UploadRange(context.Background(), 0, contentR, nil) + _require.NoError(err) + _require.NotNil(pResp.ContentMD5) + _require.NotNil(pResp.IsServerEncrypted) + _require.NotNil(pResp.ETag) + _require.Equal(pResp.LastModified.IsZero(), false) + _require.NotNil(pResp.RequestID) + _require.NotNil(pResp.Version) + _require.Equal(pResp.Date.IsZero(), false) + + // Get with rangeGetContentMD5 enabled. + // Partial data, check status code 206. + resp, err := fClient.DownloadStream(context.Background(), &file.DownloadStreamOptions{ + Range: file.HTTPRange{Offset: 0, Count: 1024}, + RangeGetContentMD5: to.Ptr(true), + }) + _require.NoError(err) + _require.Equal(*resp.ContentLength, int64(1024)) + _require.NotNil(resp.ContentMD5) + _require.Equal(*resp.ContentType, "application/octet-stream") + + downloadedData, err := ioutil.ReadAll(resp.Body) + _require.NoError(err) + _require.EqualValues(downloadedData, contentD[:1024]) + + // Set ContentMD5 for the entire file. + _, err = fClient.SetHTTPHeaders(context.Background(), &file.SetHTTPHeadersOptions{ + HTTPHeaders: &file.HTTPHeaders{ + ContentMD5: pResp.ContentMD5, + ContentLanguage: to.Ptr("test")}, + }) + _require.NoError(err) + + // Test get with another type of range index, and validate if FileContentMD5 can be got correct. + resp, err = fClient.DownloadStream(context.Background(), &file.DownloadStreamOptions{ + Range: file.HTTPRange{Offset: 1024, Count: file.CountToEnd}, + }) + _require.NoError(err) + _require.Equal(*resp.ContentLength, int64(1024)) + _require.Nil(resp.ContentMD5) + _require.EqualValues(resp.FileContentMD5, pResp.ContentMD5) + _require.Equal(*resp.ContentLanguage, "test") + // Note: when it's downloading range, range's MD5 is returned, when set rangeGetContentMD5=true, currently set it to false, so should be empty + + downloadedData, err = ioutil.ReadAll(resp.Body) + _require.NoError(err) + _require.EqualValues(downloadedData, contentD[1024:]) + + _require.Equal(*resp.AcceptRanges, "bytes") + _require.Nil(resp.CacheControl) + _require.Nil(resp.ContentDisposition) + _require.Nil(resp.ContentEncoding) + _require.Equal(*resp.ContentRange, "bytes 1024-2047/2048") + _require.Nil(resp.ContentType) // Note ContentType is set to empty during SetHTTPHeaders + _require.Nil(resp.CopyID) + _require.Nil(resp.CopyProgress) + _require.Nil(resp.CopySource) + _require.Nil(resp.CopyStatus) + _require.Nil(resp.CopyStatusDescription) + _require.Equal(resp.Date.IsZero(), false) + _require.NotEqual(*resp.ETag, "") + _require.Equal(resp.LastModified.IsZero(), false) + _require.Nil(resp.Metadata) + _require.NotEqual(*resp.RequestID, "") + _require.NotEqual(*resp.Version, "") + _require.NotNil(resp.IsServerEncrypted) + + // Get entire fClient, check status code 200. + resp, err = fClient.DownloadStream(context.Background(), nil) + _require.NoError(err) + _require.Equal(*resp.ContentLength, int64(2048)) + _require.EqualValues(resp.ContentMD5, pResp.ContentMD5) // Note: This case is inted to get entire fClient, entire file's MD5 will be returned. + _require.Nil(resp.FileContentMD5) // Note: FileContentMD5 is returned, only when range is specified explicitly. + + downloadedData, err = ioutil.ReadAll(resp.Body) + _require.NoError(err) + _require.EqualValues(downloadedData, contentD[:]) + + _require.Equal(*resp.AcceptRanges, "bytes") + _require.Nil(resp.CacheControl) + _require.Nil(resp.ContentDisposition) + _require.Nil(resp.ContentEncoding) + _require.Nil(resp.ContentRange) // Note: ContentRange is returned, only when range is specified explicitly. + _require.Nil(resp.ContentType) + _require.Nil(resp.CopyCompletionTime) + _require.Nil(resp.CopyID) + _require.Nil(resp.CopyProgress) + _require.Nil(resp.CopySource) + _require.Nil(resp.CopyStatus) + _require.Nil(resp.CopyStatusDescription) + _require.Equal(resp.Date.IsZero(), false) + _require.NotEqual(*resp.ETag, "") + _require.Equal(resp.LastModified.IsZero(), false) + _require.Nil(resp.Metadata) + _require.NotEqual(*resp.RequestID, "") + _require.NotEqual(*resp.Version, "") + _require.NotNil(resp.IsServerEncrypted) +} + +func (f *FileRecordedTestsSuite) TestFileDownloadDataNonExistentFile() { + _require := require.New(f.T()) + testName := f.T().Name() + + svcClient, err := testcommon.GetServiceClient(f.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + shareClient := testcommon.CreateNewShare(context.Background(), _require, testcommon.GenerateShareName(testName), svcClient) + defer testcommon.DeleteShare(context.Background(), _require, shareClient) + + fClient := testcommon.GetFileClientFromShare(testcommon.GenerateFileName(testName), shareClient) + + _, err = fClient.DownloadStream(context.Background(), nil) + testcommon.ValidateFileErrorCode(_require, err, fileerror.ResourceNotFound) +} + +func (f *FileRecordedTestsSuite) TestFileDownloadDataOffsetOutOfRange() { + _require := require.New(f.T()) + testName := f.T().Name() + + svcClient, err := testcommon.GetServiceClient(f.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + shareClient := testcommon.CreateNewShare(context.Background(), _require, testcommon.GenerateShareName(testName), svcClient) + defer testcommon.DeleteShare(context.Background(), _require, shareClient) + + fClient := testcommon.CreateNewFileFromShare(context.Background(), _require, testcommon.GenerateFileName(testName), 0, shareClient) + + _, err = fClient.DownloadStream(context.Background(), &file.DownloadStreamOptions{ + Range: file.HTTPRange{ + Offset: int64(len(testcommon.FileDefaultData)), + Count: file.CountToEnd, + }, + }) + testcommon.ValidateFileErrorCode(_require, err, fileerror.InvalidRange) +} + +func (f *FileRecordedTestsSuite) TestFileDownloadDataEntireFile() { + _require := require.New(f.T()) + testName := f.T().Name() + + svcClient, err := testcommon.GetServiceClient(f.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + shareClient := testcommon.CreateNewShare(context.Background(), _require, testcommon.GenerateShareName(testName), svcClient) + defer testcommon.DeleteShare(context.Background(), _require, shareClient) + + fClient := testcommon.CreateNewFileFromShareWithData(context.Background(), _require, testcommon.GenerateFileName(testName), shareClient) + + resp, err := fClient.DownloadStream(context.Background(), nil) + _require.NoError(err) + + // Specifying a count of 0 results in the value being ignored + data, err := ioutil.ReadAll(resp.Body) + _require.NoError(err) + _require.EqualValues(string(data), testcommon.FileDefaultData) +} + +func (f *FileRecordedTestsSuite) TestFileDownloadDataCountExact() { + _require := require.New(f.T()) + testName := f.T().Name() + + svcClient, err := testcommon.GetServiceClient(f.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + shareClient := testcommon.CreateNewShare(context.Background(), _require, testcommon.GenerateShareName(testName), svcClient) + defer testcommon.DeleteShare(context.Background(), _require, shareClient) + + fClient := testcommon.CreateNewFileFromShareWithData(context.Background(), _require, testcommon.GenerateFileName(testName), shareClient) + + resp, err := fClient.DownloadStream(context.Background(), &file.DownloadStreamOptions{ + Range: file.HTTPRange{ + Offset: 0, + Count: int64(len(testcommon.FileDefaultData)), + }, + }) + _require.NoError(err) + + data, err := ioutil.ReadAll(resp.Body) + _require.NoError(err) + _require.EqualValues(string(data), testcommon.FileDefaultData) +} + +func (f *FileRecordedTestsSuite) TestFileDownloadDataCountOutOfRange() { + _require := require.New(f.T()) + testName := f.T().Name() + + svcClient, err := testcommon.GetServiceClient(f.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + shareClient := testcommon.CreateNewShare(context.Background(), _require, testcommon.GenerateShareName(testName), svcClient) + defer testcommon.DeleteShare(context.Background(), _require, shareClient) + + fClient := testcommon.CreateNewFileFromShareWithData(context.Background(), _require, testcommon.GenerateFileName(testName), shareClient) + + resp, err := fClient.DownloadStream(context.Background(), &file.DownloadStreamOptions{ + Range: file.HTTPRange{ + Offset: 0, + Count: int64(len(testcommon.FileDefaultData)) * 2, + }, + }) + _require.NoError(err) + + data, err := ioutil.ReadAll(resp.Body) + _require.NoError(err) + _require.EqualValues(string(data), testcommon.FileDefaultData) +} + +func (f *FileRecordedTestsSuite) TestFileUploadRangeNilBody() { + _require := require.New(f.T()) + testName := f.T().Name() + svcClient, err := testcommon.GetServiceClient(f.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + shareClient := testcommon.CreateNewShare(context.Background(), _require, testcommon.GenerateShareName(testName), svcClient) + defer testcommon.DeleteShare(context.Background(), _require, shareClient) + + fClient := testcommon.CreateNewFileFromShare(context.Background(), _require, "src"+testcommon.GenerateFileName(testName), 0, shareClient) + + _, err = fClient.UploadRange(context.Background(), 0, nil, nil) + _require.Error(err) + _require.Contains(err.Error(), "body must not be nil") +} + +func (f *FileRecordedTestsSuite) TestFileUploadRangeEmptyBody() { + _require := require.New(f.T()) + testName := f.T().Name() + + svcClient, err := testcommon.GetServiceClient(f.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + shareClient := testcommon.CreateNewShare(context.Background(), _require, testcommon.GenerateShareName(testName), svcClient) + defer testcommon.DeleteShare(context.Background(), _require, shareClient) + + fClient := testcommon.CreateNewFileFromShare(context.Background(), _require, testcommon.GenerateFileName(testName), 0, shareClient) + + _, err = fClient.UploadRange(context.Background(), 0, streaming.NopCloser(bytes.NewReader([]byte{})), nil) + _require.Error(err) + _require.Contains(err.Error(), "body must contain readable data whose size is > 0") +} + +func (f *FileRecordedTestsSuite) TestFileUploadRangeNonExistentFile() { + _require := require.New(f.T()) + testName := f.T().Name() + svcClient, err := testcommon.GetServiceClient(f.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + shareClient := testcommon.CreateNewShare(context.Background(), _require, testcommon.GenerateShareName(testName), svcClient) + defer testcommon.DeleteShare(context.Background(), _require, shareClient) + + fClient := testcommon.GetFileClientFromShare(testcommon.GenerateFileName(testName), shareClient) + + rsc, _ := testcommon.GenerateData(12) + _, err = fClient.UploadRange(context.Background(), 0, rsc, nil) + _require.Error(err) + testcommon.ValidateFileErrorCode(_require, err, fileerror.ResourceNotFound) +} + +func (f *FileRecordedTestsSuite) TestFileUploadRangeTransactionalMD5() { + _require := require.New(f.T()) + testName := f.T().Name() + + svcClient, err := testcommon.GetServiceClient(f.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + shareClient := testcommon.CreateNewShare(context.Background(), _require, testcommon.GenerateShareName(testName), svcClient) + defer testcommon.DeleteShare(context.Background(), _require, shareClient) + + fClient := testcommon.CreateNewFileFromShare(context.Background(), _require, testcommon.GenerateFileName(testName), 2048, shareClient) + + contentR, contentD := testcommon.GenerateData(2048) + _md5 := md5.Sum(contentD) + + // Upload range with correct transactional MD5 + pResp, err := fClient.UploadRange(context.Background(), 0, contentR, &file.UploadRangeOptions{ + TransactionalValidation: file.TransferValidationTypeMD5(_md5[:]), + }) + _require.NoError(err) + _require.NotNil(pResp.ContentMD5) + _require.NotNil(pResp.ETag) + _require.Equal(pResp.LastModified.IsZero(), false) + _require.NotNil(pResp.RequestID) + _require.NotNil(pResp.Version) + _require.Equal(pResp.Date.IsZero(), false) + _require.EqualValues(pResp.ContentMD5, _md5[:]) + + // Upload range with empty MD5, nil MD5 is covered by other cases. + pResp, err = fClient.UploadRange(context.Background(), 1024, streaming.NopCloser(bytes.NewReader(contentD[1024:])), nil) + _require.NoError(err) + _require.NotNil(pResp.ContentMD5) + + resp, err := fClient.DownloadStream(context.Background(), nil) + _require.NoError(err) + _require.Equal(*resp.ContentLength, int64(2048)) + + downloadedData, err := ioutil.ReadAll(resp.Body) + _require.NoError(err) + _require.EqualValues(downloadedData, contentD[:]) +} + +func (f *FileRecordedTestsSuite) TestFileUploadRangeIncorrectTransactionalMD5() { + _require := require.New(f.T()) + testName := f.T().Name() + + svcClient, err := testcommon.GetServiceClient(f.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + shareClient := testcommon.CreateNewShare(context.Background(), _require, testcommon.GenerateShareName(testName), svcClient) + defer testcommon.DeleteShare(context.Background(), _require, shareClient) + + fClient := testcommon.CreateNewFileFromShare(context.Background(), _require, testcommon.GenerateFileName(testName), 2048, shareClient) + + contentR, _ := testcommon.GenerateData(2048) + _, incorrectMD5 := testcommon.GenerateData(16) + + // Upload range with incorrect transactional MD5 + _, err = fClient.UploadRange(context.Background(), 0, contentR, &file.UploadRangeOptions{ + TransactionalValidation: file.TransferValidationTypeMD5(incorrectMD5[:]), + }) + _require.Error(err) + testcommon.ValidateFileErrorCode(_require, err, fileerror.MD5Mismatch) +} + +// Testings for GetRangeList and ClearRange +func (f *FileRecordedTestsSuite) TestGetRangeListNonDefaultExact() { + _require := require.New(f.T()) + testName := f.T().Name() + + svcClient, err := testcommon.GetServiceClient(f.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + shareClient := testcommon.CreateNewShare(context.Background(), _require, testcommon.GenerateShareName(testName), svcClient) + defer testcommon.DeleteShare(context.Background(), _require, shareClient) + + fClient := testcommon.GetFileClientFromShare(testcommon.GenerateFileName(testName), shareClient) + + fileSize := int64(5 * 1024) + _, err = fClient.Create(context.Background(), fileSize, &file.CreateOptions{HTTPHeaders: &file.HTTPHeaders{}}) + _require.NoError(err) + defer testcommon.DeleteFile(context.Background(), _require, fClient) + + rsc, _ := testcommon.GenerateData(1024) + putResp, err := fClient.UploadRange(context.Background(), 0, rsc, nil) + _require.NoError(err) + _require.Equal(putResp.LastModified.IsZero(), false) + _require.NotNil(putResp.ETag) + _require.NotNil(putResp.ContentMD5) + _require.NotNil(putResp.RequestID) + _require.NotNil(putResp.Version) + _require.Equal(putResp.Date.IsZero(), false) + + rangeList, err := fClient.GetRangeList(context.Background(), &file.GetRangeListOptions{ + Range: file.HTTPRange{ + Offset: 0, + Count: fileSize, + }, + }) + _require.NoError(err) + _require.Equal(rangeList.LastModified.IsZero(), false) + _require.NotNil(rangeList.ETag) + _require.Equal(*rangeList.FileContentLength, fileSize) + _require.NotNil(rangeList.RequestID) + _require.NotNil(rangeList.Version) + _require.Equal(rangeList.Date.IsZero(), false) + _require.Len(rangeList.Ranges, 1) + _require.Equal(*rangeList.Ranges[0].Start, int64(0)) + _require.Equal(*rangeList.Ranges[0].End, int64(1023)) +} + +// Default means clear the entire file's range +func (f *FileRecordedTestsSuite) TestClearRangeDefault() { + _require := require.New(f.T()) + testName := f.T().Name() + + svcClient, err := testcommon.GetServiceClient(f.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + shareClient := testcommon.CreateNewShare(context.Background(), _require, testcommon.GenerateShareName(testName), svcClient) + defer testcommon.DeleteShare(context.Background(), _require, shareClient) + + fClient := testcommon.CreateNewFileFromShare(context.Background(), _require, testcommon.GenerateFileName(testName), 2048, shareClient) + defer testcommon.DeleteFile(context.Background(), _require, fClient) + + rsc, _ := testcommon.GenerateData(2048) + _, err = fClient.UploadRange(context.Background(), 0, rsc, nil) + _require.NoError(err) + + _, err = fClient.ClearRange(context.Background(), file.HTTPRange{Offset: 0, Count: 2048}, nil) + _require.NoError(err) + + rangeList, err := fClient.GetRangeList(context.Background(), &file.GetRangeListOptions{ + Range: file.HTTPRange{Offset: 0, Count: file.CountToEnd}, + }) + _require.NoError(err) + _require.Len(rangeList.Ranges, 0) +} + +func (f *FileRecordedTestsSuite) TestClearRangeNonDefault() { + _require := require.New(f.T()) + testName := f.T().Name() + svcClient, err := testcommon.GetServiceClient(f.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + shareClient := testcommon.CreateNewShare(context.Background(), _require, testcommon.GenerateShareName(testName), svcClient) + defer testcommon.DeleteShare(context.Background(), _require, shareClient) + + fClient := testcommon.CreateNewFileFromShare(context.Background(), _require, testcommon.GenerateFileName(testName), 4096, shareClient) + defer testcommon.DeleteFile(context.Background(), _require, fClient) + + rsc, _ := testcommon.GenerateData(2048) + _, err = fClient.UploadRange(context.Background(), 2048, rsc, nil) + _require.NoError(err) + + _, err = fClient.ClearRange(context.Background(), file.HTTPRange{Offset: 2048, Count: 2048}, nil) + _require.NoError(err) + + rangeList, err := fClient.GetRangeList(context.Background(), nil) + _require.NoError(err) + _require.Len(rangeList.Ranges, 0) +} + +func (f *FileRecordedTestsSuite) TestClearRangeMultipleRanges() { + _require := require.New(f.T()) + testName := f.T().Name() + svcClient, err := testcommon.GetServiceClient(f.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + shareClient := testcommon.CreateNewShare(context.Background(), _require, testcommon.GenerateShareName(testName), svcClient) + defer testcommon.DeleteShare(context.Background(), _require, shareClient) + + fClient := testcommon.CreateNewFileFromShare(context.Background(), _require, testcommon.GenerateFileName(testName), 2048, shareClient) + defer testcommon.DeleteFile(context.Background(), _require, fClient) + + rsc, _ := testcommon.GenerateData(2048) + _, err = fClient.UploadRange(context.Background(), 0, rsc, nil) + _require.NoError(err) + + _, err = fClient.ClearRange(context.Background(), file.HTTPRange{Offset: 1024, Count: 1024}, nil) + _require.NoError(err) + + rangeList, err := fClient.GetRangeList(context.Background(), nil) + _require.NoError(err) + _require.Len(rangeList.Ranges, 1) + _require.EqualValues(*rangeList.Ranges[0], file.ShareFileRange{Start: to.Ptr(int64(0)), End: to.Ptr(int64(1023))}) +} + +// When not 512 aligned, clear range will set 0 the non-512 aligned range, and will not eliminate the range. +func (f *FileRecordedTestsSuite) TestClearRangeNonDefaultCount() { + _require := require.New(f.T()) + testName := f.T().Name() + + svcClient, err := testcommon.GetServiceClient(f.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + shareClient := testcommon.CreateNewShare(context.Background(), _require, testcommon.GenerateShareName(testName), svcClient) + defer testcommon.DeleteShare(context.Background(), _require, shareClient) + + fClient := testcommon.CreateNewFileFromShare(context.Background(), _require, testcommon.GenerateFileName(testName), 1, shareClient) + defer testcommon.DeleteFile(context.Background(), _require, fClient) + + d := []byte{65} + _, err = fClient.UploadRange(context.Background(), 0, streaming.NopCloser(bytes.NewReader(d)), nil) + _require.NoError(err) + + rangeList, err := fClient.GetRangeList(context.Background(), &file.GetRangeListOptions{ + Range: file.HTTPRange{Offset: 0, Count: file.CountToEnd}, + }) + _require.NoError(err) + _require.Len(rangeList.Ranges, 1) + _require.EqualValues(*rangeList.Ranges[0], file.ShareFileRange{Start: to.Ptr(int64(0)), End: to.Ptr(int64(0))}) + + _, err = fClient.ClearRange(context.Background(), file.HTTPRange{Offset: 0, Count: 1}, nil) + _require.NoError(err) + + rangeList, err = fClient.GetRangeList(context.Background(), &file.GetRangeListOptions{ + Range: file.HTTPRange{Offset: 0, Count: file.CountToEnd}, + }) + _require.NoError(err) + _require.Len(rangeList.Ranges, 1) + _require.EqualValues(*rangeList.Ranges[0], file.ShareFileRange{Start: to.Ptr(int64(0)), End: to.Ptr(int64(0))}) + + dResp, err := fClient.DownloadStream(context.Background(), nil) + _require.NoError(err) + + _bytes, err := ioutil.ReadAll(dResp.Body) + _require.NoError(err) + _require.EqualValues(_bytes, []byte{0}) +} + +func (f *FileRecordedTestsSuite) TestFileClearRangeNegativeInvalidCount() { + _require := require.New(f.T()) + testName := f.T().Name() + svcClient, err := testcommon.GetServiceClient(f.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + shareClient := testcommon.GetShareClient(testcommon.GenerateShareName(testName), svcClient) + fClient := testcommon.GetFileClientFromShare(testcommon.GenerateFileName(testName), shareClient) + + _, err = fClient.ClearRange(context.Background(), file.HTTPRange{Offset: 0, Count: 0}, nil) + _require.Error(err) + _require.Contains(err.Error(), "invalid argument: either offset is < 0 or count <= 0") +} + +func (f *FileRecordedTestsSuite) TestFileGetRangeListDefaultEmptyFile() { + _require := require.New(f.T()) + testName := f.T().Name() + + svcClient, err := testcommon.GetServiceClient(f.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + shareClient := testcommon.CreateNewShare(context.Background(), _require, testcommon.GenerateShareName(testName), svcClient) + defer testcommon.DeleteShare(context.Background(), _require, shareClient) + + fClient := testcommon.CreateNewFileFromShare(context.Background(), _require, testcommon.GenerateFileName(testName), 0, shareClient) + + resp, err := fClient.GetRangeList(context.Background(), nil) + _require.NoError(err) + _require.Len(resp.Ranges, 0) +} + +func setupGetRangeListTest(_require *require.Assertions, testName string, fileSize int64, shareClient *share.Client) *file.Client { + fClient := testcommon.CreateNewFileFromShare(context.Background(), _require, testcommon.GenerateFileName(testName), fileSize, shareClient) + rsc, _ := testcommon.GenerateData(int(fileSize)) + _, err := fClient.UploadRange(context.Background(), 0, rsc, nil) + _require.NoError(err) + return fClient +} + +func (f *FileRecordedTestsSuite) TestFileGetRangeListDefaultRange() { + _require := require.New(f.T()) + testName := f.T().Name() + + svcClient, err := testcommon.GetServiceClient(f.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + shareClient := testcommon.CreateNewShare(context.Background(), _require, testcommon.GenerateShareName(testName), svcClient) + defer testcommon.DeleteShare(context.Background(), _require, shareClient) + + fileSize := int64(512) + fClient := setupGetRangeListTest(_require, testName, fileSize, shareClient) + + resp, err := fClient.GetRangeList(context.Background(), &file.GetRangeListOptions{ + Range: file.HTTPRange{Offset: 0, Count: file.CountToEnd}, + }) + _require.NoError(err) + _require.Len(resp.Ranges, 1) + _require.EqualValues(*resp.Ranges[0], file.ShareFileRange{Start: to.Ptr(int64(0)), End: to.Ptr(fileSize - 1)}) +} + +func (f *FileRecordedTestsSuite) TestFileGetRangeListNonContiguousRanges() { + _require := require.New(f.T()) + testName := f.T().Name() + + svcClient, err := testcommon.GetServiceClient(f.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + shareClient := testcommon.CreateNewShare(context.Background(), _require, testcommon.GenerateShareName(testName), svcClient) + defer testcommon.DeleteShare(context.Background(), _require, shareClient) + + fileSize := int64(512) + fClient := setupGetRangeListTest(_require, testName, fileSize, shareClient) + + _, err = fClient.Resize(context.Background(), fileSize*3, nil) + _require.NoError(err) + + rsc, _ := testcommon.GenerateData(int(fileSize)) + _, err = fClient.UploadRange(context.Background(), fileSize*2, rsc, nil) + _require.NoError(err) + + resp, err := fClient.GetRangeList(context.Background(), nil) + _require.NoError(err) + _require.Len(resp.Ranges, 2) + _require.EqualValues(*resp.Ranges[0], file.ShareFileRange{Start: to.Ptr(int64(0)), End: to.Ptr(fileSize - 1)}) + _require.EqualValues(*resp.Ranges[1], file.ShareFileRange{Start: to.Ptr(fileSize * 2), End: to.Ptr((fileSize * 3) - 1)}) +} + +func (f *FileRecordedTestsSuite) TestFileGetRangeListNonContiguousRangesCountLess() { + _require := require.New(f.T()) + testName := f.T().Name() + + svcClient, err := testcommon.GetServiceClient(f.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + shareClient := testcommon.CreateNewShare(context.Background(), _require, testcommon.GenerateShareName(testName), svcClient) + defer testcommon.DeleteShare(context.Background(), _require, shareClient) + + fileSize := int64(512) + fClient := setupGetRangeListTest(_require, testName, fileSize, shareClient) + + resp, err := fClient.GetRangeList(context.Background(), &file.GetRangeListOptions{ + Range: file.HTTPRange{Offset: 0, Count: fileSize}, + }) + _require.NoError(err) + _require.Len(resp.Ranges, 1) + _require.EqualValues(int64(0), *(resp.Ranges[0].Start)) + _require.EqualValues(fileSize-1, *(resp.Ranges[0].End)) +} + +func (f *FileRecordedTestsSuite) TestFileGetRangeListNonContiguousRangesCountExceed() { + _require := require.New(f.T()) + testName := f.T().Name() + + svcClient, err := testcommon.GetServiceClient(f.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + shareClient := testcommon.CreateNewShare(context.Background(), _require, testcommon.GenerateShareName(testName), svcClient) + defer testcommon.DeleteShare(context.Background(), _require, shareClient) + + fileSize := int64(512) + fClient := setupGetRangeListTest(_require, testName, fileSize, shareClient) + + resp, err := fClient.GetRangeList(context.Background(), &file.GetRangeListOptions{ + Range: file.HTTPRange{Offset: 0, Count: fileSize + 1}, + }) + _require.NoError(err) + _require.NoError(err) + _require.Len(resp.Ranges, 1) + _require.EqualValues(*resp.Ranges[0], file.ShareFileRange{Start: to.Ptr(int64(0)), End: to.Ptr(fileSize - 1)}) +} + +func (f *FileRecordedTestsSuite) TestFileGetRangeListSnapshot() { + _require := require.New(f.T()) + testName := f.T().Name() + + svcClient, err := testcommon.GetServiceClient(f.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + shareClient := testcommon.CreateNewShare(context.Background(), _require, testcommon.GenerateShareName(testName), svcClient) + defer func() { + _, err := shareClient.Delete(context.Background(), &share.DeleteOptions{DeleteSnapshots: to.Ptr(share.DeleteSnapshotsOptionTypeInclude)}) + _require.NoError(err) + }() + + fileSize := int64(512) + fClient := setupGetRangeListTest(_require, testName, fileSize, shareClient) + + resp, _ := shareClient.CreateSnapshot(context.Background(), nil) + _require.NotNil(resp.Snapshot) + + resp2, err := fClient.GetRangeList(context.Background(), &file.GetRangeListOptions{ + Range: file.HTTPRange{Offset: 0, Count: file.CountToEnd}, + ShareSnapshot: resp.Snapshot, + }) + _require.NoError(err) + _require.Len(resp2.Ranges, 1) + _require.EqualValues(*resp2.Ranges[0], file.ShareFileRange{Start: to.Ptr(int64(0)), End: to.Ptr(fileSize - 1)}) +} + +func (f *FileRecordedTestsSuite) TestFileUploadDownloadSmallBuffer() { + _require := require.New(f.T()) + testName := f.T().Name() + + svcClient, err := testcommon.GetServiceClient(f.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + shareClient := testcommon.CreateNewShare(context.Background(), _require, testcommon.GenerateShareName(testName), svcClient) + defer testcommon.DeleteShare(context.Background(), _require, shareClient) + + var fileSize int64 = 10 * 1024 + fClient := shareClient.NewRootDirectoryClient().NewFileClient(testcommon.GenerateFileName(testName)) + _, err = fClient.Create(context.Background(), fileSize, nil) + _require.NoError(err) + + gResp, err := fClient.GetProperties(context.Background(), nil) + _require.NoError(err) + _require.Equal(*gResp.ContentLength, fileSize) + + _, content := testcommon.GenerateData(int(fileSize)) + md5Value := md5.Sum(content) + contentMD5 := md5Value[:] + + err = fClient.UploadBuffer(context.Background(), content, &file.UploadBufferOptions{ + Concurrency: 5, + ChunkSize: 2 * 1024, + }) + _require.NoError(err) + + destBuffer := make([]byte, fileSize) + cnt, err := fClient.DownloadBuffer(context.Background(), destBuffer, &file.DownloadBufferOptions{ + ChunkSize: 2 * 1024, + Concurrency: 5, + }) + _require.NoError(err) + _require.Equal(cnt, fileSize) + + downloadedMD5Value := md5.Sum(destBuffer) + downloadedContentMD5 := downloadedMD5Value[:] + + _require.EqualValues(downloadedContentMD5, contentMD5) + + gResp2, err := fClient.GetProperties(context.Background(), nil) + _require.NoError(err) + _require.Equal(*gResp2.ContentLength, fileSize) + + rangeList, err := fClient.GetRangeList(context.Background(), nil) + _require.NoError(err) + _require.Len(rangeList.Ranges, 1) + _require.Equal(*rangeList.Ranges[0].Start, int64(0)) + _require.Equal(*rangeList.Ranges[0].End, fileSize-1) +} + +func (f *FileRecordedTestsSuite) TestFileUploadDownloadSmallFile() { + _require := require.New(f.T()) + testName := f.T().Name() + + svcClient, err := testcommon.GetServiceClient(f.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + shareClient := testcommon.CreateNewShare(context.Background(), _require, testcommon.GenerateShareName(testName), svcClient) + defer testcommon.DeleteShare(context.Background(), _require, shareClient) + + var fileSize int64 = 10 * 1024 + fClient := shareClient.NewRootDirectoryClient().NewFileClient(testcommon.GenerateFileName(testName)) + _, err = fClient.Create(context.Background(), fileSize, nil) + _require.NoError(err) + + gResp, err := fClient.GetProperties(context.Background(), nil) + _require.NoError(err) + _require.Equal(*gResp.ContentLength, fileSize) + + // create local file + _, content := testcommon.GenerateData(int(fileSize)) + srcFileName := "testFileUpload" + err = ioutil.WriteFile(srcFileName, content, 0644) + _require.NoError(err) + defer func() { + err = os.Remove(srcFileName) + _require.NoError(err) + }() + fh, err := os.Open(srcFileName) + _require.NoError(err) + defer func(fh *os.File) { + err := fh.Close() + _require.NoError(err) + }(fh) + + srcHash := md5.New() + _, err = io.Copy(srcHash, fh) + _require.NoError(err) + contentMD5 := srcHash.Sum(nil) + + err = fClient.UploadFile(context.Background(), fh, &file.UploadFileOptions{ + Concurrency: 5, + ChunkSize: 2 * 1024, + }) + _require.NoError(err) + + destFileName := "SmallFile-downloaded.bin" + destFile, err := os.Create(destFileName) + _require.NoError(err) + defer func(name string) { + err = os.Remove(name) + _require.NoError(err) + }(destFileName) + defer func(destFile *os.File) { + err = destFile.Close() + _require.NoError(err) + }(destFile) + + cnt, err := fClient.DownloadFile(context.Background(), destFile, &file.DownloadFileOptions{ + ChunkSize: 2 * 1024, + Concurrency: 5, + }) + _require.NoError(err) + _require.Equal(cnt, fileSize) + + destHash := md5.New() + _, err = io.Copy(destHash, destFile) + _require.NoError(err) + downloadedContentMD5 := destHash.Sum(nil) + + _require.EqualValues(downloadedContentMD5, contentMD5) + + gResp2, err := fClient.GetProperties(context.Background(), nil) + _require.NoError(err) + _require.Equal(*gResp2.ContentLength, fileSize) + + rangeList, err := fClient.GetRangeList(context.Background(), nil) + _require.NoError(err) + _require.Len(rangeList.Ranges, 1) + _require.Equal(*rangeList.Ranges[0].Start, int64(0)) + _require.Equal(*rangeList.Ranges[0].End, fileSize-1) +} + +func (f *FileRecordedTestsSuite) TestFileUploadDownloadSmallStream() { + _require := require.New(f.T()) + testName := f.T().Name() + + svcClient, err := testcommon.GetServiceClient(f.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + shareClient := testcommon.CreateNewShare(context.Background(), _require, testcommon.GenerateShareName(testName), svcClient) + defer testcommon.DeleteShare(context.Background(), _require, shareClient) + + var fileSize int64 = 10 * 1024 + fClient := shareClient.NewRootDirectoryClient().NewFileClient(testcommon.GenerateFileName(testName)) + _, err = fClient.Create(context.Background(), fileSize, nil) + _require.NoError(err) + + gResp, err := fClient.GetProperties(context.Background(), nil) + _require.NoError(err) + _require.Equal(*gResp.ContentLength, fileSize) + + _, content := testcommon.GenerateData(int(fileSize)) + md5Value := md5.Sum(content) + contentMD5 := md5Value[:] + + err = fClient.UploadStream(context.Background(), streaming.NopCloser(bytes.NewReader(content)), &file.UploadStreamOptions{ + Concurrency: 5, + ChunkSize: 2 * 1024, + }) + _require.NoError(err) + + dResp, err := fClient.DownloadStream(context.Background(), nil) + _require.NoError(err) + + data, err := io.ReadAll(dResp.Body) + _require.NoError(err) + + downloadedMD5Value := md5.Sum(data) + downloadedContentMD5 := downloadedMD5Value[:] + + _require.EqualValues(downloadedContentMD5, contentMD5) + + gResp2, err := fClient.GetProperties(context.Background(), nil) + _require.NoError(err) + _require.Equal(*gResp2.ContentLength, fileSize) + + rangeList, err := fClient.GetRangeList(context.Background(), nil) + _require.NoError(err) + _require.Len(rangeList.Ranges, 1) + _require.Equal(*rangeList.Ranges[0].Start, int64(0)) + _require.Equal(*rangeList.Ranges[0].End, fileSize-1) +} + +func (f *FileRecordedTestsSuite) TestFileUploadDownloadWithProgress() { + _require := require.New(f.T()) + testName := f.T().Name() + + svcClient, err := testcommon.GetServiceClient(f.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + shareClient := testcommon.CreateNewShare(context.Background(), _require, testcommon.GenerateShareName(testName), svcClient) + defer testcommon.DeleteShare(context.Background(), _require, shareClient) + + var fileSize int64 = 10 * 1024 + fClient := shareClient.NewRootDirectoryClient().NewFileClient(testcommon.GenerateFileName(testName)) + _, err = fClient.Create(context.Background(), fileSize, nil) + _require.NoError(err) + + gResp, err := fClient.GetProperties(context.Background(), nil) + _require.NoError(err) + _require.Equal(*gResp.ContentLength, fileSize) + + _, content := testcommon.GenerateData(int(fileSize)) + md5Value := md5.Sum(content) + contentMD5 := md5Value[:] + + bytesUploaded := int64(0) + err = fClient.UploadBuffer(context.Background(), content, &file.UploadBufferOptions{ + Concurrency: 5, + ChunkSize: 2 * 1024, + Progress: func(bytesTransferred int64) { + _require.GreaterOrEqual(bytesTransferred, bytesUploaded) + bytesUploaded = bytesTransferred + }, + }) + _require.NoError(err) + _require.Equal(bytesUploaded, fileSize) + + destBuffer := make([]byte, fileSize) + bytesDownloaded := int64(0) + cnt, err := fClient.DownloadBuffer(context.Background(), destBuffer, &file.DownloadBufferOptions{ + ChunkSize: 2 * 1024, + Concurrency: 5, + Progress: func(bytesTransferred int64) { + _require.GreaterOrEqual(bytesTransferred, bytesDownloaded) + bytesDownloaded = bytesTransferred + }, + }) + _require.NoError(err) + _require.Equal(cnt, fileSize) + _require.Equal(bytesDownloaded, fileSize) + + downloadedMD5Value := md5.Sum(destBuffer) + downloadedContentMD5 := downloadedMD5Value[:] + + _require.EqualValues(downloadedContentMD5, contentMD5) + + gResp2, err := fClient.GetProperties(context.Background(), nil) + _require.NoError(err) + _require.Equal(*gResp2.ContentLength, fileSize) + + rangeList, err := fClient.GetRangeList(context.Background(), nil) + _require.NoError(err) + _require.Len(rangeList.Ranges, 1) + _require.Equal(*rangeList.Ranges[0].Start, int64(0)) + _require.Equal(*rangeList.Ranges[0].End, fileSize-1) +} + +func (f *FileRecordedTestsSuite) TestFileListHandlesDefault() { + _require := require.New(f.T()) + testName := f.T().Name() + + svcClient, err := testcommon.GetServiceClient(f.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + shareClient := testcommon.CreateNewShare(context.Background(), _require, testcommon.GenerateShareName(testName), svcClient) + defer testcommon.DeleteShare(context.Background(), _require, shareClient) + + fClient := testcommon.CreateNewFileFromShare(context.Background(), _require, testcommon.GenerateFileName(testName), 2048, shareClient) + + resp, err := fClient.ListHandles(context.Background(), nil) + _require.NoError(err) + _require.Len(resp.Handles, 0) + _require.NotNil(resp.NextMarker) + _require.Equal(*resp.NextMarker, "") +} + +func (f *FileRecordedTestsSuite) TestFileForceCloseHandlesDefault() { + _require := require.New(f.T()) + testName := f.T().Name() + + svcClient, err := testcommon.GetServiceClient(f.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + shareClient := testcommon.CreateNewShare(context.Background(), _require, testcommon.GenerateShareName(testName), svcClient) + defer testcommon.DeleteShare(context.Background(), _require, shareClient) + + fClient := testcommon.CreateNewFileFromShare(context.Background(), _require, testcommon.GenerateFileName(testName), 2048, shareClient) + + resp, err := fClient.ForceCloseHandles(context.Background(), "*", nil) + _require.NoError(err) + _require.EqualValues(*resp.NumberOfHandlesClosed, 0) + _require.EqualValues(*resp.NumberOfHandlesFailedToClose, 0) + _require.Nil(resp.Marker) +} + +// TODO: Add tests for retry header options diff --git a/sdk/storage/azfile/file/constants.go b/sdk/storage/azfile/file/constants.go new file mode 100644 index 000000000000..c5687bd1b3b5 --- /dev/null +++ b/sdk/storage/azfile/file/constants.go @@ -0,0 +1,78 @@ +//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 file + +import ( + "github.com/Azure/azure-sdk-for-go/sdk/storage/azfile/internal/exported" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azfile/internal/generated" +) + +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 + + // 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 +) + +// CopyStatusType defines the states of the copy operation. +type CopyStatusType = generated.CopyStatusType + +const ( + CopyStatusTypePending CopyStatusType = generated.CopyStatusTypePending + CopyStatusTypeSuccess CopyStatusType = generated.CopyStatusTypeSuccess + CopyStatusTypeAborted CopyStatusType = generated.CopyStatusTypeAborted + CopyStatusTypeFailed CopyStatusType = generated.CopyStatusTypeFailed +) + +// PossibleCopyStatusTypeValues returns the possible values for the CopyStatusType const type. +func PossibleCopyStatusTypeValues() []CopyStatusType { + return generated.PossibleCopyStatusTypeValues() +} + +// PermissionCopyModeType determines the copy behavior of the security descriptor of the file. +// - source: The security descriptor on the destination file is copied from the source file. +// - override: The security descriptor on the destination file is determined via the x-ms-file-permission or x-ms-file-permission-key header. +type PermissionCopyModeType = generated.PermissionCopyModeType + +const ( + PermissionCopyModeTypeSource PermissionCopyModeType = generated.PermissionCopyModeTypeSource + PermissionCopyModeTypeOverride PermissionCopyModeType = generated.PermissionCopyModeTypeOverride +) + +// PossiblePermissionCopyModeTypeValues returns the possible values for the PermissionCopyModeType const type. +func PossiblePermissionCopyModeTypeValues() []PermissionCopyModeType { + return generated.PossiblePermissionCopyModeTypeValues() +} + +// RangeWriteType represents one of the following options. +// - update: Writes the bytes specified by the request body into the specified range. The Range and Content-Length headers must match to perform the update. +// - clear: Clears the specified range and releases the space used in storage for that range. To clear a range, set the Content-Length header to zero, +// and set the Range header to a value that indicates the range to clear, up to maximum file size. +type RangeWriteType = generated.FileRangeWriteType + +const ( + RangeWriteTypeUpdate RangeWriteType = generated.FileRangeWriteTypeUpdate + RangeWriteTypeClear RangeWriteType = generated.FileRangeWriteTypeClear +) + +// PossibleRangeWriteTypeValues returns the possible values for the RangeWriteType const type. +func PossibleRangeWriteTypeValues() []RangeWriteType { + return generated.PossibleFileRangeWriteTypeValues() +} + +// TransferValidationType abstracts the various mechanisms used to verify a transfer. +type TransferValidationType = exported.TransferValidationType + +// TransferValidationTypeMD5 is a TransferValidationType used to provide a precomputed MD5. +type TransferValidationTypeMD5 = exported.TransferValidationTypeMD5 diff --git a/sdk/storage/azfile/file/examples_test.go b/sdk/storage/azfile/file/examples_test.go new file mode 100644 index 000000000000..b54aa5aab215 --- /dev/null +++ b/sdk/storage/azfile/file/examples_test.go @@ -0,0 +1,650 @@ +//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 file_test + +import ( + "bytes" + "context" + "crypto/rand" + "fmt" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/streaming" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/to" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azfile/file" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azfile/sas" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azfile/service" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azfile/share" + "io" + "io/ioutil" + "log" + "os" + "strings" + "time" +) + +func handleError(err error) { + if err != nil { + log.Fatal(err.Error()) + } +} + +const random64BString string = "2SDgZj6RkKYzJpu04sweQek4uWHO8ndPnYlZ0tnFS61hjnFZ5IkvIGGY44eKABov" + +func generateData(sizeInBytes int) (io.ReadSeekCloser, []byte) { + data := make([]byte, sizeInBytes) + _len := len(random64BString) + if sizeInBytes > _len { + count := sizeInBytes / _len + if sizeInBytes%_len != 0 { + count = count + 1 + } + copy(data[:], strings.Repeat(random64BString, count)) + } else { + copy(data[:], random64BString) + } + return streaming.NopCloser(bytes.NewReader(data)), data +} + +func Example_client_NewClient_CreateShare_CreateDir_CreateFile() { + accountName, ok := os.LookupEnv("AZURE_STORAGE_ACCOUNT_NAME") + if !ok { + panic("AZURE_STORAGE_ACCOUNT_NAME could not be found") + } + accountKey, ok := os.LookupEnv("AZURE_STORAGE_ACCOUNT_KEY") + if !ok { + panic("AZURE_STORAGE_ACCOUNT_KEY could not be found") + } + + serviceURL := fmt.Sprintf("https://%s.file.core.windows.net/", accountName) + cred, err := service.NewSharedKeyCredential(accountName, accountKey) + handleError(err) + + client, err := service.NewClientWithSharedKeyCredential(serviceURL, cred, nil) + handleError(err) + + shareClient := client.NewShareClient("testShare") + fmt.Println(shareClient.URL()) + + dirClient := shareClient.NewDirectoryClient("testDir") + fmt.Println(dirClient.URL()) + + fileClient := dirClient.NewFileClient("testFile") + fmt.Println(fileClient.URL()) + +} + +func Example_file_NewClientFromConnectionString() { + // Your connection string can be obtained from the Azure Portal. + connectionString, ok := os.LookupEnv("AZURE_STORAGE_CONNECTION_STRING") + if !ok { + log.Fatal("the environment variable 'AZURE_STORAGE_CONNECTION_STRING' could not be found") + } + shareName := "testShare" + filePath := "testDir/testFile" + fileClient, err := file.NewClientFromConnectionString(connectionString, shareName, filePath, nil) + handleError(err) + fmt.Println(fileClient.URL()) +} + +func Example_fileClient_CreateAndDelete() { + // Your connection string can be obtained from the Azure Portal. + connectionString, ok := os.LookupEnv("AZURE_STORAGE_CONNECTION_STRING") + if !ok { + log.Fatal("the environment variable 'AZURE_STORAGE_CONNECTION_STRING' could not be found") + } + shareName := "testShare" + fileName := "testFile" + shareClient, err := share.NewClientFromConnectionString(connectionString, shareName, nil) + handleError(err) + + _, err = shareClient.Create(context.Background(), nil) + handleError(err) + + fileClient := shareClient.NewRootDirectoryClient().NewFileClient(fileName) + _, err = fileClient.Create(context.Background(), 5, nil) + handleError(err) + + _, err = fileClient.Delete(context.Background(), nil) + handleError(err) + + _, err = shareClient.Delete(context.Background(), nil) + handleError(err) +} + +func Example_fileClient_GetProperties() { + // Your connection string can be obtained from the Azure Portal. + connectionString, ok := os.LookupEnv("AZURE_STORAGE_CONNECTION_STRING") + if !ok { + log.Fatal("the environment variable 'AZURE_STORAGE_CONNECTION_STRING' could not be found") + } + shareName := "testShare" + fileName := "testFile" + shareClient, err := share.NewClientFromConnectionString(connectionString, shareName, nil) + handleError(err) + + _, err = shareClient.Create(context.Background(), nil) + handleError(err) + + fileClient := shareClient.NewRootDirectoryClient().NewFileClient(fileName) + _, err = fileClient.Create(context.Background(), 5, nil) + handleError(err) + + _, err = fileClient.GetProperties(context.Background(), nil) + handleError(err) + + _, err = fileClient.Delete(context.Background(), nil) + handleError(err) + + _, err = shareClient.Delete(context.Background(), nil) + handleError(err) + +} + +func Example_fileClient_SetAndGetMetadata() { + // Your connection string can be obtained from the Azure Portal. + connectionString, ok := os.LookupEnv("AZURE_STORAGE_CONNECTION_STRING") + if !ok { + log.Fatal("the environment variable 'AZURE_STORAGE_CONNECTION_STRING' could not be found") + } + shareName := "testShare" + fileName := "testFile" + shareClient, err := share.NewClientFromConnectionString(connectionString, shareName, nil) + handleError(err) + + _, err = shareClient.Create(context.Background(), nil) + handleError(err) + + fileClient := shareClient.NewRootDirectoryClient().NewFileClient(fileName) + _, err = fileClient.Create(context.Background(), 5, nil) + handleError(err) + + opts := file.SetMetadataOptions{Metadata: map[string]*string{"hello": to.Ptr("world")}} + _, err = fileClient.SetMetadata(context.Background(), &opts) + handleError(err) + + get, err := fileClient.GetProperties(context.Background(), nil) + handleError(err) + + if get.Metadata == nil { + log.Fatal("No metadata returned") + } + for k, v := range get.Metadata { + fmt.Print(k + "=" + *v + "\n") + } + + _, err = fileClient.Delete(context.Background(), nil) + handleError(err) + + _, err = shareClient.Delete(context.Background(), nil) + handleError(err) +} + +func Example_fileClient_UploadBuffer() { + // Your connection string can be obtained from the Azure Portal. + connectionString, ok := os.LookupEnv("AZURE_STORAGE_CONNECTION_STRING") + if !ok { + log.Fatal("the environment variable 'AZURE_STORAGE_CONNECTION_STRING' could not be found") + } + shareName := "testShare" + fileName := "testFile" + shareClient, err := share.NewClientFromConnectionString(connectionString, shareName, nil) + handleError(err) + + _, err = shareClient.Create(context.Background(), nil) + handleError(err) + + fileClient := shareClient.NewRootDirectoryClient().NewFileClient(fileName) + _, err = fileClient.Create(context.Background(), 5, nil) + handleError(err) + + data := []byte{'h', 'e', 'l', 'l', 'o'} + err = fileClient.UploadBuffer(context.Background(), data, nil) + handleError(err) + + _, err = fileClient.Delete(context.Background(), nil) + handleError(err) + + _, err = shareClient.Delete(context.Background(), nil) + handleError(err) +} + +func Example_fileClient_UploadStream() { + // Your connection string can be obtained from the Azure Portal. + connectionString, ok := os.LookupEnv("AZURE_STORAGE_CONNECTION_STRING") + if !ok { + log.Fatal("the environment variable 'AZURE_STORAGE_CONNECTION_STRING' could not be found") + } + shareName := "testShare" + fileName := "testFile" + shareClient, err := share.NewClientFromConnectionString(connectionString, shareName, nil) + handleError(err) + + _, err = shareClient.Create(context.Background(), nil) + handleError(err) + + fileClient := shareClient.NewRootDirectoryClient().NewFileClient(fileName) + _, err = fileClient.Create(context.Background(), 5, nil) + handleError(err) + + err = fileClient.UploadStream( + context.TODO(), + streaming.NopCloser(strings.NewReader("Some text")), + nil, + ) + handleError(err) + + _, err = fileClient.Delete(context.Background(), nil) + handleError(err) + + _, err = shareClient.Delete(context.Background(), nil) + handleError(err) +} + +func Example_fileClient_UploadAndClearRange() { + // Your connection string can be obtained from the Azure Portal. + connectionString, ok := os.LookupEnv("AZURE_STORAGE_CONNECTION_STRING") + if !ok { + log.Fatal("the environment variable 'AZURE_STORAGE_CONNECTION_STRING' could not be found") + } + shareName := "testShare" + fileName := "testFile" + shareClient, err := share.NewClientFromConnectionString(connectionString, shareName, nil) + handleError(err) + + _, err = shareClient.Create(context.Background(), nil) + handleError(err) + + fileClient := shareClient.NewRootDirectoryClient().NewFileClient(fileName) + _, err = fileClient.Create(context.Background(), 5, nil) + handleError(err) + + contentR, _ := generateData(5) + + _, err = fileClient.UploadRange(context.Background(), 0, contentR, nil) + handleError(err) + + rangeList, err := fileClient.GetRangeList(context.Background(), nil) + handleError(err) + fmt.Println(rangeList.Ranges) + + _, err = fileClient.ClearRange(context.Background(), file.HTTPRange{Offset: 0, Count: int64(5)}, nil) + handleError(err) + + rangeList2, err := fileClient.GetRangeList(context.Background(), nil) + handleError(err) + + fmt.Println(rangeList2.Ranges, 0) + _, err = fileClient.Delete(context.Background(), nil) + handleError(err) + + _, err = shareClient.Delete(context.Background(), nil) + handleError(err) +} + +func Example_fileClient_StartCopyFromURL() { + // Your connection string can be obtained from the Azure Portal. + connectionString, ok := os.LookupEnv("AZURE_STORAGE_CONNECTION_STRING") + if !ok { + log.Fatal("the environment variable 'AZURE_STORAGE_CONNECTION_STRING' could not be found") + } + shareName := "testShare" + srcFileName := "testFile" + dstFileName := "testFile2" + fileSize := int64(5) + + shareClient, err := share.NewClientFromConnectionString(connectionString, shareName, nil) + handleError(err) + + _, err = shareClient.Create(context.Background(), nil) + handleError(err) + + srcFileClient := shareClient.NewRootDirectoryClient().NewFileClient(srcFileName) + _, err = srcFileClient.Create(context.Background(), fileSize, nil) + handleError(err) + + dstFileClient := shareClient.NewRootDirectoryClient().NewFileClient(dstFileName) + + contentR, _ := generateData(int(fileSize)) + + _, err = srcFileClient.UploadRange(context.Background(), 0, contentR, nil) + handleError(err) + + // you can also use AbortCopy to abort copying + _, err = dstFileClient.StartCopyFromURL(context.Background(), srcFileClient.URL(), nil) + handleError(err) + + _, err = srcFileClient.Delete(context.Background(), nil) + handleError(err) + + _, err = dstFileClient.Delete(context.Background(), nil) + handleError(err) + + _, err = shareClient.Delete(context.Background(), nil) + handleError(err) +} + +func Example_fileClient_DownloadStream() { + // Your connection string can be obtained from the Azure Portal. + connectionString, ok := os.LookupEnv("AZURE_STORAGE_CONNECTION_STRING") + if !ok { + log.Fatal("the environment variable 'AZURE_STORAGE_CONNECTION_STRING' could not be found") + } + shareName := "testShare" + srcFileName := "testFile" + fileSize := int64(5) + + shareClient, err := share.NewClientFromConnectionString(connectionString, shareName, nil) + handleError(err) + + _, err = shareClient.Create(context.Background(), nil) + handleError(err) + + srcFileClient := shareClient.NewRootDirectoryClient().NewFileClient(srcFileName) + _, err = srcFileClient.Create(context.Background(), fileSize, nil) + handleError(err) + + contentR, _ := generateData(int(fileSize)) + + _, err = srcFileClient.UploadRange(context.Background(), 0, contentR, nil) + handleError(err) + + // validate data copied + resp, err := srcFileClient.DownloadStream(context.Background(), &file.DownloadStreamOptions{ + Range: file.HTTPRange{Offset: 0, Count: fileSize}, + }) + handleError(err) + + content1, err := io.ReadAll(resp.Body) + handleError(err) + fmt.Println(content1) + + _, err = srcFileClient.Delete(context.Background(), nil) + handleError(err) + + _, err = shareClient.Delete(context.Background(), nil) + handleError(err) +} + +func Example_fileClient_DownloadBuffer() { + // Your connection string can be obtained from the Azure Portal. + connectionString, ok := os.LookupEnv("AZURE_STORAGE_CONNECTION_STRING") + if !ok { + log.Fatal("the environment variable 'AZURE_STORAGE_CONNECTION_STRING' could not be found") + } + shareName := "testShare" + srcFileName := "testFile" + fileSize := int64(5) + + shareClient, err := share.NewClientFromConnectionString(connectionString, shareName, nil) + handleError(err) + + _, err = shareClient.Create(context.Background(), nil) + handleError(err) + + srcFileClient := shareClient.NewRootDirectoryClient().NewFileClient(srcFileName) + _, err = srcFileClient.Create(context.Background(), fileSize, nil) + handleError(err) + + content := make([]byte, fileSize) + _, err = rand.Read(content) + handleError(err) + + err = srcFileClient.UploadBuffer(context.Background(), content, nil) + handleError(err) + + destBuffer := make([]byte, fileSize) + _, err = srcFileClient.DownloadBuffer(context.Background(), destBuffer, nil) + handleError(err) + + _, err = srcFileClient.Delete(context.Background(), nil) + handleError(err) + + _, err = shareClient.Delete(context.Background(), nil) + handleError(err) +} + +func Example_fileClient_DownloadFile() { + // Your connection string can be obtained from the Azure Portal. + connectionString, ok := os.LookupEnv("AZURE_STORAGE_CONNECTION_STRING") + if !ok { + log.Fatal("the environment variable 'AZURE_STORAGE_CONNECTION_STRING' could not be found") + } + shareName := "testShare" + srcFileName := "testFile" + fileSize := int64(5) + + shareClient, err := share.NewClientFromConnectionString(connectionString, shareName, nil) + handleError(err) + + _, err = shareClient.Create(context.Background(), nil) + handleError(err) + + srcFileClient := shareClient.NewRootDirectoryClient().NewFileClient(srcFileName) + _, err = srcFileClient.Create(context.Background(), fileSize, nil) + handleError(err) + + content := make([]byte, fileSize) + _, err = rand.Read(content) + handleError(err) + + err = srcFileClient.UploadBuffer(context.Background(), content, nil) + handleError(err) + + destFileName := "file.bin" + destFile, err := os.Create(destFileName) + handleError(err) + defer func(name string) { + err = os.Remove(name) + handleError(err) + }(destFileName) + defer func(destFile *os.File) { + err = destFile.Close() + handleError(err) + }(destFile) + + _, err = srcFileClient.DownloadFile(context.Background(), destFile, nil) + handleError(err) + + _, err = srcFileClient.Delete(context.Background(), nil) + handleError(err) + + _, err = shareClient.Delete(context.Background(), nil) + handleError(err) +} + +func Example_fileClient_UploadFile() { + // Your connection string can be obtained from the Azure Portal. + connectionString, ok := os.LookupEnv("AZURE_STORAGE_CONNECTION_STRING") + if !ok { + log.Fatal("the environment variable 'AZURE_STORAGE_CONNECTION_STRING' could not be found") + } + shareName := "testShare" + srcFileName := "testFile" + fileSize := int64(5) + + shareClient, err := share.NewClientFromConnectionString(connectionString, shareName, nil) + handleError(err) + + _, err = shareClient.Create(context.Background(), nil) + handleError(err) + + srcFileClient := shareClient.NewRootDirectoryClient().NewFileClient(srcFileName) + _, err = srcFileClient.Create(context.Background(), fileSize, nil) + handleError(err) + + _, content := generateData(int(fileSize)) + err = ioutil.WriteFile(srcFileName, content, 0644) + handleError(err) + defer func() { + err = os.Remove(srcFileName) + handleError(err) + }() + fh, err := os.Open(srcFileName) + handleError(err) + defer func(fh *os.File) { + err := fh.Close() + handleError(err) + }(fh) + + err = srcFileClient.UploadFile(context.Background(), fh, nil) + + destFileName := "file.bin" + destFile, err := os.Create(destFileName) + handleError(err) + defer func(name string) { + err = os.Remove(name) + handleError(err) + }(destFileName) + defer func(destFile *os.File) { + err = destFile.Close() + handleError(err) + }(destFile) + + _, err = srcFileClient.DownloadFile(context.Background(), destFile, nil) + handleError(err) + + _, err = srcFileClient.Delete(context.Background(), nil) + handleError(err) + + _, err = shareClient.Delete(context.Background(), nil) + handleError(err) +} + +func Example_file_ClientGetSASURL() { + // Your connection string can be obtained from the Azure Portal. + connectionString, ok := os.LookupEnv("AZURE_STORAGE_CONNECTION_STRING") + if !ok { + log.Fatal("the environment variable 'AZURE_STORAGE_CONNECTION_STRING' could not be found") + } + shareName := "testShare" + srcFileName := "testFile" + fileSize := int64(5) + + shareClient, err := share.NewClientFromConnectionString(connectionString, shareName, nil) + handleError(err) + + _, err = shareClient.Create(context.Background(), nil) + handleError(err) + + srcFileClient := shareClient.NewRootDirectoryClient().NewFileClient(srcFileName) + _, err = srcFileClient.Create(context.Background(), fileSize, nil) + handleError(err) + + permission := sas.FilePermissions{Read: true} + start := time.Now() + expiry := start.AddDate(1, 0, 0) + options := file.GetSASURLOptions{StartTime: &start} + sasURL, err := srcFileClient.GetSASURL(permission, expiry, &options) + handleError(err) + _ = sasURL + + _, err = srcFileClient.Delete(context.Background(), nil) + handleError(err) + + _, err = shareClient.Delete(context.Background(), nil) + handleError(err) +} + +func Example_fileClient_Resize() { + // Your connection string can be obtained from the Azure Portal. + connectionString, ok := os.LookupEnv("AZURE_STORAGE_CONNECTION_STRING") + if !ok { + log.Fatal("the environment variable 'AZURE_STORAGE_CONNECTION_STRING' could not be found") + } + shareName := "testShare" + srcFileName := "testFile" + fileSize := int64(5) + + shareClient, err := share.NewClientFromConnectionString(connectionString, shareName, nil) + handleError(err) + + _, err = shareClient.Create(context.Background(), nil) + handleError(err) + + srcFileClient := shareClient.NewRootDirectoryClient().NewFileClient(srcFileName) + _, err = srcFileClient.Create(context.Background(), fileSize, nil) + handleError(err) + + resp1, err := srcFileClient.GetProperties(context.Background(), nil) + handleError(err) + fmt.Println(*resp1.ContentLength) + + _, err = srcFileClient.Resize(context.Background(), 6, nil) + handleError(err) + + resp1, err = srcFileClient.GetProperties(context.Background(), nil) + handleError(err) + fmt.Println(*resp1.ContentLength) + + _, err = srcFileClient.Delete(context.Background(), nil) + handleError(err) + + _, err = shareClient.Delete(context.Background(), nil) + handleError(err) +} + +func Example_fileClient_UploadRangeFromURL() { + accountName, ok := os.LookupEnv("AZURE_STORAGE_ACCOUNT_NAME") + if !ok { + panic("AZURE_STORAGE_ACCOUNT_NAME could not be found") + } + accountKey, ok := os.LookupEnv("AZURE_STORAGE_ACCOUNT_KEY") + if !ok { + panic("AZURE_STORAGE_ACCOUNT_KEY could not be found") + } + + serviceURL := fmt.Sprintf("https://%s.file.core.windows.net/", accountName) + cred, err := service.NewSharedKeyCredential(accountName, accountKey) + handleError(err) + + client, err := service.NewClientWithSharedKeyCredential(serviceURL, cred, nil) + handleError(err) + + shareName := "testShare" + srcFileName := "testFile" + dstFileName := "testFile2" + fileSize := int64(5) + + shareClient := client.NewShareClient(shareName) + _, err = shareClient.Create(context.Background(), nil) + handleError(err) + + srcFileClient := shareClient.NewRootDirectoryClient().NewFileClient(srcFileName) + _, err = srcFileClient.Create(context.Background(), fileSize, nil) + handleError(err) + + contentR, _ := generateData(int(fileSize)) + + _, err = srcFileClient.UploadRange(context.Background(), 0, contentR, nil) + handleError(err) + + contentSize := 1024 * 8 // 8KB + content := make([]byte, contentSize) + body := bytes.NewReader(content) + rsc := streaming.NopCloser(body) + + _, err = srcFileClient.UploadRange(context.Background(), 0, rsc, nil) + handleError(err) + + perms := sas.FilePermissions{Read: true, Write: true} + sasQueryParams, err := sas.SignatureValues{ + Protocol: sas.ProtocolHTTPS, // Users MUST use HTTPS (not HTTP) + ExpiryTime: time.Now().UTC().Add(48 * time.Hour), // 48-hours before expiration + ShareName: shareName, + FilePath: srcFileName, + Permissions: perms.String(), + }.SignWithSharedKey(cred) + handleError(err) + + srcFileSAS := srcFileClient.URL() + "?" + sasQueryParams.Encode() + + destFClient := shareClient.NewRootDirectoryClient().NewFileClient(dstFileName) + _, err = destFClient.Create(context.Background(), fileSize, nil) + handleError(err) + + _, err = destFClient.UploadRangeFromURL(context.Background(), srcFileSAS, 0, 0, int64(contentSize), nil) + handleError(err) +} diff --git a/sdk/storage/azfile/file/mmf_unix.go b/sdk/storage/azfile/file/mmf_unix.go new file mode 100644 index 000000000000..dc17528e6516 --- /dev/null +++ b/sdk/storage/azfile/file/mmf_unix.go @@ -0,0 +1,38 @@ +//go:build go1.18 && (linux || darwin || freebsd || openbsd || netbsd || solaris) +// +build go1.18 +// +build linux darwin freebsd openbsd netbsd solaris + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See License.txt in the project root for license information. + +package file + +import ( + "fmt" + "os" + "syscall" +) + +// mmb is a memory mapped buffer +type mmb []byte + +// newMMB creates a new memory mapped buffer with the specified size +func newMMB(size int64) (mmb, error) { + prot, flags := syscall.PROT_READ|syscall.PROT_WRITE, syscall.MAP_ANON|syscall.MAP_PRIVATE + addr, err := syscall.Mmap(-1, 0, int(size), prot, flags) + if err != nil { + return nil, os.NewSyscallError("Mmap", err) + } + return mmb(addr), nil +} + +// delete cleans up the memory mapped buffer +func (m *mmb) delete() { + err := syscall.Munmap(*m) + *m = nil + if err != nil { + // if we get here, there is likely memory corruption. + // please open an issue https://github.com/Azure/azure-sdk-for-go/issues + panic(fmt.Sprintf("Munmap error: %v", err)) + } +} diff --git a/sdk/storage/azfile/file/mmf_windows.go b/sdk/storage/azfile/file/mmf_windows.go new file mode 100644 index 000000000000..b59e6b415776 --- /dev/null +++ b/sdk/storage/azfile/file/mmf_windows.go @@ -0,0 +1,56 @@ +//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 file + +import ( + "fmt" + "os" + "reflect" + "syscall" + "unsafe" +) + +// mmb is a memory mapped buffer +type mmb []byte + +// newMMB creates a new memory mapped buffer with the specified size +func newMMB(size int64) (mmb, error) { + const InvalidHandleValue = ^uintptr(0) // -1 + + prot, access := uint32(syscall.PAGE_READWRITE), uint32(syscall.FILE_MAP_WRITE) + hMMF, err := syscall.CreateFileMapping(syscall.Handle(InvalidHandleValue), nil, prot, uint32(size>>32), uint32(size&0xffffffff), nil) + if err != nil { + return nil, os.NewSyscallError("CreateFileMapping", err) + } + defer func() { + _ = syscall.CloseHandle(hMMF) + }() + + addr, err := syscall.MapViewOfFile(hMMF, access, 0, 0, uintptr(size)) + if err != nil { + return nil, os.NewSyscallError("MapViewOfFile", err) + } + + m := mmb{} + h := (*reflect.SliceHeader)(unsafe.Pointer(&m)) + h.Data = addr + h.Len = int(size) + h.Cap = h.Len + return m, nil +} + +// delete cleans up the memory mapped buffer +func (m *mmb) delete() { + addr := uintptr(unsafe.Pointer(&(([]byte)(*m)[0]))) + *m = mmb{} + err := syscall.UnmapViewOfFile(addr) + if err != nil { + // if we get here, there is likely memory corruption. + // please open an issue https://github.com/Azure/azure-sdk-for-go/issues + panic(fmt.Sprintf("UnmapViewOfFile error: %v", err)) + } +} diff --git a/sdk/storage/azfile/file/models.go b/sdk/storage/azfile/file/models.go new file mode 100644 index 000000000000..d8792ba6f98b --- /dev/null +++ b/sdk/storage/azfile/file/models.go @@ -0,0 +1,743 @@ +//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 file + +import ( + "encoding/binary" + "errors" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/to" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azfile/internal/exported" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azfile/internal/generated" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azfile/internal/shared" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azfile/sas" + "io" + "time" +) + +// SharedKeyCredential contains an account's name and its primary or secondary key. +type SharedKeyCredential = exported.SharedKeyCredential + +// NewSharedKeyCredential creates an immutable SharedKeyCredential containing the +// storage account's name and either its primary or secondary key. +func NewSharedKeyCredential(accountName, accountKey string) (*SharedKeyCredential, error) { + return exported.NewSharedKeyCredential(accountName, accountKey) +} + +// SMBProperties contains the optional parameters regarding the SMB/NTFS properties for a file. +type SMBProperties = exported.SMBProperties + +// NTFSFileAttributes for Files and Directories. +// The subset of attributes is listed at: https://learn.microsoft.com/en-us/rest/api/storageservices/set-file-properties#file-system-attributes. +type NTFSFileAttributes = exported.NTFSFileAttributes + +// Permissions contains the optional parameters for the permissions on the file. +type Permissions = exported.Permissions + +// HTTPHeaders contains optional parameters for the Client.Create method. +type HTTPHeaders = generated.ShareFileHTTPHeaders + +// LeaseAccessConditions contains optional parameters to access leased entity. +type LeaseAccessConditions = generated.LeaseAccessConditions + +// SourceModifiedAccessConditions contains a group of parameters for the FileClient.UploadRangeFromURL method. +type SourceModifiedAccessConditions = generated.SourceModifiedAccessConditions + +// 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 = exported.HTTPRange + +// ShareFileRangeList - The list of file ranges. +type ShareFileRangeList = generated.ShareFileRangeList + +// ClearRange - Ranges there were cleared. +type ClearRange = generated.ClearRange + +// ShareFileRange - An Azure Storage file range. +type ShareFileRange = generated.FileRange + +// --------------------------------------------------------------------------------------------------------------------- + +// CreateOptions contains the optional parameters for the Client.Create method. +type CreateOptions struct { + // The default value is 'None' for Attributes and 'now' for CreationTime and LastWriteTime fields in file.SMBProperties. + SMBProperties *SMBProperties + // The default value is 'inherit' for Permission field in file.Permissions. + Permissions *Permissions + HTTPHeaders *HTTPHeaders + LeaseAccessConditions *LeaseAccessConditions + // A name-value pair to associate with a file storage object. + Metadata map[string]*string +} + +func (o *CreateOptions) format() (fileAttributes string, fileCreationTime string, fileLastWriteTime string, + createOptions *generated.FileClientCreateOptions, fileHTTPHeaders *generated.ShareFileHTTPHeaders, leaseAccessConditions *LeaseAccessConditions) { + if o == nil { + return shared.FileAttributesNone, shared.DefaultCurrentTimeString, shared.DefaultCurrentTimeString, &generated.FileClientCreateOptions{ + FilePermission: to.Ptr(shared.DefaultFilePermissionString), + }, nil, nil + } + + fileAttributes, fileCreationTime, fileLastWriteTime = o.SMBProperties.Format(false, shared.FileAttributesNone, shared.DefaultCurrentTimeString) + + permission, permissionKey := o.Permissions.Format(shared.DefaultFilePermissionString) + + createOptions = &generated.FileClientCreateOptions{ + FilePermission: permission, + FilePermissionKey: permissionKey, + Metadata: o.Metadata, + } + + fileHTTPHeaders = o.HTTPHeaders + leaseAccessConditions = o.LeaseAccessConditions + + return +} + +// --------------------------------------------------------------------------------------------------------------------- + +// DeleteOptions contains the optional parameters for the Client.Delete method. +type DeleteOptions struct { + // LeaseAccessConditions contains optional parameters to access leased entity. + LeaseAccessConditions *LeaseAccessConditions +} + +func (o *DeleteOptions) format() (*generated.FileClientDeleteOptions, *generated.LeaseAccessConditions) { + if o == nil { + return nil, nil + } + return nil, o.LeaseAccessConditions +} + +// --------------------------------------------------------------------------------------------------------------------- + +// GetPropertiesOptions contains the optional parameters for the Client.GetProperties method. +type GetPropertiesOptions struct { + // ShareSnapshot parameter is an opaque DateTime value that, when present, specifies the share snapshot to query for the file properties. + ShareSnapshot *string + // LeaseAccessConditions contains optional parameters to access leased entity. + LeaseAccessConditions *LeaseAccessConditions +} + +func (o *GetPropertiesOptions) format() (*generated.FileClientGetPropertiesOptions, *generated.LeaseAccessConditions) { + if o == nil { + return nil, nil + } + + return &generated.FileClientGetPropertiesOptions{ + Sharesnapshot: o.ShareSnapshot, + }, o.LeaseAccessConditions +} + +// --------------------------------------------------------------------------------------------------------------------- + +// SetHTTPHeadersOptions contains the optional parameters for the Client.SetHTTPHeaders method. +type SetHTTPHeadersOptions struct { + // Resizes a file to the specified size. If the specified byte value is less than the current size of the file, then all ranges + // above the specified byte value are cleared. + FileContentLength *int64 + // The default value is 'preserve' for Attributes, CreationTime and LastWriteTime fields in file.SMBProperties. + SMBProperties *SMBProperties + // The default value is 'preserve' for Permission field in file.Permissions. + Permissions *Permissions + HTTPHeaders *HTTPHeaders + // LeaseAccessConditions contains optional parameters to access leased entity. + LeaseAccessConditions *LeaseAccessConditions +} + +func (o *SetHTTPHeadersOptions) format() (fileAttributes string, fileCreationTime string, fileLastWriteTime string, + opts *generated.FileClientSetHTTPHeadersOptions, fileHTTPHeaders *generated.ShareFileHTTPHeaders, leaseAccessConditions *LeaseAccessConditions) { + if o == nil { + return shared.DefaultPreserveString, shared.DefaultPreserveString, shared.DefaultPreserveString, &generated.FileClientSetHTTPHeadersOptions{ + FilePermission: to.Ptr(shared.DefaultPreserveString), + }, nil, nil + } + + fileAttributes, fileCreationTime, fileLastWriteTime = o.SMBProperties.Format(false, shared.DefaultPreserveString, shared.DefaultPreserveString) + + permission, permissionKey := o.Permissions.Format(shared.DefaultPreserveString) + + opts = &generated.FileClientSetHTTPHeadersOptions{ + FileContentLength: o.FileContentLength, + FilePermission: permission, + FilePermissionKey: permissionKey, + } + + fileHTTPHeaders = o.HTTPHeaders + leaseAccessConditions = o.LeaseAccessConditions + + return +} + +// --------------------------------------------------------------------------------------------------------------------- + +// SetMetadataOptions contains the optional parameters for the Client.SetMetadata method. +type SetMetadataOptions struct { + // A name-value pair to associate with a file storage object. + Metadata map[string]*string + // LeaseAccessConditions contains optional parameters to access leased entity. + LeaseAccessConditions *LeaseAccessConditions +} + +func (o *SetMetadataOptions) format() (*generated.FileClientSetMetadataOptions, *generated.LeaseAccessConditions) { + if o == nil { + return nil, nil + } + return &generated.FileClientSetMetadataOptions{ + Metadata: o.Metadata, + }, o.LeaseAccessConditions +} + +// --------------------------------------------------------------------------------------------------------------------- + +// StartCopyFromURLOptions contains the optional parameters for the Client.StartCopyFromURL method. +type StartCopyFromURLOptions struct { + // A name-value pair to associate with a file storage object. + Metadata map[string]*string + // required if x-ms-file-permission-copy-mode is specified as override + Permissions *Permissions + CopyFileSMBInfo *CopyFileSMBInfo + // LeaseAccessConditions contains optional parameters to access leased entity. + // Required if the destination file has an active lease. + LeaseAccessConditions *LeaseAccessConditions +} + +func (o *StartCopyFromURLOptions) format() (*generated.FileClientStartCopyOptions, *generated.CopyFileSMBInfo, *generated.LeaseAccessConditions) { + if o == nil { + return nil, nil, nil + } + + var permission, permissionKey *string + if o.Permissions != nil { + permission = o.Permissions.Permission + permissionKey = o.Permissions.PermissionKey + } + + opts := &generated.FileClientStartCopyOptions{ + FilePermission: permission, + FilePermissionKey: permissionKey, + Metadata: o.Metadata, + } + return opts, o.CopyFileSMBInfo.format(), o.LeaseAccessConditions +} + +// CopyFileSMBInfo contains a group of parameters for the FileClient.StartCopy method. +type CopyFileSMBInfo struct { + // Specifies either the option to copy file attributes from a source file(source) to a target file or a list of attributes + // to set on a target file. + Attributes CopyFileAttributes + // Specifies either the option to copy file creation time from a source file(source) to a target file or a time value in ISO + // 8601 format to set as creation time on a target file. + CreationTime CopyFileCreationTime + // Specifies either the option to copy file last write time from a source file(source) to a target file or a time value in + // ISO 8601 format to set as last write time on a target file. + LastWriteTime CopyFileLastWriteTime + // Specifies the option to copy file security descriptor from source file or to set it using the value which is defined by + // the header value of x-ms-file-permission or x-ms-file-permission-key. + PermissionCopyMode *PermissionCopyModeType + // Specifies the option to overwrite the target file if it already exists and has read-only attribute set. + IgnoreReadOnly *bool + // Specifies the option to set archive attribute on a target file. True means archive attribute will be set on a target file + // despite attribute overrides or a source file state. + SetArchiveAttribute *bool +} + +func (c *CopyFileSMBInfo) format() *generated.CopyFileSMBInfo { + if c == nil { + return nil + } + + opts := &generated.CopyFileSMBInfo{ + FilePermissionCopyMode: c.PermissionCopyMode, + IgnoreReadOnly: c.IgnoreReadOnly, + SetArchiveAttribute: c.SetArchiveAttribute, + } + + if c.Attributes != nil { + opts.FileAttributes = c.Attributes.FormatAttributes() + } + if c.CreationTime != nil { + opts.FileCreationTime = c.CreationTime.FormatCreationTime() + } + if c.LastWriteTime != nil { + opts.FileLastWriteTime = c.LastWriteTime.FormatLastWriteTime() + } + + return opts +} + +// CopyFileAttributes specifies either the option to copy file attributes from a source file(source) to a target file or +// a list of attributes to set on a target file. +type CopyFileAttributes = exported.CopyFileAttributes + +// SourceCopyFileAttributes specifies to copy file attributes from a source file(source) to a target file +type SourceCopyFileAttributes = exported.SourceCopyFileAttributes + +// DestinationCopyFileAttributes specifies a list of attributes to set on a target file. +type DestinationCopyFileAttributes = exported.DestinationCopyFileAttributes + +// CopyFileCreationTime specifies either the option to copy file creation time from a source file(source) to a target file or +// a time value in ISO 8601 format to set as creation time on a target file. +type CopyFileCreationTime = exported.CopyFileCreationTime + +// SourceCopyFileCreationTime specifies to copy file creation time from a source file(source) to a target file. +type SourceCopyFileCreationTime = exported.SourceCopyFileCreationTime + +// DestinationCopyFileCreationTime specifies a time value in ISO 8601 format to set as creation time on a target file. +type DestinationCopyFileCreationTime = exported.DestinationCopyFileCreationTime + +// CopyFileLastWriteTime specifies either the option to copy file last write time from a source file(source) to a target file or +// a time value in ISO 8601 format to set as last write time on a target file. +type CopyFileLastWriteTime = exported.CopyFileLastWriteTime + +// SourceCopyFileLastWriteTime specifies to copy file last write time from a source file(source) to a target file. +type SourceCopyFileLastWriteTime = exported.SourceCopyFileLastWriteTime + +// DestinationCopyFileLastWriteTime specifies a time value in ISO 8601 format to set as last write time on a target file. +type DestinationCopyFileLastWriteTime = exported.DestinationCopyFileLastWriteTime + +// --------------------------------------------------------------------------------------------------------------------- + +// AbortCopyOptions contains the optional parameters for the Client.AbortCopy method. +type AbortCopyOptions struct { + // LeaseAccessConditions contains optional parameters to access leased entity. + // Required if the destination file has an active lease. + LeaseAccessConditions *LeaseAccessConditions +} + +func (o *AbortCopyOptions) format() (*generated.FileClientAbortCopyOptions, *generated.LeaseAccessConditions) { + if o == nil { + return nil, nil + } + + return nil, o.LeaseAccessConditions +} + +// --------------------------------------------------------------------------------------------------------------------- + +// DownloadStreamOptions contains the optional parameters for the Client.DownloadStream method. +type DownloadStreamOptions struct { + // Range specifies a range of bytes. The default value is all bytes. + Range HTTPRange + // When this header is set to true and specified together with the Range header, the service returns the MD5 hash for the + // range, as long as the range is less than or equal to 4 MB in size. + RangeGetContentMD5 *bool + // LeaseAccessConditions contains optional parameters to access leased entity. + // If specified, the operation is performed only if the file's lease is currently active and + // the lease ID that's specified in the request matches the lease ID of the file. + // Otherwise, the operation fails with status code 412 (Precondition Failed). + LeaseAccessConditions *LeaseAccessConditions +} + +func (o *DownloadStreamOptions) format() (*generated.FileClientDownloadOptions, *LeaseAccessConditions) { + if o == nil { + return nil, nil + } + return &generated.FileClientDownloadOptions{ + Range: exported.FormatHTTPRange(o.Range), + RangeGetContentMD5: o.RangeGetContentMD5, + }, o.LeaseAccessConditions +} + +// --------------------------------------------------------------------------------------------------------------------- + +// downloadOptions contains common options used by the Client.DownloadBuffer and Client.DownloadFile methods. +type downloadOptions struct { + // Range specifies a range of bytes. The default value is all bytes. + Range HTTPRange + + // ChunkSize specifies the chunk size to use for each parallel download; the default size is 4MB. + ChunkSize int64 + + // Progress is a function that is invoked periodically as bytes are received. + Progress func(bytesTransferred int64) + + // LeaseAccessConditions contains optional parameters to access leased entity. + LeaseAccessConditions *LeaseAccessConditions + + // Concurrency indicates the maximum number of chunks to download in parallel (0=default). + Concurrency uint16 + + // RetryReaderOptionsPerChunk is used when downloading each chunk. + RetryReaderOptionsPerChunk RetryReaderOptions +} + +func (o *downloadOptions) getFilePropertiesOptions() *GetPropertiesOptions { + if o == nil { + return nil + } + return &GetPropertiesOptions{ + LeaseAccessConditions: o.LeaseAccessConditions, + } +} + +func (o *downloadOptions) getDownloadFileOptions(rng HTTPRange) *DownloadStreamOptions { + downloadFileOptions := &DownloadStreamOptions{ + Range: rng, + } + if o != nil { + downloadFileOptions.LeaseAccessConditions = o.LeaseAccessConditions + } + return downloadFileOptions +} + +// DownloadBufferOptions contains the optional parameters for the Client.DownloadBuffer method. +type DownloadBufferOptions struct { + // Range specifies a range of bytes. The default value is all bytes. + Range HTTPRange + + // ChunkSize specifies the chunk size to use for each parallel download; the default size is 4MB. + ChunkSize int64 + + // Progress is a function that is invoked periodically as bytes are received. + Progress func(bytesTransferred int64) + + // LeaseAccessConditions contains optional parameters to access leased entity. + LeaseAccessConditions *LeaseAccessConditions + + // Concurrency indicates the maximum number of chunks to download in parallel (0=default). + Concurrency uint16 + + // RetryReaderOptionsPerChunk is used when downloading each chunk. + RetryReaderOptionsPerChunk RetryReaderOptions +} + +// --------------------------------------------------------------------------------------------------------------------- + +// DownloadFileOptions contains the optional parameters for the Client.DownloadFile method. +type DownloadFileOptions struct { + // Range specifies a range of bytes. The default value is all bytes. + Range HTTPRange + + // ChunkSize specifies the chunk size to use for each parallel download; the default size is 4MB. + ChunkSize int64 + + // Progress is a function that is invoked periodically as bytes are received. + Progress func(bytesTransferred int64) + + // LeaseAccessConditions contains optional parameters to access leased entity. + LeaseAccessConditions *LeaseAccessConditions + + // Concurrency indicates the maximum number of chunks to download in parallel (0=default). + Concurrency uint16 + + // RetryReaderOptionsPerChunk is used when downloading each chunk. + RetryReaderOptionsPerChunk RetryReaderOptions +} + +// --------------------------------------------------------------------------------------------------------------------- + +// ResizeOptions contains the optional parameters for the Client.Resize method. +type ResizeOptions struct { + // LeaseAccessConditions contains optional parameters to access leased entity. + LeaseAccessConditions *LeaseAccessConditions +} + +func (o *ResizeOptions) format(contentLength int64) (fileAttributes string, fileCreationTime string, fileLastWriteTime string, + opts *generated.FileClientSetHTTPHeadersOptions, leaseAccessConditions *LeaseAccessConditions) { + fileAttributes, fileCreationTime, fileLastWriteTime = shared.DefaultPreserveString, shared.DefaultPreserveString, shared.DefaultPreserveString + + opts = &generated.FileClientSetHTTPHeadersOptions{ + FileContentLength: &contentLength, + FilePermission: to.Ptr(shared.DefaultPreserveString), + } + + if o != nil { + leaseAccessConditions = o.LeaseAccessConditions + } + + return +} + +// --------------------------------------------------------------------------------------------------------------------- + +// UploadRangeOptions contains the optional parameters for the Client.UploadRange method. +type UploadRangeOptions struct { + // TransactionalValidation specifies the transfer validation type to use. + // The default is nil (no transfer validation). + TransactionalValidation TransferValidationType + // LeaseAccessConditions contains optional parameters to access leased entity. + LeaseAccessConditions *LeaseAccessConditions +} + +func (o *UploadRangeOptions) format(offset int64, body io.ReadSeekCloser) (string, int64, *generated.FileClientUploadRangeOptions, *generated.LeaseAccessConditions, error) { + if offset < 0 || body == nil { + return "", 0, nil, nil, errors.New("invalid argument: offset must be >= 0 and body must not be nil") + } + + count, err := shared.ValidateSeekableStreamAt0AndGetCount(body) + if err != nil { + return "", 0, nil, nil, err + } + + if count == 0 { + return "", 0, nil, nil, errors.New("invalid argument: body must contain readable data whose size is > 0") + } + + httpRange := exported.FormatHTTPRange(HTTPRange{ + Offset: offset, + Count: count, + }) + rangeParam := "" + if httpRange != nil { + rangeParam = *httpRange + } + + var leaseAccessConditions *LeaseAccessConditions + uploadRangeOptions := &generated.FileClientUploadRangeOptions{} + + if o != nil { + leaseAccessConditions = o.LeaseAccessConditions + } + if o != nil && o.TransactionalValidation != nil { + _, err = o.TransactionalValidation.Apply(body, uploadRangeOptions) + if err != nil { + return "", 0, nil, nil, err + } + } + + return rangeParam, count, uploadRangeOptions, leaseAccessConditions, nil +} + +// --------------------------------------------------------------------------------------------------------------------- + +// ClearRangeOptions contains the optional parameters for the Client.ClearRange method. +type ClearRangeOptions struct { + // LeaseAccessConditions contains optional parameters to access leased entity. + LeaseAccessConditions *LeaseAccessConditions +} + +func (o *ClearRangeOptions) format(contentRange HTTPRange) (string, *generated.LeaseAccessConditions, error) { + httpRange := exported.FormatHTTPRange(contentRange) + if httpRange == nil || contentRange.Offset < 0 || contentRange.Count <= 0 { + return "", nil, errors.New("invalid argument: either offset is < 0 or count <= 0") + } + + if o == nil { + return *httpRange, nil, nil + } + + return *httpRange, o.LeaseAccessConditions, nil +} + +// --------------------------------------------------------------------------------------------------------------------- + +// UploadRangeFromURLOptions contains the optional parameters for the Client.UploadRangeFromURL method. +type UploadRangeFromURLOptions struct { + // Only Bearer type is supported. Credentials should be a valid OAuth access token to copy source. + CopySourceAuthorization *string + // Specify the crc64 calculated for the range of bytes that must be read from the copy source. + SourceContentCRC64 uint64 + SourceModifiedAccessConditions *SourceModifiedAccessConditions + LeaseAccessConditions *LeaseAccessConditions +} + +func (o *UploadRangeFromURLOptions) format(sourceOffset int64, destinationOffset int64, count int64) (string, *generated.FileClientUploadRangeFromURLOptions, *generated.SourceModifiedAccessConditions, *generated.LeaseAccessConditions, error) { + if sourceOffset < 0 || destinationOffset < 0 { + return "", nil, nil, nil, errors.New("invalid argument: source and destination offsets must be >= 0") + } + + httpRangeSrc := exported.FormatHTTPRange(HTTPRange{Offset: sourceOffset, Count: count}) + httpRangeDest := exported.FormatHTTPRange(HTTPRange{Offset: destinationOffset, Count: count}) + destRange := "" + if httpRangeDest != nil { + destRange = *httpRangeDest + } + + opts := &generated.FileClientUploadRangeFromURLOptions{ + SourceRange: httpRangeSrc, + } + + var sourceModifiedAccessConditions *SourceModifiedAccessConditions + var leaseAccessConditions *LeaseAccessConditions + + if o != nil { + opts.CopySourceAuthorization = o.CopySourceAuthorization + sourceModifiedAccessConditions = o.SourceModifiedAccessConditions + leaseAccessConditions = o.LeaseAccessConditions + + buf := make([]byte, 8) + binary.LittleEndian.PutUint64(buf, o.SourceContentCRC64) + opts.SourceContentCRC64 = buf + } + + return destRange, opts, sourceModifiedAccessConditions, leaseAccessConditions, nil +} + +// --------------------------------------------------------------------------------------------------------------------- + +// GetRangeListOptions contains the optional parameters for the Client.GetRangeList method. +type GetRangeListOptions struct { + // The previous snapshot parameter is an opaque DateTime value that, when present, specifies the previous snapshot. + PrevShareSnapshot *string + // Specifies the range of bytes over which to list ranges, inclusively. + Range HTTPRange + // The snapshot parameter is an opaque DateTime value that, when present, specifies the share snapshot to query. + ShareSnapshot *string + // LeaseAccessConditions contains optional parameters to access leased entity. + LeaseAccessConditions *LeaseAccessConditions +} + +func (o *GetRangeListOptions) format() (*generated.FileClientGetRangeListOptions, *generated.LeaseAccessConditions) { + if o == nil { + return nil, nil + } + + return &generated.FileClientGetRangeListOptions{ + Prevsharesnapshot: o.PrevShareSnapshot, + Range: exported.FormatHTTPRange(o.Range), + Sharesnapshot: o.ShareSnapshot, + }, o.LeaseAccessConditions +} + +// --------------------------------------------------------------------------------------------------------------------- + +// GetSASURLOptions contains the optional parameters for the Client.GetSASURL method. +type GetSASURLOptions struct { + StartTime *time.Time +} + +func (o *GetSASURLOptions) format() time.Time { + if o == nil { + return time.Time{} + } + + var st time.Time + if o.StartTime != nil { + st = o.StartTime.UTC() + } else { + st = time.Time{} + } + return st +} + +// --------------------------------------------------------------------------------------------------------------------- + +// ForceCloseHandlesOptions contains the optional parameters for the Client.ForceCloseHandles method. +type ForceCloseHandlesOptions struct { + // A string value that identifies the portion of the list to be returned with the next list operation. The operation returns + // a marker value within the response body if the list returned was not complete. + // The marker value may then be used in a subsequent call to request the next set of list items. The marker value is opaque + // to the client. + Marker *string + // The snapshot parameter is an opaque DateTime value that, when present, specifies the share snapshot to query. + ShareSnapshot *string +} + +func (o *ForceCloseHandlesOptions) format() *generated.FileClientForceCloseHandlesOptions { + if o == nil { + return nil + } + + return &generated.FileClientForceCloseHandlesOptions{ + Marker: o.Marker, + Sharesnapshot: o.ShareSnapshot, + } +} + +// --------------------------------------------------------------------------------------------------------------------- + +// ListHandlesOptions contains the optional parameters for the Client.ListHandles method. +type ListHandlesOptions struct { + // A string value that identifies the portion of the list to be returned with the next list operation. The operation returns + // a marker value within the response body if the list returned was not complete. + // The marker value may then be used in a subsequent call to request the next set of list items. The marker value is opaque + // to the client. + Marker *string + // Specifies the maximum number of entries to return. If the request does not specify maxresults, or specifies a value greater + // than 5,000, the server will return up to 5,000 items. + MaxResults *int32 + // The snapshot parameter is an opaque DateTime value that, when present, specifies the share snapshot to query. + ShareSnapshot *string +} + +func (o *ListHandlesOptions) format() *generated.FileClientListHandlesOptions { + if o == nil { + return nil + } + + return &generated.FileClientListHandlesOptions{ + Marker: o.Marker, + Maxresults: o.MaxResults, + Sharesnapshot: o.ShareSnapshot, + } +} + +// Handle - A listed Azure Storage handle item. +type Handle = generated.Handle + +// --------------------------------------------------------------------------------------------------------------------- + +// 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 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. + Progress func(bytesTransferred int64) + + // Concurrency indicates the maximum number of chunks to upload in parallel (default is 5) + Concurrency uint16 + + // LeaseAccessConditions contains optional parameters to access leased entity. + LeaseAccessConditions *LeaseAccessConditions +} + +// UploadBufferOptions provides set of configurations for Client.UploadBuffer operation. +type UploadBufferOptions = uploadFromReaderOptions + +// UploadFileOptions provides set of configurations for Client.UploadFile operation. +type UploadFileOptions = uploadFromReaderOptions + +func (o *uploadFromReaderOptions) getUploadRangeOptions() *UploadRangeOptions { + return &UploadRangeOptions{ + LeaseAccessConditions: o.LeaseAccessConditions, + } +} + +// --------------------------------------------------------------------------------------------------------------------- + +// UploadStreamOptions provides set of configurations for Client.UploadStream operation. +type UploadStreamOptions struct { + // ChunkSize defines the size of the buffer used during upload. The default and minimum value is 1 MiB. + // Maximum size of a chunk is MaxUpdateRangeBytes. + ChunkSize int64 + + // Concurrency defines the max number of concurrent uploads to be performed to upload the file. + // Each concurrent upload will create a buffer of size ChunkSize. The default value is one. + Concurrency int + + // LeaseAccessConditions contains optional parameters to access leased entity. + LeaseAccessConditions *LeaseAccessConditions +} + +func (u *UploadStreamOptions) setDefaults() { + if u.Concurrency == 0 { + u.Concurrency = 1 + } + + if u.ChunkSize < _1MiB { + u.ChunkSize = _1MiB + } +} + +func (u *UploadStreamOptions) getUploadRangeOptions() *UploadRangeOptions { + return &UploadRangeOptions{ + LeaseAccessConditions: u.LeaseAccessConditions, + } +} + +// URLParts object represents the components that make up an Azure Storage Share/Directory/File URL. +// NOTE: Changing any SAS-related field requires computing a new SAS signature. +type URLParts = sas.URLParts + +// ParseURL parses a URL initializing URLParts' fields including any SAS-related & snapshot query parameters. Any other +// query parameters remain in the UnparsedParams field. This method overwrites all fields in the URLParts object. +func ParseURL(u string) (URLParts, error) { + return sas.ParseURL(u) +} diff --git a/sdk/storage/azfile/file/responses.go b/sdk/storage/azfile/file/responses.go new file mode 100644 index 000000000000..e47d87741861 --- /dev/null +++ b/sdk/storage/azfile/file/responses.go @@ -0,0 +1,93 @@ +//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 file + +import ( + "context" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azfile/internal/generated" + "io" +) + +// CreateResponse contains the response from method Client.Create. +type CreateResponse = generated.FileClientCreateResponse + +// DeleteResponse contains the response from method Client.Delete. +type DeleteResponse = generated.FileClientDeleteResponse + +// GetPropertiesResponse contains the response from method Client.GetProperties. +type GetPropertiesResponse = generated.FileClientGetPropertiesResponse + +// SetMetadataResponse contains the response from method Client.SetMetadata. +type SetMetadataResponse = generated.FileClientSetMetadataResponse + +// SetHTTPHeadersResponse contains the response from method Client.SetHTTPHeaders. +type SetHTTPHeadersResponse = generated.FileClientSetHTTPHeadersResponse + +// StartCopyFromURLResponse contains the response from method Client.StartCopyFromURL. +type StartCopyFromURLResponse = generated.FileClientStartCopyResponse + +// AbortCopyResponse contains the response from method Client.AbortCopy. +type AbortCopyResponse = generated.FileClientAbortCopyResponse + +// DownloadResponse contains the response from method FileClient.Download. +type DownloadResponse = generated.FileClientDownloadResponse + +// DownloadStreamResponse contains the response from method Client.DownloadStream. +// To read from the stream, read from the Body field, or call the NewRetryReader method. +type DownloadStreamResponse struct { + DownloadResponse + + client *Client + getInfo httpGetterInfo + leaseAccessConditions *LeaseAccessConditions +} + +// NewRetryReader constructs new RetryReader stream for reading data. If a connection fails while +// reading, it will make additional requests to reestablish a connection and continue reading. +// Pass nil for options to accept the default options. +// Callers of this method should not access the DownloadStreamResponse.Body field. +func (r *DownloadStreamResponse) NewRetryReader(ctx context.Context, options *RetryReaderOptions) *RetryReader { + if options == nil { + options = &RetryReaderOptions{} + } + + return newRetryReader(ctx, r.Body, r.getInfo, func(ctx context.Context, getInfo httpGetterInfo) (io.ReadCloser, error) { + options := DownloadStreamOptions{ + Range: getInfo.Range, + LeaseAccessConditions: r.leaseAccessConditions, + } + resp, err := r.client.DownloadStream(ctx, &options) + if err != nil { + return nil, err + } + return resp.Body, err + }, *options) +} + +// ResizeResponse contains the response from method Client.Resize. +type ResizeResponse = generated.FileClientSetHTTPHeadersResponse + +// UploadRangeResponse contains the response from method Client.UploadRange. +type UploadRangeResponse = generated.FileClientUploadRangeResponse + +// ClearRangeResponse contains the response from method Client.ClearRange. +type ClearRangeResponse = generated.FileClientUploadRangeResponse + +// UploadRangeFromURLResponse contains the response from method Client.UploadRangeFromURL. +type UploadRangeFromURLResponse = generated.FileClientUploadRangeFromURLResponse + +// GetRangeListResponse contains the response from method Client.GetRangeList. +type GetRangeListResponse = generated.FileClientGetRangeListResponse + +// ForceCloseHandlesResponse contains the response from method Client.ForceCloseHandles. +type ForceCloseHandlesResponse = generated.FileClientForceCloseHandlesResponse + +// ListHandlesResponse contains the response from method Client.ListHandles. +type ListHandlesResponse = generated.FileClientListHandlesResponse + +// ListHandlesSegmentResponse - An enumeration of handles. +type ListHandlesSegmentResponse = generated.ListHandlesResponse diff --git a/sdk/storage/azfile/file/retry_reader.go b/sdk/storage/azfile/file/retry_reader.go new file mode 100644 index 000000000000..2e76a91f3169 --- /dev/null +++ b/sdk/storage/azfile/file/retry_reader.go @@ -0,0 +1,186 @@ +//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 file + +import ( + "context" + "io" + "net" + "strings" + "sync" +) + +// HTTPGetter is a function type that refers to a method that performs an HTTP GET operation. +type httpGetter func(ctx context.Context, i httpGetterInfo) (io.ReadCloser, error) + +// httpGetterInfo is passed to an HTTPGetter function passing it parameters +// that should be used to make an HTTP GET request. +type httpGetterInfo struct { + Range HTTPRange +} + +// RetryReaderOptions configures the retry reader's behavior. +// Zero-value fields will have their specified default values applied during use. +// This allows for modification of a subset of fields. +type RetryReaderOptions struct { + // MaxRetries specifies the maximum number of attempts a failed read will be retried + // before producing an error. + // The default value is three. + MaxRetries int32 + + // OnFailedRead, when non-nil, is called after any failure to read. Expected usage is diagnostic logging. + OnFailedRead func(failureCount int32, lastError error, rnge HTTPRange, willRetry bool) + + // EarlyCloseAsError can be set to true to prevent retries after "read on closed response body". By default, + // retryReader has the following special behaviour: closing the response body before it is all read is treated as a + // retryable error. This is to allow callers to force a retry by closing the body from another goroutine (e.g. if the = + // read is too slow, caller may want to force a retry in the hope that the retry will be quicker). If + // TreatEarlyCloseAsError is true, then retryReader's special behaviour is suppressed, and "read on closed body" is instead + // treated as a fatal (non-retryable) error. + // Note that setting TreatEarlyCloseAsError only guarantees that Closing will produce a fatal error if the Close happens + // from the same "thread" (goroutine) as Read. Concurrent Close calls from other goroutines may instead produce network errors + // which will be retried. + // The default value is false. + EarlyCloseAsError bool + + doInjectError bool + doInjectErrorRound int32 + injectedError error +} + +// RetryReader attempts to read from response, and if there is a retry-able network error +// returned during reading, it will retry according to retry reader option through executing +// user defined action with provided data to get a new response, and continue the overall reading process +// through reading from the new response. +// RetryReader implements the io.ReadCloser interface. +type RetryReader struct { + ctx context.Context + info httpGetterInfo + retryReaderOptions RetryReaderOptions + getter httpGetter + countWasBounded bool + + // we support Close-ing during Reads (from other goroutines), so we protect the shared state, which is response + responseMu *sync.Mutex + response io.ReadCloser +} + +// newRetryReader creates a retry reader. +func newRetryReader(ctx context.Context, initialResponse io.ReadCloser, info httpGetterInfo, getter httpGetter, o RetryReaderOptions) *RetryReader { + if o.MaxRetries < 1 { + o.MaxRetries = 3 + } + return &RetryReader{ + ctx: ctx, + getter: getter, + info: info, + countWasBounded: info.Range.Count != CountToEnd, + response: initialResponse, + responseMu: &sync.Mutex{}, + retryReaderOptions: o, + } +} + +// setResponse function +func (s *RetryReader) setResponse(r io.ReadCloser) { + s.responseMu.Lock() + defer s.responseMu.Unlock() + s.response = r +} + +// Read from retry reader +func (s *RetryReader) Read(p []byte) (n int, err error) { + for try := int32(0); ; try++ { + //fmt.Println(try) // Comment out for debugging. + if s.countWasBounded && s.info.Range.Count == CountToEnd { + // User specified an original count and the remaining bytes are 0, return 0, EOF + return 0, io.EOF + } + + s.responseMu.Lock() + resp := s.response + s.responseMu.Unlock() + if resp == nil { // We don't have a response stream to read from, try to get one. + newResponse, err := s.getter(s.ctx, s.info) + if err != nil { + return 0, err + } + // Successful GET; this is the network stream we'll read from. + s.setResponse(newResponse) + resp = newResponse + } + n, err := resp.Read(p) // Read from the stream (this will return non-nil err if forceRetry is called, from another goroutine, while it is running) + + // Injection mechanism for testing. + if s.retryReaderOptions.doInjectError && try == s.retryReaderOptions.doInjectErrorRound { + if s.retryReaderOptions.injectedError != nil { + err = s.retryReaderOptions.injectedError + } else { + err = &net.DNSError{IsTemporary: true} + } + } + + // We successfully read data or end EOF. + if err == nil || err == io.EOF { + s.info.Range.Offset += int64(n) // Increments the start offset in case we need to make a new HTTP request in the future + if s.info.Range.Count != CountToEnd { + s.info.Range.Count -= int64(n) // Decrement the count in case we need to make a new HTTP request in the future + } + return n, err // Return the return to the caller + } + _ = s.Close() + + s.setResponse(nil) // Our stream is no longer good + + // Check the retry count and error code, and decide whether to retry. + retriesExhausted := try >= s.retryReaderOptions.MaxRetries + _, isNetError := err.(net.Error) + isUnexpectedEOF := err == io.ErrUnexpectedEOF + willRetry := (isNetError || isUnexpectedEOF || s.wasRetryableEarlyClose(err)) && !retriesExhausted + + // Notify, for logging purposes, of any failures + if s.retryReaderOptions.OnFailedRead != nil { + failureCount := try + 1 // because try is zero-based + s.retryReaderOptions.OnFailedRead(failureCount, err, s.info.Range, willRetry) + } + + if willRetry { + continue + // Loop around and try to get and read from new stream. + } + return n, err // Not retryable, or retries exhausted, so just return + } +} + +// By default, we allow early Closing, from another concurrent goroutine, to be used to force a retry +// Is this safe, to close early from another goroutine? Early close ultimately ends up calling +// net.Conn.Close, and that is documented as "Any blocked Read or Write operations will be unblocked and return errors" +// which is exactly the behaviour we want. +// NOTE: that if caller has forced an early Close from a separate goroutine (separate from the Read) +// then there are two different types of error that may happen - either the one we check for here, +// or a net.Error (due to closure of connection). Which one happens depends on timing. We only need this routine +// to check for one, since the other is a net.Error, which our main Read retry loop is already handing. +func (s *RetryReader) wasRetryableEarlyClose(err error) bool { + if s.retryReaderOptions.EarlyCloseAsError { + return false // user wants all early closes to be errors, and so not retryable + } + // unfortunately, http.errReadOnClosedResBody is private, so the best we can do here is to check for its text + return strings.HasSuffix(err.Error(), ReadOnClosedBodyMessage) +} + +// ReadOnClosedBodyMessage of retry reader +const ReadOnClosedBodyMessage = "read on closed response body" + +// Close retry reader +func (s *RetryReader) Close() error { + s.responseMu.Lock() + defer s.responseMu.Unlock() + if s.response != nil { + return s.response.Close() + } + return nil +} diff --git a/sdk/storage/azfile/fileerror/error_codes.go b/sdk/storage/azfile/fileerror/error_codes.go new file mode 100644 index 000000000000..c897c0953828 --- /dev/null +++ b/sdk/storage/azfile/fileerror/error_codes.go @@ -0,0 +1,107 @@ +//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 fileerror + +import ( + "errors" + + "github.com/Azure/azure-sdk-for-go/sdk/azcore" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azfile/internal/generated" +) + +// HasCode returns true if the provided error is an *azcore.ResponseError +// with its ErrorCode field equal to one of the specified Codes. +func HasCode(err error, codes ...Code) bool { + var respErr *azcore.ResponseError + if !errors.As(err, &respErr) { + return false + } + + for _, code := range codes { + if respErr.ErrorCode == string(code) { + return true + } + } + + return false +} + +// Code - Error codes returned by the service +type Code = generated.StorageErrorCode + +const ( + AccountAlreadyExists Code = "AccountAlreadyExists" + AccountBeingCreated Code = "AccountBeingCreated" + AccountIsDisabled Code = "AccountIsDisabled" + AuthenticationFailed Code = "AuthenticationFailed" + AuthorizationFailure Code = "AuthorizationFailure" + AuthorizationPermissionMismatch Code = "AuthorizationPermissionMismatch" + AuthorizationProtocolMismatch Code = "AuthorizationProtocolMismatch" + AuthorizationResourceTypeMismatch Code = "AuthorizationResourceTypeMismatch" + AuthorizationServiceMismatch Code = "AuthorizationServiceMismatch" + AuthorizationSourceIPMismatch Code = "AuthorizationSourceIPMismatch" + CannotDeleteFileOrDirectory Code = "CannotDeleteFileOrDirectory" + ClientCacheFlushDelay Code = "ClientCacheFlushDelay" + ConditionHeadersNotSupported Code = "ConditionHeadersNotSupported" + ConditionNotMet Code = "ConditionNotMet" + DeletePending Code = "DeletePending" + DirectoryNotEmpty Code = "DirectoryNotEmpty" + EmptyMetadataKey Code = "EmptyMetadataKey" + FeatureVersionMismatch Code = "FeatureVersionMismatch" + FileLockConflict Code = "FileLockConflict" + InsufficientAccountPermissions Code = "InsufficientAccountPermissions" + InternalError Code = "InternalError" + InvalidAuthenticationInfo Code = "InvalidAuthenticationInfo" + InvalidFileOrDirectoryPathName Code = "InvalidFileOrDirectoryPathName" + InvalidHTTPVerb Code = "InvalidHttpVerb" + InvalidHeaderValue Code = "InvalidHeaderValue" + InvalidInput Code = "InvalidInput" + InvalidMD5 Code = "InvalidMd5" + InvalidMetadata Code = "InvalidMetadata" + InvalidQueryParameterValue Code = "InvalidQueryParameterValue" + InvalidRange Code = "InvalidRange" + InvalidResourceName Code = "InvalidResourceName" + InvalidURI Code = "InvalidUri" + InvalidXMLDocument Code = "InvalidXmlDocument" + InvalidXMLNodeValue Code = "InvalidXmlNodeValue" + MD5Mismatch Code = "Md5Mismatch" + MetadataTooLarge Code = "MetadataTooLarge" + MissingContentLengthHeader Code = "MissingContentLengthHeader" + MissingRequiredHeader Code = "MissingRequiredHeader" + MissingRequiredQueryParameter Code = "MissingRequiredQueryParameter" + MissingRequiredXMLNode Code = "MissingRequiredXmlNode" + MultipleConditionHeadersNotSupported Code = "MultipleConditionHeadersNotSupported" + OperationTimedOut Code = "OperationTimedOut" + OutOfRangeInput Code = "OutOfRangeInput" + OutOfRangeQueryParameterValue Code = "OutOfRangeQueryParameterValue" + ParentNotFound Code = "ParentNotFound" + ReadOnlyAttribute Code = "ReadOnlyAttribute" + RequestBodyTooLarge Code = "RequestBodyTooLarge" + RequestURLFailedToParse Code = "RequestUrlFailedToParse" + ResourceAlreadyExists Code = "ResourceAlreadyExists" + ResourceNotFound Code = "ResourceNotFound" + ResourceTypeMismatch Code = "ResourceTypeMismatch" + ServerBusy Code = "ServerBusy" + ShareAlreadyExists Code = "ShareAlreadyExists" + ShareBeingDeleted Code = "ShareBeingDeleted" + ShareDisabled Code = "ShareDisabled" + ShareHasSnapshots Code = "ShareHasSnapshots" + ShareNotFound Code = "ShareNotFound" + ShareSnapshotCountExceeded Code = "ShareSnapshotCountExceeded" + ShareSnapshotInProgress Code = "ShareSnapshotInProgress" + ShareSnapshotOperationNotSupported Code = "ShareSnapshotOperationNotSupported" + SharingViolation Code = "SharingViolation" + UnsupportedHTTPVerb Code = "UnsupportedHttpVerb" + UnsupportedHeader Code = "UnsupportedHeader" + UnsupportedQueryParameter Code = "UnsupportedQueryParameter" + UnsupportedXMLNode Code = "UnsupportedXmlNode" +) + +var ( + // MissingSharedKeyCredential - Error is returned when SAS URL is being created without SharedKeyCredential. + MissingSharedKeyCredential = errors.New("SAS can only be signed with a SharedKeyCredential") +) diff --git a/sdk/storage/azfile/go.mod b/sdk/storage/azfile/go.mod new file mode 100644 index 000000000000..cbd96fa64efc --- /dev/null +++ b/sdk/storage/azfile/go.mod @@ -0,0 +1,28 @@ +module github.com/Azure/azure-sdk-for-go/sdk/storage/azfile + +go 1.18 + +require ( + github.com/Azure/azure-sdk-for-go/sdk/azcore v1.4.0 + github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.2.2 + github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0 + github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.0.0 + github.com/stretchr/testify v1.7.1 +) + +require ( + github.com/AzureAD/microsoft-authentication-library-for-go v0.9.0 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/dnaeon/go-vcr v1.1.0 // indirect + github.com/golang-jwt/jwt/v4 v4.5.0 // indirect + github.com/google/uuid v1.3.0 // indirect + github.com/kylelemons/godebug v1.1.0 // indirect + github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect + golang.org/x/crypto v0.7.0 // indirect + golang.org/x/net v0.8.0 // indirect + golang.org/x/sys v0.7.0 // indirect + golang.org/x/text v0.9.0 // indirect + gopkg.in/yaml.v2 v2.4.0 // indirect + gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect +) diff --git a/sdk/storage/azfile/go.sum b/sdk/storage/azfile/go.sum new file mode 100644 index 000000000000..8f03fb9639d6 --- /dev/null +++ b/sdk/storage/azfile/go.sum @@ -0,0 +1,46 @@ +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.4.0 h1:rTnT/Jrcm+figWlYz4Ixzt0SJVR2cMC8lvZcimipiEY= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.4.0/go.mod h1:ON4tFdPTwRcgWEaVDrN3584Ef+b7GgSJaXxe5fW9t4M= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.2.2 h1:uqM+VoHjVH6zdlkLF2b6O0ZANcHoj3rO0PoQ3jglUJA= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.2.2/go.mod h1:twTKAa1E6hLmSDjLhaCkbTMQKc7p/rNLU40rLxGEOCI= +github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0 h1:sXr+ck84g/ZlZUOZiNELInmMgOsuGwdjjVkEIde0OtY= +github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0/go.mod h1:okt5dMMTOFjX/aovMlrjvvXoPMBVSPzk9185BT0+eZM= +github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.0.0 h1:u/LLAOFgsMv7HmNL4Qufg58y+qElGOt5qv0z1mURkRY= +github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.0.0/go.mod h1:2e8rMJtl2+2j+HXbTBwnyGpm5Nou7KhvSfxOq8JpTag= +github.com/AzureAD/microsoft-authentication-library-for-go v0.9.0 h1:UE9n9rkJF62ArLb1F3DEjRt8O3jLwMWdSoypKV4f3MU= +github.com/AzureAD/microsoft-authentication-library-for-go v0.9.0/go.mod h1:kgDmCTgBzIEPFElEF+FK0SdjAor06dRq2Go927dnQ6o= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/dnaeon/go-vcr v1.1.0 h1:ReYa/UBrRyQdant9B4fNHGoCNKw6qh6P0fsdGmZpR7c= +github.com/dnaeon/go-vcr v1.1.0/go.mod h1:M7tiix8f0r6mKKJ3Yq/kqU1OYf3MnfmBWVbPx/yU9ko= +github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg= +github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= +github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= +github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= +github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= +github.com/modocache/gover v0.0.0-20171022184752-b58185e213c5/go.mod h1:caMODM3PzxT8aQXRPkAt8xlV/e7d7w8GM5g0fa5F0D8= +github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 h1:KoWmjvw+nsYOo29YJK9vDA65RGE3NrOnUtO7a+RF9HU= +github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8/go.mod h1:HKlIX3XHQyzLZPlr7++PzdhaXEj94dEiJgZDTsxEqUI= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +golang.org/x/crypto v0.7.0 h1:AvwMYaRytfdeVt3u6mLaxYtErKYjxA2OXjJ1HHq6t3A= +golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= +golang.org/x/net v0.8.0 h1:Zrh2ngAOFYneWTAIAPethzeaQLuHwhuBkuV6ZiRnUaQ= +golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= +golang.org/x/sys v0.0.0-20210616045830-e2b7044e8c71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.7.0 h1:3jlCCIQZPdOYu1h8BkNvLz8Kgwtae2cagcG/VamtZRU= +golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE= +golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo= +gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/sdk/storage/azfile/internal/base/clients.go b/sdk/storage/azfile/internal/base/clients.go new file mode 100644 index 000000000000..93317d4dc29b --- /dev/null +++ b/sdk/storage/azfile/internal/base/clients.go @@ -0,0 +1,60 @@ +//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 base + +import ( + "github.com/Azure/azure-sdk-for-go/sdk/azcore" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azfile/internal/exported" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azfile/internal/generated" +) + +// ClientOptions contains the optional parameters when creating a Client. +type ClientOptions struct { + azcore.ClientOptions +} + +type Client[T any] struct { + inner *T + sharedKey *exported.SharedKeyCredential +} + +func InnerClient[T any](client *Client[T]) *T { + return client.inner +} + +func SharedKey[T any](client *Client[T]) *exported.SharedKeyCredential { + return client.sharedKey +} + +func NewServiceClient(serviceURL string, pipeline runtime.Pipeline, sharedKey *exported.SharedKeyCredential) *Client[generated.ServiceClient] { + return &Client[generated.ServiceClient]{ + inner: generated.NewServiceClient(serviceURL, pipeline), + sharedKey: sharedKey, + } +} + +func NewShareClient(shareURL string, pipeline runtime.Pipeline, sharedKey *exported.SharedKeyCredential) *Client[generated.ShareClient] { + return &Client[generated.ShareClient]{ + inner: generated.NewShareClient(shareURL, pipeline), + sharedKey: sharedKey, + } +} + +func NewDirectoryClient(directoryURL string, pipeline runtime.Pipeline, sharedKey *exported.SharedKeyCredential) *Client[generated.DirectoryClient] { + return &Client[generated.DirectoryClient]{ + inner: generated.NewDirectoryClient(directoryURL, pipeline), + sharedKey: sharedKey, + } +} + +func NewFileClient(fileURL string, pipeline runtime.Pipeline, sharedKey *exported.SharedKeyCredential) *Client[generated.FileClient] { + return &Client[generated.FileClient]{ + inner: generated.NewFileClient(fileURL, pipeline), + sharedKey: sharedKey, + } +} diff --git a/sdk/storage/azfile/internal/exported/access_policy.go b/sdk/storage/azfile/internal/exported/access_policy.go new file mode 100644 index 000000000000..d9c95db2821a --- /dev/null +++ b/sdk/storage/azfile/internal/exported/access_policy.go @@ -0,0 +1,62 @@ +//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 exported + +import ( + "bytes" + "fmt" +) + +// The AccessPolicyPermission type simplifies creating the permissions string for a share's access policy. +// Initialize an instance of this type and then call its String method to set AccessPolicy's Permission field. +type AccessPolicyPermission struct { + Read, Create, Write, Delete, List bool +} + +// String produces the access policy permission string for an Azure Storage share. +// Call this method to set AccessPolicy's Permission field. +func (p AccessPolicyPermission) String() string { + var b bytes.Buffer + if p.Read { + b.WriteRune('r') + } + if p.Create { + b.WriteRune('c') + } + if p.Write { + b.WriteRune('w') + } + if p.Delete { + b.WriteRune('d') + } + if p.List { + b.WriteRune('l') + } + return b.String() +} + +// Parse initializes the AccessPolicyPermission's fields from a string. +func (p *AccessPolicyPermission) Parse(s string) error { + *p = AccessPolicyPermission{} // Clear the flags + for _, r := range s { + switch r { + case 'r': + p.Read = true + case 'c': + p.Create = true + case 'w': + p.Write = true + case 'd': + p.Delete = true + case 'l': + p.List = true + default: + return fmt.Errorf("invalid permission: '%v'", r) + } + } + return nil +} diff --git a/sdk/storage/azfile/internal/exported/copy_file_smb_options.go b/sdk/storage/azfile/internal/exported/copy_file_smb_options.go new file mode 100644 index 000000000000..9f0da40bba4d --- /dev/null +++ b/sdk/storage/azfile/internal/exported/copy_file_smb_options.go @@ -0,0 +1,96 @@ +//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 exported + +import ( + "github.com/Azure/azure-sdk-for-go/sdk/azcore/to" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azfile/internal/generated" + "time" +) + +// CopyFileCreationTime specifies either the option to copy file creation time from a source file(source) to a target file or +// a time value in ISO 8601 format to set as creation time on a target file. +type CopyFileCreationTime interface { + FormatCreationTime() *string + notPubliclyImplementable() +} + +// SourceCopyFileCreationTime specifies to copy file creation time from a source file(source) to a target file. +type SourceCopyFileCreationTime struct { +} + +func (s SourceCopyFileCreationTime) FormatCreationTime() *string { + return to.Ptr("source") +} + +func (s SourceCopyFileCreationTime) notPubliclyImplementable() {} + +// DestinationCopyFileCreationTime specifies a time value in ISO 8601 format to set as creation time on a target file. +type DestinationCopyFileCreationTime time.Time + +func (d DestinationCopyFileCreationTime) FormatCreationTime() *string { + return to.Ptr(time.Time(d).UTC().Format(generated.ISO8601)) +} + +func (d DestinationCopyFileCreationTime) notPubliclyImplementable() {} + +// --------------------------------------------------------------------------------------------------------------------- + +// CopyFileLastWriteTime specifies either the option to copy file last write time from a source file(source) to a target file or +// a time value in ISO 8601 format to set as last write time on a target file. +type CopyFileLastWriteTime interface { + FormatLastWriteTime() *string + notPubliclyImplementable() +} + +// SourceCopyFileLastWriteTime specifies to copy file last write time from a source file(source) to a target file. +type SourceCopyFileLastWriteTime struct { +} + +func (s SourceCopyFileLastWriteTime) FormatLastWriteTime() *string { + return to.Ptr("source") +} + +func (s SourceCopyFileLastWriteTime) notPubliclyImplementable() {} + +// DestinationCopyFileLastWriteTime specifies a time value in ISO 8601 format to set as last write time on a target file. +type DestinationCopyFileLastWriteTime time.Time + +func (d DestinationCopyFileLastWriteTime) FormatLastWriteTime() *string { + return to.Ptr(time.Time(d).UTC().Format(generated.ISO8601)) +} + +func (d DestinationCopyFileLastWriteTime) notPubliclyImplementable() {} + +// --------------------------------------------------------------------------------------------------------------------- + +// CopyFileAttributes specifies either the option to copy file attributes from a source file(source) to a target file or +// a list of attributes to set on a target file. +type CopyFileAttributes interface { + FormatAttributes() *string + notPubliclyImplementable() +} + +// SourceCopyFileAttributes specifies to copy file attributes from a source file(source) to a target file +type SourceCopyFileAttributes struct { +} + +func (s SourceCopyFileAttributes) FormatAttributes() *string { + return to.Ptr("source") +} + +func (s SourceCopyFileAttributes) notPubliclyImplementable() {} + +// DestinationCopyFileAttributes specifies a list of attributes to set on a target file. +type DestinationCopyFileAttributes NTFSFileAttributes + +func (d DestinationCopyFileAttributes) FormatAttributes() *string { + attributes := NTFSFileAttributes(d) + return to.Ptr(attributes.String()) +} + +func (d DestinationCopyFileAttributes) notPubliclyImplementable() {} diff --git a/sdk/storage/azfile/internal/exported/exported.go b/sdk/storage/azfile/internal/exported/exported.go new file mode 100644 index 000000000000..9bc1ca47df84 --- /dev/null +++ b/sdk/storage/azfile/internal/exported/exported.go @@ -0,0 +1,33 @@ +//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 exported + +import ( + "fmt" + "strconv" +) + +// 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 +} + +// FormatHTTPRange converts an HTTPRange to its string format. +func FormatHTTPRange(r HTTPRange) *string { + if r.Offset == 0 && r.Count == 0 { + return nil // No specified range + } + endOffset := "" // if count == CountToEnd (0) + if r.Count > 0 { + endOffset = strconv.FormatInt((r.Offset+r.Count)-1, 10) + } + dataRange := fmt.Sprintf("bytes=%v-%s", r.Offset, endOffset) + return &dataRange +} diff --git a/sdk/storage/azfile/internal/exported/file_permissions.go b/sdk/storage/azfile/internal/exported/file_permissions.go new file mode 100644 index 000000000000..73fce6afb27c --- /dev/null +++ b/sdk/storage/azfile/internal/exported/file_permissions.go @@ -0,0 +1,32 @@ +//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 exported + +// Permissions contains the optional parameters for the permissions on the file. +type Permissions struct { + // If specified the permission (security descriptor) shall be set for the directory/file. This header can be used if Permission + // size is <= 8KB, else x-ms-file-permission-key header shall be used. Default + // value: Inherit. If SDDL is specified as input, it must have owner, group and dacl. Note: Only one of the x-ms-file-permission + // or x-ms-file-permission-key should be specified. + Permission *string + // Key of the permission to be set for the directory/file. + // Note: Only one of the x-ms-file-permission or x-ms-file-permission-key should be specified. + PermissionKey *string +} + +// Format returns file permission string and permission key. +func (p *Permissions) Format(defaultFilePermissionStr string) (*string, *string) { + if p == nil { + return &defaultFilePermissionStr, nil + } + + if p.Permission == nil && p.PermissionKey == nil { + return &defaultFilePermissionStr, nil + } else { + return p.Permission, p.PermissionKey + } +} diff --git a/sdk/storage/azfile/internal/exported/log_events.go b/sdk/storage/azfile/internal/exported/log_events.go new file mode 100644 index 000000000000..d33528ea8eb2 --- /dev/null +++ b/sdk/storage/azfile/internal/exported/log_events.go @@ -0,0 +1,17 @@ +//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 exported + +import ( + "github.com/Azure/azure-sdk-for-go/sdk/internal/log" +) + +// NOTE: these are publicly exported via type-aliasing in azfile/log.go +const ( + // EventUpload is used when we compute number of chunks to upload and size of each chunk. + EventUpload log.Event = "azfile.Upload" +) diff --git a/sdk/storage/azfile/internal/exported/shared_key_credential.go b/sdk/storage/azfile/internal/exported/shared_key_credential.go new file mode 100644 index 000000000000..439617d07ba1 --- /dev/null +++ b/sdk/storage/azfile/internal/exported/shared_key_credential.go @@ -0,0 +1,218 @@ +//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 exported + +import ( + "bytes" + "crypto/hmac" + "crypto/sha256" + "encoding/base64" + "fmt" + "net/http" + "net/url" + "sort" + "strings" + "sync/atomic" + "time" + + azlog "github.com/Azure/azure-sdk-for-go/sdk/azcore/log" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/policy" + "github.com/Azure/azure-sdk-for-go/sdk/internal/log" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azfile/internal/shared" +) + +// SharedKeyCredential contains an account's name and its primary or secondary key. +type SharedKeyCredential struct { + // Only the NewSharedKeyCredential method should set these; all other methods should treat them as read-only + accountName string + accountKey atomic.Value // []byte +} + +// NewSharedKeyCredential creates an immutable SharedKeyCredential containing the +// storage account's name and either its primary or secondary key. +func NewSharedKeyCredential(accountName string, accountKey string) (*SharedKeyCredential, error) { + c := SharedKeyCredential{accountName: accountName} + if err := c.SetAccountKey(accountKey); err != nil { + return nil, err + } + return &c, nil +} + +// AccountName returns the Storage account's name. +func (c *SharedKeyCredential) AccountName() string { + return c.accountName +} + +// SetAccountKey replaces the existing account key with the specified account key. +func (c *SharedKeyCredential) SetAccountKey(accountKey string) error { + _bytes, err := base64.StdEncoding.DecodeString(accountKey) + if err != nil { + return fmt.Errorf("decode account key: %w", err) + } + c.accountKey.Store(_bytes) + return nil +} + +// ComputeHMACSHA256 generates a hash signature for an HTTP request or for a SAS. +func (c *SharedKeyCredential) computeHMACSHA256(message string) (string, error) { + h := hmac.New(sha256.New, c.accountKey.Load().([]byte)) + _, err := h.Write([]byte(message)) + return base64.StdEncoding.EncodeToString(h.Sum(nil)), err +} + +func (c *SharedKeyCredential) buildStringToSign(req *http.Request) (string, error) { + // https://docs.microsoft.com/en-us/rest/api/storageservices/authentication-for-the-azure-storage-services + headers := req.Header + contentLength := getHeader(shared.HeaderContentLength, headers) + if contentLength == "0" { + contentLength = "" + } + + canonicalizedResource, err := c.buildCanonicalizedResource(req.URL) + if err != nil { + return "", err + } + + stringToSign := strings.Join([]string{ + req.Method, + getHeader(shared.HeaderContentEncoding, headers), + getHeader(shared.HeaderContentLanguage, headers), + contentLength, + getHeader(shared.HeaderContentMD5, headers), + getHeader(shared.HeaderContentType, headers), + "", // Empty date because x-ms-date is expected (as per web page above) + getHeader(shared.HeaderIfModifiedSince, headers), + getHeader(shared.HeaderIfMatch, headers), + getHeader(shared.HeaderIfNoneMatch, headers), + getHeader(shared.HeaderIfUnmodifiedSince, headers), + getHeader(shared.HeaderRange, headers), + c.buildCanonicalizedHeader(headers), + canonicalizedResource, + }, "\n") + return stringToSign, nil +} + +func getHeader(key string, headers map[string][]string) string { + if headers == nil { + return "" + } + if v, ok := headers[key]; ok { + if len(v) > 0 { + return v[0] + } + } + + return "" +} + +func (c *SharedKeyCredential) buildCanonicalizedHeader(headers http.Header) string { + cm := map[string][]string{} + for k, v := range headers { + headerName := strings.TrimSpace(strings.ToLower(k)) + if strings.HasPrefix(headerName, "x-ms-") { + cm[headerName] = v // NOTE: the value must not have any whitespace around it. + } + } + if len(cm) == 0 { + return "" + } + + keys := make([]string, 0, len(cm)) + for key := range cm { + keys = append(keys, key) + } + sort.Strings(keys) + ch := bytes.NewBufferString("") + for i, key := range keys { + if i > 0 { + ch.WriteRune('\n') + } + ch.WriteString(key) + ch.WriteRune(':') + ch.WriteString(strings.Join(cm[key], ",")) + } + return ch.String() +} + +func (c *SharedKeyCredential) buildCanonicalizedResource(u *url.URL) (string, error) { + // https://docs.microsoft.com/en-us/rest/api/storageservices/authentication-for-the-azure-storage-services + cr := bytes.NewBufferString("/") + cr.WriteString(c.accountName) + + if len(u.Path) > 0 { + // Any portion of the CanonicalizedResource string that is derived from + // the resource's URI should be encoded exactly as it is in the URI. + // -- https://msdn.microsoft.com/en-gb/library/azure/dd179428.aspx + cr.WriteString(u.EscapedPath()) + } else { + // a slash is required to indicate the root path + cr.WriteString("/") + } + + // params is a map[string][]string; param name is key; params values is []string + params, err := url.ParseQuery(u.RawQuery) // Returns URL decoded values + if err != nil { + return "", fmt.Errorf("failed to parse query params: %w", err) + } + + if len(params) > 0 { // There is at least 1 query parameter + var paramNames []string // We use this to sort the parameter key names + for paramName := range params { + paramNames = append(paramNames, paramName) // paramNames must be lowercase + } + sort.Strings(paramNames) + + for _, paramName := range paramNames { + paramValues := params[paramName] + sort.Strings(paramValues) + + // Join the sorted key values separated by ',' + // Then prepend "keyName:"; then add this string to the buffer + cr.WriteString("\n" + paramName + ":" + strings.Join(paramValues, ",")) + } + } + return cr.String(), nil +} + +// ComputeHMACSHA256 is a helper for computing the signed string outside of this package. +func ComputeHMACSHA256(cred *SharedKeyCredential, message string) (string, error) { + return cred.computeHMACSHA256(message) +} + +// the following content isn't actually exported but must live +// next to SharedKeyCredential as it uses its unexported methods + +type SharedKeyCredPolicy struct { + cred *SharedKeyCredential +} + +func NewSharedKeyCredPolicy(cred *SharedKeyCredential) *SharedKeyCredPolicy { + return &SharedKeyCredPolicy{cred: cred} +} + +func (s *SharedKeyCredPolicy) Do(req *policy.Request) (*http.Response, error) { + if d := getHeader(shared.HeaderXmsDate, req.Raw().Header); d == "" { + req.Raw().Header.Set(shared.HeaderXmsDate, time.Now().UTC().Format(http.TimeFormat)) + } + stringToSign, err := s.cred.buildStringToSign(req.Raw()) + if err != nil { + return nil, err + } + signature, err := s.cred.computeHMACSHA256(stringToSign) + if err != nil { + return nil, err + } + authHeader := strings.Join([]string{"SharedKey ", s.cred.AccountName(), ":", signature}, "") + req.Raw().Header.Set(shared.HeaderAuthorization, authHeader) + + response, err := req.Next() + if err != nil && response != nil && response.StatusCode == http.StatusForbidden { + // Service failed to authenticate request, log it + log.Write(azlog.EventResponse, "===== HTTP Forbidden status, String-to-Sign:\n"+stringToSign+"\n===============================\n") + } + return response, err +} diff --git a/sdk/storage/azfile/internal/exported/smb_property.go b/sdk/storage/azfile/internal/exported/smb_property.go new file mode 100644 index 000000000000..894e9455b760 --- /dev/null +++ b/sdk/storage/azfile/internal/exported/smb_property.go @@ -0,0 +1,98 @@ +//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 exported + +import ( + "github.com/Azure/azure-sdk-for-go/sdk/storage/azfile/internal/generated" + "strings" + "time" +) + +// SMBProperties contains the optional parameters regarding the SMB/NTFS properties for a file. +type SMBProperties struct { + // NTFSFileAttributes for Files and Directories. Default value is 'None' for file and + // 'Directory' for directory. ‘None’ can also be specified as default. + Attributes *NTFSFileAttributes + // The Coordinated Universal Time (UTC) creation time for the file/directory. Default value is 'now'. + CreationTime *time.Time + // The Coordinated Universal Time (UTC) last write time for the file/directory. Default value is 'now'. + LastWriteTime *time.Time +} + +// Format returns file attributes, creation time and last write time. +func (sp *SMBProperties) Format(isDir bool, defaultFileAttributes string, defaultCurrentTimeString string) (fileAttributes string, creationTime string, lastWriteTime string) { + if sp == nil { + return defaultFileAttributes, defaultCurrentTimeString, defaultCurrentTimeString + } + + fileAttributes = defaultFileAttributes + if sp.Attributes != nil { + fileAttributes = sp.Attributes.String() + if fileAttributes == "" { + fileAttributes = defaultFileAttributes + } else if isDir && strings.ToLower(fileAttributes) != "none" { + // Directories need to have this attribute included, if setting any attributes. + fileAttributes += "|Directory" + } + } + + creationTime = defaultCurrentTimeString + if sp.CreationTime != nil { + creationTime = sp.CreationTime.UTC().Format(generated.ISO8601) + } + + lastWriteTime = defaultCurrentTimeString + if sp.LastWriteTime != nil { + lastWriteTime = sp.LastWriteTime.UTC().Format(generated.ISO8601) + } + + return +} + +// NTFSFileAttributes for Files and Directories. +// The subset of attributes is listed at: https://learn.microsoft.com/en-us/rest/api/storageservices/set-file-properties#file-system-attributes. +type NTFSFileAttributes struct { + ReadOnly, Hidden, System, Directory, Archive, None, Temporary, Offline, NotContentIndexed, NoScrubData bool +} + +// String returns a string representation of NTFSFileAttributes. +func (f *NTFSFileAttributes) String() string { + fileAttributes := "" + if f.ReadOnly { + fileAttributes += "ReadOnly|" + } + if f.Hidden { + fileAttributes += "Hidden|" + } + if f.System { + fileAttributes += "System|" + } + if f.Directory { + fileAttributes += "Directory|" + } + if f.Archive { + fileAttributes += "Archive|" + } + if f.None { + fileAttributes += "None|" + } + if f.Temporary { + fileAttributes += "Temporary|" + } + if f.Offline { + fileAttributes += "Offline|" + } + if f.NotContentIndexed { + fileAttributes += "NotContentIndexed|" + } + if f.NoScrubData { + fileAttributes += "NoScrubData|" + } + + fileAttributes = strings.TrimSuffix(fileAttributes, "|") + return fileAttributes +} diff --git a/sdk/storage/azfile/internal/exported/transfer_validation_option.go b/sdk/storage/azfile/internal/exported/transfer_validation_option.go new file mode 100644 index 000000000000..ae8df1ea0def --- /dev/null +++ b/sdk/storage/azfile/internal/exported/transfer_validation_option.go @@ -0,0 +1,28 @@ +//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 exported + +import ( + "github.com/Azure/azure-sdk-for-go/sdk/storage/azfile/internal/generated" + "io" +) + +// TransferValidationType abstracts the various mechanisms used to verify a transfer. +type TransferValidationType interface { + Apply(io.ReadSeekCloser, generated.TransactionalContentSetter) (io.ReadSeekCloser, error) + notPubliclyImplementable() +} + +// TransferValidationTypeMD5 is a TransferValidationType used to provide a precomputed MD5. +type TransferValidationTypeMD5 []byte + +func (c TransferValidationTypeMD5) Apply(rsc io.ReadSeekCloser, cfg generated.TransactionalContentSetter) (io.ReadSeekCloser, error) { + cfg.SetMD5(c) + return rsc, nil +} + +func (TransferValidationTypeMD5) notPubliclyImplementable() {} diff --git a/sdk/storage/azfile/internal/exported/version.go b/sdk/storage/azfile/internal/exported/version.go new file mode 100644 index 000000000000..fbe1575df39c --- /dev/null +++ b/sdk/storage/azfile/internal/exported/version.go @@ -0,0 +1,12 @@ +//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 exported + +const ( + ModuleName = "azfile" + ModuleVersion = "v0.1.1" +) diff --git a/sdk/storage/azfile/internal/generated/autorest.md b/sdk/storage/azfile/internal/generated/autorest.md new file mode 100644 index 000000000000..634ccff33f46 --- /dev/null +++ b/sdk/storage/azfile/internal/generated/autorest.md @@ -0,0 +1,309 @@ +# Code Generation - Azure File SDK for Golang + +### Settings + +```yaml +go: true +clear-output-folder: false +version: "^3.0.0" +license-header: MICROSOFT_MIT_NO_VERSION +input-file: "https://raw.githubusercontent.com/Azure/azure-rest-api-specs/bbea558ac43d6ebec72455233c84b0158c89fcda/specification/storage/data-plane/Microsoft.FileStorage/preview/2020-10-02/file.json" +credential-scope: "https://storage.azure.com/.default" +output-folder: ../generated +file-prefix: "zz_" +openapi-type: "data-plane" +verbose: true +security: AzureKey +modelerfour: + group-parameters: false + seal-single-value-enum-by-default: true + lenient-model-deduplication: true +export-clients: true +use: "@autorest/go@4.0.0-preview.45" +``` + +### Don't include share name, directory, or file name in path - we have direct URIs + +``` yaml +directive: +- from: swagger-document + where: $["x-ms-paths"] + transform: > + for (const property in $) + { + if (property.includes('/{shareName}/{directory}/{fileName}')) + { + $[property]["parameters"] = $[property]["parameters"].filter(function(param) { return (typeof param['$ref'] === "undefined") || (false == param['$ref'].endsWith("#/parameters/ShareName") && false == param['$ref'].endsWith("#/parameters/DirectoryPath") && false == param['$ref'].endsWith("#/parameters/FilePath"))}); + } + else if (property.includes('/{shareName}/{directory}')) + { + $[property]["parameters"] = $[property]["parameters"].filter(function(param) { return (typeof param['$ref'] === "undefined") || (false == param['$ref'].endsWith("#/parameters/ShareName") && false == param['$ref'].endsWith("#/parameters/DirectoryPath"))}); + } + else if (property.includes('/{shareName}')) + { + $[property]["parameters"] = $[property]["parameters"].filter(function(param) { return (typeof param['$ref'] === "undefined") || (false == param['$ref'].endsWith("#/parameters/ShareName"))}); + } + } +``` + +### Add Last-Modified to SetMetadata + +``` yaml +directive: +- from: swagger-document + where: $["x-ms-paths"]["/{shareName}/{directory}/{fileName}?comp=metadata"] + transform: > + $.put.responses["200"].headers["Last-Modified"] = { + "type": "string", + "format": "date-time-rfc1123", + "description": "Returns the date and time the file was last modified. Any operation that modifies the file, including an update of the file's metadata or properties, changes the last-modified time of the file." + } +``` + +### Add Content-MD5 to Put Range from URL + +``` yaml +directive: +- from: swagger-document + where: $["x-ms-paths"]["/{shareName}/{directory}/{fileName}?comp=range&fromURL"] + transform: > + $.put.responses["201"].headers["Content-MD5"] = { + "type": "string", + "format": "byte", + "description": "This header is returned so that the client can check for message content integrity. The value of this header is computed by the File service; it is not necessarily the same value as may have been specified in the request headers." + } +``` + +### Rename FileHttpHeaders to ShareFileHTTPHeaders and remove file prefix from properties + +``` yaml +directive: +- from: swagger-document + where: $.parameters + transform: > + $.FileCacheControl["x-ms-parameter-grouping"].name = "share-file-http-headers"; + $.FileCacheControl["x-ms-client-name"] = "cacheControl"; + $.FileContentDisposition["x-ms-parameter-grouping"].name = "share-file-http-headers"; + $.FileContentDisposition["x-ms-client-name"] = "contentDisposition"; + $.FileContentEncoding["x-ms-parameter-grouping"].name = "share-file-http-headers"; + $.FileContentEncoding["x-ms-client-name"] = "contentEncoding"; + $.FileContentLanguage["x-ms-parameter-grouping"].name = "share-file-http-headers"; + $.FileContentLanguage["x-ms-client-name"] = "contentLanguage"; + $.FileContentMD5["x-ms-parameter-grouping"].name = "share-file-http-headers"; + $.FileContentMD5["x-ms-client-name"] = "contentMd5"; + $.FileContentType["x-ms-parameter-grouping"].name = "share-file-http-headers"; + $.FileContentType["x-ms-client-name"] = "contentType"; +``` + +### use azcore.ETag + +``` yaml +directive: +- from: zz_models.go + where: $ + transform: >- + return $. + replace(/import "time"/, `import (\n\t"time"\n\t"github.com/Azure/azure-sdk-for-go/sdk/azcore"\n)`). + replace(/Etag\s+\*string/g, `ETag *azcore.ETag`); + +- from: zz_response_types.go + where: $ + transform: >- + return $. + replace(/"time"/, `"time"\n\t"github.com/Azure/azure-sdk-for-go/sdk/azcore"`). + replace(/ETag\s+\*string/g, `ETag *azcore.ETag`); + +- from: + - zz_directory_client.go + - zz_file_client.go + - zz_share_client.go + where: $ + transform: >- + return $. + replace(/"github\.com\/Azure\/azure\-sdk\-for\-go\/sdk\/azcore\/policy"/, `"github.com/Azure/azure-sdk-for-go/sdk/azcore"\n\t"github.com/Azure/azure-sdk-for-go/sdk/azcore/policy"`). + replace(/result\.ETag\s+=\s+&val/g, `result.ETag = (*azcore.ETag)(&val)`); +``` + +### Rename models - remove `Share` prefix + +``` yaml +directive: +- rename-model: + from: ShareProtocolSettings + to: ProtocolSettings +- rename-model: + from: ShareSmbSettings + to: SMBSettings +``` + +### Capitalise SMB field + +``` yaml +directive: +- from: + - zz_file_client.go + - zz_models.go + where: $ + transform: >- + return $. + replace(/SmbMultichannel/g, `SMBMultichannel`). + replace(/copyFileSmbInfo/g, `copyFileSMBInfo`). + replace(/CopyFileSmbInfo/g, `CopyFileSMBInfo`). + replace(/Smb\s+\*ShareSMBSettings/g, `SMB *ShareSMBSettings`); +``` + +### Rename models - remove `Item` and `Internal` suffix + +``` yaml +directive: +- rename-model: + from: DirectoryItem + to: Directory +- rename-model: + from: FileItem + to: File +- rename-model: + from: HandleItem + to: Handle +- rename-model: + from: ShareItemInternal + to: Share +- rename-model: + from: SharePropertiesInternal + to: ShareProperties +``` + +### Remove `Items` and `List` suffix + +``` yaml +directive: + - from: source-file-go + where: $ + transform: >- + return $. + replace(/DirectoryItems/g, "Directories"). + replace(/FileItems/g, "Files"). + replace(/ShareItems/g, "Shares"). + replace(/HandleList/g, "Handles"); +``` + +### Rename `FileID` to `ID` (except for Handle object) + +``` yaml +directive: +- from: swagger-document + where: $.definitions + transform: > + $.Directory.properties.FileId["x-ms-client-name"] = "ID"; + $.File.properties.FileId["x-ms-client-name"] = "ID"; + $.Handle.properties.HandleId["x-ms-client-name"] = "ID"; + +- from: + - zz_directory_client.go + - zz_file_client.go + - zz_response_types.go + where: $ + transform: >- + return $. + replace(/FileID/g, `ID`); +``` + + +### Change CORS acronym to be all caps and rename `FileParentID` to `ParentID` + +``` yaml +directive: + - from: source-file-go + where: $ + transform: >- + return $. + replace(/Cors/g, "CORS"). + replace(/FileParentID/g, "ParentID"); +``` + +### Change cors xml to be correct + +``` yaml +directive: + - from: source-file-go + where: $ + transform: >- + return $. + replace(/xml:"CORS>CORSRule"/g, "xml:\"Cors>CorsRule\""); +``` + +### Remove pager methods and export various generated methods in service client + +``` yaml +directive: + - from: zz_service_client.go + where: $ + transform: >- + return $. + replace(/func \(client \*ServiceClient\) NewListSharesSegmentPager\(.+\/\/ listSharesSegmentCreateRequest creates the ListSharesSegment request/s, `//\n// listSharesSegmentCreateRequest creates the ListSharesSegment request`). + replace(/\(client \*ServiceClient\) listSharesSegmentCreateRequest\(/, `(client *ServiceClient) ListSharesSegmentCreateRequest(`). + replace(/\(client \*ServiceClient\) listSharesSegmentHandleResponse\(/, `(client *ServiceClient) ListSharesSegmentHandleResponse(`); +``` + +### Use string type for FileCreationTime and FileLastWriteTime + +``` yaml +directive: +- from: swagger-document + where: $.parameters.FileCreationTime + transform: > + $.format = "str"; +- from: swagger-document + where: $.parameters.FileLastWriteTime + transform: > + $.format = "str"; +``` + +### Remove pager methods and export various generated methods in directory client + +``` yaml +directive: + - from: zz_directory_client.go + where: $ + transform: >- + return $. + replace(/func \(client \*DirectoryClient\) NewListFilesAndDirectoriesSegmentPager\(.+\/\/ listFilesAndDirectoriesSegmentCreateRequest creates the ListFilesAndDirectoriesSegment request/s, `//\n// listFilesAndDirectoriesSegmentCreateRequest creates the ListFilesAndDirectoriesSegment request`). + replace(/\(client \*DirectoryClient\) listFilesAndDirectoriesSegmentCreateRequest\(/, `(client *DirectoryClient) ListFilesAndDirectoriesSegmentCreateRequest(`). + replace(/\(client \*DirectoryClient\) listFilesAndDirectoriesSegmentHandleResponse\(/, `(client *DirectoryClient) ListFilesAndDirectoriesSegmentHandleResponse(`); +``` + +### Fix time format for parsing the response headers: x-ms-file-creation-time, x-ms-file-last-write-time, x-ms-file-change-time + +``` yaml +directive: + - from: + - zz_directory_client.go + - zz_file_client.go + where: $ + transform: >- + return $. + replace(/fileCreationTime,\s+err\s+\:=\s+time\.Parse\(time\.RFC1123,\s+val\)/g, `fileCreationTime, err := time.Parse(ISO8601, val)`). + replace(/fileLastWriteTime,\s+err\s+\:=\s+time\.Parse\(time\.RFC1123,\s+val\)/g, `fileLastWriteTime, err := time.Parse(ISO8601, val)`). + replace(/fileChangeTime,\s+err\s+\:=\s+time\.Parse\(time\.RFC1123,\s+val\)/g, `fileChangeTime, err := time.Parse(ISO8601, val)`); +``` + +### Change `Duration` parameter in leases to be required + +``` yaml +directive: +- from: swagger-document + where: $.parameters.LeaseDuration + transform: > + $.required = true; +``` + +### Convert ShareUsageBytes to int64 + +``` yaml +directive: + - from: zz_models.go + where: $ + transform: >- + return $. + replace(/ShareUsageBytes\s+\*int32/g, `ShareUsageBytes *int64`); +``` diff --git a/sdk/storage/azfile/internal/generated/build.go b/sdk/storage/azfile/internal/generated/build.go new file mode 100644 index 000000000000..57f112001bd2 --- /dev/null +++ b/sdk/storage/azfile/internal/generated/build.go @@ -0,0 +1,10 @@ +//go:build go1.18 +// +build go1.18 + +//go:generate autorest ./autorest.md +//go:generate gofmt -w . + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See License.txt in the project root for license information. + +package generated diff --git a/sdk/storage/azfile/internal/generated/directory_client.go b/sdk/storage/azfile/internal/generated/directory_client.go new file mode 100644 index 000000000000..11a75a9f50c8 --- /dev/null +++ b/sdk/storage/azfile/internal/generated/directory_client.go @@ -0,0 +1,22 @@ +//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 generated + +import "github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime" + +const ( + // ISO8601 is used for formatting file creation, last write and change time. + ISO8601 = "2006-01-02T15:04:05.0000000Z07:00" +) + +func (client *DirectoryClient) Endpoint() string { + return client.endpoint +} + +func (client *DirectoryClient) Pipeline() runtime.Pipeline { + return client.pl +} diff --git a/sdk/storage/azfile/internal/generated/file_client.go b/sdk/storage/azfile/internal/generated/file_client.go new file mode 100644 index 000000000000..f4a01a783938 --- /dev/null +++ b/sdk/storage/azfile/internal/generated/file_client.go @@ -0,0 +1,17 @@ +//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 generated + +import "github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime" + +func (client *FileClient) Endpoint() string { + return client.endpoint +} + +func (client *FileClient) Pipeline() runtime.Pipeline { + return client.pl +} diff --git a/sdk/storage/azfile/internal/generated/models.go b/sdk/storage/azfile/internal/generated/models.go new file mode 100644 index 000000000000..6450b7de2e82 --- /dev/null +++ b/sdk/storage/azfile/internal/generated/models.go @@ -0,0 +1,25 @@ +//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 generated + +type TransactionalContentSetter interface { + SetMD5([]byte) + // add SetCRC64() when Azure File service starts supporting it. +} + +func (f *FileClientUploadRangeOptions) SetMD5(v []byte) { + f.ContentMD5 = v +} + +type SourceContentSetter interface { + SetSourceContentCRC64(v []byte) + // add SetSourceContentMD5() when Azure File service starts supporting it. +} + +func (f *FileClientUploadRangeFromURLOptions) SetSourceContentCRC64(v []byte) { + f.SourceContentCRC64 = v +} diff --git a/sdk/storage/azfile/internal/generated/service_client.go b/sdk/storage/azfile/internal/generated/service_client.go new file mode 100644 index 000000000000..1f449b955e82 --- /dev/null +++ b/sdk/storage/azfile/internal/generated/service_client.go @@ -0,0 +1,17 @@ +//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 generated + +import "github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime" + +func (client *ServiceClient) Endpoint() string { + return client.endpoint +} + +func (client *ServiceClient) Pipeline() runtime.Pipeline { + return client.pl +} diff --git a/sdk/storage/azfile/internal/generated/share_client.go b/sdk/storage/azfile/internal/generated/share_client.go new file mode 100644 index 000000000000..040785814606 --- /dev/null +++ b/sdk/storage/azfile/internal/generated/share_client.go @@ -0,0 +1,17 @@ +//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 generated + +import "github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime" + +func (client *ShareClient) Endpoint() string { + return client.endpoint +} + +func (client *ShareClient) Pipeline() runtime.Pipeline { + return client.pl +} diff --git a/sdk/storage/azfile/internal/generated/zz_constants.go b/sdk/storage/azfile/internal/generated/zz_constants.go new file mode 100644 index 000000000000..13ee55aa841e --- /dev/null +++ b/sdk/storage/azfile/internal/generated/zz_constants.go @@ -0,0 +1,342 @@ +//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. +// Code generated by Microsoft (R) AutoRest Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. +// DO NOT EDIT. + +package generated + +type CopyStatusType string + +const ( + CopyStatusTypePending CopyStatusType = "pending" + CopyStatusTypeSuccess CopyStatusType = "success" + CopyStatusTypeAborted CopyStatusType = "aborted" + CopyStatusTypeFailed CopyStatusType = "failed" +) + +// PossibleCopyStatusTypeValues returns the possible values for the CopyStatusType const type. +func PossibleCopyStatusTypeValues() []CopyStatusType { + return []CopyStatusType{ + CopyStatusTypePending, + CopyStatusTypeSuccess, + CopyStatusTypeAborted, + CopyStatusTypeFailed, + } +} + +type DeleteSnapshotsOptionType string + +const ( + DeleteSnapshotsOptionTypeInclude DeleteSnapshotsOptionType = "include" + DeleteSnapshotsOptionTypeIncludeLeased DeleteSnapshotsOptionType = "include-leased" +) + +// PossibleDeleteSnapshotsOptionTypeValues returns the possible values for the DeleteSnapshotsOptionType const type. +func PossibleDeleteSnapshotsOptionTypeValues() []DeleteSnapshotsOptionType { + return []DeleteSnapshotsOptionType{ + DeleteSnapshotsOptionTypeInclude, + DeleteSnapshotsOptionTypeIncludeLeased, + } +} + +type FileRangeWriteType string + +const ( + FileRangeWriteTypeUpdate FileRangeWriteType = "update" + FileRangeWriteTypeClear FileRangeWriteType = "clear" +) + +// PossibleFileRangeWriteTypeValues returns the possible values for the FileRangeWriteType const type. +func PossibleFileRangeWriteTypeValues() []FileRangeWriteType { + return []FileRangeWriteType{ + FileRangeWriteTypeUpdate, + FileRangeWriteTypeClear, + } +} + +// LeaseDurationType - When a share is leased, specifies whether the lease is of infinite or fixed duration. +type LeaseDurationType string + +const ( + LeaseDurationTypeInfinite LeaseDurationType = "infinite" + LeaseDurationTypeFixed LeaseDurationType = "fixed" +) + +// PossibleLeaseDurationTypeValues returns the possible values for the LeaseDurationType const type. +func PossibleLeaseDurationTypeValues() []LeaseDurationType { + return []LeaseDurationType{ + LeaseDurationTypeInfinite, + LeaseDurationTypeFixed, + } +} + +// LeaseStateType - Lease state of the share. +type LeaseStateType string + +const ( + LeaseStateTypeAvailable LeaseStateType = "available" + LeaseStateTypeLeased LeaseStateType = "leased" + LeaseStateTypeExpired LeaseStateType = "expired" + LeaseStateTypeBreaking LeaseStateType = "breaking" + LeaseStateTypeBroken LeaseStateType = "broken" +) + +// PossibleLeaseStateTypeValues returns the possible values for the LeaseStateType const type. +func PossibleLeaseStateTypeValues() []LeaseStateType { + return []LeaseStateType{ + LeaseStateTypeAvailable, + LeaseStateTypeLeased, + LeaseStateTypeExpired, + LeaseStateTypeBreaking, + LeaseStateTypeBroken, + } +} + +// LeaseStatusType - The current lease status of the share. +type LeaseStatusType string + +const ( + LeaseStatusTypeLocked LeaseStatusType = "locked" + LeaseStatusTypeUnlocked LeaseStatusType = "unlocked" +) + +// PossibleLeaseStatusTypeValues returns the possible values for the LeaseStatusType const type. +func PossibleLeaseStatusTypeValues() []LeaseStatusType { + return []LeaseStatusType{ + LeaseStatusTypeLocked, + LeaseStatusTypeUnlocked, + } +} + +type ListFilesIncludeType string + +const ( + ListFilesIncludeTypeTimestamps ListFilesIncludeType = "Timestamps" + ListFilesIncludeTypeEtag ListFilesIncludeType = "Etag" + ListFilesIncludeTypeAttributes ListFilesIncludeType = "Attributes" + ListFilesIncludeTypePermissionKey ListFilesIncludeType = "PermissionKey" +) + +// PossibleListFilesIncludeTypeValues returns the possible values for the ListFilesIncludeType const type. +func PossibleListFilesIncludeTypeValues() []ListFilesIncludeType { + return []ListFilesIncludeType{ + ListFilesIncludeTypeTimestamps, + ListFilesIncludeTypeEtag, + ListFilesIncludeTypeAttributes, + ListFilesIncludeTypePermissionKey, + } +} + +type ListSharesIncludeType string + +const ( + ListSharesIncludeTypeSnapshots ListSharesIncludeType = "snapshots" + ListSharesIncludeTypeMetadata ListSharesIncludeType = "metadata" + ListSharesIncludeTypeDeleted ListSharesIncludeType = "deleted" +) + +// PossibleListSharesIncludeTypeValues returns the possible values for the ListSharesIncludeType const type. +func PossibleListSharesIncludeTypeValues() []ListSharesIncludeType { + return []ListSharesIncludeType{ + ListSharesIncludeTypeSnapshots, + ListSharesIncludeTypeMetadata, + ListSharesIncludeTypeDeleted, + } +} + +type PermissionCopyModeType string + +const ( + PermissionCopyModeTypeSource PermissionCopyModeType = "source" + PermissionCopyModeTypeOverride PermissionCopyModeType = "override" +) + +// PossiblePermissionCopyModeTypeValues returns the possible values for the PermissionCopyModeType const type. +func PossiblePermissionCopyModeTypeValues() []PermissionCopyModeType { + return []PermissionCopyModeType{ + PermissionCopyModeTypeSource, + PermissionCopyModeTypeOverride, + } +} + +type ShareAccessTier string + +const ( + ShareAccessTierCool ShareAccessTier = "Cool" + ShareAccessTierHot ShareAccessTier = "Hot" + ShareAccessTierTransactionOptimized ShareAccessTier = "TransactionOptimized" +) + +// PossibleShareAccessTierValues returns the possible values for the ShareAccessTier const type. +func PossibleShareAccessTierValues() []ShareAccessTier { + return []ShareAccessTier{ + ShareAccessTierCool, + ShareAccessTierHot, + ShareAccessTierTransactionOptimized, + } +} + +type ShareRootSquash string + +const ( + ShareRootSquashNoRootSquash ShareRootSquash = "NoRootSquash" + ShareRootSquashRootSquash ShareRootSquash = "RootSquash" + ShareRootSquashAllSquash ShareRootSquash = "AllSquash" +) + +// PossibleShareRootSquashValues returns the possible values for the ShareRootSquash const type. +func PossibleShareRootSquashValues() []ShareRootSquash { + return []ShareRootSquash{ + ShareRootSquashNoRootSquash, + ShareRootSquashRootSquash, + ShareRootSquashAllSquash, + } +} + +// StorageErrorCode - Error codes returned by the service +type StorageErrorCode string + +const ( + StorageErrorCodeAccountAlreadyExists StorageErrorCode = "AccountAlreadyExists" + StorageErrorCodeAccountBeingCreated StorageErrorCode = "AccountBeingCreated" + StorageErrorCodeAccountIsDisabled StorageErrorCode = "AccountIsDisabled" + StorageErrorCodeAuthenticationFailed StorageErrorCode = "AuthenticationFailed" + StorageErrorCodeAuthorizationFailure StorageErrorCode = "AuthorizationFailure" + StorageErrorCodeAuthorizationPermissionMismatch StorageErrorCode = "AuthorizationPermissionMismatch" + StorageErrorCodeAuthorizationProtocolMismatch StorageErrorCode = "AuthorizationProtocolMismatch" + StorageErrorCodeAuthorizationResourceTypeMismatch StorageErrorCode = "AuthorizationResourceTypeMismatch" + StorageErrorCodeAuthorizationServiceMismatch StorageErrorCode = "AuthorizationServiceMismatch" + StorageErrorCodeAuthorizationSourceIPMismatch StorageErrorCode = "AuthorizationSourceIPMismatch" + StorageErrorCodeCannotDeleteFileOrDirectory StorageErrorCode = "CannotDeleteFileOrDirectory" + StorageErrorCodeClientCacheFlushDelay StorageErrorCode = "ClientCacheFlushDelay" + StorageErrorCodeConditionHeadersNotSupported StorageErrorCode = "ConditionHeadersNotSupported" + StorageErrorCodeConditionNotMet StorageErrorCode = "ConditionNotMet" + StorageErrorCodeContainerQuotaDowngradeNotAllowed StorageErrorCode = "ContainerQuotaDowngradeNotAllowed" + StorageErrorCodeDeletePending StorageErrorCode = "DeletePending" + StorageErrorCodeDirectoryNotEmpty StorageErrorCode = "DirectoryNotEmpty" + StorageErrorCodeEmptyMetadataKey StorageErrorCode = "EmptyMetadataKey" + StorageErrorCodeFeatureVersionMismatch StorageErrorCode = "FeatureVersionMismatch" + StorageErrorCodeFileLockConflict StorageErrorCode = "FileLockConflict" + StorageErrorCodeInsufficientAccountPermissions StorageErrorCode = "InsufficientAccountPermissions" + StorageErrorCodeInternalError StorageErrorCode = "InternalError" + StorageErrorCodeInvalidAuthenticationInfo StorageErrorCode = "InvalidAuthenticationInfo" + StorageErrorCodeInvalidFileOrDirectoryPathName StorageErrorCode = "InvalidFileOrDirectoryPathName" + StorageErrorCodeInvalidHTTPVerb StorageErrorCode = "InvalidHttpVerb" + StorageErrorCodeInvalidHeaderValue StorageErrorCode = "InvalidHeaderValue" + StorageErrorCodeInvalidInput StorageErrorCode = "InvalidInput" + StorageErrorCodeInvalidMD5 StorageErrorCode = "InvalidMd5" + StorageErrorCodeInvalidMetadata StorageErrorCode = "InvalidMetadata" + StorageErrorCodeInvalidQueryParameterValue StorageErrorCode = "InvalidQueryParameterValue" + StorageErrorCodeInvalidRange StorageErrorCode = "InvalidRange" + StorageErrorCodeInvalidResourceName StorageErrorCode = "InvalidResourceName" + StorageErrorCodeInvalidURI StorageErrorCode = "InvalidUri" + StorageErrorCodeInvalidXMLDocument StorageErrorCode = "InvalidXmlDocument" + StorageErrorCodeInvalidXMLNodeValue StorageErrorCode = "InvalidXmlNodeValue" + StorageErrorCodeMD5Mismatch StorageErrorCode = "Md5Mismatch" + StorageErrorCodeMetadataTooLarge StorageErrorCode = "MetadataTooLarge" + StorageErrorCodeMissingContentLengthHeader StorageErrorCode = "MissingContentLengthHeader" + StorageErrorCodeMissingRequiredHeader StorageErrorCode = "MissingRequiredHeader" + StorageErrorCodeMissingRequiredQueryParameter StorageErrorCode = "MissingRequiredQueryParameter" + StorageErrorCodeMissingRequiredXMLNode StorageErrorCode = "MissingRequiredXmlNode" + StorageErrorCodeMultipleConditionHeadersNotSupported StorageErrorCode = "MultipleConditionHeadersNotSupported" + StorageErrorCodeOperationTimedOut StorageErrorCode = "OperationTimedOut" + StorageErrorCodeOutOfRangeInput StorageErrorCode = "OutOfRangeInput" + StorageErrorCodeOutOfRangeQueryParameterValue StorageErrorCode = "OutOfRangeQueryParameterValue" + StorageErrorCodeParentNotFound StorageErrorCode = "ParentNotFound" + StorageErrorCodeReadOnlyAttribute StorageErrorCode = "ReadOnlyAttribute" + StorageErrorCodeRequestBodyTooLarge StorageErrorCode = "RequestBodyTooLarge" + StorageErrorCodeRequestURLFailedToParse StorageErrorCode = "RequestUrlFailedToParse" + StorageErrorCodeResourceAlreadyExists StorageErrorCode = "ResourceAlreadyExists" + StorageErrorCodeResourceNotFound StorageErrorCode = "ResourceNotFound" + StorageErrorCodeResourceTypeMismatch StorageErrorCode = "ResourceTypeMismatch" + StorageErrorCodeServerBusy StorageErrorCode = "ServerBusy" + StorageErrorCodeShareAlreadyExists StorageErrorCode = "ShareAlreadyExists" + StorageErrorCodeShareBeingDeleted StorageErrorCode = "ShareBeingDeleted" + StorageErrorCodeShareDisabled StorageErrorCode = "ShareDisabled" + StorageErrorCodeShareHasSnapshots StorageErrorCode = "ShareHasSnapshots" + StorageErrorCodeShareNotFound StorageErrorCode = "ShareNotFound" + StorageErrorCodeShareSnapshotCountExceeded StorageErrorCode = "ShareSnapshotCountExceeded" + StorageErrorCodeShareSnapshotInProgress StorageErrorCode = "ShareSnapshotInProgress" + StorageErrorCodeShareSnapshotOperationNotSupported StorageErrorCode = "ShareSnapshotOperationNotSupported" + StorageErrorCodeSharingViolation StorageErrorCode = "SharingViolation" + StorageErrorCodeUnsupportedHTTPVerb StorageErrorCode = "UnsupportedHttpVerb" + StorageErrorCodeUnsupportedHeader StorageErrorCode = "UnsupportedHeader" + StorageErrorCodeUnsupportedQueryParameter StorageErrorCode = "UnsupportedQueryParameter" + StorageErrorCodeUnsupportedXMLNode StorageErrorCode = "UnsupportedXmlNode" +) + +// PossibleStorageErrorCodeValues returns the possible values for the StorageErrorCode const type. +func PossibleStorageErrorCodeValues() []StorageErrorCode { + return []StorageErrorCode{ + StorageErrorCodeAccountAlreadyExists, + StorageErrorCodeAccountBeingCreated, + StorageErrorCodeAccountIsDisabled, + StorageErrorCodeAuthenticationFailed, + StorageErrorCodeAuthorizationFailure, + StorageErrorCodeAuthorizationPermissionMismatch, + StorageErrorCodeAuthorizationProtocolMismatch, + StorageErrorCodeAuthorizationResourceTypeMismatch, + StorageErrorCodeAuthorizationServiceMismatch, + StorageErrorCodeAuthorizationSourceIPMismatch, + StorageErrorCodeCannotDeleteFileOrDirectory, + StorageErrorCodeClientCacheFlushDelay, + StorageErrorCodeConditionHeadersNotSupported, + StorageErrorCodeConditionNotMet, + StorageErrorCodeContainerQuotaDowngradeNotAllowed, + StorageErrorCodeDeletePending, + StorageErrorCodeDirectoryNotEmpty, + StorageErrorCodeEmptyMetadataKey, + StorageErrorCodeFeatureVersionMismatch, + StorageErrorCodeFileLockConflict, + StorageErrorCodeInsufficientAccountPermissions, + StorageErrorCodeInternalError, + StorageErrorCodeInvalidAuthenticationInfo, + StorageErrorCodeInvalidFileOrDirectoryPathName, + StorageErrorCodeInvalidHTTPVerb, + StorageErrorCodeInvalidHeaderValue, + StorageErrorCodeInvalidInput, + StorageErrorCodeInvalidMD5, + StorageErrorCodeInvalidMetadata, + StorageErrorCodeInvalidQueryParameterValue, + StorageErrorCodeInvalidRange, + StorageErrorCodeInvalidResourceName, + StorageErrorCodeInvalidURI, + StorageErrorCodeInvalidXMLDocument, + StorageErrorCodeInvalidXMLNodeValue, + StorageErrorCodeMD5Mismatch, + StorageErrorCodeMetadataTooLarge, + StorageErrorCodeMissingContentLengthHeader, + StorageErrorCodeMissingRequiredHeader, + StorageErrorCodeMissingRequiredQueryParameter, + StorageErrorCodeMissingRequiredXMLNode, + StorageErrorCodeMultipleConditionHeadersNotSupported, + StorageErrorCodeOperationTimedOut, + StorageErrorCodeOutOfRangeInput, + StorageErrorCodeOutOfRangeQueryParameterValue, + StorageErrorCodeParentNotFound, + StorageErrorCodeReadOnlyAttribute, + StorageErrorCodeRequestBodyTooLarge, + StorageErrorCodeRequestURLFailedToParse, + StorageErrorCodeResourceAlreadyExists, + StorageErrorCodeResourceNotFound, + StorageErrorCodeResourceTypeMismatch, + StorageErrorCodeServerBusy, + StorageErrorCodeShareAlreadyExists, + StorageErrorCodeShareBeingDeleted, + StorageErrorCodeShareDisabled, + StorageErrorCodeShareHasSnapshots, + StorageErrorCodeShareNotFound, + StorageErrorCodeShareSnapshotCountExceeded, + StorageErrorCodeShareSnapshotInProgress, + StorageErrorCodeShareSnapshotOperationNotSupported, + StorageErrorCodeSharingViolation, + StorageErrorCodeUnsupportedHTTPVerb, + StorageErrorCodeUnsupportedHeader, + StorageErrorCodeUnsupportedQueryParameter, + StorageErrorCodeUnsupportedXMLNode, + } +} diff --git a/sdk/storage/azfile/internal/generated/zz_directory_client.go b/sdk/storage/azfile/internal/generated/zz_directory_client.go new file mode 100644 index 000000000000..1b1eed71d03f --- /dev/null +++ b/sdk/storage/azfile/internal/generated/zz_directory_client.go @@ -0,0 +1,766 @@ +//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. +// Code generated by Microsoft (R) AutoRest Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. +// DO NOT EDIT. + +package generated + +import ( + "context" + "fmt" + "github.com/Azure/azure-sdk-for-go/sdk/azcore" + "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/azcore/to" + "net/http" + "strconv" + "strings" + "time" +) + +// DirectoryClient contains the methods for the Directory group. +// Don't use this type directly, use NewDirectoryClient() instead. +type DirectoryClient struct { + endpoint string + pl runtime.Pipeline +} + +// NewDirectoryClient creates a new instance of DirectoryClient with the specified values. +// - endpoint - The URL of the service account, share, directory or file that is the target of the desired operation. +// - pl - the pipeline used for sending requests and handling responses. +func NewDirectoryClient(endpoint string, pl runtime.Pipeline) *DirectoryClient { + client := &DirectoryClient{ + endpoint: endpoint, + pl: pl, + } + return client +} + +// Create - Creates a new directory under the specified share or parent directory. +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2020-10-02 +// - fileAttributes - If specified, the provided file attributes shall be set. Default value: ‘Archive’ for file and ‘Directory’ +// for directory. ‘None’ can also be specified as default. +// - fileCreationTime - Creation time for the file/directory. Default value: Now. +// - fileLastWriteTime - Last write time for the file/directory. Default value: Now. +// - options - DirectoryClientCreateOptions contains the optional parameters for the DirectoryClient.Create method. +func (client *DirectoryClient) Create(ctx context.Context, fileAttributes string, fileCreationTime string, fileLastWriteTime string, options *DirectoryClientCreateOptions) (DirectoryClientCreateResponse, error) { + req, err := client.createCreateRequest(ctx, fileAttributes, fileCreationTime, fileLastWriteTime, options) + if err != nil { + return DirectoryClientCreateResponse{}, err + } + resp, err := client.pl.Do(req) + if err != nil { + return DirectoryClientCreateResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusCreated) { + return DirectoryClientCreateResponse{}, runtime.NewResponseError(resp) + } + return client.createHandleResponse(resp) +} + +// createCreateRequest creates the Create request. +func (client *DirectoryClient) createCreateRequest(ctx context.Context, fileAttributes string, fileCreationTime string, fileLastWriteTime string, options *DirectoryClientCreateOptions) (*policy.Request, error) { + req, err := runtime.NewRequest(ctx, http.MethodPut, client.endpoint) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("restype", "directory") + if options != nil && options.Timeout != nil { + reqQP.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + } + req.Raw().URL.RawQuery = reqQP.Encode() + if options != nil && options.Metadata != nil { + for k, v := range options.Metadata { + if v != nil { + req.Raw().Header["x-ms-meta-"+k] = []string{*v} + } + } + } + req.Raw().Header["x-ms-version"] = []string{"2020-10-02"} + if options != nil && options.FilePermission != nil { + req.Raw().Header["x-ms-file-permission"] = []string{*options.FilePermission} + } + if options != nil && options.FilePermissionKey != nil { + req.Raw().Header["x-ms-file-permission-key"] = []string{*options.FilePermissionKey} + } + req.Raw().Header["x-ms-file-attributes"] = []string{fileAttributes} + req.Raw().Header["x-ms-file-creation-time"] = []string{fileCreationTime} + req.Raw().Header["x-ms-file-last-write-time"] = []string{fileLastWriteTime} + req.Raw().Header["Accept"] = []string{"application/xml"} + return req, nil +} + +// createHandleResponse handles the Create response. +func (client *DirectoryClient) createHandleResponse(resp *http.Response) (DirectoryClientCreateResponse, error) { + result := DirectoryClientCreateResponse{} + if val := resp.Header.Get("ETag"); val != "" { + result.ETag = (*azcore.ETag)(&val) + } + if val := resp.Header.Get("Last-Modified"); val != "" { + lastModified, err := time.Parse(time.RFC1123, val) + if err != nil { + return DirectoryClientCreateResponse{}, err + } + result.LastModified = &lastModified + } + if val := resp.Header.Get("x-ms-request-id"); val != "" { + result.RequestID = &val + } + if val := resp.Header.Get("x-ms-version"); val != "" { + result.Version = &val + } + if val := resp.Header.Get("Date"); val != "" { + date, err := time.Parse(time.RFC1123, val) + if err != nil { + return DirectoryClientCreateResponse{}, err + } + result.Date = &date + } + if val := resp.Header.Get("x-ms-request-server-encrypted"); val != "" { + isServerEncrypted, err := strconv.ParseBool(val) + if err != nil { + return DirectoryClientCreateResponse{}, err + } + result.IsServerEncrypted = &isServerEncrypted + } + if val := resp.Header.Get("x-ms-file-permission-key"); val != "" { + result.FilePermissionKey = &val + } + if val := resp.Header.Get("x-ms-file-attributes"); val != "" { + result.FileAttributes = &val + } + if val := resp.Header.Get("x-ms-file-creation-time"); val != "" { + fileCreationTime, err := time.Parse(ISO8601, val) + if err != nil { + return DirectoryClientCreateResponse{}, err + } + result.FileCreationTime = &fileCreationTime + } + if val := resp.Header.Get("x-ms-file-last-write-time"); val != "" { + fileLastWriteTime, err := time.Parse(ISO8601, val) + if err != nil { + return DirectoryClientCreateResponse{}, err + } + result.FileLastWriteTime = &fileLastWriteTime + } + if val := resp.Header.Get("x-ms-file-change-time"); val != "" { + fileChangeTime, err := time.Parse(ISO8601, val) + if err != nil { + return DirectoryClientCreateResponse{}, err + } + result.FileChangeTime = &fileChangeTime + } + if val := resp.Header.Get("x-ms-file-id"); val != "" { + result.ID = &val + } + if val := resp.Header.Get("x-ms-file-parent-id"); val != "" { + result.ParentID = &val + } + return result, nil +} + +// Delete - Removes the specified empty directory. Note that the directory must be empty before it can be deleted. +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2020-10-02 +// - options - DirectoryClientDeleteOptions contains the optional parameters for the DirectoryClient.Delete method. +func (client *DirectoryClient) Delete(ctx context.Context, options *DirectoryClientDeleteOptions) (DirectoryClientDeleteResponse, error) { + req, err := client.deleteCreateRequest(ctx, options) + if err != nil { + return DirectoryClientDeleteResponse{}, err + } + resp, err := client.pl.Do(req) + if err != nil { + return DirectoryClientDeleteResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusAccepted) { + return DirectoryClientDeleteResponse{}, runtime.NewResponseError(resp) + } + return client.deleteHandleResponse(resp) +} + +// deleteCreateRequest creates the Delete request. +func (client *DirectoryClient) deleteCreateRequest(ctx context.Context, options *DirectoryClientDeleteOptions) (*policy.Request, error) { + req, err := runtime.NewRequest(ctx, http.MethodDelete, client.endpoint) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("restype", "directory") + if options != nil && options.Timeout != nil { + reqQP.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + } + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["x-ms-version"] = []string{"2020-10-02"} + req.Raw().Header["Accept"] = []string{"application/xml"} + return req, nil +} + +// deleteHandleResponse handles the Delete response. +func (client *DirectoryClient) deleteHandleResponse(resp *http.Response) (DirectoryClientDeleteResponse, error) { + result := DirectoryClientDeleteResponse{} + if val := resp.Header.Get("x-ms-request-id"); val != "" { + result.RequestID = &val + } + if val := resp.Header.Get("x-ms-version"); val != "" { + result.Version = &val + } + if val := resp.Header.Get("Date"); val != "" { + date, err := time.Parse(time.RFC1123, val) + if err != nil { + return DirectoryClientDeleteResponse{}, err + } + result.Date = &date + } + return result, nil +} + +// ForceCloseHandles - Closes all handles open for given directory. +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2020-10-02 +// - handleID - Specifies handle ID opened on the file or directory to be closed. Asterisk (‘*’) is a wildcard that specifies +// all handles. +// - options - DirectoryClientForceCloseHandlesOptions contains the optional parameters for the DirectoryClient.ForceCloseHandles +// method. +func (client *DirectoryClient) ForceCloseHandles(ctx context.Context, handleID string, options *DirectoryClientForceCloseHandlesOptions) (DirectoryClientForceCloseHandlesResponse, error) { + req, err := client.forceCloseHandlesCreateRequest(ctx, handleID, options) + if err != nil { + return DirectoryClientForceCloseHandlesResponse{}, err + } + resp, err := client.pl.Do(req) + if err != nil { + return DirectoryClientForceCloseHandlesResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusOK) { + return DirectoryClientForceCloseHandlesResponse{}, runtime.NewResponseError(resp) + } + return client.forceCloseHandlesHandleResponse(resp) +} + +// forceCloseHandlesCreateRequest creates the ForceCloseHandles request. +func (client *DirectoryClient) forceCloseHandlesCreateRequest(ctx context.Context, handleID string, options *DirectoryClientForceCloseHandlesOptions) (*policy.Request, error) { + req, err := runtime.NewRequest(ctx, http.MethodPut, client.endpoint) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("comp", "forceclosehandles") + if options != nil && options.Timeout != nil { + reqQP.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + } + if options != nil && options.Marker != nil { + reqQP.Set("marker", *options.Marker) + } + if options != nil && options.Sharesnapshot != nil { + reqQP.Set("sharesnapshot", *options.Sharesnapshot) + } + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["x-ms-handle-id"] = []string{handleID} + if options != nil && options.Recursive != nil { + req.Raw().Header["x-ms-recursive"] = []string{strconv.FormatBool(*options.Recursive)} + } + req.Raw().Header["x-ms-version"] = []string{"2020-10-02"} + req.Raw().Header["Accept"] = []string{"application/xml"} + return req, nil +} + +// forceCloseHandlesHandleResponse handles the ForceCloseHandles response. +func (client *DirectoryClient) forceCloseHandlesHandleResponse(resp *http.Response) (DirectoryClientForceCloseHandlesResponse, error) { + result := DirectoryClientForceCloseHandlesResponse{} + if val := resp.Header.Get("x-ms-request-id"); val != "" { + result.RequestID = &val + } + if val := resp.Header.Get("x-ms-version"); val != "" { + result.Version = &val + } + if val := resp.Header.Get("Date"); val != "" { + date, err := time.Parse(time.RFC1123, val) + if err != nil { + return DirectoryClientForceCloseHandlesResponse{}, err + } + result.Date = &date + } + if val := resp.Header.Get("x-ms-marker"); val != "" { + result.Marker = &val + } + if val := resp.Header.Get("x-ms-number-of-handles-closed"); val != "" { + numberOfHandlesClosed32, err := strconv.ParseInt(val, 10, 32) + numberOfHandlesClosed := int32(numberOfHandlesClosed32) + if err != nil { + return DirectoryClientForceCloseHandlesResponse{}, err + } + result.NumberOfHandlesClosed = &numberOfHandlesClosed + } + if val := resp.Header.Get("x-ms-number-of-handles-failed"); val != "" { + numberOfHandlesFailedToClose32, err := strconv.ParseInt(val, 10, 32) + numberOfHandlesFailedToClose := int32(numberOfHandlesFailedToClose32) + if err != nil { + return DirectoryClientForceCloseHandlesResponse{}, err + } + result.NumberOfHandlesFailedToClose = &numberOfHandlesFailedToClose + } + return result, nil +} + +// GetProperties - Returns all system properties for the specified directory, and can also be used to check the existence +// of a directory. The data returned does not include the files in the directory or any +// subdirectories. +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2020-10-02 +// - options - DirectoryClientGetPropertiesOptions contains the optional parameters for the DirectoryClient.GetProperties method. +func (client *DirectoryClient) GetProperties(ctx context.Context, options *DirectoryClientGetPropertiesOptions) (DirectoryClientGetPropertiesResponse, error) { + req, err := client.getPropertiesCreateRequest(ctx, options) + if err != nil { + return DirectoryClientGetPropertiesResponse{}, err + } + resp, err := client.pl.Do(req) + if err != nil { + return DirectoryClientGetPropertiesResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusOK) { + return DirectoryClientGetPropertiesResponse{}, runtime.NewResponseError(resp) + } + return client.getPropertiesHandleResponse(resp) +} + +// getPropertiesCreateRequest creates the GetProperties request. +func (client *DirectoryClient) getPropertiesCreateRequest(ctx context.Context, options *DirectoryClientGetPropertiesOptions) (*policy.Request, error) { + req, err := runtime.NewRequest(ctx, http.MethodGet, client.endpoint) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("restype", "directory") + if options != nil && options.Sharesnapshot != nil { + reqQP.Set("sharesnapshot", *options.Sharesnapshot) + } + if options != nil && options.Timeout != nil { + reqQP.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + } + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["x-ms-version"] = []string{"2020-10-02"} + req.Raw().Header["Accept"] = []string{"application/xml"} + return req, nil +} + +// getPropertiesHandleResponse handles the GetProperties response. +func (client *DirectoryClient) getPropertiesHandleResponse(resp *http.Response) (DirectoryClientGetPropertiesResponse, error) { + result := DirectoryClientGetPropertiesResponse{} + for hh := range resp.Header { + if len(hh) > len("x-ms-meta-") && strings.EqualFold(hh[:len("x-ms-meta-")], "x-ms-meta-") { + if result.Metadata == nil { + result.Metadata = map[string]*string{} + } + result.Metadata[hh[len("x-ms-meta-"):]] = to.Ptr(resp.Header.Get(hh)) + } + } + if val := resp.Header.Get("ETag"); val != "" { + result.ETag = (*azcore.ETag)(&val) + } + if val := resp.Header.Get("Last-Modified"); val != "" { + lastModified, err := time.Parse(time.RFC1123, val) + if err != nil { + return DirectoryClientGetPropertiesResponse{}, err + } + result.LastModified = &lastModified + } + if val := resp.Header.Get("x-ms-request-id"); val != "" { + result.RequestID = &val + } + if val := resp.Header.Get("x-ms-version"); val != "" { + result.Version = &val + } + if val := resp.Header.Get("Date"); val != "" { + date, err := time.Parse(time.RFC1123, val) + if err != nil { + return DirectoryClientGetPropertiesResponse{}, err + } + result.Date = &date + } + if val := resp.Header.Get("x-ms-server-encrypted"); val != "" { + isServerEncrypted, err := strconv.ParseBool(val) + if err != nil { + return DirectoryClientGetPropertiesResponse{}, err + } + result.IsServerEncrypted = &isServerEncrypted + } + if val := resp.Header.Get("x-ms-file-attributes"); val != "" { + result.FileAttributes = &val + } + if val := resp.Header.Get("x-ms-file-creation-time"); val != "" { + fileCreationTime, err := time.Parse(ISO8601, val) + if err != nil { + return DirectoryClientGetPropertiesResponse{}, err + } + result.FileCreationTime = &fileCreationTime + } + if val := resp.Header.Get("x-ms-file-last-write-time"); val != "" { + fileLastWriteTime, err := time.Parse(ISO8601, val) + if err != nil { + return DirectoryClientGetPropertiesResponse{}, err + } + result.FileLastWriteTime = &fileLastWriteTime + } + if val := resp.Header.Get("x-ms-file-change-time"); val != "" { + fileChangeTime, err := time.Parse(ISO8601, val) + if err != nil { + return DirectoryClientGetPropertiesResponse{}, err + } + result.FileChangeTime = &fileChangeTime + } + if val := resp.Header.Get("x-ms-file-permission-key"); val != "" { + result.FilePermissionKey = &val + } + if val := resp.Header.Get("x-ms-file-id"); val != "" { + result.ID = &val + } + if val := resp.Header.Get("x-ms-file-parent-id"); val != "" { + result.ParentID = &val + } + return result, nil +} + +// NewListFilesAndDirectoriesSegmentPager - Returns a list of files or directories under the specified share or directory. +// It lists the contents only for a single level of the directory hierarchy. +// +// Generated from API version 2020-10-02 +// - options - DirectoryClientListFilesAndDirectoriesSegmentOptions contains the optional parameters for the DirectoryClient.NewListFilesAndDirectoriesSegmentPager +// method. +// +// listFilesAndDirectoriesSegmentCreateRequest creates the ListFilesAndDirectoriesSegment request. +func (client *DirectoryClient) ListFilesAndDirectoriesSegmentCreateRequest(ctx context.Context, options *DirectoryClientListFilesAndDirectoriesSegmentOptions) (*policy.Request, error) { + req, err := runtime.NewRequest(ctx, http.MethodGet, client.endpoint) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("restype", "directory") + reqQP.Set("comp", "list") + if options != nil && options.Prefix != nil { + reqQP.Set("prefix", *options.Prefix) + } + if options != nil && options.Sharesnapshot != nil { + reqQP.Set("sharesnapshot", *options.Sharesnapshot) + } + if options != nil && options.Marker != nil { + reqQP.Set("marker", *options.Marker) + } + if options != nil && options.Maxresults != nil { + reqQP.Set("maxresults", strconv.FormatInt(int64(*options.Maxresults), 10)) + } + if options != nil && options.Timeout != nil { + reqQP.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + } + if options != nil && options.Include != nil { + reqQP.Set("include", strings.Join(strings.Fields(strings.Trim(fmt.Sprint(options.Include), "[]")), ",")) + } + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["x-ms-version"] = []string{"2020-10-02"} + if options != nil && options.IncludeExtendedInfo != nil { + req.Raw().Header["x-ms-file-extended-info"] = []string{strconv.FormatBool(*options.IncludeExtendedInfo)} + } + req.Raw().Header["Accept"] = []string{"application/xml"} + return req, nil +} + +// listFilesAndDirectoriesSegmentHandleResponse handles the ListFilesAndDirectoriesSegment response. +func (client *DirectoryClient) ListFilesAndDirectoriesSegmentHandleResponse(resp *http.Response) (DirectoryClientListFilesAndDirectoriesSegmentResponse, error) { + result := DirectoryClientListFilesAndDirectoriesSegmentResponse{} + if val := resp.Header.Get("Content-Type"); val != "" { + result.ContentType = &val + } + if val := resp.Header.Get("x-ms-request-id"); val != "" { + result.RequestID = &val + } + if val := resp.Header.Get("x-ms-version"); val != "" { + result.Version = &val + } + if val := resp.Header.Get("Date"); val != "" { + date, err := time.Parse(time.RFC1123, val) + if err != nil { + return DirectoryClientListFilesAndDirectoriesSegmentResponse{}, err + } + result.Date = &date + } + if err := runtime.UnmarshalAsXML(resp, &result.ListFilesAndDirectoriesSegmentResponse); err != nil { + return DirectoryClientListFilesAndDirectoriesSegmentResponse{}, err + } + return result, nil +} + +// ListHandles - Lists handles for directory. +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2020-10-02 +// - options - DirectoryClientListHandlesOptions contains the optional parameters for the DirectoryClient.ListHandles method. +func (client *DirectoryClient) ListHandles(ctx context.Context, options *DirectoryClientListHandlesOptions) (DirectoryClientListHandlesResponse, error) { + req, err := client.listHandlesCreateRequest(ctx, options) + if err != nil { + return DirectoryClientListHandlesResponse{}, err + } + resp, err := client.pl.Do(req) + if err != nil { + return DirectoryClientListHandlesResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusOK) { + return DirectoryClientListHandlesResponse{}, runtime.NewResponseError(resp) + } + return client.listHandlesHandleResponse(resp) +} + +// listHandlesCreateRequest creates the ListHandles request. +func (client *DirectoryClient) listHandlesCreateRequest(ctx context.Context, options *DirectoryClientListHandlesOptions) (*policy.Request, error) { + req, err := runtime.NewRequest(ctx, http.MethodGet, client.endpoint) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("comp", "listhandles") + if options != nil && options.Marker != nil { + reqQP.Set("marker", *options.Marker) + } + if options != nil && options.Maxresults != nil { + reqQP.Set("maxresults", strconv.FormatInt(int64(*options.Maxresults), 10)) + } + if options != nil && options.Timeout != nil { + reqQP.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + } + if options != nil && options.Sharesnapshot != nil { + reqQP.Set("sharesnapshot", *options.Sharesnapshot) + } + req.Raw().URL.RawQuery = reqQP.Encode() + if options != nil && options.Recursive != nil { + req.Raw().Header["x-ms-recursive"] = []string{strconv.FormatBool(*options.Recursive)} + } + req.Raw().Header["x-ms-version"] = []string{"2020-10-02"} + req.Raw().Header["Accept"] = []string{"application/xml"} + return req, nil +} + +// listHandlesHandleResponse handles the ListHandles response. +func (client *DirectoryClient) listHandlesHandleResponse(resp *http.Response) (DirectoryClientListHandlesResponse, error) { + result := DirectoryClientListHandlesResponse{} + if val := resp.Header.Get("Content-Type"); val != "" { + result.ContentType = &val + } + if val := resp.Header.Get("x-ms-request-id"); val != "" { + result.RequestID = &val + } + if val := resp.Header.Get("x-ms-version"); val != "" { + result.Version = &val + } + if val := resp.Header.Get("Date"); val != "" { + date, err := time.Parse(time.RFC1123, val) + if err != nil { + return DirectoryClientListHandlesResponse{}, err + } + result.Date = &date + } + if err := runtime.UnmarshalAsXML(resp, &result.ListHandlesResponse); err != nil { + return DirectoryClientListHandlesResponse{}, err + } + return result, nil +} + +// SetMetadata - Updates user defined metadata for the specified directory. +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2020-10-02 +// - options - DirectoryClientSetMetadataOptions contains the optional parameters for the DirectoryClient.SetMetadata method. +func (client *DirectoryClient) SetMetadata(ctx context.Context, options *DirectoryClientSetMetadataOptions) (DirectoryClientSetMetadataResponse, error) { + req, err := client.setMetadataCreateRequest(ctx, options) + if err != nil { + return DirectoryClientSetMetadataResponse{}, err + } + resp, err := client.pl.Do(req) + if err != nil { + return DirectoryClientSetMetadataResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusOK) { + return DirectoryClientSetMetadataResponse{}, runtime.NewResponseError(resp) + } + return client.setMetadataHandleResponse(resp) +} + +// setMetadataCreateRequest creates the SetMetadata request. +func (client *DirectoryClient) setMetadataCreateRequest(ctx context.Context, options *DirectoryClientSetMetadataOptions) (*policy.Request, error) { + req, err := runtime.NewRequest(ctx, http.MethodPut, client.endpoint) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("restype", "directory") + reqQP.Set("comp", "metadata") + if options != nil && options.Timeout != nil { + reqQP.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + } + req.Raw().URL.RawQuery = reqQP.Encode() + if options != nil && options.Metadata != nil { + for k, v := range options.Metadata { + if v != nil { + req.Raw().Header["x-ms-meta-"+k] = []string{*v} + } + } + } + req.Raw().Header["x-ms-version"] = []string{"2020-10-02"} + req.Raw().Header["Accept"] = []string{"application/xml"} + return req, nil +} + +// setMetadataHandleResponse handles the SetMetadata response. +func (client *DirectoryClient) setMetadataHandleResponse(resp *http.Response) (DirectoryClientSetMetadataResponse, error) { + result := DirectoryClientSetMetadataResponse{} + if val := resp.Header.Get("ETag"); val != "" { + result.ETag = (*azcore.ETag)(&val) + } + if val := resp.Header.Get("x-ms-request-id"); val != "" { + result.RequestID = &val + } + if val := resp.Header.Get("x-ms-version"); val != "" { + result.Version = &val + } + if val := resp.Header.Get("Date"); val != "" { + date, err := time.Parse(time.RFC1123, val) + if err != nil { + return DirectoryClientSetMetadataResponse{}, err + } + result.Date = &date + } + if val := resp.Header.Get("x-ms-request-server-encrypted"); val != "" { + isServerEncrypted, err := strconv.ParseBool(val) + if err != nil { + return DirectoryClientSetMetadataResponse{}, err + } + result.IsServerEncrypted = &isServerEncrypted + } + return result, nil +} + +// SetProperties - Sets properties on the directory. +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2020-10-02 +// - fileAttributes - If specified, the provided file attributes shall be set. Default value: ‘Archive’ for file and ‘Directory’ +// for directory. ‘None’ can also be specified as default. +// - fileCreationTime - Creation time for the file/directory. Default value: Now. +// - fileLastWriteTime - Last write time for the file/directory. Default value: Now. +// - options - DirectoryClientSetPropertiesOptions contains the optional parameters for the DirectoryClient.SetProperties method. +func (client *DirectoryClient) SetProperties(ctx context.Context, fileAttributes string, fileCreationTime string, fileLastWriteTime string, options *DirectoryClientSetPropertiesOptions) (DirectoryClientSetPropertiesResponse, error) { + req, err := client.setPropertiesCreateRequest(ctx, fileAttributes, fileCreationTime, fileLastWriteTime, options) + if err != nil { + return DirectoryClientSetPropertiesResponse{}, err + } + resp, err := client.pl.Do(req) + if err != nil { + return DirectoryClientSetPropertiesResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusOK) { + return DirectoryClientSetPropertiesResponse{}, runtime.NewResponseError(resp) + } + return client.setPropertiesHandleResponse(resp) +} + +// setPropertiesCreateRequest creates the SetProperties request. +func (client *DirectoryClient) setPropertiesCreateRequest(ctx context.Context, fileAttributes string, fileCreationTime string, fileLastWriteTime string, options *DirectoryClientSetPropertiesOptions) (*policy.Request, error) { + req, err := runtime.NewRequest(ctx, http.MethodPut, client.endpoint) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("restype", "directory") + reqQP.Set("comp", "properties") + if options != nil && options.Timeout != nil { + reqQP.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + } + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["x-ms-version"] = []string{"2020-10-02"} + if options != nil && options.FilePermission != nil { + req.Raw().Header["x-ms-file-permission"] = []string{*options.FilePermission} + } + if options != nil && options.FilePermissionKey != nil { + req.Raw().Header["x-ms-file-permission-key"] = []string{*options.FilePermissionKey} + } + req.Raw().Header["x-ms-file-attributes"] = []string{fileAttributes} + req.Raw().Header["x-ms-file-creation-time"] = []string{fileCreationTime} + req.Raw().Header["x-ms-file-last-write-time"] = []string{fileLastWriteTime} + req.Raw().Header["Accept"] = []string{"application/xml"} + return req, nil +} + +// setPropertiesHandleResponse handles the SetProperties response. +func (client *DirectoryClient) setPropertiesHandleResponse(resp *http.Response) (DirectoryClientSetPropertiesResponse, error) { + result := DirectoryClientSetPropertiesResponse{} + if val := resp.Header.Get("ETag"); val != "" { + result.ETag = (*azcore.ETag)(&val) + } + if val := resp.Header.Get("x-ms-request-id"); val != "" { + result.RequestID = &val + } + if val := resp.Header.Get("Last-Modified"); val != "" { + lastModified, err := time.Parse(time.RFC1123, val) + if err != nil { + return DirectoryClientSetPropertiesResponse{}, err + } + result.LastModified = &lastModified + } + if val := resp.Header.Get("x-ms-version"); val != "" { + result.Version = &val + } + if val := resp.Header.Get("Date"); val != "" { + date, err := time.Parse(time.RFC1123, val) + if err != nil { + return DirectoryClientSetPropertiesResponse{}, err + } + result.Date = &date + } + if val := resp.Header.Get("x-ms-request-server-encrypted"); val != "" { + isServerEncrypted, err := strconv.ParseBool(val) + if err != nil { + return DirectoryClientSetPropertiesResponse{}, err + } + result.IsServerEncrypted = &isServerEncrypted + } + if val := resp.Header.Get("x-ms-file-permission-key"); val != "" { + result.FilePermissionKey = &val + } + if val := resp.Header.Get("x-ms-file-attributes"); val != "" { + result.FileAttributes = &val + } + if val := resp.Header.Get("x-ms-file-creation-time"); val != "" { + fileCreationTime, err := time.Parse(ISO8601, val) + if err != nil { + return DirectoryClientSetPropertiesResponse{}, err + } + result.FileCreationTime = &fileCreationTime + } + if val := resp.Header.Get("x-ms-file-last-write-time"); val != "" { + fileLastWriteTime, err := time.Parse(ISO8601, val) + if err != nil { + return DirectoryClientSetPropertiesResponse{}, err + } + result.FileLastWriteTime = &fileLastWriteTime + } + if val := resp.Header.Get("x-ms-file-change-time"); val != "" { + fileChangeTime, err := time.Parse(ISO8601, val) + if err != nil { + return DirectoryClientSetPropertiesResponse{}, err + } + result.FileChangeTime = &fileChangeTime + } + if val := resp.Header.Get("x-ms-file-id"); val != "" { + result.ID = &val + } + if val := resp.Header.Get("x-ms-file-parent-id"); val != "" { + result.ParentID = &val + } + return result, nil +} diff --git a/sdk/storage/azfile/internal/generated/zz_file_client.go b/sdk/storage/azfile/internal/generated/zz_file_client.go new file mode 100644 index 000000000000..cfe2ea780a3b --- /dev/null +++ b/sdk/storage/azfile/internal/generated/zz_file_client.go @@ -0,0 +1,1826 @@ +//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. +// Code generated by Microsoft (R) AutoRest Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. +// DO NOT EDIT. + +package generated + +import ( + "context" + "encoding/base64" + "github.com/Azure/azure-sdk-for-go/sdk/azcore" + "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/azcore/to" + "io" + "net/http" + "strconv" + "strings" + "time" +) + +// FileClient contains the methods for the File group. +// Don't use this type directly, use NewFileClient() instead. +type FileClient struct { + endpoint string + pl runtime.Pipeline +} + +// NewFileClient creates a new instance of FileClient with the specified values. +// - endpoint - The URL of the service account, share, directory or file that is the target of the desired operation. +// - pl - the pipeline used for sending requests and handling responses. +func NewFileClient(endpoint string, pl runtime.Pipeline) *FileClient { + client := &FileClient{ + endpoint: endpoint, + pl: pl, + } + return client +} + +// AbortCopy - Aborts a pending Copy File operation, and leaves a destination file with zero length and full metadata. +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2020-10-02 +// - copyID - The copy identifier provided in the x-ms-copy-id header of the original Copy File operation. +// - options - FileClientAbortCopyOptions contains the optional parameters for the FileClient.AbortCopy method. +// - LeaseAccessConditions - LeaseAccessConditions contains a group of parameters for the ShareClient.GetProperties method. +func (client *FileClient) AbortCopy(ctx context.Context, copyID string, options *FileClientAbortCopyOptions, leaseAccessConditions *LeaseAccessConditions) (FileClientAbortCopyResponse, error) { + req, err := client.abortCopyCreateRequest(ctx, copyID, options, leaseAccessConditions) + if err != nil { + return FileClientAbortCopyResponse{}, err + } + resp, err := client.pl.Do(req) + if err != nil { + return FileClientAbortCopyResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusNoContent) { + return FileClientAbortCopyResponse{}, runtime.NewResponseError(resp) + } + return client.abortCopyHandleResponse(resp) +} + +// abortCopyCreateRequest creates the AbortCopy request. +func (client *FileClient) abortCopyCreateRequest(ctx context.Context, copyID string, options *FileClientAbortCopyOptions, leaseAccessConditions *LeaseAccessConditions) (*policy.Request, error) { + req, err := runtime.NewRequest(ctx, http.MethodPut, client.endpoint) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("comp", "copy") + reqQP.Set("copyid", copyID) + if options != nil && options.Timeout != nil { + reqQP.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + } + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["x-ms-copy-action"] = []string{"abort"} + req.Raw().Header["x-ms-version"] = []string{"2020-10-02"} + if leaseAccessConditions != nil && leaseAccessConditions.LeaseID != nil { + req.Raw().Header["x-ms-lease-id"] = []string{*leaseAccessConditions.LeaseID} + } + req.Raw().Header["Accept"] = []string{"application/xml"} + return req, nil +} + +// abortCopyHandleResponse handles the AbortCopy response. +func (client *FileClient) abortCopyHandleResponse(resp *http.Response) (FileClientAbortCopyResponse, error) { + result := FileClientAbortCopyResponse{} + if val := resp.Header.Get("x-ms-request-id"); val != "" { + result.RequestID = &val + } + if val := resp.Header.Get("x-ms-version"); val != "" { + result.Version = &val + } + if val := resp.Header.Get("Date"); val != "" { + date, err := time.Parse(time.RFC1123, val) + if err != nil { + return FileClientAbortCopyResponse{}, err + } + result.Date = &date + } + return result, nil +} + +// AcquireLease - [Update] The Lease File operation establishes and manages a lock on a file for write and delete operations +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2020-10-02 +// - duration - 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. A lease duration cannot be changed using +// renew or change. +// - options - FileClientAcquireLeaseOptions contains the optional parameters for the FileClient.AcquireLease method. +func (client *FileClient) AcquireLease(ctx context.Context, duration int32, options *FileClientAcquireLeaseOptions) (FileClientAcquireLeaseResponse, error) { + req, err := client.acquireLeaseCreateRequest(ctx, duration, options) + if err != nil { + return FileClientAcquireLeaseResponse{}, err + } + resp, err := client.pl.Do(req) + if err != nil { + return FileClientAcquireLeaseResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusCreated) { + return FileClientAcquireLeaseResponse{}, runtime.NewResponseError(resp) + } + return client.acquireLeaseHandleResponse(resp) +} + +// acquireLeaseCreateRequest creates the AcquireLease request. +func (client *FileClient) acquireLeaseCreateRequest(ctx context.Context, duration int32, options *FileClientAcquireLeaseOptions) (*policy.Request, error) { + req, err := runtime.NewRequest(ctx, http.MethodPut, client.endpoint) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("comp", "lease") + if options != nil && options.Timeout != nil { + reqQP.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + } + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["x-ms-lease-action"] = []string{"acquire"} + req.Raw().Header["x-ms-lease-duration"] = []string{strconv.FormatInt(int64(duration), 10)} + if options != nil && options.ProposedLeaseID != nil { + req.Raw().Header["x-ms-proposed-lease-id"] = []string{*options.ProposedLeaseID} + } + req.Raw().Header["x-ms-version"] = []string{"2020-10-02"} + if options != nil && options.RequestID != nil { + req.Raw().Header["x-ms-client-request-id"] = []string{*options.RequestID} + } + req.Raw().Header["Accept"] = []string{"application/xml"} + return req, nil +} + +// acquireLeaseHandleResponse handles the AcquireLease response. +func (client *FileClient) acquireLeaseHandleResponse(resp *http.Response) (FileClientAcquireLeaseResponse, error) { + result := FileClientAcquireLeaseResponse{} + if val := resp.Header.Get("ETag"); val != "" { + result.ETag = (*azcore.ETag)(&val) + } + if val := resp.Header.Get("Last-Modified"); val != "" { + lastModified, err := time.Parse(time.RFC1123, val) + if err != nil { + return FileClientAcquireLeaseResponse{}, err + } + result.LastModified = &lastModified + } + if val := resp.Header.Get("x-ms-lease-id"); val != "" { + result.LeaseID = &val + } + if val := resp.Header.Get("x-ms-client-request-id"); val != "" { + result.ClientRequestID = &val + } + if val := resp.Header.Get("x-ms-request-id"); val != "" { + result.RequestID = &val + } + if val := resp.Header.Get("x-ms-version"); val != "" { + result.Version = &val + } + if val := resp.Header.Get("Date"); val != "" { + date, err := time.Parse(time.RFC1123, val) + if err != nil { + return FileClientAcquireLeaseResponse{}, err + } + result.Date = &date + } + return result, nil +} + +// BreakLease - [Update] The Lease File operation establishes and manages a lock on a file for write and delete operations +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2020-10-02 +// - options - FileClientBreakLeaseOptions contains the optional parameters for the FileClient.BreakLease method. +// - LeaseAccessConditions - LeaseAccessConditions contains a group of parameters for the ShareClient.GetProperties method. +func (client *FileClient) BreakLease(ctx context.Context, options *FileClientBreakLeaseOptions, leaseAccessConditions *LeaseAccessConditions) (FileClientBreakLeaseResponse, error) { + req, err := client.breakLeaseCreateRequest(ctx, options, leaseAccessConditions) + if err != nil { + return FileClientBreakLeaseResponse{}, err + } + resp, err := client.pl.Do(req) + if err != nil { + return FileClientBreakLeaseResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusAccepted) { + return FileClientBreakLeaseResponse{}, runtime.NewResponseError(resp) + } + return client.breakLeaseHandleResponse(resp) +} + +// breakLeaseCreateRequest creates the BreakLease request. +func (client *FileClient) breakLeaseCreateRequest(ctx context.Context, options *FileClientBreakLeaseOptions, leaseAccessConditions *LeaseAccessConditions) (*policy.Request, error) { + req, err := runtime.NewRequest(ctx, http.MethodPut, client.endpoint) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("comp", "lease") + if options != nil && options.Timeout != nil { + reqQP.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + } + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["x-ms-lease-action"] = []string{"break"} + if leaseAccessConditions != nil && leaseAccessConditions.LeaseID != nil { + req.Raw().Header["x-ms-lease-id"] = []string{*leaseAccessConditions.LeaseID} + } + req.Raw().Header["x-ms-version"] = []string{"2020-10-02"} + if options != nil && options.RequestID != nil { + req.Raw().Header["x-ms-client-request-id"] = []string{*options.RequestID} + } + req.Raw().Header["Accept"] = []string{"application/xml"} + return req, nil +} + +// breakLeaseHandleResponse handles the BreakLease response. +func (client *FileClient) breakLeaseHandleResponse(resp *http.Response) (FileClientBreakLeaseResponse, error) { + result := FileClientBreakLeaseResponse{} + if val := resp.Header.Get("ETag"); val != "" { + result.ETag = (*azcore.ETag)(&val) + } + if val := resp.Header.Get("Last-Modified"); val != "" { + lastModified, err := time.Parse(time.RFC1123, val) + if err != nil { + return FileClientBreakLeaseResponse{}, err + } + result.LastModified = &lastModified + } + if val := resp.Header.Get("x-ms-lease-id"); val != "" { + result.LeaseID = &val + } + if val := resp.Header.Get("x-ms-client-request-id"); val != "" { + result.ClientRequestID = &val + } + if val := resp.Header.Get("x-ms-request-id"); val != "" { + result.RequestID = &val + } + if val := resp.Header.Get("x-ms-version"); val != "" { + result.Version = &val + } + if val := resp.Header.Get("Date"); val != "" { + date, err := time.Parse(time.RFC1123, val) + if err != nil { + return FileClientBreakLeaseResponse{}, err + } + result.Date = &date + } + return result, nil +} + +// ChangeLease - [Update] The Lease File operation establishes and manages a lock on a file for write and delete operations +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2020-10-02 +// - leaseID - Specifies the current lease ID on the resource. +// - options - FileClientChangeLeaseOptions contains the optional parameters for the FileClient.ChangeLease method. +func (client *FileClient) ChangeLease(ctx context.Context, leaseID string, options *FileClientChangeLeaseOptions) (FileClientChangeLeaseResponse, error) { + req, err := client.changeLeaseCreateRequest(ctx, leaseID, options) + if err != nil { + return FileClientChangeLeaseResponse{}, err + } + resp, err := client.pl.Do(req) + if err != nil { + return FileClientChangeLeaseResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusOK) { + return FileClientChangeLeaseResponse{}, runtime.NewResponseError(resp) + } + return client.changeLeaseHandleResponse(resp) +} + +// changeLeaseCreateRequest creates the ChangeLease request. +func (client *FileClient) changeLeaseCreateRequest(ctx context.Context, leaseID string, options *FileClientChangeLeaseOptions) (*policy.Request, error) { + req, err := runtime.NewRequest(ctx, http.MethodPut, client.endpoint) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("comp", "lease") + if options != nil && options.Timeout != nil { + reqQP.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + } + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["x-ms-lease-action"] = []string{"change"} + req.Raw().Header["x-ms-lease-id"] = []string{leaseID} + if options != nil && options.ProposedLeaseID != nil { + req.Raw().Header["x-ms-proposed-lease-id"] = []string{*options.ProposedLeaseID} + } + req.Raw().Header["x-ms-version"] = []string{"2020-10-02"} + if options != nil && options.RequestID != nil { + req.Raw().Header["x-ms-client-request-id"] = []string{*options.RequestID} + } + req.Raw().Header["Accept"] = []string{"application/xml"} + return req, nil +} + +// changeLeaseHandleResponse handles the ChangeLease response. +func (client *FileClient) changeLeaseHandleResponse(resp *http.Response) (FileClientChangeLeaseResponse, error) { + result := FileClientChangeLeaseResponse{} + if val := resp.Header.Get("ETag"); val != "" { + result.ETag = (*azcore.ETag)(&val) + } + if val := resp.Header.Get("Last-Modified"); val != "" { + lastModified, err := time.Parse(time.RFC1123, val) + if err != nil { + return FileClientChangeLeaseResponse{}, err + } + result.LastModified = &lastModified + } + if val := resp.Header.Get("x-ms-lease-id"); val != "" { + result.LeaseID = &val + } + if val := resp.Header.Get("x-ms-client-request-id"); val != "" { + result.ClientRequestID = &val + } + if val := resp.Header.Get("x-ms-request-id"); val != "" { + result.RequestID = &val + } + if val := resp.Header.Get("x-ms-version"); val != "" { + result.Version = &val + } + if val := resp.Header.Get("Date"); val != "" { + date, err := time.Parse(time.RFC1123, val) + if err != nil { + return FileClientChangeLeaseResponse{}, err + } + result.Date = &date + } + return result, nil +} + +// Create - Creates a new file or replaces a file. Note it only initializes the file with no content. +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2020-10-02 +// - fileContentLength - Specifies the maximum size for the file, up to 4 TB. +// - fileAttributes - If specified, the provided file attributes shall be set. Default value: ‘Archive’ for file and ‘Directory’ +// for directory. ‘None’ can also be specified as default. +// - fileCreationTime - Creation time for the file/directory. Default value: Now. +// - fileLastWriteTime - Last write time for the file/directory. Default value: Now. +// - options - FileClientCreateOptions contains the optional parameters for the FileClient.Create method. +// - ShareFileHTTPHeaders - ShareFileHTTPHeaders contains a group of parameters for the FileClient.Create method. +// - LeaseAccessConditions - LeaseAccessConditions contains a group of parameters for the ShareClient.GetProperties method. +func (client *FileClient) Create(ctx context.Context, fileContentLength int64, fileAttributes string, fileCreationTime string, fileLastWriteTime string, options *FileClientCreateOptions, shareFileHTTPHeaders *ShareFileHTTPHeaders, leaseAccessConditions *LeaseAccessConditions) (FileClientCreateResponse, error) { + req, err := client.createCreateRequest(ctx, fileContentLength, fileAttributes, fileCreationTime, fileLastWriteTime, options, shareFileHTTPHeaders, leaseAccessConditions) + if err != nil { + return FileClientCreateResponse{}, err + } + resp, err := client.pl.Do(req) + if err != nil { + return FileClientCreateResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusCreated) { + return FileClientCreateResponse{}, runtime.NewResponseError(resp) + } + return client.createHandleResponse(resp) +} + +// createCreateRequest creates the Create request. +func (client *FileClient) createCreateRequest(ctx context.Context, fileContentLength int64, fileAttributes string, fileCreationTime string, fileLastWriteTime string, options *FileClientCreateOptions, shareFileHTTPHeaders *ShareFileHTTPHeaders, leaseAccessConditions *LeaseAccessConditions) (*policy.Request, error) { + req, err := runtime.NewRequest(ctx, http.MethodPut, client.endpoint) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + if options != nil && options.Timeout != nil { + reqQP.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + } + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["x-ms-version"] = []string{"2020-10-02"} + req.Raw().Header["x-ms-content-length"] = []string{strconv.FormatInt(fileContentLength, 10)} + req.Raw().Header["x-ms-type"] = []string{"file"} + if shareFileHTTPHeaders != nil && shareFileHTTPHeaders.ContentType != nil { + req.Raw().Header["x-ms-content-type"] = []string{*shareFileHTTPHeaders.ContentType} + } + if shareFileHTTPHeaders != nil && shareFileHTTPHeaders.ContentEncoding != nil { + req.Raw().Header["x-ms-content-encoding"] = []string{*shareFileHTTPHeaders.ContentEncoding} + } + if shareFileHTTPHeaders != nil && shareFileHTTPHeaders.ContentLanguage != nil { + req.Raw().Header["x-ms-content-language"] = []string{*shareFileHTTPHeaders.ContentLanguage} + } + if shareFileHTTPHeaders != nil && shareFileHTTPHeaders.CacheControl != nil { + req.Raw().Header["x-ms-cache-control"] = []string{*shareFileHTTPHeaders.CacheControl} + } + if shareFileHTTPHeaders != nil && shareFileHTTPHeaders.ContentMD5 != nil { + req.Raw().Header["x-ms-content-md5"] = []string{base64.StdEncoding.EncodeToString(shareFileHTTPHeaders.ContentMD5)} + } + if shareFileHTTPHeaders != nil && shareFileHTTPHeaders.ContentDisposition != nil { + req.Raw().Header["x-ms-content-disposition"] = []string{*shareFileHTTPHeaders.ContentDisposition} + } + if options != nil && options.Metadata != nil { + for k, v := range options.Metadata { + if v != nil { + req.Raw().Header["x-ms-meta-"+k] = []string{*v} + } + } + } + if options != nil && options.FilePermission != nil { + req.Raw().Header["x-ms-file-permission"] = []string{*options.FilePermission} + } + if options != nil && options.FilePermissionKey != nil { + req.Raw().Header["x-ms-file-permission-key"] = []string{*options.FilePermissionKey} + } + req.Raw().Header["x-ms-file-attributes"] = []string{fileAttributes} + req.Raw().Header["x-ms-file-creation-time"] = []string{fileCreationTime} + req.Raw().Header["x-ms-file-last-write-time"] = []string{fileLastWriteTime} + if leaseAccessConditions != nil && leaseAccessConditions.LeaseID != nil { + req.Raw().Header["x-ms-lease-id"] = []string{*leaseAccessConditions.LeaseID} + } + req.Raw().Header["Accept"] = []string{"application/xml"} + return req, nil +} + +// createHandleResponse handles the Create response. +func (client *FileClient) createHandleResponse(resp *http.Response) (FileClientCreateResponse, error) { + result := FileClientCreateResponse{} + if val := resp.Header.Get("ETag"); val != "" { + result.ETag = (*azcore.ETag)(&val) + } + if val := resp.Header.Get("Last-Modified"); val != "" { + lastModified, err := time.Parse(time.RFC1123, val) + if err != nil { + return FileClientCreateResponse{}, err + } + result.LastModified = &lastModified + } + if val := resp.Header.Get("x-ms-request-id"); val != "" { + result.RequestID = &val + } + if val := resp.Header.Get("x-ms-version"); val != "" { + result.Version = &val + } + if val := resp.Header.Get("Date"); val != "" { + date, err := time.Parse(time.RFC1123, val) + if err != nil { + return FileClientCreateResponse{}, err + } + result.Date = &date + } + if val := resp.Header.Get("x-ms-request-server-encrypted"); val != "" { + isServerEncrypted, err := strconv.ParseBool(val) + if err != nil { + return FileClientCreateResponse{}, err + } + result.IsServerEncrypted = &isServerEncrypted + } + if val := resp.Header.Get("x-ms-file-permission-key"); val != "" { + result.FilePermissionKey = &val + } + if val := resp.Header.Get("x-ms-file-attributes"); val != "" { + result.FileAttributes = &val + } + if val := resp.Header.Get("x-ms-file-creation-time"); val != "" { + fileCreationTime, err := time.Parse(ISO8601, val) + if err != nil { + return FileClientCreateResponse{}, err + } + result.FileCreationTime = &fileCreationTime + } + if val := resp.Header.Get("x-ms-file-last-write-time"); val != "" { + fileLastWriteTime, err := time.Parse(ISO8601, val) + if err != nil { + return FileClientCreateResponse{}, err + } + result.FileLastWriteTime = &fileLastWriteTime + } + if val := resp.Header.Get("x-ms-file-change-time"); val != "" { + fileChangeTime, err := time.Parse(ISO8601, val) + if err != nil { + return FileClientCreateResponse{}, err + } + result.FileChangeTime = &fileChangeTime + } + if val := resp.Header.Get("x-ms-file-id"); val != "" { + result.ID = &val + } + if val := resp.Header.Get("x-ms-file-parent-id"); val != "" { + result.ParentID = &val + } + return result, nil +} + +// Delete - removes the file from the storage account. +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2020-10-02 +// - options - FileClientDeleteOptions contains the optional parameters for the FileClient.Delete method. +// - LeaseAccessConditions - LeaseAccessConditions contains a group of parameters for the ShareClient.GetProperties method. +func (client *FileClient) Delete(ctx context.Context, options *FileClientDeleteOptions, leaseAccessConditions *LeaseAccessConditions) (FileClientDeleteResponse, error) { + req, err := client.deleteCreateRequest(ctx, options, leaseAccessConditions) + if err != nil { + return FileClientDeleteResponse{}, err + } + resp, err := client.pl.Do(req) + if err != nil { + return FileClientDeleteResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusAccepted) { + return FileClientDeleteResponse{}, runtime.NewResponseError(resp) + } + return client.deleteHandleResponse(resp) +} + +// deleteCreateRequest creates the Delete request. +func (client *FileClient) deleteCreateRequest(ctx context.Context, options *FileClientDeleteOptions, leaseAccessConditions *LeaseAccessConditions) (*policy.Request, error) { + req, err := runtime.NewRequest(ctx, http.MethodDelete, client.endpoint) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + if options != nil && options.Timeout != nil { + reqQP.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + } + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["x-ms-version"] = []string{"2020-10-02"} + if leaseAccessConditions != nil && leaseAccessConditions.LeaseID != nil { + req.Raw().Header["x-ms-lease-id"] = []string{*leaseAccessConditions.LeaseID} + } + req.Raw().Header["Accept"] = []string{"application/xml"} + return req, nil +} + +// deleteHandleResponse handles the Delete response. +func (client *FileClient) deleteHandleResponse(resp *http.Response) (FileClientDeleteResponse, error) { + result := FileClientDeleteResponse{} + if val := resp.Header.Get("x-ms-request-id"); val != "" { + result.RequestID = &val + } + if val := resp.Header.Get("x-ms-version"); val != "" { + result.Version = &val + } + if val := resp.Header.Get("Date"); val != "" { + date, err := time.Parse(time.RFC1123, val) + if err != nil { + return FileClientDeleteResponse{}, err + } + result.Date = &date + } + return result, nil +} + +// Download - Reads or downloads a file from the system, including its metadata and properties. +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2020-10-02 +// - options - FileClientDownloadOptions contains the optional parameters for the FileClient.Download method. +// - LeaseAccessConditions - LeaseAccessConditions contains a group of parameters for the ShareClient.GetProperties method. +func (client *FileClient) Download(ctx context.Context, options *FileClientDownloadOptions, leaseAccessConditions *LeaseAccessConditions) (FileClientDownloadResponse, error) { + req, err := client.downloadCreateRequest(ctx, options, leaseAccessConditions) + if err != nil { + return FileClientDownloadResponse{}, err + } + resp, err := client.pl.Do(req) + if err != nil { + return FileClientDownloadResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusOK, http.StatusPartialContent) { + return FileClientDownloadResponse{}, runtime.NewResponseError(resp) + } + return client.downloadHandleResponse(resp) +} + +// downloadCreateRequest creates the Download request. +func (client *FileClient) downloadCreateRequest(ctx context.Context, options *FileClientDownloadOptions, leaseAccessConditions *LeaseAccessConditions) (*policy.Request, error) { + req, err := runtime.NewRequest(ctx, http.MethodGet, client.endpoint) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + if options != nil && options.Timeout != nil { + reqQP.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + } + req.Raw().URL.RawQuery = reqQP.Encode() + runtime.SkipBodyDownload(req) + req.Raw().Header["x-ms-version"] = []string{"2020-10-02"} + if options != nil && options.Range != nil { + req.Raw().Header["x-ms-range"] = []string{*options.Range} + } + if options != nil && options.RangeGetContentMD5 != nil { + req.Raw().Header["x-ms-range-get-content-md5"] = []string{strconv.FormatBool(*options.RangeGetContentMD5)} + } + if leaseAccessConditions != nil && leaseAccessConditions.LeaseID != nil { + req.Raw().Header["x-ms-lease-id"] = []string{*leaseAccessConditions.LeaseID} + } + req.Raw().Header["Accept"] = []string{"application/xml"} + return req, nil +} + +// downloadHandleResponse handles the Download response. +func (client *FileClient) downloadHandleResponse(resp *http.Response) (FileClientDownloadResponse, error) { + result := FileClientDownloadResponse{Body: resp.Body} + if val := resp.Header.Get("Last-Modified"); val != "" { + lastModified, err := time.Parse(time.RFC1123, val) + if err != nil { + return FileClientDownloadResponse{}, err + } + result.LastModified = &lastModified + } + for hh := range resp.Header { + if len(hh) > len("x-ms-meta-") && strings.EqualFold(hh[:len("x-ms-meta-")], "x-ms-meta-") { + if result.Metadata == nil { + result.Metadata = map[string]*string{} + } + result.Metadata[hh[len("x-ms-meta-"):]] = to.Ptr(resp.Header.Get(hh)) + } + } + if val := resp.Header.Get("Content-Length"); val != "" { + contentLength, err := strconv.ParseInt(val, 10, 64) + if err != nil { + return FileClientDownloadResponse{}, err + } + result.ContentLength = &contentLength + } + if val := resp.Header.Get("Content-Type"); val != "" { + result.ContentType = &val + } + if val := resp.Header.Get("Content-Range"); val != "" { + result.ContentRange = &val + } + if val := resp.Header.Get("ETag"); val != "" { + result.ETag = (*azcore.ETag)(&val) + } + if val := resp.Header.Get("Content-MD5"); val != "" { + contentMD5, err := base64.StdEncoding.DecodeString(val) + if err != nil { + return FileClientDownloadResponse{}, err + } + result.ContentMD5 = contentMD5 + } + if val := resp.Header.Get("Content-Encoding"); val != "" { + result.ContentEncoding = &val + } + if val := resp.Header.Get("Cache-Control"); val != "" { + result.CacheControl = &val + } + if val := resp.Header.Get("Content-Disposition"); val != "" { + result.ContentDisposition = &val + } + if val := resp.Header.Get("Content-Language"); val != "" { + result.ContentLanguage = &val + } + if val := resp.Header.Get("x-ms-request-id"); val != "" { + result.RequestID = &val + } + if val := resp.Header.Get("x-ms-version"); val != "" { + result.Version = &val + } + if val := resp.Header.Get("Accept-Ranges"); val != "" { + result.AcceptRanges = &val + } + if val := resp.Header.Get("Date"); val != "" { + date, err := time.Parse(time.RFC1123, val) + if err != nil { + return FileClientDownloadResponse{}, err + } + result.Date = &date + } + if val := resp.Header.Get("x-ms-copy-completion-time"); val != "" { + copyCompletionTime, err := time.Parse(time.RFC1123, val) + if err != nil { + return FileClientDownloadResponse{}, err + } + result.CopyCompletionTime = ©CompletionTime + } + if val := resp.Header.Get("x-ms-copy-status-description"); val != "" { + result.CopyStatusDescription = &val + } + if val := resp.Header.Get("x-ms-copy-id"); val != "" { + result.CopyID = &val + } + if val := resp.Header.Get("x-ms-copy-progress"); val != "" { + result.CopyProgress = &val + } + if val := resp.Header.Get("x-ms-copy-source"); val != "" { + result.CopySource = &val + } + if val := resp.Header.Get("x-ms-copy-status"); val != "" { + result.CopyStatus = (*CopyStatusType)(&val) + } + if val := resp.Header.Get("x-ms-content-md5"); val != "" { + fileContentMD5, err := base64.StdEncoding.DecodeString(val) + if err != nil { + return FileClientDownloadResponse{}, err + } + result.FileContentMD5 = fileContentMD5 + } + if val := resp.Header.Get("x-ms-server-encrypted"); val != "" { + isServerEncrypted, err := strconv.ParseBool(val) + if err != nil { + return FileClientDownloadResponse{}, err + } + result.IsServerEncrypted = &isServerEncrypted + } + if val := resp.Header.Get("x-ms-file-attributes"); val != "" { + result.FileAttributes = &val + } + if val := resp.Header.Get("x-ms-file-creation-time"); val != "" { + fileCreationTime, err := time.Parse(ISO8601, val) + if err != nil { + return FileClientDownloadResponse{}, err + } + result.FileCreationTime = &fileCreationTime + } + if val := resp.Header.Get("x-ms-file-last-write-time"); val != "" { + fileLastWriteTime, err := time.Parse(ISO8601, val) + if err != nil { + return FileClientDownloadResponse{}, err + } + result.FileLastWriteTime = &fileLastWriteTime + } + if val := resp.Header.Get("x-ms-file-change-time"); val != "" { + fileChangeTime, err := time.Parse(ISO8601, val) + if err != nil { + return FileClientDownloadResponse{}, err + } + result.FileChangeTime = &fileChangeTime + } + if val := resp.Header.Get("x-ms-file-permission-key"); val != "" { + result.FilePermissionKey = &val + } + if val := resp.Header.Get("x-ms-file-id"); val != "" { + result.ID = &val + } + if val := resp.Header.Get("x-ms-file-parent-id"); val != "" { + result.ParentID = &val + } + if val := resp.Header.Get("x-ms-lease-duration"); val != "" { + result.LeaseDuration = (*LeaseDurationType)(&val) + } + if val := resp.Header.Get("x-ms-lease-state"); val != "" { + result.LeaseState = (*LeaseStateType)(&val) + } + if val := resp.Header.Get("x-ms-lease-status"); val != "" { + result.LeaseStatus = (*LeaseStatusType)(&val) + } + return result, nil +} + +// ForceCloseHandles - Closes all handles open for given file +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2020-10-02 +// - handleID - Specifies handle ID opened on the file or directory to be closed. Asterisk (‘*’) is a wildcard that specifies +// all handles. +// - options - FileClientForceCloseHandlesOptions contains the optional parameters for the FileClient.ForceCloseHandles method. +func (client *FileClient) ForceCloseHandles(ctx context.Context, handleID string, options *FileClientForceCloseHandlesOptions) (FileClientForceCloseHandlesResponse, error) { + req, err := client.forceCloseHandlesCreateRequest(ctx, handleID, options) + if err != nil { + return FileClientForceCloseHandlesResponse{}, err + } + resp, err := client.pl.Do(req) + if err != nil { + return FileClientForceCloseHandlesResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusOK) { + return FileClientForceCloseHandlesResponse{}, runtime.NewResponseError(resp) + } + return client.forceCloseHandlesHandleResponse(resp) +} + +// forceCloseHandlesCreateRequest creates the ForceCloseHandles request. +func (client *FileClient) forceCloseHandlesCreateRequest(ctx context.Context, handleID string, options *FileClientForceCloseHandlesOptions) (*policy.Request, error) { + req, err := runtime.NewRequest(ctx, http.MethodPut, client.endpoint) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("comp", "forceclosehandles") + if options != nil && options.Timeout != nil { + reqQP.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + } + if options != nil && options.Marker != nil { + reqQP.Set("marker", *options.Marker) + } + if options != nil && options.Sharesnapshot != nil { + reqQP.Set("sharesnapshot", *options.Sharesnapshot) + } + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["x-ms-handle-id"] = []string{handleID} + req.Raw().Header["x-ms-version"] = []string{"2020-10-02"} + req.Raw().Header["Accept"] = []string{"application/xml"} + return req, nil +} + +// forceCloseHandlesHandleResponse handles the ForceCloseHandles response. +func (client *FileClient) forceCloseHandlesHandleResponse(resp *http.Response) (FileClientForceCloseHandlesResponse, error) { + result := FileClientForceCloseHandlesResponse{} + if val := resp.Header.Get("x-ms-request-id"); val != "" { + result.RequestID = &val + } + if val := resp.Header.Get("x-ms-version"); val != "" { + result.Version = &val + } + if val := resp.Header.Get("Date"); val != "" { + date, err := time.Parse(time.RFC1123, val) + if err != nil { + return FileClientForceCloseHandlesResponse{}, err + } + result.Date = &date + } + if val := resp.Header.Get("x-ms-marker"); val != "" { + result.Marker = &val + } + if val := resp.Header.Get("x-ms-number-of-handles-closed"); val != "" { + numberOfHandlesClosed32, err := strconv.ParseInt(val, 10, 32) + numberOfHandlesClosed := int32(numberOfHandlesClosed32) + if err != nil { + return FileClientForceCloseHandlesResponse{}, err + } + result.NumberOfHandlesClosed = &numberOfHandlesClosed + } + if val := resp.Header.Get("x-ms-number-of-handles-failed"); val != "" { + numberOfHandlesFailedToClose32, err := strconv.ParseInt(val, 10, 32) + numberOfHandlesFailedToClose := int32(numberOfHandlesFailedToClose32) + if err != nil { + return FileClientForceCloseHandlesResponse{}, err + } + result.NumberOfHandlesFailedToClose = &numberOfHandlesFailedToClose + } + return result, nil +} + +// GetProperties - Returns all user-defined metadata, standard HTTP properties, and system properties for the file. It does +// not return the content of the file. +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2020-10-02 +// - options - FileClientGetPropertiesOptions contains the optional parameters for the FileClient.GetProperties method. +// - LeaseAccessConditions - LeaseAccessConditions contains a group of parameters for the ShareClient.GetProperties method. +func (client *FileClient) GetProperties(ctx context.Context, options *FileClientGetPropertiesOptions, leaseAccessConditions *LeaseAccessConditions) (FileClientGetPropertiesResponse, error) { + req, err := client.getPropertiesCreateRequest(ctx, options, leaseAccessConditions) + if err != nil { + return FileClientGetPropertiesResponse{}, err + } + resp, err := client.pl.Do(req) + if err != nil { + return FileClientGetPropertiesResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusOK) { + return FileClientGetPropertiesResponse{}, runtime.NewResponseError(resp) + } + return client.getPropertiesHandleResponse(resp) +} + +// getPropertiesCreateRequest creates the GetProperties request. +func (client *FileClient) getPropertiesCreateRequest(ctx context.Context, options *FileClientGetPropertiesOptions, leaseAccessConditions *LeaseAccessConditions) (*policy.Request, error) { + req, err := runtime.NewRequest(ctx, http.MethodHead, client.endpoint) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + if options != nil && options.Sharesnapshot != nil { + reqQP.Set("sharesnapshot", *options.Sharesnapshot) + } + if options != nil && options.Timeout != nil { + reqQP.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + } + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["x-ms-version"] = []string{"2020-10-02"} + if leaseAccessConditions != nil && leaseAccessConditions.LeaseID != nil { + req.Raw().Header["x-ms-lease-id"] = []string{*leaseAccessConditions.LeaseID} + } + req.Raw().Header["Accept"] = []string{"application/xml"} + return req, nil +} + +// getPropertiesHandleResponse handles the GetProperties response. +func (client *FileClient) getPropertiesHandleResponse(resp *http.Response) (FileClientGetPropertiesResponse, error) { + result := FileClientGetPropertiesResponse{} + if val := resp.Header.Get("Last-Modified"); val != "" { + lastModified, err := time.Parse(time.RFC1123, val) + if err != nil { + return FileClientGetPropertiesResponse{}, err + } + result.LastModified = &lastModified + } + for hh := range resp.Header { + if len(hh) > len("x-ms-meta-") && strings.EqualFold(hh[:len("x-ms-meta-")], "x-ms-meta-") { + if result.Metadata == nil { + result.Metadata = map[string]*string{} + } + result.Metadata[hh[len("x-ms-meta-"):]] = to.Ptr(resp.Header.Get(hh)) + } + } + if val := resp.Header.Get("x-ms-type"); val != "" { + result.FileType = &val + } + if val := resp.Header.Get("Content-Length"); val != "" { + contentLength, err := strconv.ParseInt(val, 10, 64) + if err != nil { + return FileClientGetPropertiesResponse{}, err + } + result.ContentLength = &contentLength + } + if val := resp.Header.Get("Content-Type"); val != "" { + result.ContentType = &val + } + if val := resp.Header.Get("ETag"); val != "" { + result.ETag = (*azcore.ETag)(&val) + } + if val := resp.Header.Get("Content-MD5"); val != "" { + contentMD5, err := base64.StdEncoding.DecodeString(val) + if err != nil { + return FileClientGetPropertiesResponse{}, err + } + result.ContentMD5 = contentMD5 + } + if val := resp.Header.Get("Content-Encoding"); val != "" { + result.ContentEncoding = &val + } + if val := resp.Header.Get("Cache-Control"); val != "" { + result.CacheControl = &val + } + if val := resp.Header.Get("Content-Disposition"); val != "" { + result.ContentDisposition = &val + } + if val := resp.Header.Get("Content-Language"); val != "" { + result.ContentLanguage = &val + } + if val := resp.Header.Get("x-ms-request-id"); val != "" { + result.RequestID = &val + } + if val := resp.Header.Get("x-ms-version"); val != "" { + result.Version = &val + } + if val := resp.Header.Get("Date"); val != "" { + date, err := time.Parse(time.RFC1123, val) + if err != nil { + return FileClientGetPropertiesResponse{}, err + } + result.Date = &date + } + if val := resp.Header.Get("x-ms-copy-completion-time"); val != "" { + copyCompletionTime, err := time.Parse(time.RFC1123, val) + if err != nil { + return FileClientGetPropertiesResponse{}, err + } + result.CopyCompletionTime = ©CompletionTime + } + if val := resp.Header.Get("x-ms-copy-status-description"); val != "" { + result.CopyStatusDescription = &val + } + if val := resp.Header.Get("x-ms-copy-id"); val != "" { + result.CopyID = &val + } + if val := resp.Header.Get("x-ms-copy-progress"); val != "" { + result.CopyProgress = &val + } + if val := resp.Header.Get("x-ms-copy-source"); val != "" { + result.CopySource = &val + } + if val := resp.Header.Get("x-ms-copy-status"); val != "" { + result.CopyStatus = (*CopyStatusType)(&val) + } + if val := resp.Header.Get("x-ms-server-encrypted"); val != "" { + isServerEncrypted, err := strconv.ParseBool(val) + if err != nil { + return FileClientGetPropertiesResponse{}, err + } + result.IsServerEncrypted = &isServerEncrypted + } + if val := resp.Header.Get("x-ms-file-attributes"); val != "" { + result.FileAttributes = &val + } + if val := resp.Header.Get("x-ms-file-creation-time"); val != "" { + fileCreationTime, err := time.Parse(ISO8601, val) + if err != nil { + return FileClientGetPropertiesResponse{}, err + } + result.FileCreationTime = &fileCreationTime + } + if val := resp.Header.Get("x-ms-file-last-write-time"); val != "" { + fileLastWriteTime, err := time.Parse(ISO8601, val) + if err != nil { + return FileClientGetPropertiesResponse{}, err + } + result.FileLastWriteTime = &fileLastWriteTime + } + if val := resp.Header.Get("x-ms-file-change-time"); val != "" { + fileChangeTime, err := time.Parse(ISO8601, val) + if err != nil { + return FileClientGetPropertiesResponse{}, err + } + result.FileChangeTime = &fileChangeTime + } + if val := resp.Header.Get("x-ms-file-permission-key"); val != "" { + result.FilePermissionKey = &val + } + if val := resp.Header.Get("x-ms-file-id"); val != "" { + result.ID = &val + } + if val := resp.Header.Get("x-ms-file-parent-id"); val != "" { + result.ParentID = &val + } + if val := resp.Header.Get("x-ms-lease-duration"); val != "" { + result.LeaseDuration = (*LeaseDurationType)(&val) + } + if val := resp.Header.Get("x-ms-lease-state"); val != "" { + result.LeaseState = (*LeaseStateType)(&val) + } + if val := resp.Header.Get("x-ms-lease-status"); val != "" { + result.LeaseStatus = (*LeaseStatusType)(&val) + } + return result, nil +} + +// GetRangeList - Returns the list of valid ranges for a file. +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2020-10-02 +// - options - FileClientGetRangeListOptions contains the optional parameters for the FileClient.GetRangeList method. +// - LeaseAccessConditions - LeaseAccessConditions contains a group of parameters for the ShareClient.GetProperties method. +func (client *FileClient) GetRangeList(ctx context.Context, options *FileClientGetRangeListOptions, leaseAccessConditions *LeaseAccessConditions) (FileClientGetRangeListResponse, error) { + req, err := client.getRangeListCreateRequest(ctx, options, leaseAccessConditions) + if err != nil { + return FileClientGetRangeListResponse{}, err + } + resp, err := client.pl.Do(req) + if err != nil { + return FileClientGetRangeListResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusOK) { + return FileClientGetRangeListResponse{}, runtime.NewResponseError(resp) + } + return client.getRangeListHandleResponse(resp) +} + +// getRangeListCreateRequest creates the GetRangeList request. +func (client *FileClient) getRangeListCreateRequest(ctx context.Context, options *FileClientGetRangeListOptions, leaseAccessConditions *LeaseAccessConditions) (*policy.Request, error) { + req, err := runtime.NewRequest(ctx, http.MethodGet, client.endpoint) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("comp", "rangelist") + if options != nil && options.Sharesnapshot != nil { + reqQP.Set("sharesnapshot", *options.Sharesnapshot) + } + if options != nil && options.Prevsharesnapshot != nil { + reqQP.Set("prevsharesnapshot", *options.Prevsharesnapshot) + } + if options != nil && options.Timeout != nil { + reqQP.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + } + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["x-ms-version"] = []string{"2020-10-02"} + if options != nil && options.Range != nil { + req.Raw().Header["x-ms-range"] = []string{*options.Range} + } + if leaseAccessConditions != nil && leaseAccessConditions.LeaseID != nil { + req.Raw().Header["x-ms-lease-id"] = []string{*leaseAccessConditions.LeaseID} + } + req.Raw().Header["Accept"] = []string{"application/xml"} + return req, nil +} + +// getRangeListHandleResponse handles the GetRangeList response. +func (client *FileClient) getRangeListHandleResponse(resp *http.Response) (FileClientGetRangeListResponse, error) { + result := FileClientGetRangeListResponse{} + if val := resp.Header.Get("Last-Modified"); val != "" { + lastModified, err := time.Parse(time.RFC1123, val) + if err != nil { + return FileClientGetRangeListResponse{}, err + } + result.LastModified = &lastModified + } + if val := resp.Header.Get("ETag"); val != "" { + result.ETag = (*azcore.ETag)(&val) + } + if val := resp.Header.Get("x-ms-content-length"); val != "" { + fileContentLength, err := strconv.ParseInt(val, 10, 64) + if err != nil { + return FileClientGetRangeListResponse{}, err + } + result.FileContentLength = &fileContentLength + } + if val := resp.Header.Get("x-ms-request-id"); val != "" { + result.RequestID = &val + } + if val := resp.Header.Get("x-ms-version"); val != "" { + result.Version = &val + } + if val := resp.Header.Get("Date"); val != "" { + date, err := time.Parse(time.RFC1123, val) + if err != nil { + return FileClientGetRangeListResponse{}, err + } + result.Date = &date + } + if err := runtime.UnmarshalAsXML(resp, &result.ShareFileRangeList); err != nil { + return FileClientGetRangeListResponse{}, err + } + return result, nil +} + +// ListHandles - Lists handles for file +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2020-10-02 +// - options - FileClientListHandlesOptions contains the optional parameters for the FileClient.ListHandles method. +func (client *FileClient) ListHandles(ctx context.Context, options *FileClientListHandlesOptions) (FileClientListHandlesResponse, error) { + req, err := client.listHandlesCreateRequest(ctx, options) + if err != nil { + return FileClientListHandlesResponse{}, err + } + resp, err := client.pl.Do(req) + if err != nil { + return FileClientListHandlesResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusOK) { + return FileClientListHandlesResponse{}, runtime.NewResponseError(resp) + } + return client.listHandlesHandleResponse(resp) +} + +// listHandlesCreateRequest creates the ListHandles request. +func (client *FileClient) listHandlesCreateRequest(ctx context.Context, options *FileClientListHandlesOptions) (*policy.Request, error) { + req, err := runtime.NewRequest(ctx, http.MethodGet, client.endpoint) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("comp", "listhandles") + if options != nil && options.Marker != nil { + reqQP.Set("marker", *options.Marker) + } + if options != nil && options.Maxresults != nil { + reqQP.Set("maxresults", strconv.FormatInt(int64(*options.Maxresults), 10)) + } + if options != nil && options.Timeout != nil { + reqQP.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + } + if options != nil && options.Sharesnapshot != nil { + reqQP.Set("sharesnapshot", *options.Sharesnapshot) + } + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["x-ms-version"] = []string{"2020-10-02"} + req.Raw().Header["Accept"] = []string{"application/xml"} + return req, nil +} + +// listHandlesHandleResponse handles the ListHandles response. +func (client *FileClient) listHandlesHandleResponse(resp *http.Response) (FileClientListHandlesResponse, error) { + result := FileClientListHandlesResponse{} + if val := resp.Header.Get("Content-Type"); val != "" { + result.ContentType = &val + } + if val := resp.Header.Get("x-ms-request-id"); val != "" { + result.RequestID = &val + } + if val := resp.Header.Get("x-ms-version"); val != "" { + result.Version = &val + } + if val := resp.Header.Get("Date"); val != "" { + date, err := time.Parse(time.RFC1123, val) + if err != nil { + return FileClientListHandlesResponse{}, err + } + result.Date = &date + } + if err := runtime.UnmarshalAsXML(resp, &result.ListHandlesResponse); err != nil { + return FileClientListHandlesResponse{}, err + } + return result, nil +} + +// ReleaseLease - [Update] The Lease File operation establishes and manages a lock on a file for write and delete operations +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2020-10-02 +// - leaseID - Specifies the current lease ID on the resource. +// - options - FileClientReleaseLeaseOptions contains the optional parameters for the FileClient.ReleaseLease method. +func (client *FileClient) ReleaseLease(ctx context.Context, leaseID string, options *FileClientReleaseLeaseOptions) (FileClientReleaseLeaseResponse, error) { + req, err := client.releaseLeaseCreateRequest(ctx, leaseID, options) + if err != nil { + return FileClientReleaseLeaseResponse{}, err + } + resp, err := client.pl.Do(req) + if err != nil { + return FileClientReleaseLeaseResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusOK) { + return FileClientReleaseLeaseResponse{}, runtime.NewResponseError(resp) + } + return client.releaseLeaseHandleResponse(resp) +} + +// releaseLeaseCreateRequest creates the ReleaseLease request. +func (client *FileClient) releaseLeaseCreateRequest(ctx context.Context, leaseID string, options *FileClientReleaseLeaseOptions) (*policy.Request, error) { + req, err := runtime.NewRequest(ctx, http.MethodPut, client.endpoint) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("comp", "lease") + if options != nil && options.Timeout != nil { + reqQP.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + } + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["x-ms-lease-action"] = []string{"release"} + req.Raw().Header["x-ms-lease-id"] = []string{leaseID} + req.Raw().Header["x-ms-version"] = []string{"2020-10-02"} + if options != nil && options.RequestID != nil { + req.Raw().Header["x-ms-client-request-id"] = []string{*options.RequestID} + } + req.Raw().Header["Accept"] = []string{"application/xml"} + return req, nil +} + +// releaseLeaseHandleResponse handles the ReleaseLease response. +func (client *FileClient) releaseLeaseHandleResponse(resp *http.Response) (FileClientReleaseLeaseResponse, error) { + result := FileClientReleaseLeaseResponse{} + if val := resp.Header.Get("ETag"); val != "" { + result.ETag = (*azcore.ETag)(&val) + } + if val := resp.Header.Get("Last-Modified"); val != "" { + lastModified, err := time.Parse(time.RFC1123, val) + if err != nil { + return FileClientReleaseLeaseResponse{}, err + } + result.LastModified = &lastModified + } + if val := resp.Header.Get("x-ms-client-request-id"); val != "" { + result.ClientRequestID = &val + } + if val := resp.Header.Get("x-ms-request-id"); val != "" { + result.RequestID = &val + } + if val := resp.Header.Get("x-ms-version"); val != "" { + result.Version = &val + } + if val := resp.Header.Get("Date"); val != "" { + date, err := time.Parse(time.RFC1123, val) + if err != nil { + return FileClientReleaseLeaseResponse{}, err + } + result.Date = &date + } + return result, nil +} + +// SetHTTPHeaders - Sets HTTP headers on the file. +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2020-10-02 +// - fileAttributes - If specified, the provided file attributes shall be set. Default value: ‘Archive’ for file and ‘Directory’ +// for directory. ‘None’ can also be specified as default. +// - fileCreationTime - Creation time for the file/directory. Default value: Now. +// - fileLastWriteTime - Last write time for the file/directory. Default value: Now. +// - options - FileClientSetHTTPHeadersOptions contains the optional parameters for the FileClient.SetHTTPHeaders method. +// - ShareFileHTTPHeaders - ShareFileHTTPHeaders contains a group of parameters for the FileClient.Create method. +// - LeaseAccessConditions - LeaseAccessConditions contains a group of parameters for the ShareClient.GetProperties method. +func (client *FileClient) SetHTTPHeaders(ctx context.Context, fileAttributes string, fileCreationTime string, fileLastWriteTime string, options *FileClientSetHTTPHeadersOptions, shareFileHTTPHeaders *ShareFileHTTPHeaders, leaseAccessConditions *LeaseAccessConditions) (FileClientSetHTTPHeadersResponse, error) { + req, err := client.setHTTPHeadersCreateRequest(ctx, fileAttributes, fileCreationTime, fileLastWriteTime, options, shareFileHTTPHeaders, leaseAccessConditions) + if err != nil { + return FileClientSetHTTPHeadersResponse{}, err + } + resp, err := client.pl.Do(req) + if err != nil { + return FileClientSetHTTPHeadersResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusOK) { + return FileClientSetHTTPHeadersResponse{}, runtime.NewResponseError(resp) + } + return client.setHTTPHeadersHandleResponse(resp) +} + +// setHTTPHeadersCreateRequest creates the SetHTTPHeaders request. +func (client *FileClient) setHTTPHeadersCreateRequest(ctx context.Context, fileAttributes string, fileCreationTime string, fileLastWriteTime string, options *FileClientSetHTTPHeadersOptions, shareFileHTTPHeaders *ShareFileHTTPHeaders, leaseAccessConditions *LeaseAccessConditions) (*policy.Request, error) { + req, err := runtime.NewRequest(ctx, http.MethodPut, client.endpoint) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("comp", "properties") + if options != nil && options.Timeout != nil { + reqQP.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + } + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["x-ms-version"] = []string{"2020-10-02"} + if options != nil && options.FileContentLength != nil { + req.Raw().Header["x-ms-content-length"] = []string{strconv.FormatInt(*options.FileContentLength, 10)} + } + if shareFileHTTPHeaders != nil && shareFileHTTPHeaders.ContentType != nil { + req.Raw().Header["x-ms-content-type"] = []string{*shareFileHTTPHeaders.ContentType} + } + if shareFileHTTPHeaders != nil && shareFileHTTPHeaders.ContentEncoding != nil { + req.Raw().Header["x-ms-content-encoding"] = []string{*shareFileHTTPHeaders.ContentEncoding} + } + if shareFileHTTPHeaders != nil && shareFileHTTPHeaders.ContentLanguage != nil { + req.Raw().Header["x-ms-content-language"] = []string{*shareFileHTTPHeaders.ContentLanguage} + } + if shareFileHTTPHeaders != nil && shareFileHTTPHeaders.CacheControl != nil { + req.Raw().Header["x-ms-cache-control"] = []string{*shareFileHTTPHeaders.CacheControl} + } + if shareFileHTTPHeaders != nil && shareFileHTTPHeaders.ContentMD5 != nil { + req.Raw().Header["x-ms-content-md5"] = []string{base64.StdEncoding.EncodeToString(shareFileHTTPHeaders.ContentMD5)} + } + if shareFileHTTPHeaders != nil && shareFileHTTPHeaders.ContentDisposition != nil { + req.Raw().Header["x-ms-content-disposition"] = []string{*shareFileHTTPHeaders.ContentDisposition} + } + if options != nil && options.FilePermission != nil { + req.Raw().Header["x-ms-file-permission"] = []string{*options.FilePermission} + } + if options != nil && options.FilePermissionKey != nil { + req.Raw().Header["x-ms-file-permission-key"] = []string{*options.FilePermissionKey} + } + req.Raw().Header["x-ms-file-attributes"] = []string{fileAttributes} + req.Raw().Header["x-ms-file-creation-time"] = []string{fileCreationTime} + req.Raw().Header["x-ms-file-last-write-time"] = []string{fileLastWriteTime} + if leaseAccessConditions != nil && leaseAccessConditions.LeaseID != nil { + req.Raw().Header["x-ms-lease-id"] = []string{*leaseAccessConditions.LeaseID} + } + req.Raw().Header["Accept"] = []string{"application/xml"} + return req, nil +} + +// setHTTPHeadersHandleResponse handles the SetHTTPHeaders response. +func (client *FileClient) setHTTPHeadersHandleResponse(resp *http.Response) (FileClientSetHTTPHeadersResponse, error) { + result := FileClientSetHTTPHeadersResponse{} + if val := resp.Header.Get("ETag"); val != "" { + result.ETag = (*azcore.ETag)(&val) + } + if val := resp.Header.Get("Last-Modified"); val != "" { + lastModified, err := time.Parse(time.RFC1123, val) + if err != nil { + return FileClientSetHTTPHeadersResponse{}, err + } + result.LastModified = &lastModified + } + if val := resp.Header.Get("x-ms-request-id"); val != "" { + result.RequestID = &val + } + if val := resp.Header.Get("x-ms-version"); val != "" { + result.Version = &val + } + if val := resp.Header.Get("Date"); val != "" { + date, err := time.Parse(time.RFC1123, val) + if err != nil { + return FileClientSetHTTPHeadersResponse{}, err + } + result.Date = &date + } + if val := resp.Header.Get("x-ms-request-server-encrypted"); val != "" { + isServerEncrypted, err := strconv.ParseBool(val) + if err != nil { + return FileClientSetHTTPHeadersResponse{}, err + } + result.IsServerEncrypted = &isServerEncrypted + } + if val := resp.Header.Get("x-ms-file-permission-key"); val != "" { + result.FilePermissionKey = &val + } + if val := resp.Header.Get("x-ms-file-attributes"); val != "" { + result.FileAttributes = &val + } + if val := resp.Header.Get("x-ms-file-creation-time"); val != "" { + fileCreationTime, err := time.Parse(ISO8601, val) + if err != nil { + return FileClientSetHTTPHeadersResponse{}, err + } + result.FileCreationTime = &fileCreationTime + } + if val := resp.Header.Get("x-ms-file-last-write-time"); val != "" { + fileLastWriteTime, err := time.Parse(ISO8601, val) + if err != nil { + return FileClientSetHTTPHeadersResponse{}, err + } + result.FileLastWriteTime = &fileLastWriteTime + } + if val := resp.Header.Get("x-ms-file-change-time"); val != "" { + fileChangeTime, err := time.Parse(ISO8601, val) + if err != nil { + return FileClientSetHTTPHeadersResponse{}, err + } + result.FileChangeTime = &fileChangeTime + } + if val := resp.Header.Get("x-ms-file-id"); val != "" { + result.ID = &val + } + if val := resp.Header.Get("x-ms-file-parent-id"); val != "" { + result.ParentID = &val + } + return result, nil +} + +// SetMetadata - Updates user-defined metadata for the specified file. +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2020-10-02 +// - options - FileClientSetMetadataOptions contains the optional parameters for the FileClient.SetMetadata method. +// - LeaseAccessConditions - LeaseAccessConditions contains a group of parameters for the ShareClient.GetProperties method. +func (client *FileClient) SetMetadata(ctx context.Context, options *FileClientSetMetadataOptions, leaseAccessConditions *LeaseAccessConditions) (FileClientSetMetadataResponse, error) { + req, err := client.setMetadataCreateRequest(ctx, options, leaseAccessConditions) + if err != nil { + return FileClientSetMetadataResponse{}, err + } + resp, err := client.pl.Do(req) + if err != nil { + return FileClientSetMetadataResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusOK) { + return FileClientSetMetadataResponse{}, runtime.NewResponseError(resp) + } + return client.setMetadataHandleResponse(resp) +} + +// setMetadataCreateRequest creates the SetMetadata request. +func (client *FileClient) setMetadataCreateRequest(ctx context.Context, options *FileClientSetMetadataOptions, leaseAccessConditions *LeaseAccessConditions) (*policy.Request, error) { + req, err := runtime.NewRequest(ctx, http.MethodPut, client.endpoint) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("comp", "metadata") + if options != nil && options.Timeout != nil { + reqQP.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + } + req.Raw().URL.RawQuery = reqQP.Encode() + if options != nil && options.Metadata != nil { + for k, v := range options.Metadata { + if v != nil { + req.Raw().Header["x-ms-meta-"+k] = []string{*v} + } + } + } + req.Raw().Header["x-ms-version"] = []string{"2020-10-02"} + if leaseAccessConditions != nil && leaseAccessConditions.LeaseID != nil { + req.Raw().Header["x-ms-lease-id"] = []string{*leaseAccessConditions.LeaseID} + } + req.Raw().Header["Accept"] = []string{"application/xml"} + return req, nil +} + +// setMetadataHandleResponse handles the SetMetadata response. +func (client *FileClient) setMetadataHandleResponse(resp *http.Response) (FileClientSetMetadataResponse, error) { + result := FileClientSetMetadataResponse{} + if val := resp.Header.Get("ETag"); val != "" { + result.ETag = (*azcore.ETag)(&val) + } + if val := resp.Header.Get("x-ms-request-id"); val != "" { + result.RequestID = &val + } + if val := resp.Header.Get("x-ms-version"); val != "" { + result.Version = &val + } + if val := resp.Header.Get("Date"); val != "" { + date, err := time.Parse(time.RFC1123, val) + if err != nil { + return FileClientSetMetadataResponse{}, err + } + result.Date = &date + } + if val := resp.Header.Get("x-ms-request-server-encrypted"); val != "" { + isServerEncrypted, err := strconv.ParseBool(val) + if err != nil { + return FileClientSetMetadataResponse{}, err + } + result.IsServerEncrypted = &isServerEncrypted + } + if val := resp.Header.Get("Last-Modified"); val != "" { + lastModified, err := time.Parse(time.RFC1123, val) + if err != nil { + return FileClientSetMetadataResponse{}, err + } + result.LastModified = &lastModified + } + return result, nil +} + +// StartCopy - Copies a blob or file to a destination file within the storage account. +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2020-10-02 +// - copySource - Specifies the URL of the source file or blob, up to 2 KB in length. To copy a file to another file within +// the same storage account, you may use Shared Key to authenticate the source file. If you are +// copying a file from another storage account, or if you are copying a blob from the same storage account or another storage +// account, then you must authenticate the source file or blob using a shared +// access signature. If the source is a public blob, no authentication is required to perform the copy operation. A file in +// a share snapshot can also be specified as a copy source. +// - options - FileClientStartCopyOptions contains the optional parameters for the FileClient.StartCopy method. +// - CopyFileSMBInfo - CopyFileSMBInfo contains a group of parameters for the FileClient.StartCopy method. +// - LeaseAccessConditions - LeaseAccessConditions contains a group of parameters for the ShareClient.GetProperties method. +func (client *FileClient) StartCopy(ctx context.Context, copySource string, options *FileClientStartCopyOptions, copyFileSMBInfo *CopyFileSMBInfo, leaseAccessConditions *LeaseAccessConditions) (FileClientStartCopyResponse, error) { + req, err := client.startCopyCreateRequest(ctx, copySource, options, copyFileSMBInfo, leaseAccessConditions) + if err != nil { + return FileClientStartCopyResponse{}, err + } + resp, err := client.pl.Do(req) + if err != nil { + return FileClientStartCopyResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusAccepted) { + return FileClientStartCopyResponse{}, runtime.NewResponseError(resp) + } + return client.startCopyHandleResponse(resp) +} + +// startCopyCreateRequest creates the StartCopy request. +func (client *FileClient) startCopyCreateRequest(ctx context.Context, copySource string, options *FileClientStartCopyOptions, copyFileSMBInfo *CopyFileSMBInfo, leaseAccessConditions *LeaseAccessConditions) (*policy.Request, error) { + req, err := runtime.NewRequest(ctx, http.MethodPut, client.endpoint) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + if options != nil && options.Timeout != nil { + reqQP.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + } + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["x-ms-version"] = []string{"2020-10-02"} + if options != nil && options.Metadata != nil { + for k, v := range options.Metadata { + if v != nil { + req.Raw().Header["x-ms-meta-"+k] = []string{*v} + } + } + } + req.Raw().Header["x-ms-copy-source"] = []string{copySource} + if options != nil && options.FilePermission != nil { + req.Raw().Header["x-ms-file-permission"] = []string{*options.FilePermission} + } + if options != nil && options.FilePermissionKey != nil { + req.Raw().Header["x-ms-file-permission-key"] = []string{*options.FilePermissionKey} + } + if copyFileSMBInfo != nil && copyFileSMBInfo.FilePermissionCopyMode != nil { + req.Raw().Header["x-ms-file-permission-copy-mode"] = []string{string(*copyFileSMBInfo.FilePermissionCopyMode)} + } + if copyFileSMBInfo != nil && copyFileSMBInfo.IgnoreReadOnly != nil { + req.Raw().Header["x-ms-file-copy-ignore-readonly"] = []string{strconv.FormatBool(*copyFileSMBInfo.IgnoreReadOnly)} + } + if copyFileSMBInfo != nil && copyFileSMBInfo.FileAttributes != nil { + req.Raw().Header["x-ms-file-attributes"] = []string{*copyFileSMBInfo.FileAttributes} + } + if copyFileSMBInfo != nil && copyFileSMBInfo.FileCreationTime != nil { + req.Raw().Header["x-ms-file-creation-time"] = []string{*copyFileSMBInfo.FileCreationTime} + } + if copyFileSMBInfo != nil && copyFileSMBInfo.FileLastWriteTime != nil { + req.Raw().Header["x-ms-file-last-write-time"] = []string{*copyFileSMBInfo.FileLastWriteTime} + } + if copyFileSMBInfo != nil && copyFileSMBInfo.SetArchiveAttribute != nil { + req.Raw().Header["x-ms-file-copy-set-archive"] = []string{strconv.FormatBool(*copyFileSMBInfo.SetArchiveAttribute)} + } + if leaseAccessConditions != nil && leaseAccessConditions.LeaseID != nil { + req.Raw().Header["x-ms-lease-id"] = []string{*leaseAccessConditions.LeaseID} + } + req.Raw().Header["Accept"] = []string{"application/xml"} + return req, nil +} + +// startCopyHandleResponse handles the StartCopy response. +func (client *FileClient) startCopyHandleResponse(resp *http.Response) (FileClientStartCopyResponse, error) { + result := FileClientStartCopyResponse{} + if val := resp.Header.Get("ETag"); val != "" { + result.ETag = (*azcore.ETag)(&val) + } + if val := resp.Header.Get("Last-Modified"); val != "" { + lastModified, err := time.Parse(time.RFC1123, val) + if err != nil { + return FileClientStartCopyResponse{}, err + } + result.LastModified = &lastModified + } + if val := resp.Header.Get("x-ms-request-id"); val != "" { + result.RequestID = &val + } + if val := resp.Header.Get("x-ms-version"); val != "" { + result.Version = &val + } + if val := resp.Header.Get("Date"); val != "" { + date, err := time.Parse(time.RFC1123, val) + if err != nil { + return FileClientStartCopyResponse{}, err + } + result.Date = &date + } + if val := resp.Header.Get("x-ms-copy-id"); val != "" { + result.CopyID = &val + } + if val := resp.Header.Get("x-ms-copy-status"); val != "" { + result.CopyStatus = (*CopyStatusType)(&val) + } + return result, nil +} + +// UploadRange - Upload a range of bytes to a file. +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2020-10-02 +// - rangeParam - Specifies the range of bytes to be written. Both the start and end of the range must be specified. For an +// update operation, the range can be up to 4 MB in size. For a clear operation, the range can be +// up to the value of the file's full size. The File service accepts only a single byte range for the Range and 'x-ms-range' +// headers, and the byte range must be specified in the following format: +// bytes=startByte-endByte. +// - fileRangeWrite - Specify one of the following options: - Update: Writes the bytes specified by the request body into the +// specified range. The Range and Content-Length headers must match to perform the update. - Clear: +// Clears the specified range and releases the space used in storage for that range. To clear a range, set the Content-Length +// header to zero, and set the Range header to a value that indicates the range +// to clear, up to maximum file size. +// - contentLength - Specifies the number of bytes being transmitted in the request body. When the x-ms-write header is set +// to clear, the value of this header must be set to zero. +// - optionalbody - Initial data. +// - options - FileClientUploadRangeOptions contains the optional parameters for the FileClient.UploadRange method. +// - LeaseAccessConditions - LeaseAccessConditions contains a group of parameters for the ShareClient.GetProperties method. +func (client *FileClient) UploadRange(ctx context.Context, rangeParam string, fileRangeWrite FileRangeWriteType, contentLength int64, optionalbody io.ReadSeekCloser, options *FileClientUploadRangeOptions, leaseAccessConditions *LeaseAccessConditions) (FileClientUploadRangeResponse, error) { + req, err := client.uploadRangeCreateRequest(ctx, rangeParam, fileRangeWrite, contentLength, optionalbody, options, leaseAccessConditions) + if err != nil { + return FileClientUploadRangeResponse{}, err + } + resp, err := client.pl.Do(req) + if err != nil { + return FileClientUploadRangeResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusCreated) { + return FileClientUploadRangeResponse{}, runtime.NewResponseError(resp) + } + return client.uploadRangeHandleResponse(resp) +} + +// uploadRangeCreateRequest creates the UploadRange request. +func (client *FileClient) uploadRangeCreateRequest(ctx context.Context, rangeParam string, fileRangeWrite FileRangeWriteType, contentLength int64, optionalbody io.ReadSeekCloser, options *FileClientUploadRangeOptions, leaseAccessConditions *LeaseAccessConditions) (*policy.Request, error) { + req, err := runtime.NewRequest(ctx, http.MethodPut, client.endpoint) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("comp", "range") + if options != nil && options.Timeout != nil { + reqQP.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + } + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["x-ms-range"] = []string{rangeParam} + req.Raw().Header["x-ms-write"] = []string{string(fileRangeWrite)} + req.Raw().Header["Content-Length"] = []string{strconv.FormatInt(contentLength, 10)} + if options != nil && options.ContentMD5 != nil { + req.Raw().Header["Content-MD5"] = []string{base64.StdEncoding.EncodeToString(options.ContentMD5)} + } + req.Raw().Header["x-ms-version"] = []string{"2020-10-02"} + if leaseAccessConditions != nil && leaseAccessConditions.LeaseID != nil { + req.Raw().Header["x-ms-lease-id"] = []string{*leaseAccessConditions.LeaseID} + } + req.Raw().Header["Accept"] = []string{"application/xml"} + return req, req.SetBody(optionalbody, "application/octet-stream") +} + +// uploadRangeHandleResponse handles the UploadRange response. +func (client *FileClient) uploadRangeHandleResponse(resp *http.Response) (FileClientUploadRangeResponse, error) { + result := FileClientUploadRangeResponse{} + if val := resp.Header.Get("ETag"); val != "" { + result.ETag = (*azcore.ETag)(&val) + } + if val := resp.Header.Get("Last-Modified"); val != "" { + lastModified, err := time.Parse(time.RFC1123, val) + if err != nil { + return FileClientUploadRangeResponse{}, err + } + result.LastModified = &lastModified + } + if val := resp.Header.Get("Content-MD5"); val != "" { + contentMD5, err := base64.StdEncoding.DecodeString(val) + if err != nil { + return FileClientUploadRangeResponse{}, err + } + result.ContentMD5 = contentMD5 + } + if val := resp.Header.Get("x-ms-request-id"); val != "" { + result.RequestID = &val + } + if val := resp.Header.Get("x-ms-version"); val != "" { + result.Version = &val + } + if val := resp.Header.Get("Date"); val != "" { + date, err := time.Parse(time.RFC1123, val) + if err != nil { + return FileClientUploadRangeResponse{}, err + } + result.Date = &date + } + if val := resp.Header.Get("x-ms-request-server-encrypted"); val != "" { + isServerEncrypted, err := strconv.ParseBool(val) + if err != nil { + return FileClientUploadRangeResponse{}, err + } + result.IsServerEncrypted = &isServerEncrypted + } + return result, nil +} + +// UploadRangeFromURL - Upload a range of bytes to a file where the contents are read from a URL. +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2020-10-02 +// - rangeParam - Writes data to the specified byte range in the file. +// - copySource - Specifies the URL of the source file or blob, up to 2 KB in length. To copy a file to another file within +// the same storage account, you may use Shared Key to authenticate the source file. If you are +// copying a file from another storage account, or if you are copying a blob from the same storage account or another storage +// account, then you must authenticate the source file or blob using a shared +// access signature. If the source is a public blob, no authentication is required to perform the copy operation. A file in +// a share snapshot can also be specified as a copy source. +// - contentLength - Specifies the number of bytes being transmitted in the request body. When the x-ms-write header is set +// to clear, the value of this header must be set to zero. +// - options - FileClientUploadRangeFromURLOptions contains the optional parameters for the FileClient.UploadRangeFromURL method. +// - SourceModifiedAccessConditions - SourceModifiedAccessConditions contains a group of parameters for the FileClient.UploadRangeFromURL +// method. +// - LeaseAccessConditions - LeaseAccessConditions contains a group of parameters for the ShareClient.GetProperties method. +func (client *FileClient) UploadRangeFromURL(ctx context.Context, rangeParam string, copySource string, contentLength int64, options *FileClientUploadRangeFromURLOptions, sourceModifiedAccessConditions *SourceModifiedAccessConditions, leaseAccessConditions *LeaseAccessConditions) (FileClientUploadRangeFromURLResponse, error) { + req, err := client.uploadRangeFromURLCreateRequest(ctx, rangeParam, copySource, contentLength, options, sourceModifiedAccessConditions, leaseAccessConditions) + if err != nil { + return FileClientUploadRangeFromURLResponse{}, err + } + resp, err := client.pl.Do(req) + if err != nil { + return FileClientUploadRangeFromURLResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusCreated) { + return FileClientUploadRangeFromURLResponse{}, runtime.NewResponseError(resp) + } + return client.uploadRangeFromURLHandleResponse(resp) +} + +// uploadRangeFromURLCreateRequest creates the UploadRangeFromURL request. +func (client *FileClient) uploadRangeFromURLCreateRequest(ctx context.Context, rangeParam string, copySource string, contentLength int64, options *FileClientUploadRangeFromURLOptions, sourceModifiedAccessConditions *SourceModifiedAccessConditions, leaseAccessConditions *LeaseAccessConditions) (*policy.Request, error) { + req, err := runtime.NewRequest(ctx, http.MethodPut, client.endpoint) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("comp", "range") + if options != nil && options.Timeout != nil { + reqQP.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + } + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["x-ms-range"] = []string{rangeParam} + req.Raw().Header["x-ms-copy-source"] = []string{copySource} + if options != nil && options.SourceRange != nil { + req.Raw().Header["x-ms-source-range"] = []string{*options.SourceRange} + } + req.Raw().Header["x-ms-write"] = []string{"update"} + req.Raw().Header["Content-Length"] = []string{strconv.FormatInt(contentLength, 10)} + if options != nil && options.SourceContentCRC64 != nil { + req.Raw().Header["x-ms-source-content-crc64"] = []string{base64.StdEncoding.EncodeToString(options.SourceContentCRC64)} + } + if sourceModifiedAccessConditions != nil && sourceModifiedAccessConditions.SourceIfMatchCRC64 != nil { + req.Raw().Header["x-ms-source-if-match-crc64"] = []string{base64.StdEncoding.EncodeToString(sourceModifiedAccessConditions.SourceIfMatchCRC64)} + } + if sourceModifiedAccessConditions != nil && sourceModifiedAccessConditions.SourceIfNoneMatchCRC64 != nil { + req.Raw().Header["x-ms-source-if-none-match-crc64"] = []string{base64.StdEncoding.EncodeToString(sourceModifiedAccessConditions.SourceIfNoneMatchCRC64)} + } + req.Raw().Header["x-ms-version"] = []string{"2020-10-02"} + if leaseAccessConditions != nil && leaseAccessConditions.LeaseID != nil { + req.Raw().Header["x-ms-lease-id"] = []string{*leaseAccessConditions.LeaseID} + } + if options != nil && options.CopySourceAuthorization != nil { + req.Raw().Header["x-ms-copy-source-authorization"] = []string{*options.CopySourceAuthorization} + } + req.Raw().Header["Accept"] = []string{"application/xml"} + return req, nil +} + +// uploadRangeFromURLHandleResponse handles the UploadRangeFromURL response. +func (client *FileClient) uploadRangeFromURLHandleResponse(resp *http.Response) (FileClientUploadRangeFromURLResponse, error) { + result := FileClientUploadRangeFromURLResponse{} + if val := resp.Header.Get("ETag"); val != "" { + result.ETag = (*azcore.ETag)(&val) + } + if val := resp.Header.Get("Last-Modified"); val != "" { + lastModified, err := time.Parse(time.RFC1123, val) + if err != nil { + return FileClientUploadRangeFromURLResponse{}, err + } + result.LastModified = &lastModified + } + if val := resp.Header.Get("x-ms-content-crc64"); val != "" { + xMSContentCRC64, err := base64.StdEncoding.DecodeString(val) + if err != nil { + return FileClientUploadRangeFromURLResponse{}, err + } + result.XMSContentCRC64 = xMSContentCRC64 + } + if val := resp.Header.Get("x-ms-request-id"); val != "" { + result.RequestID = &val + } + if val := resp.Header.Get("x-ms-version"); val != "" { + result.Version = &val + } + if val := resp.Header.Get("Date"); val != "" { + date, err := time.Parse(time.RFC1123, val) + if err != nil { + return FileClientUploadRangeFromURLResponse{}, err + } + result.Date = &date + } + if val := resp.Header.Get("x-ms-request-server-encrypted"); val != "" { + isServerEncrypted, err := strconv.ParseBool(val) + if err != nil { + return FileClientUploadRangeFromURLResponse{}, err + } + result.IsServerEncrypted = &isServerEncrypted + } + if val := resp.Header.Get("Content-MD5"); val != "" { + contentMD5, err := base64.StdEncoding.DecodeString(val) + if err != nil { + return FileClientUploadRangeFromURLResponse{}, err + } + result.ContentMD5 = contentMD5 + } + return result, nil +} diff --git a/sdk/storage/azfile/internal/generated/zz_models.go b/sdk/storage/azfile/internal/generated/zz_models.go new file mode 100644 index 000000000000..95443aea430f --- /dev/null +++ b/sdk/storage/azfile/internal/generated/zz_models.go @@ -0,0 +1,932 @@ +//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. +// Code generated by Microsoft (R) AutoRest Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. +// DO NOT EDIT. + +package generated + +import ( + "github.com/Azure/azure-sdk-for-go/sdk/azcore" + "time" +) + +// AccessPolicy - An Access policy. +type AccessPolicy struct { + // The date-time the policy expires. + Expiry *time.Time `xml:"Expiry"` + + // The permissions for the ACL policy. + Permission *string `xml:"Permission"` + + // The date-time the policy is active. + Start *time.Time `xml:"Start"` +} + +type ClearRange struct { + // REQUIRED + End *int64 `xml:"End"` + + // REQUIRED + Start *int64 `xml:"Start"` +} + +// CopyFileSMBInfo contains a group of parameters for the FileClient.StartCopy method. +type CopyFileSMBInfo struct { + // Specifies either the option to copy file attributes from a source file(source) to a target file or a list of attributes + // to set on a target file. + FileAttributes *string + // Specifies either the option to copy file creation time from a source file(source) to a target file or a time value in ISO + // 8601 format to set as creation time on a target file. + FileCreationTime *string + // Specifies either the option to copy file last write time from a source file(source) to a target file or a time value in + // ISO 8601 format to set as last write time on a target file. + FileLastWriteTime *string + // Specifies the option to copy file security descriptor from source file or to set it using the value which is defined by + // the header value of x-ms-file-permission or x-ms-file-permission-key. + FilePermissionCopyMode *PermissionCopyModeType + // Specifies the option to overwrite the target file if it already exists and has read-only attribute set. + IgnoreReadOnly *bool + // Specifies the option to set archive attribute on a target file. True means archive attribute will be set on a target file + // despite attribute overrides or a source file state. + SetArchiveAttribute *bool +} + +// CORSRule - CORS is an HTTP feature that enables a web application running under one domain to access resources in another +// domain. Web browsers implement a security restriction known as same-origin policy that +// prevents a web page from calling APIs in a different domain; CORS provides a secure way to allow one domain (the origin +// domain) to call APIs in another domain. +type CORSRule struct { + // REQUIRED; The request headers that the origin domain may specify on the CORS request. + AllowedHeaders *string `xml:"AllowedHeaders"` + + // REQUIRED; The methods (HTTP request verbs) that the origin domain may use for a CORS request. (comma separated) + AllowedMethods *string `xml:"AllowedMethods"` + + // REQUIRED; The origin domains that are permitted to make a request against the storage service via CORS. The origin domain + // is the domain from which the request originates. Note that the origin must be an exact + // case-sensitive match with the origin that the user age sends to the service. You can also use the wildcard character '*' + // to allow all origin domains to make requests via CORS. + AllowedOrigins *string `xml:"AllowedOrigins"` + + // REQUIRED; The response headers that may be sent in the response to the CORS request and exposed by the browser to the request + // issuer. + ExposedHeaders *string `xml:"ExposedHeaders"` + + // REQUIRED; The maximum amount time that a browser should cache the preflight OPTIONS request. + MaxAgeInSeconds *int32 `xml:"MaxAgeInSeconds"` +} + +// Directory - A listed directory item. +type Directory struct { + // REQUIRED + Name *string `xml:"Name"` + Attributes *string `xml:"Attributes"` + ID *string `xml:"FileId"` + PermissionKey *string `xml:"PermissionKey"` + + // File properties. + Properties *FileProperty `xml:"Properties"` +} + +// DirectoryClientCreateOptions contains the optional parameters for the DirectoryClient.Create method. +type DirectoryClientCreateOptions struct { + // If specified the permission (security descriptor) shall be set for the directory/file. This header can be used if Permission + // size is <= 8KB, else x-ms-file-permission-key header shall be used. Default + // value: Inherit. If SDDL is specified as input, it must have owner, group and dacl. Note: Only one of the x-ms-file-permission + // or x-ms-file-permission-key should be specified. + FilePermission *string + // Key of the permission to be set for the directory/file. Note: Only one of the x-ms-file-permission or x-ms-file-permission-key + // should be specified. + FilePermissionKey *string + // A name-value pair to associate with a file storage object. + Metadata map[string]*string + // The timeout parameter is expressed in seconds. For more information, see Setting Timeouts for File Service Operations. + // [https://docs.microsoft.com/en-us/rest/api/storageservices/Setting-Timeouts-for-File-Service-Operations?redirectedfrom=MSDN] + Timeout *int32 +} + +// DirectoryClientDeleteOptions contains the optional parameters for the DirectoryClient.Delete method. +type DirectoryClientDeleteOptions struct { + // The timeout parameter is expressed in seconds. For more information, see Setting Timeouts for File Service Operations. + // [https://docs.microsoft.com/en-us/rest/api/storageservices/Setting-Timeouts-for-File-Service-Operations?redirectedfrom=MSDN] + Timeout *int32 +} + +// DirectoryClientForceCloseHandlesOptions contains the optional parameters for the DirectoryClient.ForceCloseHandles method. +type DirectoryClientForceCloseHandlesOptions struct { + // A string value that identifies the portion of the list to be returned with the next list operation. The operation returns + // a marker value within the response body if the list returned was not complete. + // The marker value may then be used in a subsequent call to request the next set of list items. The marker value is opaque + // to the client. + Marker *string + // Specifies operation should apply to the directory specified in the URI, its files, its subdirectories and their files. + Recursive *bool + // The snapshot parameter is an opaque DateTime value that, when present, specifies the share snapshot to query. + Sharesnapshot *string + // The timeout parameter is expressed in seconds. For more information, see Setting Timeouts for File Service Operations. + // [https://docs.microsoft.com/en-us/rest/api/storageservices/Setting-Timeouts-for-File-Service-Operations?redirectedfrom=MSDN] + Timeout *int32 +} + +// DirectoryClientGetPropertiesOptions contains the optional parameters for the DirectoryClient.GetProperties method. +type DirectoryClientGetPropertiesOptions struct { + // The snapshot parameter is an opaque DateTime value that, when present, specifies the share snapshot to query. + Sharesnapshot *string + // The timeout parameter is expressed in seconds. For more information, see Setting Timeouts for File Service Operations. + // [https://docs.microsoft.com/en-us/rest/api/storageservices/Setting-Timeouts-for-File-Service-Operations?redirectedfrom=MSDN] + Timeout *int32 +} + +// DirectoryClientListFilesAndDirectoriesSegmentOptions contains the optional parameters for the DirectoryClient.NewListFilesAndDirectoriesSegmentPager +// method. +type DirectoryClientListFilesAndDirectoriesSegmentOptions struct { + // Include this parameter to specify one or more datasets to include in the response. + Include []ListFilesIncludeType + // Include extended information. + IncludeExtendedInfo *bool + // A string value that identifies the portion of the list to be returned with the next list operation. The operation returns + // a marker value within the response body if the list returned was not complete. + // The marker value may then be used in a subsequent call to request the next set of list items. The marker value is opaque + // to the client. + Marker *string + // Specifies the maximum number of entries to return. If the request does not specify maxresults, or specifies a value greater + // than 5,000, the server will return up to 5,000 items. + Maxresults *int32 + // Filters the results to return only entries whose name begins with the specified prefix. + Prefix *string + // The snapshot parameter is an opaque DateTime value that, when present, specifies the share snapshot to query. + Sharesnapshot *string + // The timeout parameter is expressed in seconds. For more information, see Setting Timeouts for File Service Operations. + // [https://docs.microsoft.com/en-us/rest/api/storageservices/Setting-Timeouts-for-File-Service-Operations?redirectedfrom=MSDN] + Timeout *int32 +} + +// DirectoryClientListHandlesOptions contains the optional parameters for the DirectoryClient.ListHandles method. +type DirectoryClientListHandlesOptions struct { + // A string value that identifies the portion of the list to be returned with the next list operation. The operation returns + // a marker value within the response body if the list returned was not complete. + // The marker value may then be used in a subsequent call to request the next set of list items. The marker value is opaque + // to the client. + Marker *string + // Specifies the maximum number of entries to return. If the request does not specify maxresults, or specifies a value greater + // than 5,000, the server will return up to 5,000 items. + Maxresults *int32 + // Specifies operation should apply to the directory specified in the URI, its files, its subdirectories and their files. + Recursive *bool + // The snapshot parameter is an opaque DateTime value that, when present, specifies the share snapshot to query. + Sharesnapshot *string + // The timeout parameter is expressed in seconds. For more information, see Setting Timeouts for File Service Operations. + // [https://docs.microsoft.com/en-us/rest/api/storageservices/Setting-Timeouts-for-File-Service-Operations?redirectedfrom=MSDN] + Timeout *int32 +} + +// DirectoryClientSetMetadataOptions contains the optional parameters for the DirectoryClient.SetMetadata method. +type DirectoryClientSetMetadataOptions struct { + // A name-value pair to associate with a file storage object. + Metadata map[string]*string + // The timeout parameter is expressed in seconds. For more information, see Setting Timeouts for File Service Operations. + // [https://docs.microsoft.com/en-us/rest/api/storageservices/Setting-Timeouts-for-File-Service-Operations?redirectedfrom=MSDN] + Timeout *int32 +} + +// DirectoryClientSetPropertiesOptions contains the optional parameters for the DirectoryClient.SetProperties method. +type DirectoryClientSetPropertiesOptions struct { + // If specified the permission (security descriptor) shall be set for the directory/file. This header can be used if Permission + // size is <= 8KB, else x-ms-file-permission-key header shall be used. Default + // value: Inherit. If SDDL is specified as input, it must have owner, group and dacl. Note: Only one of the x-ms-file-permission + // or x-ms-file-permission-key should be specified. + FilePermission *string + // Key of the permission to be set for the directory/file. Note: Only one of the x-ms-file-permission or x-ms-file-permission-key + // should be specified. + FilePermissionKey *string + // The timeout parameter is expressed in seconds. For more information, see Setting Timeouts for File Service Operations. + // [https://docs.microsoft.com/en-us/rest/api/storageservices/Setting-Timeouts-for-File-Service-Operations?redirectedfrom=MSDN] + Timeout *int32 +} + +// File - A listed file item. +type File struct { + // REQUIRED + Name *string `xml:"Name"` + + // REQUIRED; File properties. + Properties *FileProperty `xml:"Properties"` + Attributes *string `xml:"Attributes"` + ID *string `xml:"FileId"` + PermissionKey *string `xml:"PermissionKey"` +} + +// FileClientAbortCopyOptions contains the optional parameters for the FileClient.AbortCopy method. +type FileClientAbortCopyOptions struct { + // The timeout parameter is expressed in seconds. For more information, see Setting Timeouts for File Service Operations. + // [https://docs.microsoft.com/en-us/rest/api/storageservices/Setting-Timeouts-for-File-Service-Operations?redirectedfrom=MSDN] + Timeout *int32 +} + +// FileClientAcquireLeaseOptions contains the optional parameters for the FileClient.AcquireLease method. +type FileClientAcquireLeaseOptions struct { + // Proposed lease ID, in a GUID string format. The File service returns 400 (Invalid request) if the proposed lease ID is + // not in the correct format. See Guid Constructor (String) for a list of valid GUID + // string formats. + ProposedLeaseID *string + // Provides a client-generated, opaque value with a 1 KB character limit that is recorded in the analytics logs when storage + // analytics logging is enabled. + RequestID *string + // The timeout parameter is expressed in seconds. For more information, see Setting Timeouts for File Service Operations. + // [https://docs.microsoft.com/en-us/rest/api/storageservices/Setting-Timeouts-for-File-Service-Operations?redirectedfrom=MSDN] + Timeout *int32 +} + +// FileClientBreakLeaseOptions contains the optional parameters for the FileClient.BreakLease method. +type FileClientBreakLeaseOptions struct { + // Provides a client-generated, opaque value with a 1 KB character limit that is recorded in the analytics logs when storage + // analytics logging is enabled. + RequestID *string + // The timeout parameter is expressed in seconds. For more information, see Setting Timeouts for File Service Operations. + // [https://docs.microsoft.com/en-us/rest/api/storageservices/Setting-Timeouts-for-File-Service-Operations?redirectedfrom=MSDN] + Timeout *int32 +} + +// FileClientChangeLeaseOptions contains the optional parameters for the FileClient.ChangeLease method. +type FileClientChangeLeaseOptions struct { + // Proposed lease ID, in a GUID string format. The File service returns 400 (Invalid request) if the proposed lease ID is + // not in the correct format. See Guid Constructor (String) for a list of valid GUID + // string formats. + ProposedLeaseID *string + // Provides a client-generated, opaque value with a 1 KB character limit that is recorded in the analytics logs when storage + // analytics logging is enabled. + RequestID *string + // The timeout parameter is expressed in seconds. For more information, see Setting Timeouts for File Service Operations. + // [https://docs.microsoft.com/en-us/rest/api/storageservices/Setting-Timeouts-for-File-Service-Operations?redirectedfrom=MSDN] + Timeout *int32 +} + +// FileClientCreateOptions contains the optional parameters for the FileClient.Create method. +type FileClientCreateOptions struct { + // If specified the permission (security descriptor) shall be set for the directory/file. This header can be used if Permission + // size is <= 8KB, else x-ms-file-permission-key header shall be used. Default + // value: Inherit. If SDDL is specified as input, it must have owner, group and dacl. Note: Only one of the x-ms-file-permission + // or x-ms-file-permission-key should be specified. + FilePermission *string + // Key of the permission to be set for the directory/file. Note: Only one of the x-ms-file-permission or x-ms-file-permission-key + // should be specified. + FilePermissionKey *string + // A name-value pair to associate with a file storage object. + Metadata map[string]*string + // The timeout parameter is expressed in seconds. For more information, see Setting Timeouts for File Service Operations. + // [https://docs.microsoft.com/en-us/rest/api/storageservices/Setting-Timeouts-for-File-Service-Operations?redirectedfrom=MSDN] + Timeout *int32 +} + +// FileClientDeleteOptions contains the optional parameters for the FileClient.Delete method. +type FileClientDeleteOptions struct { + // The timeout parameter is expressed in seconds. For more information, see Setting Timeouts for File Service Operations. + // [https://docs.microsoft.com/en-us/rest/api/storageservices/Setting-Timeouts-for-File-Service-Operations?redirectedfrom=MSDN] + Timeout *int32 +} + +// FileClientDownloadOptions contains the optional parameters for the FileClient.Download method. +type FileClientDownloadOptions struct { + // Return file data only from the specified byte range. + Range *string + // When this header is set to true and specified together with the Range header, the service returns the MD5 hash for the + // range, as long as the range is less than or equal to 4 MB in size. + RangeGetContentMD5 *bool + // The timeout parameter is expressed in seconds. For more information, see Setting Timeouts for File Service Operations. + // [https://docs.microsoft.com/en-us/rest/api/storageservices/Setting-Timeouts-for-File-Service-Operations?redirectedfrom=MSDN] + Timeout *int32 +} + +// FileClientForceCloseHandlesOptions contains the optional parameters for the FileClient.ForceCloseHandles method. +type FileClientForceCloseHandlesOptions struct { + // A string value that identifies the portion of the list to be returned with the next list operation. The operation returns + // a marker value within the response body if the list returned was not complete. + // The marker value may then be used in a subsequent call to request the next set of list items. The marker value is opaque + // to the client. + Marker *string + // The snapshot parameter is an opaque DateTime value that, when present, specifies the share snapshot to query. + Sharesnapshot *string + // The timeout parameter is expressed in seconds. For more information, see Setting Timeouts for File Service Operations. + // [https://docs.microsoft.com/en-us/rest/api/storageservices/Setting-Timeouts-for-File-Service-Operations?redirectedfrom=MSDN] + Timeout *int32 +} + +// FileClientGetPropertiesOptions contains the optional parameters for the FileClient.GetProperties method. +type FileClientGetPropertiesOptions struct { + // The snapshot parameter is an opaque DateTime value that, when present, specifies the share snapshot to query. + Sharesnapshot *string + // The timeout parameter is expressed in seconds. For more information, see Setting Timeouts for File Service Operations. + // [https://docs.microsoft.com/en-us/rest/api/storageservices/Setting-Timeouts-for-File-Service-Operations?redirectedfrom=MSDN] + Timeout *int32 +} + +// FileClientGetRangeListOptions contains the optional parameters for the FileClient.GetRangeList method. +type FileClientGetRangeListOptions struct { + // The previous snapshot parameter is an opaque DateTime value that, when present, specifies the previous snapshot. + Prevsharesnapshot *string + // Specifies the range of bytes over which to list ranges, inclusively. + Range *string + // The snapshot parameter is an opaque DateTime value that, when present, specifies the share snapshot to query. + Sharesnapshot *string + // The timeout parameter is expressed in seconds. For more information, see Setting Timeouts for File Service Operations. + // [https://docs.microsoft.com/en-us/rest/api/storageservices/Setting-Timeouts-for-File-Service-Operations?redirectedfrom=MSDN] + Timeout *int32 +} + +// FileClientListHandlesOptions contains the optional parameters for the FileClient.ListHandles method. +type FileClientListHandlesOptions struct { + // A string value that identifies the portion of the list to be returned with the next list operation. The operation returns + // a marker value within the response body if the list returned was not complete. + // The marker value may then be used in a subsequent call to request the next set of list items. The marker value is opaque + // to the client. + Marker *string + // Specifies the maximum number of entries to return. If the request does not specify maxresults, or specifies a value greater + // than 5,000, the server will return up to 5,000 items. + Maxresults *int32 + // The snapshot parameter is an opaque DateTime value that, when present, specifies the share snapshot to query. + Sharesnapshot *string + // The timeout parameter is expressed in seconds. For more information, see Setting Timeouts for File Service Operations. + // [https://docs.microsoft.com/en-us/rest/api/storageservices/Setting-Timeouts-for-File-Service-Operations?redirectedfrom=MSDN] + Timeout *int32 +} + +// FileClientReleaseLeaseOptions contains the optional parameters for the FileClient.ReleaseLease method. +type FileClientReleaseLeaseOptions struct { + // Provides a client-generated, opaque value with a 1 KB character limit that is recorded in the analytics logs when storage + // analytics logging is enabled. + RequestID *string + // The timeout parameter is expressed in seconds. For more information, see Setting Timeouts for File Service Operations. + // [https://docs.microsoft.com/en-us/rest/api/storageservices/Setting-Timeouts-for-File-Service-Operations?redirectedfrom=MSDN] + Timeout *int32 +} + +// FileClientSetHTTPHeadersOptions contains the optional parameters for the FileClient.SetHTTPHeaders method. +type FileClientSetHTTPHeadersOptions struct { + // Resizes a file to the specified size. If the specified byte value is less than the current size of the file, then all ranges + // above the specified byte value are cleared. + FileContentLength *int64 + // If specified the permission (security descriptor) shall be set for the directory/file. This header can be used if Permission + // size is <= 8KB, else x-ms-file-permission-key header shall be used. Default + // value: Inherit. If SDDL is specified as input, it must have owner, group and dacl. Note: Only one of the x-ms-file-permission + // or x-ms-file-permission-key should be specified. + FilePermission *string + // Key of the permission to be set for the directory/file. Note: Only one of the x-ms-file-permission or x-ms-file-permission-key + // should be specified. + FilePermissionKey *string + // The timeout parameter is expressed in seconds. For more information, see Setting Timeouts for File Service Operations. + // [https://docs.microsoft.com/en-us/rest/api/storageservices/Setting-Timeouts-for-File-Service-Operations?redirectedfrom=MSDN] + Timeout *int32 +} + +// FileClientSetMetadataOptions contains the optional parameters for the FileClient.SetMetadata method. +type FileClientSetMetadataOptions struct { + // A name-value pair to associate with a file storage object. + Metadata map[string]*string + // The timeout parameter is expressed in seconds. For more information, see Setting Timeouts for File Service Operations. + // [https://docs.microsoft.com/en-us/rest/api/storageservices/Setting-Timeouts-for-File-Service-Operations?redirectedfrom=MSDN] + Timeout *int32 +} + +// FileClientStartCopyOptions contains the optional parameters for the FileClient.StartCopy method. +type FileClientStartCopyOptions struct { + // If specified the permission (security descriptor) shall be set for the directory/file. This header can be used if Permission + // size is <= 8KB, else x-ms-file-permission-key header shall be used. Default + // value: Inherit. If SDDL is specified as input, it must have owner, group and dacl. Note: Only one of the x-ms-file-permission + // or x-ms-file-permission-key should be specified. + FilePermission *string + // Key of the permission to be set for the directory/file. Note: Only one of the x-ms-file-permission or x-ms-file-permission-key + // should be specified. + FilePermissionKey *string + // A name-value pair to associate with a file storage object. + Metadata map[string]*string + // The timeout parameter is expressed in seconds. For more information, see Setting Timeouts for File Service Operations. + // [https://docs.microsoft.com/en-us/rest/api/storageservices/Setting-Timeouts-for-File-Service-Operations?redirectedfrom=MSDN] + Timeout *int32 +} + +// FileClientUploadRangeFromURLOptions contains the optional parameters for the FileClient.UploadRangeFromURL method. +type FileClientUploadRangeFromURLOptions struct { + // Only Bearer type is supported. Credentials should be a valid OAuth access token to copy source. + CopySourceAuthorization *string + // Specify the crc64 calculated for the range of bytes that must be read from the copy source. + SourceContentCRC64 []byte + // Bytes of source data in the specified range. + SourceRange *string + // The timeout parameter is expressed in seconds. For more information, see Setting Timeouts for File Service Operations. + // [https://docs.microsoft.com/en-us/rest/api/storageservices/Setting-Timeouts-for-File-Service-Operations?redirectedfrom=MSDN] + Timeout *int32 +} + +// FileClientUploadRangeOptions contains the optional parameters for the FileClient.UploadRange method. +type FileClientUploadRangeOptions struct { + // An MD5 hash of the content. This hash is used to verify the integrity of the data during transport. When the Content-MD5 + // header is specified, the File service compares the hash of the content that has + // arrived with the header value that was sent. If the two hashes do not match, the operation will fail with error code 400 + // (Bad Request). + ContentMD5 []byte + // The timeout parameter is expressed in seconds. For more information, see Setting Timeouts for File Service Operations. + // [https://docs.microsoft.com/en-us/rest/api/storageservices/Setting-Timeouts-for-File-Service-Operations?redirectedfrom=MSDN] + Timeout *int32 +} + +// FileProperty - File properties. +type FileProperty struct { + // REQUIRED; Content length of the file. This value may not be up-to-date since an SMB client may have modified the file locally. + // The value of Content-Length may not reflect that fact until the handle is closed or + // the op-lock is broken. To retrieve current property values, call Get File Properties. + ContentLength *int64 `xml:"Content-Length"` + ChangeTime *time.Time `xml:"ChangeTime"` + CreationTime *time.Time `xml:"CreationTime"` + ETag *azcore.ETag `xml:"Etag"` + LastAccessTime *time.Time `xml:"LastAccessTime"` + LastModified *time.Time `xml:"Last-Modified"` + LastWriteTime *time.Time `xml:"LastWriteTime"` +} + +// FileRange - An Azure Storage file range. +type FileRange struct { + // REQUIRED; End of the range. + End *int64 `xml:"End"` + + // REQUIRED; Start of the range. + Start *int64 `xml:"Start"` +} + +// FilesAndDirectoriesListSegment - Abstract for entries that can be listed from Directory. +type FilesAndDirectoriesListSegment struct { + // REQUIRED + Directories []*Directory `xml:"Directory"` + + // REQUIRED + Files []*File `xml:"File"` +} + +// Handle - A listed Azure Storage handle item. +type Handle struct { + // REQUIRED; Client IP that opened the handle + ClientIP *string `xml:"ClientIp"` + + // REQUIRED; FileId uniquely identifies the file or directory. + FileID *string `xml:"FileId"` + + // REQUIRED; XSMB service handle ID + ID *string `xml:"HandleId"` + + // REQUIRED; Time when the session that previously opened the handle has last been reconnected. (UTC) + OpenTime *time.Time `xml:"OpenTime"` + + // REQUIRED; File or directory name including full path starting from share root + Path *string `xml:"Path"` + + // REQUIRED; SMB session ID in context of which the file handle was opened + SessionID *string `xml:"SessionId"` + + // Time handle was last connected to (UTC) + LastReconnectTime *time.Time `xml:"LastReconnectTime"` + + // ParentId uniquely identifies the parent directory of the object. + ParentID *string `xml:"ParentId"` +} + +// LeaseAccessConditions contains a group of parameters for the ShareClient.GetProperties method. +type LeaseAccessConditions struct { + // If specified, the operation only succeeds if the resource's lease is active and matches this ID. + LeaseID *string +} + +// ListFilesAndDirectoriesSegmentResponse - An enumeration of directories and files. +type ListFilesAndDirectoriesSegmentResponse struct { + // REQUIRED + DirectoryPath *string `xml:"DirectoryPath,attr"` + + // REQUIRED + NextMarker *string `xml:"NextMarker"` + + // REQUIRED + Prefix *string `xml:"Prefix"` + + // REQUIRED; Abstract for entries that can be listed from Directory. + Segment *FilesAndDirectoriesListSegment `xml:"Entries"` + + // REQUIRED + ServiceEndpoint *string `xml:"ServiceEndpoint,attr"` + + // REQUIRED + ShareName *string `xml:"ShareName,attr"` + DirectoryID *string `xml:"DirectoryId"` + Marker *string `xml:"Marker"` + MaxResults *int32 `xml:"MaxResults"` + ShareSnapshot *string `xml:"ShareSnapshot,attr"` +} + +// ListHandlesResponse - An enumeration of handles. +type ListHandlesResponse struct { + // REQUIRED + NextMarker *string `xml:"NextMarker"` + Handles []*Handle `xml:"Entries>Handle"` +} + +// ListSharesResponse - An enumeration of shares. +type ListSharesResponse struct { + // REQUIRED + NextMarker *string `xml:"NextMarker"` + + // REQUIRED + ServiceEndpoint *string `xml:"ServiceEndpoint,attr"` + Marker *string `xml:"Marker"` + MaxResults *int32 `xml:"MaxResults"` + Prefix *string `xml:"Prefix"` + Shares []*Share `xml:"Shares>Share"` +} + +// Metrics - Storage Analytics metrics for file service. +type Metrics struct { + // REQUIRED; Indicates whether metrics are enabled for the File service. + Enabled *bool `xml:"Enabled"` + + // REQUIRED; The version of Storage Analytics to configure. + Version *string `xml:"Version"` + + // Indicates whether metrics should generate summary statistics for called API operations. + IncludeAPIs *bool `xml:"IncludeAPIs"` + + // The retention policy. + RetentionPolicy *RetentionPolicy `xml:"RetentionPolicy"` +} + +// ProtocolSettings - Protocol settings +type ProtocolSettings struct { + // Settings for SMB protocol. + Smb *SMBSettings `xml:"SMB"` +} + +// RetentionPolicy - The retention policy. +type RetentionPolicy struct { + // REQUIRED; Indicates whether a retention policy is enabled for the File service. If false, metrics data is retained, and + // the user is responsible for deleting it. + Enabled *bool `xml:"Enabled"` + + // Indicates the number of days that metrics data should be retained. All data older than this value will be deleted. Metrics + // data is deleted on a best-effort basis after the retention period expires. + Days *int32 `xml:"Days"` +} + +// SMBSettings - Settings for SMB protocol. +type SMBSettings struct { + // Settings for SMB Multichannel. + Multichannel *SMBMultichannel `xml:"Multichannel"` +} + +// ServiceClientGetPropertiesOptions contains the optional parameters for the ServiceClient.GetProperties method. +type ServiceClientGetPropertiesOptions struct { + // The timeout parameter is expressed in seconds. For more information, see Setting Timeouts for File Service Operations. + // [https://docs.microsoft.com/en-us/rest/api/storageservices/Setting-Timeouts-for-File-Service-Operations?redirectedfrom=MSDN] + Timeout *int32 +} + +// ServiceClientListSharesSegmentOptions contains the optional parameters for the ServiceClient.NewListSharesSegmentPager +// method. +type ServiceClientListSharesSegmentOptions struct { + // Include this parameter to specify one or more datasets to include in the response. + Include []ListSharesIncludeType + // A string value that identifies the portion of the list to be returned with the next list operation. The operation returns + // a marker value within the response body if the list returned was not complete. + // The marker value may then be used in a subsequent call to request the next set of list items. The marker value is opaque + // to the client. + Marker *string + // Specifies the maximum number of entries to return. If the request does not specify maxresults, or specifies a value greater + // than 5,000, the server will return up to 5,000 items. + Maxresults *int32 + // Filters the results to return only entries whose name begins with the specified prefix. + Prefix *string + // The timeout parameter is expressed in seconds. For more information, see Setting Timeouts for File Service Operations. + // [https://docs.microsoft.com/en-us/rest/api/storageservices/Setting-Timeouts-for-File-Service-Operations?redirectedfrom=MSDN] + Timeout *int32 +} + +// ServiceClientSetPropertiesOptions contains the optional parameters for the ServiceClient.SetProperties method. +type ServiceClientSetPropertiesOptions struct { + // The timeout parameter is expressed in seconds. For more information, see Setting Timeouts for File Service Operations. + // [https://docs.microsoft.com/en-us/rest/api/storageservices/Setting-Timeouts-for-File-Service-Operations?redirectedfrom=MSDN] + Timeout *int32 +} + +// Share - A listed Azure Storage share item. +type Share struct { + // REQUIRED + Name *string `xml:"Name"` + + // REQUIRED; Properties of a share. + Properties *ShareProperties `xml:"Properties"` + Deleted *bool `xml:"Deleted"` + + // Dictionary of + Metadata map[string]*string `xml:"Metadata"` + Snapshot *string `xml:"Snapshot"` + Version *string `xml:"Version"` +} + +// ShareClientAcquireLeaseOptions contains the optional parameters for the ShareClient.AcquireLease method. +type ShareClientAcquireLeaseOptions struct { + // Proposed lease ID, in a GUID string format. The File service returns 400 (Invalid request) if the proposed lease ID is + // not in the correct format. See Guid Constructor (String) for a list of valid GUID + // string formats. + ProposedLeaseID *string + // Provides a client-generated, opaque value with a 1 KB character limit that is recorded in the analytics logs when storage + // analytics logging is enabled. + RequestID *string + // The snapshot parameter is an opaque DateTime value that, when present, specifies the share snapshot to query. + Sharesnapshot *string + // The timeout parameter is expressed in seconds. For more information, see Setting Timeouts for File Service Operations. + // [https://docs.microsoft.com/en-us/rest/api/storageservices/Setting-Timeouts-for-File-Service-Operations?redirectedfrom=MSDN] + Timeout *int32 +} + +// ShareClientBreakLeaseOptions contains the optional parameters for the ShareClient.BreakLease method. +type ShareClientBreakLeaseOptions struct { + // For a break operation, proposed duration the lease should continue before it is broken, in seconds, between 0 and 60. This + // break period is only used if it is shorter than the time remaining on the + // lease. If longer, the time remaining on the lease is used. A new lease will not be available before the break period has + // expired, but the lease may be held for longer than the break period. If this + // header does not appear with a break operation, a fixed-duration lease breaks after the remaining lease period elapses, + // and an infinite lease breaks immediately. + BreakPeriod *int32 + // Provides a client-generated, opaque value with a 1 KB character limit that is recorded in the analytics logs when storage + // analytics logging is enabled. + RequestID *string + // The snapshot parameter is an opaque DateTime value that, when present, specifies the share snapshot to query. + Sharesnapshot *string + // The timeout parameter is expressed in seconds. For more information, see Setting Timeouts for File Service Operations. + // [https://docs.microsoft.com/en-us/rest/api/storageservices/Setting-Timeouts-for-File-Service-Operations?redirectedfrom=MSDN] + Timeout *int32 +} + +// ShareClientChangeLeaseOptions contains the optional parameters for the ShareClient.ChangeLease method. +type ShareClientChangeLeaseOptions struct { + // Proposed lease ID, in a GUID string format. The File service returns 400 (Invalid request) if the proposed lease ID is + // not in the correct format. See Guid Constructor (String) for a list of valid GUID + // string formats. + ProposedLeaseID *string + // Provides a client-generated, opaque value with a 1 KB character limit that is recorded in the analytics logs when storage + // analytics logging is enabled. + RequestID *string + // The snapshot parameter is an opaque DateTime value that, when present, specifies the share snapshot to query. + Sharesnapshot *string + // The timeout parameter is expressed in seconds. For more information, see Setting Timeouts for File Service Operations. + // [https://docs.microsoft.com/en-us/rest/api/storageservices/Setting-Timeouts-for-File-Service-Operations?redirectedfrom=MSDN] + Timeout *int32 +} + +// ShareClientCreateOptions contains the optional parameters for the ShareClient.Create method. +type ShareClientCreateOptions struct { + // Specifies the access tier of the share. + AccessTier *ShareAccessTier + // Protocols to enable on the share. + EnabledProtocols *string + // A name-value pair to associate with a file storage object. + Metadata map[string]*string + // Specifies the maximum size of the share, in gigabytes. + Quota *int32 + // Root squash to set on the share. Only valid for NFS shares. + RootSquash *ShareRootSquash + // The timeout parameter is expressed in seconds. For more information, see Setting Timeouts for File Service Operations. + // [https://docs.microsoft.com/en-us/rest/api/storageservices/Setting-Timeouts-for-File-Service-Operations?redirectedfrom=MSDN] + Timeout *int32 +} + +// ShareClientCreatePermissionOptions contains the optional parameters for the ShareClient.CreatePermission method. +type ShareClientCreatePermissionOptions struct { + // The timeout parameter is expressed in seconds. For more information, see Setting Timeouts for File Service Operations. + // [https://docs.microsoft.com/en-us/rest/api/storageservices/Setting-Timeouts-for-File-Service-Operations?redirectedfrom=MSDN] + Timeout *int32 +} + +// ShareClientCreateSnapshotOptions contains the optional parameters for the ShareClient.CreateSnapshot method. +type ShareClientCreateSnapshotOptions struct { + // A name-value pair to associate with a file storage object. + Metadata map[string]*string + // The timeout parameter is expressed in seconds. For more information, see Setting Timeouts for File Service Operations. + // [https://docs.microsoft.com/en-us/rest/api/storageservices/Setting-Timeouts-for-File-Service-Operations?redirectedfrom=MSDN] + Timeout *int32 +} + +// ShareClientDeleteOptions contains the optional parameters for the ShareClient.Delete method. +type ShareClientDeleteOptions struct { + // Specifies the option include to delete the base share and all of its snapshots. + DeleteSnapshots *DeleteSnapshotsOptionType + // The snapshot parameter is an opaque DateTime value that, when present, specifies the share snapshot to query. + Sharesnapshot *string + // The timeout parameter is expressed in seconds. For more information, see Setting Timeouts for File Service Operations. + // [https://docs.microsoft.com/en-us/rest/api/storageservices/Setting-Timeouts-for-File-Service-Operations?redirectedfrom=MSDN] + Timeout *int32 +} + +// ShareClientGetAccessPolicyOptions contains the optional parameters for the ShareClient.GetAccessPolicy method. +type ShareClientGetAccessPolicyOptions struct { + // The timeout parameter is expressed in seconds. For more information, see Setting Timeouts for File Service Operations. + // [https://docs.microsoft.com/en-us/rest/api/storageservices/Setting-Timeouts-for-File-Service-Operations?redirectedfrom=MSDN] + Timeout *int32 +} + +// ShareClientGetPermissionOptions contains the optional parameters for the ShareClient.GetPermission method. +type ShareClientGetPermissionOptions struct { + // The timeout parameter is expressed in seconds. For more information, see Setting Timeouts for File Service Operations. + // [https://docs.microsoft.com/en-us/rest/api/storageservices/Setting-Timeouts-for-File-Service-Operations?redirectedfrom=MSDN] + Timeout *int32 +} + +// ShareClientGetPropertiesOptions contains the optional parameters for the ShareClient.GetProperties method. +type ShareClientGetPropertiesOptions struct { + // The snapshot parameter is an opaque DateTime value that, when present, specifies the share snapshot to query. + Sharesnapshot *string + // The timeout parameter is expressed in seconds. For more information, see Setting Timeouts for File Service Operations. + // [https://docs.microsoft.com/en-us/rest/api/storageservices/Setting-Timeouts-for-File-Service-Operations?redirectedfrom=MSDN] + Timeout *int32 +} + +// ShareClientGetStatisticsOptions contains the optional parameters for the ShareClient.GetStatistics method. +type ShareClientGetStatisticsOptions struct { + // The timeout parameter is expressed in seconds. For more information, see Setting Timeouts for File Service Operations. + // [https://docs.microsoft.com/en-us/rest/api/storageservices/Setting-Timeouts-for-File-Service-Operations?redirectedfrom=MSDN] + Timeout *int32 +} + +// ShareClientReleaseLeaseOptions contains the optional parameters for the ShareClient.ReleaseLease method. +type ShareClientReleaseLeaseOptions struct { + // Provides a client-generated, opaque value with a 1 KB character limit that is recorded in the analytics logs when storage + // analytics logging is enabled. + RequestID *string + // The snapshot parameter is an opaque DateTime value that, when present, specifies the share snapshot to query. + Sharesnapshot *string + // The timeout parameter is expressed in seconds. For more information, see Setting Timeouts for File Service Operations. + // [https://docs.microsoft.com/en-us/rest/api/storageservices/Setting-Timeouts-for-File-Service-Operations?redirectedfrom=MSDN] + Timeout *int32 +} + +// ShareClientRenewLeaseOptions contains the optional parameters for the ShareClient.RenewLease method. +type ShareClientRenewLeaseOptions struct { + // Provides a client-generated, opaque value with a 1 KB character limit that is recorded in the analytics logs when storage + // analytics logging is enabled. + RequestID *string + // The snapshot parameter is an opaque DateTime value that, when present, specifies the share snapshot to query. + Sharesnapshot *string + // The timeout parameter is expressed in seconds. For more information, see Setting Timeouts for File Service Operations. + // [https://docs.microsoft.com/en-us/rest/api/storageservices/Setting-Timeouts-for-File-Service-Operations?redirectedfrom=MSDN] + Timeout *int32 +} + +// ShareClientRestoreOptions contains the optional parameters for the ShareClient.Restore method. +type ShareClientRestoreOptions struct { + // Specifies the name of the previously-deleted share. + DeletedShareName *string + // Specifies the version of the previously-deleted share. + DeletedShareVersion *string + // Provides a client-generated, opaque value with a 1 KB character limit that is recorded in the analytics logs when storage + // analytics logging is enabled. + RequestID *string + // The timeout parameter is expressed in seconds. For more information, see Setting Timeouts for File Service Operations. + // [https://docs.microsoft.com/en-us/rest/api/storageservices/Setting-Timeouts-for-File-Service-Operations?redirectedfrom=MSDN] + Timeout *int32 +} + +// ShareClientSetAccessPolicyOptions contains the optional parameters for the ShareClient.SetAccessPolicy method. +type ShareClientSetAccessPolicyOptions struct { + // The timeout parameter is expressed in seconds. For more information, see Setting Timeouts for File Service Operations. + // [https://docs.microsoft.com/en-us/rest/api/storageservices/Setting-Timeouts-for-File-Service-Operations?redirectedfrom=MSDN] + Timeout *int32 +} + +// ShareClientSetMetadataOptions contains the optional parameters for the ShareClient.SetMetadata method. +type ShareClientSetMetadataOptions struct { + // A name-value pair to associate with a file storage object. + Metadata map[string]*string + // The timeout parameter is expressed in seconds. For more information, see Setting Timeouts for File Service Operations. + // [https://docs.microsoft.com/en-us/rest/api/storageservices/Setting-Timeouts-for-File-Service-Operations?redirectedfrom=MSDN] + Timeout *int32 +} + +// ShareClientSetPropertiesOptions contains the optional parameters for the ShareClient.SetProperties method. +type ShareClientSetPropertiesOptions struct { + // Specifies the access tier of the share. + AccessTier *ShareAccessTier + // Specifies the maximum size of the share, in gigabytes. + Quota *int32 + // Root squash to set on the share. Only valid for NFS shares. + RootSquash *ShareRootSquash + // The timeout parameter is expressed in seconds. For more information, see Setting Timeouts for File Service Operations. + // [https://docs.microsoft.com/en-us/rest/api/storageservices/Setting-Timeouts-for-File-Service-Operations?redirectedfrom=MSDN] + Timeout *int32 +} + +// ShareFileHTTPHeaders contains a group of parameters for the FileClient.Create method. +type ShareFileHTTPHeaders struct { + // Sets the file's cache control. The File service stores this value but does not use or modify it. + CacheControl *string + // Sets the file's Content-Disposition header. + ContentDisposition *string + // Specifies which content encodings have been applied to the file. + ContentEncoding *string + // Specifies the natural languages used by this resource. + ContentLanguage *string + // Sets the file's MD5 hash. + ContentMD5 []byte + // Sets the MIME content type of the file. The default type is 'application/octet-stream'. + ContentType *string +} + +// ShareFileRangeList - The list of file ranges +type ShareFileRangeList struct { + ClearRanges []*ClearRange `xml:"ClearRange"` + Ranges []*FileRange `xml:"Range"` +} + +// SharePermission - A permission (a security descriptor) at the share level. +type SharePermission struct { + // REQUIRED; The permission in the Security Descriptor Definition Language (SDDL). + Permission *string `json:"permission,omitempty"` +} + +// ShareProperties - Properties of a share. +type ShareProperties struct { + // REQUIRED + ETag *azcore.ETag `xml:"Etag"` + + // REQUIRED + LastModified *time.Time `xml:"Last-Modified"` + + // REQUIRED + Quota *int32 `xml:"Quota"` + AccessTier *string `xml:"AccessTier"` + AccessTierChangeTime *time.Time `xml:"AccessTierChangeTime"` + AccessTierTransitionState *string `xml:"AccessTierTransitionState"` + DeletedTime *time.Time `xml:"DeletedTime"` + EnabledProtocols *string `xml:"EnabledProtocols"` + + // When a share is leased, specifies whether the lease is of infinite or fixed duration. + LeaseDuration *LeaseDurationType `xml:"LeaseDuration"` + + // Lease state of the share. + LeaseState *LeaseStateType `xml:"LeaseState"` + + // The current lease status of the share. + LeaseStatus *LeaseStatusType `xml:"LeaseStatus"` + NextAllowedQuotaDowngradeTime *time.Time `xml:"NextAllowedQuotaDowngradeTime"` + ProvisionedEgressMBps *int32 `xml:"ProvisionedEgressMBps"` + ProvisionedIngressMBps *int32 `xml:"ProvisionedIngressMBps"` + ProvisionedIops *int32 `xml:"ProvisionedIops"` + RemainingRetentionDays *int32 `xml:"RemainingRetentionDays"` + RootSquash *ShareRootSquash `xml:"RootSquash"` +} + +// ShareStats - Stats for the share. +type ShareStats struct { + // REQUIRED; The approximate size of the data stored in bytes. Note that this value may not include all recently created or + // recently resized files. + ShareUsageBytes *int64 `xml:"ShareUsageBytes"` +} + +// SignedIdentifier - Signed identifier. +type SignedIdentifier struct { + // REQUIRED; A unique id. + ID *string `xml:"Id"` + + // The access policy. + AccessPolicy *AccessPolicy `xml:"AccessPolicy"` +} + +// SMBMultichannel - Settings for SMB multichannel +type SMBMultichannel struct { + // If SMB multichannel is enabled. + Enabled *bool `xml:"Enabled"` +} + +// SourceModifiedAccessConditions contains a group of parameters for the FileClient.UploadRangeFromURL method. +type SourceModifiedAccessConditions struct { + // Specify the crc64 value to operate only on range with a matching crc64 checksum. + SourceIfMatchCRC64 []byte + // Specify the crc64 value to operate only on range without a matching crc64 checksum. + SourceIfNoneMatchCRC64 []byte +} + +type StorageError struct { + Message *string `json:"Message,omitempty"` +} + +// StorageServiceProperties - Storage service properties. +type StorageServiceProperties struct { + // The set of CORS rules. + CORS []*CORSRule `xml:"Cors>CorsRule"` + + // A summary of request statistics grouped by API in hourly aggregates for files. + HourMetrics *Metrics `xml:"HourMetrics"` + + // A summary of request statistics grouped by API in minute aggregates for files. + MinuteMetrics *Metrics `xml:"MinuteMetrics"` + + // Protocol settings + Protocol *ProtocolSettings `xml:"ProtocolSettings"` +} diff --git a/sdk/storage/azfile/internal/generated/zz_models_serde.go b/sdk/storage/azfile/internal/generated/zz_models_serde.go new file mode 100644 index 000000000000..7f837baac65c --- /dev/null +++ b/sdk/storage/azfile/internal/generated/zz_models_serde.go @@ -0,0 +1,344 @@ +//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. +// Code generated by Microsoft (R) AutoRest Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. +// DO NOT EDIT. + +package generated + +import ( + "encoding/json" + "encoding/xml" + "fmt" + "github.com/Azure/azure-sdk-for-go/sdk/azcore" + "reflect" + "time" +) + +// MarshalXML implements the xml.Marshaller interface for type AccessPolicy. +func (a AccessPolicy) MarshalXML(enc *xml.Encoder, start xml.StartElement) error { + type alias AccessPolicy + aux := &struct { + *alias + Expiry *timeRFC3339 `xml:"Expiry"` + Start *timeRFC3339 `xml:"Start"` + }{ + alias: (*alias)(&a), + Expiry: (*timeRFC3339)(a.Expiry), + Start: (*timeRFC3339)(a.Start), + } + return enc.EncodeElement(aux, start) +} + +// UnmarshalXML implements the xml.Unmarshaller interface for type AccessPolicy. +func (a *AccessPolicy) UnmarshalXML(dec *xml.Decoder, start xml.StartElement) error { + type alias AccessPolicy + aux := &struct { + *alias + Expiry *timeRFC3339 `xml:"Expiry"` + Start *timeRFC3339 `xml:"Start"` + }{ + alias: (*alias)(a), + } + if err := dec.DecodeElement(aux, &start); err != nil { + return err + } + a.Expiry = (*time.Time)(aux.Expiry) + a.Start = (*time.Time)(aux.Start) + return nil +} + +// MarshalXML implements the xml.Marshaller interface for type FileProperty. +func (f FileProperty) MarshalXML(enc *xml.Encoder, start xml.StartElement) error { + type alias FileProperty + aux := &struct { + *alias + ChangeTime *timeRFC3339 `xml:"ChangeTime"` + CreationTime *timeRFC3339 `xml:"CreationTime"` + LastAccessTime *timeRFC3339 `xml:"LastAccessTime"` + LastModified *timeRFC1123 `xml:"Last-Modified"` + LastWriteTime *timeRFC3339 `xml:"LastWriteTime"` + }{ + alias: (*alias)(&f), + ChangeTime: (*timeRFC3339)(f.ChangeTime), + CreationTime: (*timeRFC3339)(f.CreationTime), + LastAccessTime: (*timeRFC3339)(f.LastAccessTime), + LastModified: (*timeRFC1123)(f.LastModified), + LastWriteTime: (*timeRFC3339)(f.LastWriteTime), + } + return enc.EncodeElement(aux, start) +} + +// UnmarshalXML implements the xml.Unmarshaller interface for type FileProperty. +func (f *FileProperty) UnmarshalXML(dec *xml.Decoder, start xml.StartElement) error { + type alias FileProperty + aux := &struct { + *alias + ChangeTime *timeRFC3339 `xml:"ChangeTime"` + CreationTime *timeRFC3339 `xml:"CreationTime"` + LastAccessTime *timeRFC3339 `xml:"LastAccessTime"` + LastModified *timeRFC1123 `xml:"Last-Modified"` + LastWriteTime *timeRFC3339 `xml:"LastWriteTime"` + }{ + alias: (*alias)(f), + } + if err := dec.DecodeElement(aux, &start); err != nil { + return err + } + f.ChangeTime = (*time.Time)(aux.ChangeTime) + f.CreationTime = (*time.Time)(aux.CreationTime) + f.LastAccessTime = (*time.Time)(aux.LastAccessTime) + f.LastModified = (*time.Time)(aux.LastModified) + f.LastWriteTime = (*time.Time)(aux.LastWriteTime) + return nil +} + +// MarshalXML implements the xml.Marshaller interface for type FilesAndDirectoriesListSegment. +func (f FilesAndDirectoriesListSegment) MarshalXML(enc *xml.Encoder, start xml.StartElement) error { + type alias FilesAndDirectoriesListSegment + aux := &struct { + *alias + Directories *[]*Directory `xml:"Directory"` + Files *[]*File `xml:"File"` + }{ + alias: (*alias)(&f), + } + if f.Directories != nil { + aux.Directories = &f.Directories + } + if f.Files != nil { + aux.Files = &f.Files + } + return enc.EncodeElement(aux, start) +} + +// MarshalXML implements the xml.Marshaller interface for type Handle. +func (h Handle) MarshalXML(enc *xml.Encoder, start xml.StartElement) error { + type alias Handle + aux := &struct { + *alias + LastReconnectTime *timeRFC1123 `xml:"LastReconnectTime"` + OpenTime *timeRFC1123 `xml:"OpenTime"` + }{ + alias: (*alias)(&h), + LastReconnectTime: (*timeRFC1123)(h.LastReconnectTime), + OpenTime: (*timeRFC1123)(h.OpenTime), + } + return enc.EncodeElement(aux, start) +} + +// UnmarshalXML implements the xml.Unmarshaller interface for type Handle. +func (h *Handle) UnmarshalXML(dec *xml.Decoder, start xml.StartElement) error { + type alias Handle + aux := &struct { + *alias + LastReconnectTime *timeRFC1123 `xml:"LastReconnectTime"` + OpenTime *timeRFC1123 `xml:"OpenTime"` + }{ + alias: (*alias)(h), + } + if err := dec.DecodeElement(aux, &start); err != nil { + return err + } + h.LastReconnectTime = (*time.Time)(aux.LastReconnectTime) + h.OpenTime = (*time.Time)(aux.OpenTime) + return nil +} + +// MarshalXML implements the xml.Marshaller interface for type ListHandlesResponse. +func (l ListHandlesResponse) MarshalXML(enc *xml.Encoder, start xml.StartElement) error { + type alias ListHandlesResponse + aux := &struct { + *alias + Handles *[]*Handle `xml:"Entries>Handle"` + }{ + alias: (*alias)(&l), + } + if l.Handles != nil { + aux.Handles = &l.Handles + } + return enc.EncodeElement(aux, start) +} + +// MarshalXML implements the xml.Marshaller interface for type ListSharesResponse. +func (l ListSharesResponse) MarshalXML(enc *xml.Encoder, start xml.StartElement) error { + type alias ListSharesResponse + aux := &struct { + *alias + Shares *[]*Share `xml:"Shares>Share"` + }{ + alias: (*alias)(&l), + } + if l.Shares != nil { + aux.Shares = &l.Shares + } + return enc.EncodeElement(aux, start) +} + +// UnmarshalXML implements the xml.Unmarshaller interface for type Share. +func (s *Share) UnmarshalXML(dec *xml.Decoder, start xml.StartElement) error { + type alias Share + aux := &struct { + *alias + Metadata additionalProperties `xml:"Metadata"` + }{ + alias: (*alias)(s), + } + if err := dec.DecodeElement(aux, &start); err != nil { + return err + } + s.Metadata = (map[string]*string)(aux.Metadata) + return nil +} + +// MarshalXML implements the xml.Marshaller interface for type ShareFileRangeList. +func (s ShareFileRangeList) MarshalXML(enc *xml.Encoder, start xml.StartElement) error { + type alias ShareFileRangeList + aux := &struct { + *alias + ClearRanges *[]*ClearRange `xml:"ClearRange"` + Ranges *[]*FileRange `xml:"Range"` + }{ + alias: (*alias)(&s), + } + if s.ClearRanges != nil { + aux.ClearRanges = &s.ClearRanges + } + if s.Ranges != nil { + aux.Ranges = &s.Ranges + } + return enc.EncodeElement(aux, start) +} + +// MarshalJSON implements the json.Marshaller interface for type SharePermission. +func (s SharePermission) MarshalJSON() ([]byte, error) { + objectMap := make(map[string]any) + populate(objectMap, "permission", s.Permission) + return json.Marshal(objectMap) +} + +// UnmarshalJSON implements the json.Unmarshaller interface for type SharePermission. +func (s *SharePermission) UnmarshalJSON(data []byte) error { + var rawMsg map[string]json.RawMessage + if err := json.Unmarshal(data, &rawMsg); err != nil { + return fmt.Errorf("unmarshalling type %T: %v", s, err) + } + for key, val := range rawMsg { + var err error + switch key { + case "permission": + err = unpopulate(val, "Permission", &s.Permission) + delete(rawMsg, key) + } + if err != nil { + return fmt.Errorf("unmarshalling type %T: %v", s, err) + } + } + return nil +} + +// MarshalXML implements the xml.Marshaller interface for type ShareProperties. +func (s ShareProperties) MarshalXML(enc *xml.Encoder, start xml.StartElement) error { + type alias ShareProperties + aux := &struct { + *alias + AccessTierChangeTime *timeRFC1123 `xml:"AccessTierChangeTime"` + DeletedTime *timeRFC1123 `xml:"DeletedTime"` + LastModified *timeRFC1123 `xml:"Last-Modified"` + NextAllowedQuotaDowngradeTime *timeRFC1123 `xml:"NextAllowedQuotaDowngradeTime"` + }{ + alias: (*alias)(&s), + AccessTierChangeTime: (*timeRFC1123)(s.AccessTierChangeTime), + DeletedTime: (*timeRFC1123)(s.DeletedTime), + LastModified: (*timeRFC1123)(s.LastModified), + NextAllowedQuotaDowngradeTime: (*timeRFC1123)(s.NextAllowedQuotaDowngradeTime), + } + return enc.EncodeElement(aux, start) +} + +// UnmarshalXML implements the xml.Unmarshaller interface for type ShareProperties. +func (s *ShareProperties) UnmarshalXML(dec *xml.Decoder, start xml.StartElement) error { + type alias ShareProperties + aux := &struct { + *alias + AccessTierChangeTime *timeRFC1123 `xml:"AccessTierChangeTime"` + DeletedTime *timeRFC1123 `xml:"DeletedTime"` + LastModified *timeRFC1123 `xml:"Last-Modified"` + NextAllowedQuotaDowngradeTime *timeRFC1123 `xml:"NextAllowedQuotaDowngradeTime"` + }{ + alias: (*alias)(s), + } + if err := dec.DecodeElement(aux, &start); err != nil { + return err + } + s.AccessTierChangeTime = (*time.Time)(aux.AccessTierChangeTime) + s.DeletedTime = (*time.Time)(aux.DeletedTime) + s.LastModified = (*time.Time)(aux.LastModified) + s.NextAllowedQuotaDowngradeTime = (*time.Time)(aux.NextAllowedQuotaDowngradeTime) + return nil +} + +// MarshalJSON implements the json.Marshaller interface for type StorageError. +func (s StorageError) MarshalJSON() ([]byte, error) { + objectMap := make(map[string]any) + populate(objectMap, "Message", s.Message) + return json.Marshal(objectMap) +} + +// UnmarshalJSON implements the json.Unmarshaller interface for type StorageError. +func (s *StorageError) UnmarshalJSON(data []byte) error { + var rawMsg map[string]json.RawMessage + if err := json.Unmarshal(data, &rawMsg); err != nil { + return fmt.Errorf("unmarshalling type %T: %v", s, err) + } + for key, val := range rawMsg { + var err error + switch key { + case "Message": + err = unpopulate(val, "Message", &s.Message) + delete(rawMsg, key) + } + if err != nil { + return fmt.Errorf("unmarshalling type %T: %v", s, err) + } + } + return nil +} + +// MarshalXML implements the xml.Marshaller interface for type StorageServiceProperties. +func (s StorageServiceProperties) MarshalXML(enc *xml.Encoder, start xml.StartElement) error { + type alias StorageServiceProperties + aux := &struct { + *alias + CORS *[]*CORSRule `xml:"Cors>CorsRule"` + }{ + alias: (*alias)(&s), + } + if s.CORS != nil { + aux.CORS = &s.CORS + } + return enc.EncodeElement(aux, start) +} + +func populate(m map[string]any, k string, v any) { + if v == nil { + return + } else if azcore.IsNullValue(v) { + m[k] = nil + } else if !reflect.ValueOf(v).IsNil() { + m[k] = v + } +} + +func unpopulate(data json.RawMessage, fn string, v any) error { + if data == nil { + return nil + } + if err := json.Unmarshal(data, v); err != nil { + return fmt.Errorf("struct field %s: %v", fn, err) + } + return nil +} diff --git a/sdk/storage/azfile/internal/generated/zz_response_types.go b/sdk/storage/azfile/internal/generated/zz_response_types.go new file mode 100644 index 000000000000..be6bf1f60562 --- /dev/null +++ b/sdk/storage/azfile/internal/generated/zz_response_types.go @@ -0,0 +1,1189 @@ +//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. +// Code generated by Microsoft (R) AutoRest Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. +// DO NOT EDIT. + +package generated + +import ( + "github.com/Azure/azure-sdk-for-go/sdk/azcore" + "io" + "time" +) + +// DirectoryClientCreateResponse contains the response from method DirectoryClient.Create. +type DirectoryClientCreateResponse struct { + // Date contains the information returned from the Date header response. + Date *time.Time + + // ETag contains the information returned from the ETag header response. + ETag *azcore.ETag + + // FileAttributes contains the information returned from the x-ms-file-attributes header response. + FileAttributes *string + + // FileChangeTime contains the information returned from the x-ms-file-change-time header response. + FileChangeTime *time.Time + + // FileCreationTime contains the information returned from the x-ms-file-creation-time header response. + FileCreationTime *time.Time + + // ID contains the information returned from the x-ms-file-id header response. + ID *string + + // FileLastWriteTime contains the information returned from the x-ms-file-last-write-time header response. + FileLastWriteTime *time.Time + + // ParentID contains the information returned from the x-ms-file-parent-id header response. + ParentID *string + + // FilePermissionKey contains the information returned from the x-ms-file-permission-key header response. + FilePermissionKey *string + + // IsServerEncrypted contains the information returned from the x-ms-request-server-encrypted header response. + IsServerEncrypted *bool + + // LastModified contains the information returned from the Last-Modified header response. + LastModified *time.Time + + // RequestID contains the information returned from the x-ms-request-id header response. + RequestID *string + + // Version contains the information returned from the x-ms-version header response. + Version *string +} + +// DirectoryClientDeleteResponse contains the response from method DirectoryClient.Delete. +type DirectoryClientDeleteResponse struct { + // Date contains the information returned from the Date header response. + Date *time.Time + + // RequestID contains the information returned from the x-ms-request-id header response. + RequestID *string + + // Version contains the information returned from the x-ms-version header response. + Version *string +} + +// DirectoryClientForceCloseHandlesResponse contains the response from method DirectoryClient.ForceCloseHandles. +type DirectoryClientForceCloseHandlesResponse struct { + // Date contains the information returned from the Date header response. + Date *time.Time + + // Marker contains the information returned from the x-ms-marker header response. + Marker *string + + // NumberOfHandlesClosed contains the information returned from the x-ms-number-of-handles-closed header response. + NumberOfHandlesClosed *int32 + + // NumberOfHandlesFailedToClose contains the information returned from the x-ms-number-of-handles-failed header response. + NumberOfHandlesFailedToClose *int32 + + // RequestID contains the information returned from the x-ms-request-id header response. + RequestID *string + + // Version contains the information returned from the x-ms-version header response. + Version *string +} + +// DirectoryClientGetPropertiesResponse contains the response from method DirectoryClient.GetProperties. +type DirectoryClientGetPropertiesResponse struct { + // Date contains the information returned from the Date header response. + Date *time.Time + + // ETag contains the information returned from the ETag header response. + ETag *azcore.ETag + + // FileAttributes contains the information returned from the x-ms-file-attributes header response. + FileAttributes *string + + // FileChangeTime contains the information returned from the x-ms-file-change-time header response. + FileChangeTime *time.Time + + // FileCreationTime contains the information returned from the x-ms-file-creation-time header response. + FileCreationTime *time.Time + + // ID contains the information returned from the x-ms-file-id header response. + ID *string + + // FileLastWriteTime contains the information returned from the x-ms-file-last-write-time header response. + FileLastWriteTime *time.Time + + // ParentID contains the information returned from the x-ms-file-parent-id header response. + ParentID *string + + // FilePermissionKey contains the information returned from the x-ms-file-permission-key header response. + FilePermissionKey *string + + // IsServerEncrypted contains the information returned from the x-ms-server-encrypted header response. + IsServerEncrypted *bool + + // LastModified contains the information returned from the Last-Modified header response. + LastModified *time.Time + + // Metadata contains the information returned from the x-ms-meta header response. + Metadata map[string]*string + + // RequestID contains the information returned from the x-ms-request-id header response. + RequestID *string + + // Version contains the information returned from the x-ms-version header response. + Version *string +} + +// DirectoryClientListFilesAndDirectoriesSegmentResponse contains the response from method DirectoryClient.NewListFilesAndDirectoriesSegmentPager. +type DirectoryClientListFilesAndDirectoriesSegmentResponse struct { + ListFilesAndDirectoriesSegmentResponse + // ContentType contains the information returned from the Content-Type header response. + ContentType *string `xml:"ContentType"` + + // Date contains the information returned from the Date header response. + Date *time.Time `xml:"Date"` + + // RequestID contains the information returned from the x-ms-request-id header response. + RequestID *string `xml:"RequestID"` + + // Version contains the information returned from the x-ms-version header response. + Version *string `xml:"Version"` +} + +// DirectoryClientListHandlesResponse contains the response from method DirectoryClient.ListHandles. +type DirectoryClientListHandlesResponse struct { + ListHandlesResponse + // ContentType contains the information returned from the Content-Type header response. + ContentType *string `xml:"ContentType"` + + // Date contains the information returned from the Date header response. + Date *time.Time `xml:"Date"` + + // RequestID contains the information returned from the x-ms-request-id header response. + RequestID *string `xml:"RequestID"` + + // Version contains the information returned from the x-ms-version header response. + Version *string `xml:"Version"` +} + +// DirectoryClientSetMetadataResponse contains the response from method DirectoryClient.SetMetadata. +type DirectoryClientSetMetadataResponse struct { + // Date contains the information returned from the Date header response. + Date *time.Time + + // ETag contains the information returned from the ETag header response. + ETag *azcore.ETag + + // IsServerEncrypted contains the information returned from the x-ms-request-server-encrypted header response. + IsServerEncrypted *bool + + // RequestID contains the information returned from the x-ms-request-id header response. + RequestID *string + + // Version contains the information returned from the x-ms-version header response. + Version *string +} + +// DirectoryClientSetPropertiesResponse contains the response from method DirectoryClient.SetProperties. +type DirectoryClientSetPropertiesResponse struct { + // Date contains the information returned from the Date header response. + Date *time.Time + + // ETag contains the information returned from the ETag header response. + ETag *azcore.ETag + + // FileAttributes contains the information returned from the x-ms-file-attributes header response. + FileAttributes *string + + // FileChangeTime contains the information returned from the x-ms-file-change-time header response. + FileChangeTime *time.Time + + // FileCreationTime contains the information returned from the x-ms-file-creation-time header response. + FileCreationTime *time.Time + + // ID contains the information returned from the x-ms-file-id header response. + ID *string + + // FileLastWriteTime contains the information returned from the x-ms-file-last-write-time header response. + FileLastWriteTime *time.Time + + // ParentID contains the information returned from the x-ms-file-parent-id header response. + ParentID *string + + // FilePermissionKey contains the information returned from the x-ms-file-permission-key header response. + FilePermissionKey *string + + // IsServerEncrypted contains the information returned from the x-ms-request-server-encrypted header response. + IsServerEncrypted *bool + + // LastModified contains the information returned from the Last-Modified header response. + LastModified *time.Time + + // RequestID contains the information returned from the x-ms-request-id header response. + RequestID *string + + // Version contains the information returned from the x-ms-version header response. + Version *string +} + +// FileClientAbortCopyResponse contains the response from method FileClient.AbortCopy. +type FileClientAbortCopyResponse struct { + // Date contains the information returned from the Date header response. + Date *time.Time + + // RequestID contains the information returned from the x-ms-request-id header response. + RequestID *string + + // Version contains the information returned from the x-ms-version header response. + Version *string +} + +// FileClientAcquireLeaseResponse contains the response from method FileClient.AcquireLease. +type FileClientAcquireLeaseResponse struct { + // ClientRequestID contains the information returned from the x-ms-client-request-id header response. + ClientRequestID *string + + // Date contains the information returned from the Date header response. + Date *time.Time + + // ETag contains the information returned from the ETag header response. + ETag *azcore.ETag + + // LastModified contains the information returned from the Last-Modified header response. + LastModified *time.Time + + // LeaseID contains the information returned from the x-ms-lease-id header response. + LeaseID *string + + // RequestID contains the information returned from the x-ms-request-id header response. + RequestID *string + + // Version contains the information returned from the x-ms-version header response. + Version *string +} + +// FileClientBreakLeaseResponse contains the response from method FileClient.BreakLease. +type FileClientBreakLeaseResponse struct { + // ClientRequestID contains the information returned from the x-ms-client-request-id header response. + ClientRequestID *string + + // Date contains the information returned from the Date header response. + Date *time.Time + + // ETag contains the information returned from the ETag header response. + ETag *azcore.ETag + + // LastModified contains the information returned from the Last-Modified header response. + LastModified *time.Time + + // LeaseID contains the information returned from the x-ms-lease-id header response. + LeaseID *string + + // RequestID contains the information returned from the x-ms-request-id header response. + RequestID *string + + // Version contains the information returned from the x-ms-version header response. + Version *string +} + +// FileClientChangeLeaseResponse contains the response from method FileClient.ChangeLease. +type FileClientChangeLeaseResponse struct { + // ClientRequestID contains the information returned from the x-ms-client-request-id header response. + ClientRequestID *string + + // Date contains the information returned from the Date header response. + Date *time.Time + + // ETag contains the information returned from the ETag header response. + ETag *azcore.ETag + + // LastModified contains the information returned from the Last-Modified header response. + LastModified *time.Time + + // LeaseID contains the information returned from the x-ms-lease-id header response. + LeaseID *string + + // RequestID contains the information returned from the x-ms-request-id header response. + RequestID *string + + // Version contains the information returned from the x-ms-version header response. + Version *string +} + +// FileClientCreateResponse contains the response from method FileClient.Create. +type FileClientCreateResponse struct { + // Date contains the information returned from the Date header response. + Date *time.Time + + // ETag contains the information returned from the ETag header response. + ETag *azcore.ETag + + // FileAttributes contains the information returned from the x-ms-file-attributes header response. + FileAttributes *string + + // FileChangeTime contains the information returned from the x-ms-file-change-time header response. + FileChangeTime *time.Time + + // FileCreationTime contains the information returned from the x-ms-file-creation-time header response. + FileCreationTime *time.Time + + // ID contains the information returned from the x-ms-file-id header response. + ID *string + + // FileLastWriteTime contains the information returned from the x-ms-file-last-write-time header response. + FileLastWriteTime *time.Time + + // ParentID contains the information returned from the x-ms-file-parent-id header response. + ParentID *string + + // FilePermissionKey contains the information returned from the x-ms-file-permission-key header response. + FilePermissionKey *string + + // IsServerEncrypted contains the information returned from the x-ms-request-server-encrypted header response. + IsServerEncrypted *bool + + // LastModified contains the information returned from the Last-Modified header response. + LastModified *time.Time + + // RequestID contains the information returned from the x-ms-request-id header response. + RequestID *string + + // Version contains the information returned from the x-ms-version header response. + Version *string +} + +// FileClientDeleteResponse contains the response from method FileClient.Delete. +type FileClientDeleteResponse struct { + // Date contains the information returned from the Date header response. + Date *time.Time + + // RequestID contains the information returned from the x-ms-request-id header response. + RequestID *string + + // Version contains the information returned from the x-ms-version header response. + Version *string +} + +// FileClientDownloadResponse contains the response from method FileClient.Download. +type FileClientDownloadResponse struct { + // AcceptRanges contains the information returned from the Accept-Ranges header response. + AcceptRanges *string + + // Body contains the streaming response. + Body io.ReadCloser + + // CacheControl contains the information returned from the Cache-Control header response. + CacheControl *string + + // ContentDisposition contains the information returned from the Content-Disposition header response. + ContentDisposition *string + + // ContentEncoding contains the information returned from the Content-Encoding header response. + ContentEncoding *string + + // ContentLanguage contains the information returned from the Content-Language header response. + ContentLanguage *string + + // ContentLength contains the information returned from the Content-Length header response. + ContentLength *int64 + + // ContentMD5 contains the information returned from the Content-MD5 header response. + ContentMD5 []byte + + // ContentRange contains the information returned from the Content-Range header response. + ContentRange *string + + // ContentType contains the information returned from the Content-Type header response. + ContentType *string + + // CopyCompletionTime contains the information returned from the x-ms-copy-completion-time header response. + CopyCompletionTime *time.Time + + // CopyID contains the information returned from the x-ms-copy-id header response. + CopyID *string + + // CopyProgress contains the information returned from the x-ms-copy-progress header response. + CopyProgress *string + + // CopySource contains the information returned from the x-ms-copy-source header response. + CopySource *string + + // CopyStatus contains the information returned from the x-ms-copy-status header response. + CopyStatus *CopyStatusType + + // CopyStatusDescription contains the information returned from the x-ms-copy-status-description header response. + CopyStatusDescription *string + + // Date contains the information returned from the Date header response. + Date *time.Time + + // ETag contains the information returned from the ETag header response. + ETag *azcore.ETag + + // FileAttributes contains the information returned from the x-ms-file-attributes header response. + FileAttributes *string + + // FileChangeTime contains the information returned from the x-ms-file-change-time header response. + FileChangeTime *time.Time + + // FileContentMD5 contains the information returned from the x-ms-content-md5 header response. + FileContentMD5 []byte + + // FileCreationTime contains the information returned from the x-ms-file-creation-time header response. + FileCreationTime *time.Time + + // ID contains the information returned from the x-ms-file-id header response. + ID *string + + // FileLastWriteTime contains the information returned from the x-ms-file-last-write-time header response. + FileLastWriteTime *time.Time + + // ParentID contains the information returned from the x-ms-file-parent-id header response. + ParentID *string + + // FilePermissionKey contains the information returned from the x-ms-file-permission-key header response. + FilePermissionKey *string + + // IsServerEncrypted contains the information returned from the x-ms-server-encrypted header response. + IsServerEncrypted *bool + + // LastModified contains the information returned from the Last-Modified header response. + LastModified *time.Time + + // LeaseDuration contains the information returned from the x-ms-lease-duration header response. + LeaseDuration *LeaseDurationType + + // LeaseState contains the information returned from the x-ms-lease-state header response. + LeaseState *LeaseStateType + + // LeaseStatus contains the information returned from the x-ms-lease-status header response. + LeaseStatus *LeaseStatusType + + // Metadata contains the information returned from the x-ms-meta header response. + Metadata map[string]*string + + // RequestID contains the information returned from the x-ms-request-id header response. + RequestID *string + + // Version contains the information returned from the x-ms-version header response. + Version *string +} + +// FileClientForceCloseHandlesResponse contains the response from method FileClient.ForceCloseHandles. +type FileClientForceCloseHandlesResponse struct { + // Date contains the information returned from the Date header response. + Date *time.Time + + // Marker contains the information returned from the x-ms-marker header response. + Marker *string + + // NumberOfHandlesClosed contains the information returned from the x-ms-number-of-handles-closed header response. + NumberOfHandlesClosed *int32 + + // NumberOfHandlesFailedToClose contains the information returned from the x-ms-number-of-handles-failed header response. + NumberOfHandlesFailedToClose *int32 + + // RequestID contains the information returned from the x-ms-request-id header response. + RequestID *string + + // Version contains the information returned from the x-ms-version header response. + Version *string +} + +// FileClientGetPropertiesResponse contains the response from method FileClient.GetProperties. +type FileClientGetPropertiesResponse struct { + // CacheControl contains the information returned from the Cache-Control header response. + CacheControl *string + + // ContentDisposition contains the information returned from the Content-Disposition header response. + ContentDisposition *string + + // ContentEncoding contains the information returned from the Content-Encoding header response. + ContentEncoding *string + + // ContentLanguage contains the information returned from the Content-Language header response. + ContentLanguage *string + + // ContentLength contains the information returned from the Content-Length header response. + ContentLength *int64 + + // ContentMD5 contains the information returned from the Content-MD5 header response. + ContentMD5 []byte + + // ContentType contains the information returned from the Content-Type header response. + ContentType *string + + // CopyCompletionTime contains the information returned from the x-ms-copy-completion-time header response. + CopyCompletionTime *time.Time + + // CopyID contains the information returned from the x-ms-copy-id header response. + CopyID *string + + // CopyProgress contains the information returned from the x-ms-copy-progress header response. + CopyProgress *string + + // CopySource contains the information returned from the x-ms-copy-source header response. + CopySource *string + + // CopyStatus contains the information returned from the x-ms-copy-status header response. + CopyStatus *CopyStatusType + + // CopyStatusDescription contains the information returned from the x-ms-copy-status-description header response. + CopyStatusDescription *string + + // Date contains the information returned from the Date header response. + Date *time.Time + + // ETag contains the information returned from the ETag header response. + ETag *azcore.ETag + + // FileAttributes contains the information returned from the x-ms-file-attributes header response. + FileAttributes *string + + // FileChangeTime contains the information returned from the x-ms-file-change-time header response. + FileChangeTime *time.Time + + // FileCreationTime contains the information returned from the x-ms-file-creation-time header response. + FileCreationTime *time.Time + + // ID contains the information returned from the x-ms-file-id header response. + ID *string + + // FileLastWriteTime contains the information returned from the x-ms-file-last-write-time header response. + FileLastWriteTime *time.Time + + // ParentID contains the information returned from the x-ms-file-parent-id header response. + ParentID *string + + // FilePermissionKey contains the information returned from the x-ms-file-permission-key header response. + FilePermissionKey *string + + // FileType contains the information returned from the x-ms-type header response. + FileType *string + + // IsServerEncrypted contains the information returned from the x-ms-server-encrypted header response. + IsServerEncrypted *bool + + // LastModified contains the information returned from the Last-Modified header response. + LastModified *time.Time + + // LeaseDuration contains the information returned from the x-ms-lease-duration header response. + LeaseDuration *LeaseDurationType + + // LeaseState contains the information returned from the x-ms-lease-state header response. + LeaseState *LeaseStateType + + // LeaseStatus contains the information returned from the x-ms-lease-status header response. + LeaseStatus *LeaseStatusType + + // Metadata contains the information returned from the x-ms-meta header response. + Metadata map[string]*string + + // RequestID contains the information returned from the x-ms-request-id header response. + RequestID *string + + // Version contains the information returned from the x-ms-version header response. + Version *string +} + +// FileClientGetRangeListResponse contains the response from method FileClient.GetRangeList. +type FileClientGetRangeListResponse struct { + ShareFileRangeList + // Date contains the information returned from the Date header response. + Date *time.Time `xml:"Date"` + + // ETag contains the information returned from the ETag header response. + ETag *azcore.ETag `xml:"ETag"` + + // FileContentLength contains the information returned from the x-ms-content-length header response. + FileContentLength *int64 `xml:"FileContentLength"` + + // LastModified contains the information returned from the Last-Modified header response. + LastModified *time.Time `xml:"LastModified"` + + // RequestID contains the information returned from the x-ms-request-id header response. + RequestID *string `xml:"RequestID"` + + // Version contains the information returned from the x-ms-version header response. + Version *string `xml:"Version"` +} + +// FileClientListHandlesResponse contains the response from method FileClient.ListHandles. +type FileClientListHandlesResponse struct { + ListHandlesResponse + // ContentType contains the information returned from the Content-Type header response. + ContentType *string `xml:"ContentType"` + + // Date contains the information returned from the Date header response. + Date *time.Time `xml:"Date"` + + // RequestID contains the information returned from the x-ms-request-id header response. + RequestID *string `xml:"RequestID"` + + // Version contains the information returned from the x-ms-version header response. + Version *string `xml:"Version"` +} + +// FileClientReleaseLeaseResponse contains the response from method FileClient.ReleaseLease. +type FileClientReleaseLeaseResponse struct { + // ClientRequestID contains the information returned from the x-ms-client-request-id header response. + ClientRequestID *string + + // Date contains the information returned from the Date header response. + Date *time.Time + + // ETag contains the information returned from the ETag header response. + ETag *azcore.ETag + + // LastModified contains the information returned from the Last-Modified header response. + LastModified *time.Time + + // RequestID contains the information returned from the x-ms-request-id header response. + RequestID *string + + // Version contains the information returned from the x-ms-version header response. + Version *string +} + +// FileClientSetHTTPHeadersResponse contains the response from method FileClient.SetHTTPHeaders. +type FileClientSetHTTPHeadersResponse struct { + // Date contains the information returned from the Date header response. + Date *time.Time + + // ETag contains the information returned from the ETag header response. + ETag *azcore.ETag + + // FileAttributes contains the information returned from the x-ms-file-attributes header response. + FileAttributes *string + + // FileChangeTime contains the information returned from the x-ms-file-change-time header response. + FileChangeTime *time.Time + + // FileCreationTime contains the information returned from the x-ms-file-creation-time header response. + FileCreationTime *time.Time + + // ID contains the information returned from the x-ms-file-id header response. + ID *string + + // FileLastWriteTime contains the information returned from the x-ms-file-last-write-time header response. + FileLastWriteTime *time.Time + + // ParentID contains the information returned from the x-ms-file-parent-id header response. + ParentID *string + + // FilePermissionKey contains the information returned from the x-ms-file-permission-key header response. + FilePermissionKey *string + + // IsServerEncrypted contains the information returned from the x-ms-request-server-encrypted header response. + IsServerEncrypted *bool + + // LastModified contains the information returned from the Last-Modified header response. + LastModified *time.Time + + // RequestID contains the information returned from the x-ms-request-id header response. + RequestID *string + + // Version contains the information returned from the x-ms-version header response. + Version *string +} + +// FileClientSetMetadataResponse contains the response from method FileClient.SetMetadata. +type FileClientSetMetadataResponse struct { + // Date contains the information returned from the Date header response. + Date *time.Time + + // ETag contains the information returned from the ETag header response. + ETag *azcore.ETag + + // IsServerEncrypted contains the information returned from the x-ms-request-server-encrypted header response. + IsServerEncrypted *bool + + // LastModified contains the information returned from the Last-Modified header response. + LastModified *time.Time + + // RequestID contains the information returned from the x-ms-request-id header response. + RequestID *string + + // Version contains the information returned from the x-ms-version header response. + Version *string +} + +// FileClientStartCopyResponse contains the response from method FileClient.StartCopy. +type FileClientStartCopyResponse struct { + // CopyID contains the information returned from the x-ms-copy-id header response. + CopyID *string + + // CopyStatus contains the information returned from the x-ms-copy-status header response. + CopyStatus *CopyStatusType + + // Date contains the information returned from the Date header response. + Date *time.Time + + // ETag contains the information returned from the ETag header response. + ETag *azcore.ETag + + // LastModified contains the information returned from the Last-Modified header response. + LastModified *time.Time + + // RequestID contains the information returned from the x-ms-request-id header response. + RequestID *string + + // Version contains the information returned from the x-ms-version header response. + Version *string +} + +// FileClientUploadRangeFromURLResponse contains the response from method FileClient.UploadRangeFromURL. +type FileClientUploadRangeFromURLResponse struct { + // ContentMD5 contains the information returned from the Content-MD5 header response. + ContentMD5 []byte + + // Date contains the information returned from the Date header response. + Date *time.Time + + // ETag contains the information returned from the ETag header response. + ETag *azcore.ETag + + // IsServerEncrypted contains the information returned from the x-ms-request-server-encrypted header response. + IsServerEncrypted *bool + + // LastModified contains the information returned from the Last-Modified header response. + LastModified *time.Time + + // RequestID contains the information returned from the x-ms-request-id header response. + RequestID *string + + // Version contains the information returned from the x-ms-version header response. + Version *string + + // XMSContentCRC64 contains the information returned from the x-ms-content-crc64 header response. + XMSContentCRC64 []byte +} + +// FileClientUploadRangeResponse contains the response from method FileClient.UploadRange. +type FileClientUploadRangeResponse struct { + // ContentMD5 contains the information returned from the Content-MD5 header response. + ContentMD5 []byte + + // Date contains the information returned from the Date header response. + Date *time.Time + + // ETag contains the information returned from the ETag header response. + ETag *azcore.ETag + + // IsServerEncrypted contains the information returned from the x-ms-request-server-encrypted header response. + IsServerEncrypted *bool + + // LastModified contains the information returned from the Last-Modified header response. + LastModified *time.Time + + // RequestID contains the information returned from the x-ms-request-id header response. + RequestID *string + + // Version contains the information returned from the x-ms-version header response. + Version *string +} + +// ServiceClientGetPropertiesResponse contains the response from method ServiceClient.GetProperties. +type ServiceClientGetPropertiesResponse struct { + StorageServiceProperties + // RequestID contains the information returned from the x-ms-request-id header response. + RequestID *string `xml:"RequestID"` + + // Version contains the information returned from the x-ms-version header response. + Version *string `xml:"Version"` +} + +// ServiceClientListSharesSegmentResponse contains the response from method ServiceClient.NewListSharesSegmentPager. +type ServiceClientListSharesSegmentResponse struct { + ListSharesResponse + // RequestID contains the information returned from the x-ms-request-id header response. + RequestID *string `xml:"RequestID"` + + // Version contains the information returned from the x-ms-version header response. + Version *string `xml:"Version"` +} + +// ServiceClientSetPropertiesResponse contains the response from method ServiceClient.SetProperties. +type ServiceClientSetPropertiesResponse struct { + // RequestID contains the information returned from the x-ms-request-id header response. + RequestID *string + + // Version contains the information returned from the x-ms-version header response. + Version *string +} + +// ShareClientAcquireLeaseResponse contains the response from method ShareClient.AcquireLease. +type ShareClientAcquireLeaseResponse struct { + // ClientRequestID contains the information returned from the x-ms-client-request-id header response. + ClientRequestID *string + + // Date contains the information returned from the Date header response. + Date *time.Time + + // ETag contains the information returned from the ETag header response. + ETag *azcore.ETag + + // LastModified contains the information returned from the Last-Modified header response. + LastModified *time.Time + + // LeaseID contains the information returned from the x-ms-lease-id header response. + LeaseID *string + + // RequestID contains the information returned from the x-ms-request-id header response. + RequestID *string + + // Version contains the information returned from the x-ms-version header response. + Version *string +} + +// ShareClientBreakLeaseResponse contains the response from method ShareClient.BreakLease. +type ShareClientBreakLeaseResponse struct { + // ClientRequestID contains the information returned from the x-ms-client-request-id header response. + ClientRequestID *string + + // Date contains the information returned from the Date header response. + Date *time.Time + + // ETag contains the information returned from the ETag header response. + ETag *azcore.ETag + + // LastModified contains the information returned from the Last-Modified header response. + LastModified *time.Time + + // LeaseID contains the information returned from the x-ms-lease-id header response. + LeaseID *string + + // LeaseTime contains the information returned from the x-ms-lease-time header response. + LeaseTime *int32 + + // RequestID contains the information returned from the x-ms-request-id header response. + RequestID *string + + // Version contains the information returned from the x-ms-version header response. + Version *string +} + +// ShareClientChangeLeaseResponse contains the response from method ShareClient.ChangeLease. +type ShareClientChangeLeaseResponse struct { + // ClientRequestID contains the information returned from the x-ms-client-request-id header response. + ClientRequestID *string + + // Date contains the information returned from the Date header response. + Date *time.Time + + // ETag contains the information returned from the ETag header response. + ETag *azcore.ETag + + // LastModified contains the information returned from the Last-Modified header response. + LastModified *time.Time + + // LeaseID contains the information returned from the x-ms-lease-id header response. + LeaseID *string + + // RequestID contains the information returned from the x-ms-request-id header response. + RequestID *string + + // Version contains the information returned from the x-ms-version header response. + Version *string +} + +// ShareClientCreatePermissionResponse contains the response from method ShareClient.CreatePermission. +type ShareClientCreatePermissionResponse struct { + // Date contains the information returned from the Date header response. + Date *time.Time + + // FilePermissionKey contains the information returned from the x-ms-file-permission-key header response. + FilePermissionKey *string + + // RequestID contains the information returned from the x-ms-request-id header response. + RequestID *string + + // Version contains the information returned from the x-ms-version header response. + Version *string +} + +// ShareClientCreateResponse contains the response from method ShareClient.Create. +type ShareClientCreateResponse struct { + // Date contains the information returned from the Date header response. + Date *time.Time + + // ETag contains the information returned from the ETag header response. + ETag *azcore.ETag + + // LastModified contains the information returned from the Last-Modified header response. + LastModified *time.Time + + // RequestID contains the information returned from the x-ms-request-id header response. + RequestID *string + + // Version contains the information returned from the x-ms-version header response. + Version *string +} + +// ShareClientCreateSnapshotResponse contains the response from method ShareClient.CreateSnapshot. +type ShareClientCreateSnapshotResponse struct { + // Date contains the information returned from the Date header response. + Date *time.Time + + // ETag contains the information returned from the ETag header response. + ETag *azcore.ETag + + // LastModified contains the information returned from the Last-Modified header response. + LastModified *time.Time + + // RequestID contains the information returned from the x-ms-request-id header response. + RequestID *string + + // Snapshot contains the information returned from the x-ms-snapshot header response. + Snapshot *string + + // Version contains the information returned from the x-ms-version header response. + Version *string +} + +// ShareClientDeleteResponse contains the response from method ShareClient.Delete. +type ShareClientDeleteResponse struct { + // Date contains the information returned from the Date header response. + Date *time.Time + + // RequestID contains the information returned from the x-ms-request-id header response. + RequestID *string + + // Version contains the information returned from the x-ms-version header response. + Version *string +} + +// ShareClientGetAccessPolicyResponse contains the response from method ShareClient.GetAccessPolicy. +type ShareClientGetAccessPolicyResponse struct { + // Date contains the information returned from the Date header response. + Date *time.Time `xml:"Date"` + + // ETag contains the information returned from the ETag header response. + ETag *azcore.ETag `xml:"ETag"` + + // LastModified contains the information returned from the Last-Modified header response. + LastModified *time.Time `xml:"LastModified"` + + // RequestID contains the information returned from the x-ms-request-id header response. + RequestID *string `xml:"RequestID"` + + // A collection of signed identifiers. + SignedIdentifiers []*SignedIdentifier `xml:"SignedIdentifier"` + + // Version contains the information returned from the x-ms-version header response. + Version *string `xml:"Version"` +} + +// ShareClientGetPermissionResponse contains the response from method ShareClient.GetPermission. +type ShareClientGetPermissionResponse struct { + SharePermission + // Date contains the information returned from the Date header response. + Date *time.Time + + // RequestID contains the information returned from the x-ms-request-id header response. + RequestID *string + + // Version contains the information returned from the x-ms-version header response. + Version *string +} + +// ShareClientGetPropertiesResponse contains the response from method ShareClient.GetProperties. +type ShareClientGetPropertiesResponse struct { + // AccessTier contains the information returned from the x-ms-access-tier header response. + AccessTier *string + + // AccessTierChangeTime contains the information returned from the x-ms-access-tier-change-time header response. + AccessTierChangeTime *time.Time + + // AccessTierTransitionState contains the information returned from the x-ms-access-tier-transition-state header response. + AccessTierTransitionState *string + + // Date contains the information returned from the Date header response. + Date *time.Time + + // ETag contains the information returned from the ETag header response. + ETag *azcore.ETag + + // EnabledProtocols contains the information returned from the x-ms-enabled-protocols header response. + EnabledProtocols *string + + // LastModified contains the information returned from the Last-Modified header response. + LastModified *time.Time + + // LeaseDuration contains the information returned from the x-ms-lease-duration header response. + LeaseDuration *LeaseDurationType + + // LeaseState contains the information returned from the x-ms-lease-state header response. + LeaseState *LeaseStateType + + // LeaseStatus contains the information returned from the x-ms-lease-status header response. + LeaseStatus *LeaseStatusType + + // Metadata contains the information returned from the x-ms-meta header response. + Metadata map[string]*string + + // NextAllowedQuotaDowngradeTime contains the information returned from the x-ms-share-next-allowed-quota-downgrade-time header + // response. + NextAllowedQuotaDowngradeTime *time.Time + + // ProvisionedEgressMBps contains the information returned from the x-ms-share-provisioned-egress-mbps header response. + ProvisionedEgressMBps *int32 + + // ProvisionedIngressMBps contains the information returned from the x-ms-share-provisioned-ingress-mbps header response. + ProvisionedIngressMBps *int32 + + // ProvisionedIops contains the information returned from the x-ms-share-provisioned-iops header response. + ProvisionedIops *int32 + + // Quota contains the information returned from the x-ms-share-quota header response. + Quota *int32 + + // RequestID contains the information returned from the x-ms-request-id header response. + RequestID *string + + // RootSquash contains the information returned from the x-ms-root-squash header response. + RootSquash *ShareRootSquash + + // Version contains the information returned from the x-ms-version header response. + Version *string +} + +// ShareClientGetStatisticsResponse contains the response from method ShareClient.GetStatistics. +type ShareClientGetStatisticsResponse struct { + ShareStats + // Date contains the information returned from the Date header response. + Date *time.Time `xml:"Date"` + + // ETag contains the information returned from the ETag header response. + ETag *azcore.ETag `xml:"ETag"` + + // LastModified contains the information returned from the Last-Modified header response. + LastModified *time.Time `xml:"LastModified"` + + // RequestID contains the information returned from the x-ms-request-id header response. + RequestID *string `xml:"RequestID"` + + // Version contains the information returned from the x-ms-version header response. + Version *string `xml:"Version"` +} + +// ShareClientReleaseLeaseResponse contains the response from method ShareClient.ReleaseLease. +type ShareClientReleaseLeaseResponse struct { + // ClientRequestID contains the information returned from the x-ms-client-request-id header response. + ClientRequestID *string + + // Date contains the information returned from the Date header response. + Date *time.Time + + // ETag contains the information returned from the ETag header response. + ETag *azcore.ETag + + // LastModified contains the information returned from the Last-Modified header response. + LastModified *time.Time + + // RequestID contains the information returned from the x-ms-request-id header response. + RequestID *string + + // Version contains the information returned from the x-ms-version header response. + Version *string +} + +// ShareClientRenewLeaseResponse contains the response from method ShareClient.RenewLease. +type ShareClientRenewLeaseResponse struct { + // ClientRequestID contains the information returned from the x-ms-client-request-id header response. + ClientRequestID *string + + // Date contains the information returned from the Date header response. + Date *time.Time + + // ETag contains the information returned from the ETag header response. + ETag *azcore.ETag + + // LastModified contains the information returned from the Last-Modified header response. + LastModified *time.Time + + // LeaseID contains the information returned from the x-ms-lease-id header response. + LeaseID *string + + // RequestID contains the information returned from the x-ms-request-id header response. + RequestID *string + + // Version contains the information returned from the x-ms-version header response. + Version *string +} + +// ShareClientRestoreResponse contains the response from method ShareClient.Restore. +type ShareClientRestoreResponse struct { + // ClientRequestID contains the information returned from the x-ms-client-request-id header response. + ClientRequestID *string + + // Date contains the information returned from the Date header response. + Date *time.Time + + // ETag contains the information returned from the ETag header response. + ETag *azcore.ETag + + // LastModified contains the information returned from the Last-Modified header response. + LastModified *time.Time + + // RequestID contains the information returned from the x-ms-request-id header response. + RequestID *string + + // Version contains the information returned from the x-ms-version header response. + Version *string +} + +// ShareClientSetAccessPolicyResponse contains the response from method ShareClient.SetAccessPolicy. +type ShareClientSetAccessPolicyResponse struct { + // Date contains the information returned from the Date header response. + Date *time.Time + + // ETag contains the information returned from the ETag header response. + ETag *azcore.ETag + + // LastModified contains the information returned from the Last-Modified header response. + LastModified *time.Time + + // RequestID contains the information returned from the x-ms-request-id header response. + RequestID *string + + // Version contains the information returned from the x-ms-version header response. + Version *string +} + +// ShareClientSetMetadataResponse contains the response from method ShareClient.SetMetadata. +type ShareClientSetMetadataResponse struct { + // Date contains the information returned from the Date header response. + Date *time.Time + + // ETag contains the information returned from the ETag header response. + ETag *azcore.ETag + + // LastModified contains the information returned from the Last-Modified header response. + LastModified *time.Time + + // RequestID contains the information returned from the x-ms-request-id header response. + RequestID *string + + // Version contains the information returned from the x-ms-version header response. + Version *string +} + +// ShareClientSetPropertiesResponse contains the response from method ShareClient.SetProperties. +type ShareClientSetPropertiesResponse struct { + // Date contains the information returned from the Date header response. + Date *time.Time + + // ETag contains the information returned from the ETag header response. + ETag *azcore.ETag + + // LastModified contains the information returned from the Last-Modified header response. + LastModified *time.Time + + // RequestID contains the information returned from the x-ms-request-id header response. + RequestID *string + + // Version contains the information returned from the x-ms-version header response. + Version *string +} diff --git a/sdk/storage/azfile/internal/generated/zz_service_client.go b/sdk/storage/azfile/internal/generated/zz_service_client.go new file mode 100644 index 000000000000..efd5f4708912 --- /dev/null +++ b/sdk/storage/azfile/internal/generated/zz_service_client.go @@ -0,0 +1,195 @@ +//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. +// Code generated by Microsoft (R) AutoRest Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. +// DO NOT EDIT. + +package generated + +import ( + "context" + "fmt" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/policy" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime" + "net/http" + "strconv" + "strings" +) + +// ServiceClient contains the methods for the Service group. +// Don't use this type directly, use NewServiceClient() instead. +type ServiceClient struct { + endpoint string + pl runtime.Pipeline +} + +// NewServiceClient creates a new instance of ServiceClient with the specified values. +// - endpoint - The URL of the service account, share, directory or file that is the target of the desired operation. +// - pl - the pipeline used for sending requests and handling responses. +func NewServiceClient(endpoint string, pl runtime.Pipeline) *ServiceClient { + client := &ServiceClient{ + endpoint: endpoint, + pl: pl, + } + return client +} + +// GetProperties - Gets the properties of a storage account's File service, including properties for Storage Analytics metrics +// and CORS (Cross-Origin Resource Sharing) rules. +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2020-10-02 +// - options - ServiceClientGetPropertiesOptions contains the optional parameters for the ServiceClient.GetProperties method. +func (client *ServiceClient) GetProperties(ctx context.Context, options *ServiceClientGetPropertiesOptions) (ServiceClientGetPropertiesResponse, error) { + req, err := client.getPropertiesCreateRequest(ctx, options) + if err != nil { + return ServiceClientGetPropertiesResponse{}, err + } + resp, err := client.pl.Do(req) + if err != nil { + return ServiceClientGetPropertiesResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusOK) { + return ServiceClientGetPropertiesResponse{}, runtime.NewResponseError(resp) + } + return client.getPropertiesHandleResponse(resp) +} + +// getPropertiesCreateRequest creates the GetProperties request. +func (client *ServiceClient) getPropertiesCreateRequest(ctx context.Context, options *ServiceClientGetPropertiesOptions) (*policy.Request, error) { + req, err := runtime.NewRequest(ctx, http.MethodGet, client.endpoint) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("restype", "service") + reqQP.Set("comp", "properties") + if options != nil && options.Timeout != nil { + reqQP.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + } + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["x-ms-version"] = []string{"2020-10-02"} + req.Raw().Header["Accept"] = []string{"application/xml"} + return req, nil +} + +// getPropertiesHandleResponse handles the GetProperties response. +func (client *ServiceClient) getPropertiesHandleResponse(resp *http.Response) (ServiceClientGetPropertiesResponse, error) { + result := ServiceClientGetPropertiesResponse{} + if val := resp.Header.Get("x-ms-request-id"); val != "" { + result.RequestID = &val + } + if val := resp.Header.Get("x-ms-version"); val != "" { + result.Version = &val + } + if err := runtime.UnmarshalAsXML(resp, &result.StorageServiceProperties); err != nil { + return ServiceClientGetPropertiesResponse{}, err + } + return result, nil +} + +// NewListSharesSegmentPager - The List Shares Segment operation returns a list of the shares and share snapshots under the +// specified account. +// +// Generated from API version 2020-10-02 +// - options - ServiceClientListSharesSegmentOptions contains the optional parameters for the ServiceClient.NewListSharesSegmentPager +// method. +// +// listSharesSegmentCreateRequest creates the ListSharesSegment request. +func (client *ServiceClient) ListSharesSegmentCreateRequest(ctx context.Context, options *ServiceClientListSharesSegmentOptions) (*policy.Request, error) { + req, err := runtime.NewRequest(ctx, http.MethodGet, client.endpoint) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("comp", "list") + if options != nil && options.Prefix != nil { + reqQP.Set("prefix", *options.Prefix) + } + if options != nil && options.Marker != nil { + reqQP.Set("marker", *options.Marker) + } + if options != nil && options.Maxresults != nil { + reqQP.Set("maxresults", strconv.FormatInt(int64(*options.Maxresults), 10)) + } + if options != nil && options.Include != nil { + reqQP.Set("include", strings.Join(strings.Fields(strings.Trim(fmt.Sprint(options.Include), "[]")), ",")) + } + if options != nil && options.Timeout != nil { + reqQP.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + } + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["x-ms-version"] = []string{"2020-10-02"} + req.Raw().Header["Accept"] = []string{"application/xml"} + return req, nil +} + +// listSharesSegmentHandleResponse handles the ListSharesSegment response. +func (client *ServiceClient) ListSharesSegmentHandleResponse(resp *http.Response) (ServiceClientListSharesSegmentResponse, error) { + result := ServiceClientListSharesSegmentResponse{} + if val := resp.Header.Get("x-ms-request-id"); val != "" { + result.RequestID = &val + } + if val := resp.Header.Get("x-ms-version"); val != "" { + result.Version = &val + } + if err := runtime.UnmarshalAsXML(resp, &result.ListSharesResponse); err != nil { + return ServiceClientListSharesSegmentResponse{}, err + } + return result, nil +} + +// SetProperties - Sets properties for a storage account's File service endpoint, including properties for Storage Analytics +// metrics and CORS (Cross-Origin Resource Sharing) rules. +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2020-10-02 +// - storageServiceProperties - The StorageService properties. +// - options - ServiceClientSetPropertiesOptions contains the optional parameters for the ServiceClient.SetProperties method. +func (client *ServiceClient) SetProperties(ctx context.Context, storageServiceProperties StorageServiceProperties, options *ServiceClientSetPropertiesOptions) (ServiceClientSetPropertiesResponse, error) { + req, err := client.setPropertiesCreateRequest(ctx, storageServiceProperties, options) + if err != nil { + return ServiceClientSetPropertiesResponse{}, err + } + resp, err := client.pl.Do(req) + if err != nil { + return ServiceClientSetPropertiesResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusAccepted) { + return ServiceClientSetPropertiesResponse{}, runtime.NewResponseError(resp) + } + return client.setPropertiesHandleResponse(resp) +} + +// setPropertiesCreateRequest creates the SetProperties request. +func (client *ServiceClient) setPropertiesCreateRequest(ctx context.Context, storageServiceProperties StorageServiceProperties, options *ServiceClientSetPropertiesOptions) (*policy.Request, error) { + req, err := runtime.NewRequest(ctx, http.MethodPut, client.endpoint) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("restype", "service") + reqQP.Set("comp", "properties") + if options != nil && options.Timeout != nil { + reqQP.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + } + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["x-ms-version"] = []string{"2020-10-02"} + req.Raw().Header["Accept"] = []string{"application/xml"} + return req, runtime.MarshalAsXML(req, storageServiceProperties) +} + +// setPropertiesHandleResponse handles the SetProperties response. +func (client *ServiceClient) setPropertiesHandleResponse(resp *http.Response) (ServiceClientSetPropertiesResponse, error) { + result := ServiceClientSetPropertiesResponse{} + if val := resp.Header.Get("x-ms-request-id"); val != "" { + result.RequestID = &val + } + if val := resp.Header.Get("x-ms-version"); val != "" { + result.Version = &val + } + return result, nil +} diff --git a/sdk/storage/azfile/internal/generated/zz_share_client.go b/sdk/storage/azfile/internal/generated/zz_share_client.go new file mode 100644 index 000000000000..1ba2fda44963 --- /dev/null +++ b/sdk/storage/azfile/internal/generated/zz_share_client.go @@ -0,0 +1,1437 @@ +//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. +// Code generated by Microsoft (R) AutoRest Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. +// DO NOT EDIT. + +package generated + +import ( + "context" + "encoding/xml" + "github.com/Azure/azure-sdk-for-go/sdk/azcore" + "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/azcore/to" + "net/http" + "strconv" + "strings" + "time" +) + +// ShareClient contains the methods for the Share group. +// Don't use this type directly, use NewShareClient() instead. +type ShareClient struct { + endpoint string + pl runtime.Pipeline +} + +// NewShareClient creates a new instance of ShareClient with the specified values. +// - endpoint - The URL of the service account, share, directory or file that is the target of the desired operation. +// - pl - the pipeline used for sending requests and handling responses. +func NewShareClient(endpoint string, pl runtime.Pipeline) *ShareClient { + client := &ShareClient{ + endpoint: endpoint, + pl: pl, + } + return client +} + +// AcquireLease - The Lease Share operation establishes and manages a lock on a share, or the specified snapshot for set and +// delete share operations. +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2020-10-02 +// - duration - 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. A lease duration cannot be changed using +// renew or change. +// - options - ShareClientAcquireLeaseOptions contains the optional parameters for the ShareClient.AcquireLease method. +func (client *ShareClient) AcquireLease(ctx context.Context, duration int32, options *ShareClientAcquireLeaseOptions) (ShareClientAcquireLeaseResponse, error) { + req, err := client.acquireLeaseCreateRequest(ctx, duration, options) + if err != nil { + return ShareClientAcquireLeaseResponse{}, err + } + resp, err := client.pl.Do(req) + if err != nil { + return ShareClientAcquireLeaseResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusCreated) { + return ShareClientAcquireLeaseResponse{}, runtime.NewResponseError(resp) + } + return client.acquireLeaseHandleResponse(resp) +} + +// acquireLeaseCreateRequest creates the AcquireLease request. +func (client *ShareClient) acquireLeaseCreateRequest(ctx context.Context, duration int32, options *ShareClientAcquireLeaseOptions) (*policy.Request, error) { + req, err := runtime.NewRequest(ctx, http.MethodPut, client.endpoint) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("comp", "lease") + reqQP.Set("restype", "share") + if options != nil && options.Timeout != nil { + reqQP.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + } + if options != nil && options.Sharesnapshot != nil { + reqQP.Set("sharesnapshot", *options.Sharesnapshot) + } + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["x-ms-lease-action"] = []string{"acquire"} + req.Raw().Header["x-ms-lease-duration"] = []string{strconv.FormatInt(int64(duration), 10)} + if options != nil && options.ProposedLeaseID != nil { + req.Raw().Header["x-ms-proposed-lease-id"] = []string{*options.ProposedLeaseID} + } + req.Raw().Header["x-ms-version"] = []string{"2020-10-02"} + if options != nil && options.RequestID != nil { + req.Raw().Header["x-ms-client-request-id"] = []string{*options.RequestID} + } + req.Raw().Header["Accept"] = []string{"application/xml"} + return req, nil +} + +// acquireLeaseHandleResponse handles the AcquireLease response. +func (client *ShareClient) acquireLeaseHandleResponse(resp *http.Response) (ShareClientAcquireLeaseResponse, error) { + result := ShareClientAcquireLeaseResponse{} + if val := resp.Header.Get("ETag"); val != "" { + result.ETag = (*azcore.ETag)(&val) + } + if val := resp.Header.Get("Last-Modified"); val != "" { + lastModified, err := time.Parse(time.RFC1123, val) + if err != nil { + return ShareClientAcquireLeaseResponse{}, err + } + result.LastModified = &lastModified + } + if val := resp.Header.Get("x-ms-lease-id"); val != "" { + result.LeaseID = &val + } + if val := resp.Header.Get("x-ms-client-request-id"); val != "" { + result.ClientRequestID = &val + } + if val := resp.Header.Get("x-ms-request-id"); val != "" { + result.RequestID = &val + } + if val := resp.Header.Get("x-ms-version"); val != "" { + result.Version = &val + } + if val := resp.Header.Get("Date"); val != "" { + date, err := time.Parse(time.RFC1123, val) + if err != nil { + return ShareClientAcquireLeaseResponse{}, err + } + result.Date = &date + } + return result, nil +} + +// BreakLease - The Lease Share operation establishes and manages a lock on a share, or the specified snapshot for set and +// delete share operations. +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2020-10-02 +// - options - ShareClientBreakLeaseOptions contains the optional parameters for the ShareClient.BreakLease method. +// - LeaseAccessConditions - LeaseAccessConditions contains a group of parameters for the ShareClient.GetProperties method. +func (client *ShareClient) BreakLease(ctx context.Context, options *ShareClientBreakLeaseOptions, leaseAccessConditions *LeaseAccessConditions) (ShareClientBreakLeaseResponse, error) { + req, err := client.breakLeaseCreateRequest(ctx, options, leaseAccessConditions) + if err != nil { + return ShareClientBreakLeaseResponse{}, err + } + resp, err := client.pl.Do(req) + if err != nil { + return ShareClientBreakLeaseResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusAccepted) { + return ShareClientBreakLeaseResponse{}, runtime.NewResponseError(resp) + } + return client.breakLeaseHandleResponse(resp) +} + +// breakLeaseCreateRequest creates the BreakLease request. +func (client *ShareClient) breakLeaseCreateRequest(ctx context.Context, options *ShareClientBreakLeaseOptions, leaseAccessConditions *LeaseAccessConditions) (*policy.Request, error) { + req, err := runtime.NewRequest(ctx, http.MethodPut, client.endpoint) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("comp", "lease") + reqQP.Set("restype", "share") + if options != nil && options.Timeout != nil { + reqQP.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + } + if options != nil && options.Sharesnapshot != nil { + reqQP.Set("sharesnapshot", *options.Sharesnapshot) + } + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["x-ms-lease-action"] = []string{"break"} + if options != nil && options.BreakPeriod != nil { + req.Raw().Header["x-ms-lease-break-period"] = []string{strconv.FormatInt(int64(*options.BreakPeriod), 10)} + } + if leaseAccessConditions != nil && leaseAccessConditions.LeaseID != nil { + req.Raw().Header["x-ms-lease-id"] = []string{*leaseAccessConditions.LeaseID} + } + req.Raw().Header["x-ms-version"] = []string{"2020-10-02"} + if options != nil && options.RequestID != nil { + req.Raw().Header["x-ms-client-request-id"] = []string{*options.RequestID} + } + req.Raw().Header["Accept"] = []string{"application/xml"} + return req, nil +} + +// breakLeaseHandleResponse handles the BreakLease response. +func (client *ShareClient) breakLeaseHandleResponse(resp *http.Response) (ShareClientBreakLeaseResponse, error) { + result := ShareClientBreakLeaseResponse{} + if val := resp.Header.Get("ETag"); val != "" { + result.ETag = (*azcore.ETag)(&val) + } + if val := resp.Header.Get("Last-Modified"); val != "" { + lastModified, err := time.Parse(time.RFC1123, val) + if err != nil { + return ShareClientBreakLeaseResponse{}, err + } + result.LastModified = &lastModified + } + if val := resp.Header.Get("x-ms-lease-time"); val != "" { + leaseTime32, err := strconv.ParseInt(val, 10, 32) + leaseTime := int32(leaseTime32) + if err != nil { + return ShareClientBreakLeaseResponse{}, err + } + result.LeaseTime = &leaseTime + } + if val := resp.Header.Get("x-ms-lease-id"); val != "" { + result.LeaseID = &val + } + if val := resp.Header.Get("x-ms-client-request-id"); val != "" { + result.ClientRequestID = &val + } + if val := resp.Header.Get("x-ms-request-id"); val != "" { + result.RequestID = &val + } + if val := resp.Header.Get("x-ms-version"); val != "" { + result.Version = &val + } + if val := resp.Header.Get("Date"); val != "" { + date, err := time.Parse(time.RFC1123, val) + if err != nil { + return ShareClientBreakLeaseResponse{}, err + } + result.Date = &date + } + return result, nil +} + +// ChangeLease - The Lease Share operation establishes and manages a lock on a share, or the specified snapshot for set and +// delete share operations. +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2020-10-02 +// - leaseID - Specifies the current lease ID on the resource. +// - options - ShareClientChangeLeaseOptions contains the optional parameters for the ShareClient.ChangeLease method. +func (client *ShareClient) ChangeLease(ctx context.Context, leaseID string, options *ShareClientChangeLeaseOptions) (ShareClientChangeLeaseResponse, error) { + req, err := client.changeLeaseCreateRequest(ctx, leaseID, options) + if err != nil { + return ShareClientChangeLeaseResponse{}, err + } + resp, err := client.pl.Do(req) + if err != nil { + return ShareClientChangeLeaseResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusOK) { + return ShareClientChangeLeaseResponse{}, runtime.NewResponseError(resp) + } + return client.changeLeaseHandleResponse(resp) +} + +// changeLeaseCreateRequest creates the ChangeLease request. +func (client *ShareClient) changeLeaseCreateRequest(ctx context.Context, leaseID string, options *ShareClientChangeLeaseOptions) (*policy.Request, error) { + req, err := runtime.NewRequest(ctx, http.MethodPut, client.endpoint) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("comp", "lease") + reqQP.Set("restype", "share") + if options != nil && options.Timeout != nil { + reqQP.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + } + if options != nil && options.Sharesnapshot != nil { + reqQP.Set("sharesnapshot", *options.Sharesnapshot) + } + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["x-ms-lease-action"] = []string{"change"} + req.Raw().Header["x-ms-lease-id"] = []string{leaseID} + if options != nil && options.ProposedLeaseID != nil { + req.Raw().Header["x-ms-proposed-lease-id"] = []string{*options.ProposedLeaseID} + } + req.Raw().Header["x-ms-version"] = []string{"2020-10-02"} + if options != nil && options.RequestID != nil { + req.Raw().Header["x-ms-client-request-id"] = []string{*options.RequestID} + } + req.Raw().Header["Accept"] = []string{"application/xml"} + return req, nil +} + +// changeLeaseHandleResponse handles the ChangeLease response. +func (client *ShareClient) changeLeaseHandleResponse(resp *http.Response) (ShareClientChangeLeaseResponse, error) { + result := ShareClientChangeLeaseResponse{} + if val := resp.Header.Get("ETag"); val != "" { + result.ETag = (*azcore.ETag)(&val) + } + if val := resp.Header.Get("Last-Modified"); val != "" { + lastModified, err := time.Parse(time.RFC1123, val) + if err != nil { + return ShareClientChangeLeaseResponse{}, err + } + result.LastModified = &lastModified + } + if val := resp.Header.Get("x-ms-lease-id"); val != "" { + result.LeaseID = &val + } + if val := resp.Header.Get("x-ms-client-request-id"); val != "" { + result.ClientRequestID = &val + } + if val := resp.Header.Get("x-ms-request-id"); val != "" { + result.RequestID = &val + } + if val := resp.Header.Get("x-ms-version"); val != "" { + result.Version = &val + } + if val := resp.Header.Get("Date"); val != "" { + date, err := time.Parse(time.RFC1123, val) + if err != nil { + return ShareClientChangeLeaseResponse{}, err + } + result.Date = &date + } + return result, nil +} + +// Create - Creates a new share under the specified account. If the share with the same name already exists, the operation +// fails. +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2020-10-02 +// - options - ShareClientCreateOptions contains the optional parameters for the ShareClient.Create method. +func (client *ShareClient) Create(ctx context.Context, options *ShareClientCreateOptions) (ShareClientCreateResponse, error) { + req, err := client.createCreateRequest(ctx, options) + if err != nil { + return ShareClientCreateResponse{}, err + } + resp, err := client.pl.Do(req) + if err != nil { + return ShareClientCreateResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusCreated) { + return ShareClientCreateResponse{}, runtime.NewResponseError(resp) + } + return client.createHandleResponse(resp) +} + +// createCreateRequest creates the Create request. +func (client *ShareClient) createCreateRequest(ctx context.Context, options *ShareClientCreateOptions) (*policy.Request, error) { + req, err := runtime.NewRequest(ctx, http.MethodPut, client.endpoint) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("restype", "share") + if options != nil && options.Timeout != nil { + reqQP.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + } + req.Raw().URL.RawQuery = reqQP.Encode() + if options != nil && options.Metadata != nil { + for k, v := range options.Metadata { + if v != nil { + req.Raw().Header["x-ms-meta-"+k] = []string{*v} + } + } + } + if options != nil && options.Quota != nil { + req.Raw().Header["x-ms-share-quota"] = []string{strconv.FormatInt(int64(*options.Quota), 10)} + } + if options != nil && options.AccessTier != nil { + req.Raw().Header["x-ms-access-tier"] = []string{string(*options.AccessTier)} + } + req.Raw().Header["x-ms-version"] = []string{"2020-10-02"} + if options != nil && options.EnabledProtocols != nil { + req.Raw().Header["x-ms-enabled-protocols"] = []string{*options.EnabledProtocols} + } + if options != nil && options.RootSquash != nil { + req.Raw().Header["x-ms-root-squash"] = []string{string(*options.RootSquash)} + } + req.Raw().Header["Accept"] = []string{"application/xml"} + return req, nil +} + +// createHandleResponse handles the Create response. +func (client *ShareClient) createHandleResponse(resp *http.Response) (ShareClientCreateResponse, error) { + result := ShareClientCreateResponse{} + if val := resp.Header.Get("ETag"); val != "" { + result.ETag = (*azcore.ETag)(&val) + } + if val := resp.Header.Get("Last-Modified"); val != "" { + lastModified, err := time.Parse(time.RFC1123, val) + if err != nil { + return ShareClientCreateResponse{}, err + } + result.LastModified = &lastModified + } + if val := resp.Header.Get("x-ms-request-id"); val != "" { + result.RequestID = &val + } + if val := resp.Header.Get("x-ms-version"); val != "" { + result.Version = &val + } + if val := resp.Header.Get("Date"); val != "" { + date, err := time.Parse(time.RFC1123, val) + if err != nil { + return ShareClientCreateResponse{}, err + } + result.Date = &date + } + return result, nil +} + +// CreatePermission - Create a permission (a security descriptor). +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2020-10-02 +// - sharePermission - A permission (a security descriptor) at the share level. +// - options - ShareClientCreatePermissionOptions contains the optional parameters for the ShareClient.CreatePermission method. +func (client *ShareClient) CreatePermission(ctx context.Context, sharePermission SharePermission, options *ShareClientCreatePermissionOptions) (ShareClientCreatePermissionResponse, error) { + req, err := client.createPermissionCreateRequest(ctx, sharePermission, options) + if err != nil { + return ShareClientCreatePermissionResponse{}, err + } + resp, err := client.pl.Do(req) + if err != nil { + return ShareClientCreatePermissionResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusCreated) { + return ShareClientCreatePermissionResponse{}, runtime.NewResponseError(resp) + } + return client.createPermissionHandleResponse(resp) +} + +// createPermissionCreateRequest creates the CreatePermission request. +func (client *ShareClient) createPermissionCreateRequest(ctx context.Context, sharePermission SharePermission, options *ShareClientCreatePermissionOptions) (*policy.Request, error) { + req, err := runtime.NewRequest(ctx, http.MethodPut, client.endpoint) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("restype", "share") + reqQP.Set("comp", "filepermission") + if options != nil && options.Timeout != nil { + reqQP.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + } + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["x-ms-version"] = []string{"2020-10-02"} + req.Raw().Header["Accept"] = []string{"application/xml"} + return req, runtime.MarshalAsJSON(req, sharePermission) +} + +// createPermissionHandleResponse handles the CreatePermission response. +func (client *ShareClient) createPermissionHandleResponse(resp *http.Response) (ShareClientCreatePermissionResponse, error) { + result := ShareClientCreatePermissionResponse{} + if val := resp.Header.Get("x-ms-request-id"); val != "" { + result.RequestID = &val + } + if val := resp.Header.Get("x-ms-version"); val != "" { + result.Version = &val + } + if val := resp.Header.Get("Date"); val != "" { + date, err := time.Parse(time.RFC1123, val) + if err != nil { + return ShareClientCreatePermissionResponse{}, err + } + result.Date = &date + } + if val := resp.Header.Get("x-ms-file-permission-key"); val != "" { + result.FilePermissionKey = &val + } + return result, nil +} + +// CreateSnapshot - Creates a read-only snapshot of a share. +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2020-10-02 +// - options - ShareClientCreateSnapshotOptions contains the optional parameters for the ShareClient.CreateSnapshot method. +func (client *ShareClient) CreateSnapshot(ctx context.Context, options *ShareClientCreateSnapshotOptions) (ShareClientCreateSnapshotResponse, error) { + req, err := client.createSnapshotCreateRequest(ctx, options) + if err != nil { + return ShareClientCreateSnapshotResponse{}, err + } + resp, err := client.pl.Do(req) + if err != nil { + return ShareClientCreateSnapshotResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusCreated) { + return ShareClientCreateSnapshotResponse{}, runtime.NewResponseError(resp) + } + return client.createSnapshotHandleResponse(resp) +} + +// createSnapshotCreateRequest creates the CreateSnapshot request. +func (client *ShareClient) createSnapshotCreateRequest(ctx context.Context, options *ShareClientCreateSnapshotOptions) (*policy.Request, error) { + req, err := runtime.NewRequest(ctx, http.MethodPut, client.endpoint) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("restype", "share") + reqQP.Set("comp", "snapshot") + if options != nil && options.Timeout != nil { + reqQP.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + } + req.Raw().URL.RawQuery = reqQP.Encode() + if options != nil && options.Metadata != nil { + for k, v := range options.Metadata { + if v != nil { + req.Raw().Header["x-ms-meta-"+k] = []string{*v} + } + } + } + req.Raw().Header["x-ms-version"] = []string{"2020-10-02"} + req.Raw().Header["Accept"] = []string{"application/xml"} + return req, nil +} + +// createSnapshotHandleResponse handles the CreateSnapshot response. +func (client *ShareClient) createSnapshotHandleResponse(resp *http.Response) (ShareClientCreateSnapshotResponse, error) { + result := ShareClientCreateSnapshotResponse{} + if val := resp.Header.Get("x-ms-snapshot"); val != "" { + result.Snapshot = &val + } + if val := resp.Header.Get("ETag"); val != "" { + result.ETag = (*azcore.ETag)(&val) + } + if val := resp.Header.Get("Last-Modified"); val != "" { + lastModified, err := time.Parse(time.RFC1123, val) + if err != nil { + return ShareClientCreateSnapshotResponse{}, err + } + result.LastModified = &lastModified + } + if val := resp.Header.Get("x-ms-request-id"); val != "" { + result.RequestID = &val + } + if val := resp.Header.Get("x-ms-version"); val != "" { + result.Version = &val + } + if val := resp.Header.Get("Date"); val != "" { + date, err := time.Parse(time.RFC1123, val) + if err != nil { + return ShareClientCreateSnapshotResponse{}, err + } + result.Date = &date + } + return result, nil +} + +// Delete - Operation marks the specified share or share snapshot for deletion. The share or share snapshot and any files +// contained within it are later deleted during garbage collection. +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2020-10-02 +// - options - ShareClientDeleteOptions contains the optional parameters for the ShareClient.Delete method. +// - LeaseAccessConditions - LeaseAccessConditions contains a group of parameters for the ShareClient.GetProperties method. +func (client *ShareClient) Delete(ctx context.Context, options *ShareClientDeleteOptions, leaseAccessConditions *LeaseAccessConditions) (ShareClientDeleteResponse, error) { + req, err := client.deleteCreateRequest(ctx, options, leaseAccessConditions) + if err != nil { + return ShareClientDeleteResponse{}, err + } + resp, err := client.pl.Do(req) + if err != nil { + return ShareClientDeleteResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusAccepted) { + return ShareClientDeleteResponse{}, runtime.NewResponseError(resp) + } + return client.deleteHandleResponse(resp) +} + +// deleteCreateRequest creates the Delete request. +func (client *ShareClient) deleteCreateRequest(ctx context.Context, options *ShareClientDeleteOptions, leaseAccessConditions *LeaseAccessConditions) (*policy.Request, error) { + req, err := runtime.NewRequest(ctx, http.MethodDelete, client.endpoint) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("restype", "share") + if options != nil && options.Sharesnapshot != nil { + reqQP.Set("sharesnapshot", *options.Sharesnapshot) + } + if options != nil && options.Timeout != nil { + reqQP.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + } + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["x-ms-version"] = []string{"2020-10-02"} + if options != nil && options.DeleteSnapshots != nil { + req.Raw().Header["x-ms-delete-snapshots"] = []string{string(*options.DeleteSnapshots)} + } + if leaseAccessConditions != nil && leaseAccessConditions.LeaseID != nil { + req.Raw().Header["x-ms-lease-id"] = []string{*leaseAccessConditions.LeaseID} + } + req.Raw().Header["Accept"] = []string{"application/xml"} + return req, nil +} + +// deleteHandleResponse handles the Delete response. +func (client *ShareClient) deleteHandleResponse(resp *http.Response) (ShareClientDeleteResponse, error) { + result := ShareClientDeleteResponse{} + if val := resp.Header.Get("x-ms-request-id"); val != "" { + result.RequestID = &val + } + if val := resp.Header.Get("x-ms-version"); val != "" { + result.Version = &val + } + if val := resp.Header.Get("Date"); val != "" { + date, err := time.Parse(time.RFC1123, val) + if err != nil { + return ShareClientDeleteResponse{}, err + } + result.Date = &date + } + return result, nil +} + +// GetAccessPolicy - Returns information about stored access policies specified on the share. +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2020-10-02 +// - options - ShareClientGetAccessPolicyOptions contains the optional parameters for the ShareClient.GetAccessPolicy method. +// - LeaseAccessConditions - LeaseAccessConditions contains a group of parameters for the ShareClient.GetProperties method. +func (client *ShareClient) GetAccessPolicy(ctx context.Context, options *ShareClientGetAccessPolicyOptions, leaseAccessConditions *LeaseAccessConditions) (ShareClientGetAccessPolicyResponse, error) { + req, err := client.getAccessPolicyCreateRequest(ctx, options, leaseAccessConditions) + if err != nil { + return ShareClientGetAccessPolicyResponse{}, err + } + resp, err := client.pl.Do(req) + if err != nil { + return ShareClientGetAccessPolicyResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusOK) { + return ShareClientGetAccessPolicyResponse{}, runtime.NewResponseError(resp) + } + return client.getAccessPolicyHandleResponse(resp) +} + +// getAccessPolicyCreateRequest creates the GetAccessPolicy request. +func (client *ShareClient) getAccessPolicyCreateRequest(ctx context.Context, options *ShareClientGetAccessPolicyOptions, leaseAccessConditions *LeaseAccessConditions) (*policy.Request, error) { + req, err := runtime.NewRequest(ctx, http.MethodGet, client.endpoint) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("restype", "share") + reqQP.Set("comp", "acl") + if options != nil && options.Timeout != nil { + reqQP.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + } + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["x-ms-version"] = []string{"2020-10-02"} + if leaseAccessConditions != nil && leaseAccessConditions.LeaseID != nil { + req.Raw().Header["x-ms-lease-id"] = []string{*leaseAccessConditions.LeaseID} + } + req.Raw().Header["Accept"] = []string{"application/xml"} + return req, nil +} + +// getAccessPolicyHandleResponse handles the GetAccessPolicy response. +func (client *ShareClient) getAccessPolicyHandleResponse(resp *http.Response) (ShareClientGetAccessPolicyResponse, error) { + result := ShareClientGetAccessPolicyResponse{} + if val := resp.Header.Get("ETag"); val != "" { + result.ETag = (*azcore.ETag)(&val) + } + if val := resp.Header.Get("Last-Modified"); val != "" { + lastModified, err := time.Parse(time.RFC1123, val) + if err != nil { + return ShareClientGetAccessPolicyResponse{}, err + } + result.LastModified = &lastModified + } + if val := resp.Header.Get("x-ms-request-id"); val != "" { + result.RequestID = &val + } + if val := resp.Header.Get("x-ms-version"); val != "" { + result.Version = &val + } + if val := resp.Header.Get("Date"); val != "" { + date, err := time.Parse(time.RFC1123, val) + if err != nil { + return ShareClientGetAccessPolicyResponse{}, err + } + result.Date = &date + } + if err := runtime.UnmarshalAsXML(resp, &result); err != nil { + return ShareClientGetAccessPolicyResponse{}, err + } + return result, nil +} + +// GetPermission - Returns the permission (security descriptor) for a given key +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2020-10-02 +// - filePermissionKey - Key of the permission to be set for the directory/file. +// - options - ShareClientGetPermissionOptions contains the optional parameters for the ShareClient.GetPermission method. +func (client *ShareClient) GetPermission(ctx context.Context, filePermissionKey string, options *ShareClientGetPermissionOptions) (ShareClientGetPermissionResponse, error) { + req, err := client.getPermissionCreateRequest(ctx, filePermissionKey, options) + if err != nil { + return ShareClientGetPermissionResponse{}, err + } + resp, err := client.pl.Do(req) + if err != nil { + return ShareClientGetPermissionResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusOK) { + return ShareClientGetPermissionResponse{}, runtime.NewResponseError(resp) + } + return client.getPermissionHandleResponse(resp) +} + +// getPermissionCreateRequest creates the GetPermission request. +func (client *ShareClient) getPermissionCreateRequest(ctx context.Context, filePermissionKey string, options *ShareClientGetPermissionOptions) (*policy.Request, error) { + req, err := runtime.NewRequest(ctx, http.MethodGet, client.endpoint) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("restype", "share") + reqQP.Set("comp", "filepermission") + if options != nil && options.Timeout != nil { + reqQP.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + } + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["x-ms-file-permission-key"] = []string{filePermissionKey} + req.Raw().Header["x-ms-version"] = []string{"2020-10-02"} + req.Raw().Header["Accept"] = []string{"application/json"} + return req, nil +} + +// getPermissionHandleResponse handles the GetPermission response. +func (client *ShareClient) getPermissionHandleResponse(resp *http.Response) (ShareClientGetPermissionResponse, error) { + result := ShareClientGetPermissionResponse{} + if val := resp.Header.Get("x-ms-request-id"); val != "" { + result.RequestID = &val + } + if val := resp.Header.Get("x-ms-version"); val != "" { + result.Version = &val + } + if val := resp.Header.Get("Date"); val != "" { + date, err := time.Parse(time.RFC1123, val) + if err != nil { + return ShareClientGetPermissionResponse{}, err + } + result.Date = &date + } + if err := runtime.UnmarshalAsJSON(resp, &result.SharePermission); err != nil { + return ShareClientGetPermissionResponse{}, err + } + return result, nil +} + +// GetProperties - Returns all user-defined metadata and system properties for the specified share or share snapshot. The +// data returned does not include the share's list of files. +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2020-10-02 +// - options - ShareClientGetPropertiesOptions contains the optional parameters for the ShareClient.GetProperties method. +// - LeaseAccessConditions - LeaseAccessConditions contains a group of parameters for the ShareClient.GetProperties method. +func (client *ShareClient) GetProperties(ctx context.Context, options *ShareClientGetPropertiesOptions, leaseAccessConditions *LeaseAccessConditions) (ShareClientGetPropertiesResponse, error) { + req, err := client.getPropertiesCreateRequest(ctx, options, leaseAccessConditions) + if err != nil { + return ShareClientGetPropertiesResponse{}, err + } + resp, err := client.pl.Do(req) + if err != nil { + return ShareClientGetPropertiesResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusOK) { + return ShareClientGetPropertiesResponse{}, runtime.NewResponseError(resp) + } + return client.getPropertiesHandleResponse(resp) +} + +// getPropertiesCreateRequest creates the GetProperties request. +func (client *ShareClient) getPropertiesCreateRequest(ctx context.Context, options *ShareClientGetPropertiesOptions, leaseAccessConditions *LeaseAccessConditions) (*policy.Request, error) { + req, err := runtime.NewRequest(ctx, http.MethodGet, client.endpoint) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("restype", "share") + if options != nil && options.Sharesnapshot != nil { + reqQP.Set("sharesnapshot", *options.Sharesnapshot) + } + if options != nil && options.Timeout != nil { + reqQP.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + } + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["x-ms-version"] = []string{"2020-10-02"} + if leaseAccessConditions != nil && leaseAccessConditions.LeaseID != nil { + req.Raw().Header["x-ms-lease-id"] = []string{*leaseAccessConditions.LeaseID} + } + req.Raw().Header["Accept"] = []string{"application/xml"} + return req, nil +} + +// getPropertiesHandleResponse handles the GetProperties response. +func (client *ShareClient) getPropertiesHandleResponse(resp *http.Response) (ShareClientGetPropertiesResponse, error) { + result := ShareClientGetPropertiesResponse{} + for hh := range resp.Header { + if len(hh) > len("x-ms-meta-") && strings.EqualFold(hh[:len("x-ms-meta-")], "x-ms-meta-") { + if result.Metadata == nil { + result.Metadata = map[string]*string{} + } + result.Metadata[hh[len("x-ms-meta-"):]] = to.Ptr(resp.Header.Get(hh)) + } + } + if val := resp.Header.Get("ETag"); val != "" { + result.ETag = (*azcore.ETag)(&val) + } + if val := resp.Header.Get("Last-Modified"); val != "" { + lastModified, err := time.Parse(time.RFC1123, val) + if err != nil { + return ShareClientGetPropertiesResponse{}, err + } + result.LastModified = &lastModified + } + if val := resp.Header.Get("x-ms-request-id"); val != "" { + result.RequestID = &val + } + if val := resp.Header.Get("x-ms-version"); val != "" { + result.Version = &val + } + if val := resp.Header.Get("Date"); val != "" { + date, err := time.Parse(time.RFC1123, val) + if err != nil { + return ShareClientGetPropertiesResponse{}, err + } + result.Date = &date + } + if val := resp.Header.Get("x-ms-share-quota"); val != "" { + quota32, err := strconv.ParseInt(val, 10, 32) + quota := int32(quota32) + if err != nil { + return ShareClientGetPropertiesResponse{}, err + } + result.Quota = "a + } + if val := resp.Header.Get("x-ms-share-provisioned-iops"); val != "" { + provisionedIops32, err := strconv.ParseInt(val, 10, 32) + provisionedIops := int32(provisionedIops32) + if err != nil { + return ShareClientGetPropertiesResponse{}, err + } + result.ProvisionedIops = &provisionedIops + } + if val := resp.Header.Get("x-ms-share-provisioned-ingress-mbps"); val != "" { + provisionedIngressMBps32, err := strconv.ParseInt(val, 10, 32) + provisionedIngressMBps := int32(provisionedIngressMBps32) + if err != nil { + return ShareClientGetPropertiesResponse{}, err + } + result.ProvisionedIngressMBps = &provisionedIngressMBps + } + if val := resp.Header.Get("x-ms-share-provisioned-egress-mbps"); val != "" { + provisionedEgressMBps32, err := strconv.ParseInt(val, 10, 32) + provisionedEgressMBps := int32(provisionedEgressMBps32) + if err != nil { + return ShareClientGetPropertiesResponse{}, err + } + result.ProvisionedEgressMBps = &provisionedEgressMBps + } + if val := resp.Header.Get("x-ms-share-next-allowed-quota-downgrade-time"); val != "" { + nextAllowedQuotaDowngradeTime, err := time.Parse(time.RFC1123, val) + if err != nil { + return ShareClientGetPropertiesResponse{}, err + } + result.NextAllowedQuotaDowngradeTime = &nextAllowedQuotaDowngradeTime + } + if val := resp.Header.Get("x-ms-lease-duration"); val != "" { + result.LeaseDuration = (*LeaseDurationType)(&val) + } + if val := resp.Header.Get("x-ms-lease-state"); val != "" { + result.LeaseState = (*LeaseStateType)(&val) + } + if val := resp.Header.Get("x-ms-lease-status"); val != "" { + result.LeaseStatus = (*LeaseStatusType)(&val) + } + if val := resp.Header.Get("x-ms-access-tier"); val != "" { + result.AccessTier = &val + } + if val := resp.Header.Get("x-ms-access-tier-change-time"); val != "" { + accessTierChangeTime, err := time.Parse(time.RFC1123, val) + if err != nil { + return ShareClientGetPropertiesResponse{}, err + } + result.AccessTierChangeTime = &accessTierChangeTime + } + if val := resp.Header.Get("x-ms-access-tier-transition-state"); val != "" { + result.AccessTierTransitionState = &val + } + if val := resp.Header.Get("x-ms-enabled-protocols"); val != "" { + result.EnabledProtocols = &val + } + if val := resp.Header.Get("x-ms-root-squash"); val != "" { + result.RootSquash = (*ShareRootSquash)(&val) + } + return result, nil +} + +// GetStatistics - Retrieves statistics related to the share. +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2020-10-02 +// - options - ShareClientGetStatisticsOptions contains the optional parameters for the ShareClient.GetStatistics method. +// - LeaseAccessConditions - LeaseAccessConditions contains a group of parameters for the ShareClient.GetProperties method. +func (client *ShareClient) GetStatistics(ctx context.Context, options *ShareClientGetStatisticsOptions, leaseAccessConditions *LeaseAccessConditions) (ShareClientGetStatisticsResponse, error) { + req, err := client.getStatisticsCreateRequest(ctx, options, leaseAccessConditions) + if err != nil { + return ShareClientGetStatisticsResponse{}, err + } + resp, err := client.pl.Do(req) + if err != nil { + return ShareClientGetStatisticsResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusOK) { + return ShareClientGetStatisticsResponse{}, runtime.NewResponseError(resp) + } + return client.getStatisticsHandleResponse(resp) +} + +// getStatisticsCreateRequest creates the GetStatistics request. +func (client *ShareClient) getStatisticsCreateRequest(ctx context.Context, options *ShareClientGetStatisticsOptions, leaseAccessConditions *LeaseAccessConditions) (*policy.Request, error) { + req, err := runtime.NewRequest(ctx, http.MethodGet, client.endpoint) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("restype", "share") + reqQP.Set("comp", "stats") + if options != nil && options.Timeout != nil { + reqQP.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + } + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["x-ms-version"] = []string{"2020-10-02"} + if leaseAccessConditions != nil && leaseAccessConditions.LeaseID != nil { + req.Raw().Header["x-ms-lease-id"] = []string{*leaseAccessConditions.LeaseID} + } + req.Raw().Header["Accept"] = []string{"application/xml"} + return req, nil +} + +// getStatisticsHandleResponse handles the GetStatistics response. +func (client *ShareClient) getStatisticsHandleResponse(resp *http.Response) (ShareClientGetStatisticsResponse, error) { + result := ShareClientGetStatisticsResponse{} + if val := resp.Header.Get("ETag"); val != "" { + result.ETag = (*azcore.ETag)(&val) + } + if val := resp.Header.Get("Last-Modified"); val != "" { + lastModified, err := time.Parse(time.RFC1123, val) + if err != nil { + return ShareClientGetStatisticsResponse{}, err + } + result.LastModified = &lastModified + } + if val := resp.Header.Get("x-ms-request-id"); val != "" { + result.RequestID = &val + } + if val := resp.Header.Get("x-ms-version"); val != "" { + result.Version = &val + } + if val := resp.Header.Get("Date"); val != "" { + date, err := time.Parse(time.RFC1123, val) + if err != nil { + return ShareClientGetStatisticsResponse{}, err + } + result.Date = &date + } + if err := runtime.UnmarshalAsXML(resp, &result.ShareStats); err != nil { + return ShareClientGetStatisticsResponse{}, err + } + return result, nil +} + +// ReleaseLease - The Lease Share operation establishes and manages a lock on a share, or the specified snapshot for set and +// delete share operations. +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2020-10-02 +// - leaseID - Specifies the current lease ID on the resource. +// - options - ShareClientReleaseLeaseOptions contains the optional parameters for the ShareClient.ReleaseLease method. +func (client *ShareClient) ReleaseLease(ctx context.Context, leaseID string, options *ShareClientReleaseLeaseOptions) (ShareClientReleaseLeaseResponse, error) { + req, err := client.releaseLeaseCreateRequest(ctx, leaseID, options) + if err != nil { + return ShareClientReleaseLeaseResponse{}, err + } + resp, err := client.pl.Do(req) + if err != nil { + return ShareClientReleaseLeaseResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusOK) { + return ShareClientReleaseLeaseResponse{}, runtime.NewResponseError(resp) + } + return client.releaseLeaseHandleResponse(resp) +} + +// releaseLeaseCreateRequest creates the ReleaseLease request. +func (client *ShareClient) releaseLeaseCreateRequest(ctx context.Context, leaseID string, options *ShareClientReleaseLeaseOptions) (*policy.Request, error) { + req, err := runtime.NewRequest(ctx, http.MethodPut, client.endpoint) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("comp", "lease") + reqQP.Set("restype", "share") + if options != nil && options.Timeout != nil { + reqQP.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + } + if options != nil && options.Sharesnapshot != nil { + reqQP.Set("sharesnapshot", *options.Sharesnapshot) + } + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["x-ms-lease-action"] = []string{"release"} + req.Raw().Header["x-ms-lease-id"] = []string{leaseID} + req.Raw().Header["x-ms-version"] = []string{"2020-10-02"} + if options != nil && options.RequestID != nil { + req.Raw().Header["x-ms-client-request-id"] = []string{*options.RequestID} + } + req.Raw().Header["Accept"] = []string{"application/xml"} + return req, nil +} + +// releaseLeaseHandleResponse handles the ReleaseLease response. +func (client *ShareClient) releaseLeaseHandleResponse(resp *http.Response) (ShareClientReleaseLeaseResponse, error) { + result := ShareClientReleaseLeaseResponse{} + if val := resp.Header.Get("ETag"); val != "" { + result.ETag = (*azcore.ETag)(&val) + } + if val := resp.Header.Get("Last-Modified"); val != "" { + lastModified, err := time.Parse(time.RFC1123, val) + if err != nil { + return ShareClientReleaseLeaseResponse{}, err + } + result.LastModified = &lastModified + } + if val := resp.Header.Get("x-ms-client-request-id"); val != "" { + result.ClientRequestID = &val + } + if val := resp.Header.Get("x-ms-request-id"); val != "" { + result.RequestID = &val + } + if val := resp.Header.Get("x-ms-version"); val != "" { + result.Version = &val + } + if val := resp.Header.Get("Date"); val != "" { + date, err := time.Parse(time.RFC1123, val) + if err != nil { + return ShareClientReleaseLeaseResponse{}, err + } + result.Date = &date + } + return result, nil +} + +// RenewLease - The Lease Share operation establishes and manages a lock on a share, or the specified snapshot for set and +// delete share operations. +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2020-10-02 +// - leaseID - Specifies the current lease ID on the resource. +// - options - ShareClientRenewLeaseOptions contains the optional parameters for the ShareClient.RenewLease method. +func (client *ShareClient) RenewLease(ctx context.Context, leaseID string, options *ShareClientRenewLeaseOptions) (ShareClientRenewLeaseResponse, error) { + req, err := client.renewLeaseCreateRequest(ctx, leaseID, options) + if err != nil { + return ShareClientRenewLeaseResponse{}, err + } + resp, err := client.pl.Do(req) + if err != nil { + return ShareClientRenewLeaseResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusOK) { + return ShareClientRenewLeaseResponse{}, runtime.NewResponseError(resp) + } + return client.renewLeaseHandleResponse(resp) +} + +// renewLeaseCreateRequest creates the RenewLease request. +func (client *ShareClient) renewLeaseCreateRequest(ctx context.Context, leaseID string, options *ShareClientRenewLeaseOptions) (*policy.Request, error) { + req, err := runtime.NewRequest(ctx, http.MethodPut, client.endpoint) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("comp", "lease") + reqQP.Set("restype", "share") + if options != nil && options.Timeout != nil { + reqQP.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + } + if options != nil && options.Sharesnapshot != nil { + reqQP.Set("sharesnapshot", *options.Sharesnapshot) + } + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["x-ms-lease-action"] = []string{"renew"} + req.Raw().Header["x-ms-lease-id"] = []string{leaseID} + req.Raw().Header["x-ms-version"] = []string{"2020-10-02"} + if options != nil && options.RequestID != nil { + req.Raw().Header["x-ms-client-request-id"] = []string{*options.RequestID} + } + req.Raw().Header["Accept"] = []string{"application/xml"} + return req, nil +} + +// renewLeaseHandleResponse handles the RenewLease response. +func (client *ShareClient) renewLeaseHandleResponse(resp *http.Response) (ShareClientRenewLeaseResponse, error) { + result := ShareClientRenewLeaseResponse{} + if val := resp.Header.Get("ETag"); val != "" { + result.ETag = (*azcore.ETag)(&val) + } + if val := resp.Header.Get("Last-Modified"); val != "" { + lastModified, err := time.Parse(time.RFC1123, val) + if err != nil { + return ShareClientRenewLeaseResponse{}, err + } + result.LastModified = &lastModified + } + if val := resp.Header.Get("x-ms-lease-id"); val != "" { + result.LeaseID = &val + } + if val := resp.Header.Get("x-ms-client-request-id"); val != "" { + result.ClientRequestID = &val + } + if val := resp.Header.Get("x-ms-request-id"); val != "" { + result.RequestID = &val + } + if val := resp.Header.Get("x-ms-version"); val != "" { + result.Version = &val + } + if val := resp.Header.Get("Date"); val != "" { + date, err := time.Parse(time.RFC1123, val) + if err != nil { + return ShareClientRenewLeaseResponse{}, err + } + result.Date = &date + } + return result, nil +} + +// Restore - Restores a previously deleted Share. +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2020-10-02 +// - options - ShareClientRestoreOptions contains the optional parameters for the ShareClient.Restore method. +func (client *ShareClient) Restore(ctx context.Context, options *ShareClientRestoreOptions) (ShareClientRestoreResponse, error) { + req, err := client.restoreCreateRequest(ctx, options) + if err != nil { + return ShareClientRestoreResponse{}, err + } + resp, err := client.pl.Do(req) + if err != nil { + return ShareClientRestoreResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusCreated) { + return ShareClientRestoreResponse{}, runtime.NewResponseError(resp) + } + return client.restoreHandleResponse(resp) +} + +// restoreCreateRequest creates the Restore request. +func (client *ShareClient) restoreCreateRequest(ctx context.Context, options *ShareClientRestoreOptions) (*policy.Request, error) { + req, err := runtime.NewRequest(ctx, http.MethodPut, client.endpoint) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("restype", "share") + reqQP.Set("comp", "undelete") + if options != nil && options.Timeout != nil { + reqQP.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + } + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["x-ms-version"] = []string{"2020-10-02"} + if options != nil && options.RequestID != nil { + req.Raw().Header["x-ms-client-request-id"] = []string{*options.RequestID} + } + if options != nil && options.DeletedShareName != nil { + req.Raw().Header["x-ms-deleted-share-name"] = []string{*options.DeletedShareName} + } + if options != nil && options.DeletedShareVersion != nil { + req.Raw().Header["x-ms-deleted-share-version"] = []string{*options.DeletedShareVersion} + } + req.Raw().Header["Accept"] = []string{"application/xml"} + return req, nil +} + +// restoreHandleResponse handles the Restore response. +func (client *ShareClient) restoreHandleResponse(resp *http.Response) (ShareClientRestoreResponse, error) { + result := ShareClientRestoreResponse{} + if val := resp.Header.Get("ETag"); val != "" { + result.ETag = (*azcore.ETag)(&val) + } + if val := resp.Header.Get("Last-Modified"); val != "" { + lastModified, err := time.Parse(time.RFC1123, val) + if err != nil { + return ShareClientRestoreResponse{}, err + } + result.LastModified = &lastModified + } + if val := resp.Header.Get("x-ms-request-id"); val != "" { + result.RequestID = &val + } + if val := resp.Header.Get("x-ms-client-request-id"); val != "" { + result.ClientRequestID = &val + } + if val := resp.Header.Get("x-ms-version"); val != "" { + result.Version = &val + } + if val := resp.Header.Get("Date"); val != "" { + date, err := time.Parse(time.RFC1123, val) + if err != nil { + return ShareClientRestoreResponse{}, err + } + result.Date = &date + } + return result, nil +} + +// SetAccessPolicy - Sets a stored access policy for use with shared access signatures. +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2020-10-02 +// - shareACL - The ACL for the share. +// - options - ShareClientSetAccessPolicyOptions contains the optional parameters for the ShareClient.SetAccessPolicy method. +// - LeaseAccessConditions - LeaseAccessConditions contains a group of parameters for the ShareClient.GetProperties method. +func (client *ShareClient) SetAccessPolicy(ctx context.Context, shareACL []*SignedIdentifier, options *ShareClientSetAccessPolicyOptions, leaseAccessConditions *LeaseAccessConditions) (ShareClientSetAccessPolicyResponse, error) { + req, err := client.setAccessPolicyCreateRequest(ctx, shareACL, options, leaseAccessConditions) + if err != nil { + return ShareClientSetAccessPolicyResponse{}, err + } + resp, err := client.pl.Do(req) + if err != nil { + return ShareClientSetAccessPolicyResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusOK) { + return ShareClientSetAccessPolicyResponse{}, runtime.NewResponseError(resp) + } + return client.setAccessPolicyHandleResponse(resp) +} + +// setAccessPolicyCreateRequest creates the SetAccessPolicy request. +func (client *ShareClient) setAccessPolicyCreateRequest(ctx context.Context, shareACL []*SignedIdentifier, options *ShareClientSetAccessPolicyOptions, leaseAccessConditions *LeaseAccessConditions) (*policy.Request, error) { + req, err := runtime.NewRequest(ctx, http.MethodPut, client.endpoint) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("restype", "share") + reqQP.Set("comp", "acl") + if options != nil && options.Timeout != nil { + reqQP.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + } + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["x-ms-version"] = []string{"2020-10-02"} + if leaseAccessConditions != nil && leaseAccessConditions.LeaseID != nil { + req.Raw().Header["x-ms-lease-id"] = []string{*leaseAccessConditions.LeaseID} + } + req.Raw().Header["Accept"] = []string{"application/xml"} + type wrapper struct { + XMLName xml.Name `xml:"SignedIdentifiers"` + ShareACL *[]*SignedIdentifier `xml:"SignedIdentifier"` + } + return req, runtime.MarshalAsXML(req, wrapper{ShareACL: &shareACL}) +} + +// setAccessPolicyHandleResponse handles the SetAccessPolicy response. +func (client *ShareClient) setAccessPolicyHandleResponse(resp *http.Response) (ShareClientSetAccessPolicyResponse, error) { + result := ShareClientSetAccessPolicyResponse{} + if val := resp.Header.Get("ETag"); val != "" { + result.ETag = (*azcore.ETag)(&val) + } + if val := resp.Header.Get("Last-Modified"); val != "" { + lastModified, err := time.Parse(time.RFC1123, val) + if err != nil { + return ShareClientSetAccessPolicyResponse{}, err + } + result.LastModified = &lastModified + } + if val := resp.Header.Get("x-ms-request-id"); val != "" { + result.RequestID = &val + } + if val := resp.Header.Get("x-ms-version"); val != "" { + result.Version = &val + } + if val := resp.Header.Get("Date"); val != "" { + date, err := time.Parse(time.RFC1123, val) + if err != nil { + return ShareClientSetAccessPolicyResponse{}, err + } + result.Date = &date + } + return result, nil +} + +// SetMetadata - Sets one or more user-defined name-value pairs for the specified share. +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2020-10-02 +// - options - ShareClientSetMetadataOptions contains the optional parameters for the ShareClient.SetMetadata method. +// - LeaseAccessConditions - LeaseAccessConditions contains a group of parameters for the ShareClient.GetProperties method. +func (client *ShareClient) SetMetadata(ctx context.Context, options *ShareClientSetMetadataOptions, leaseAccessConditions *LeaseAccessConditions) (ShareClientSetMetadataResponse, error) { + req, err := client.setMetadataCreateRequest(ctx, options, leaseAccessConditions) + if err != nil { + return ShareClientSetMetadataResponse{}, err + } + resp, err := client.pl.Do(req) + if err != nil { + return ShareClientSetMetadataResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusOK) { + return ShareClientSetMetadataResponse{}, runtime.NewResponseError(resp) + } + return client.setMetadataHandleResponse(resp) +} + +// setMetadataCreateRequest creates the SetMetadata request. +func (client *ShareClient) setMetadataCreateRequest(ctx context.Context, options *ShareClientSetMetadataOptions, leaseAccessConditions *LeaseAccessConditions) (*policy.Request, error) { + req, err := runtime.NewRequest(ctx, http.MethodPut, client.endpoint) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("restype", "share") + reqQP.Set("comp", "metadata") + if options != nil && options.Timeout != nil { + reqQP.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + } + req.Raw().URL.RawQuery = reqQP.Encode() + if options != nil && options.Metadata != nil { + for k, v := range options.Metadata { + if v != nil { + req.Raw().Header["x-ms-meta-"+k] = []string{*v} + } + } + } + req.Raw().Header["x-ms-version"] = []string{"2020-10-02"} + if leaseAccessConditions != nil && leaseAccessConditions.LeaseID != nil { + req.Raw().Header["x-ms-lease-id"] = []string{*leaseAccessConditions.LeaseID} + } + req.Raw().Header["Accept"] = []string{"application/xml"} + return req, nil +} + +// setMetadataHandleResponse handles the SetMetadata response. +func (client *ShareClient) setMetadataHandleResponse(resp *http.Response) (ShareClientSetMetadataResponse, error) { + result := ShareClientSetMetadataResponse{} + if val := resp.Header.Get("ETag"); val != "" { + result.ETag = (*azcore.ETag)(&val) + } + if val := resp.Header.Get("Last-Modified"); val != "" { + lastModified, err := time.Parse(time.RFC1123, val) + if err != nil { + return ShareClientSetMetadataResponse{}, err + } + result.LastModified = &lastModified + } + if val := resp.Header.Get("x-ms-request-id"); val != "" { + result.RequestID = &val + } + if val := resp.Header.Get("x-ms-version"); val != "" { + result.Version = &val + } + if val := resp.Header.Get("Date"); val != "" { + date, err := time.Parse(time.RFC1123, val) + if err != nil { + return ShareClientSetMetadataResponse{}, err + } + result.Date = &date + } + return result, nil +} + +// SetProperties - Sets properties for the specified share. +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2020-10-02 +// - options - ShareClientSetPropertiesOptions contains the optional parameters for the ShareClient.SetProperties method. +// - LeaseAccessConditions - LeaseAccessConditions contains a group of parameters for the ShareClient.GetProperties method. +func (client *ShareClient) SetProperties(ctx context.Context, options *ShareClientSetPropertiesOptions, leaseAccessConditions *LeaseAccessConditions) (ShareClientSetPropertiesResponse, error) { + req, err := client.setPropertiesCreateRequest(ctx, options, leaseAccessConditions) + if err != nil { + return ShareClientSetPropertiesResponse{}, err + } + resp, err := client.pl.Do(req) + if err != nil { + return ShareClientSetPropertiesResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusOK) { + return ShareClientSetPropertiesResponse{}, runtime.NewResponseError(resp) + } + return client.setPropertiesHandleResponse(resp) +} + +// setPropertiesCreateRequest creates the SetProperties request. +func (client *ShareClient) setPropertiesCreateRequest(ctx context.Context, options *ShareClientSetPropertiesOptions, leaseAccessConditions *LeaseAccessConditions) (*policy.Request, error) { + req, err := runtime.NewRequest(ctx, http.MethodPut, client.endpoint) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("restype", "share") + reqQP.Set("comp", "properties") + if options != nil && options.Timeout != nil { + reqQP.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + } + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["x-ms-version"] = []string{"2020-10-02"} + if options != nil && options.Quota != nil { + req.Raw().Header["x-ms-share-quota"] = []string{strconv.FormatInt(int64(*options.Quota), 10)} + } + if options != nil && options.AccessTier != nil { + req.Raw().Header["x-ms-access-tier"] = []string{string(*options.AccessTier)} + } + if leaseAccessConditions != nil && leaseAccessConditions.LeaseID != nil { + req.Raw().Header["x-ms-lease-id"] = []string{*leaseAccessConditions.LeaseID} + } + if options != nil && options.RootSquash != nil { + req.Raw().Header["x-ms-root-squash"] = []string{string(*options.RootSquash)} + } + req.Raw().Header["Accept"] = []string{"application/xml"} + return req, nil +} + +// setPropertiesHandleResponse handles the SetProperties response. +func (client *ShareClient) setPropertiesHandleResponse(resp *http.Response) (ShareClientSetPropertiesResponse, error) { + result := ShareClientSetPropertiesResponse{} + if val := resp.Header.Get("ETag"); val != "" { + result.ETag = (*azcore.ETag)(&val) + } + if val := resp.Header.Get("Last-Modified"); val != "" { + lastModified, err := time.Parse(time.RFC1123, val) + if err != nil { + return ShareClientSetPropertiesResponse{}, err + } + result.LastModified = &lastModified + } + if val := resp.Header.Get("x-ms-request-id"); val != "" { + result.RequestID = &val + } + if val := resp.Header.Get("x-ms-version"); val != "" { + result.Version = &val + } + if val := resp.Header.Get("Date"); val != "" { + date, err := time.Parse(time.RFC1123, val) + if err != nil { + return ShareClientSetPropertiesResponse{}, err + } + result.Date = &date + } + return result, nil +} diff --git a/sdk/storage/azfile/internal/generated/zz_time_rfc1123.go b/sdk/storage/azfile/internal/generated/zz_time_rfc1123.go new file mode 100644 index 000000000000..4b4d51aa3994 --- /dev/null +++ b/sdk/storage/azfile/internal/generated/zz_time_rfc1123.go @@ -0,0 +1,43 @@ +//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. +// Code generated by Microsoft (R) AutoRest Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. +// DO NOT EDIT. + +package generated + +import ( + "strings" + "time" +) + +const ( + rfc1123JSON = `"` + time.RFC1123 + `"` +) + +type timeRFC1123 time.Time + +func (t timeRFC1123) MarshalJSON() ([]byte, error) { + b := []byte(time.Time(t).Format(rfc1123JSON)) + return b, nil +} + +func (t timeRFC1123) MarshalText() ([]byte, error) { + b := []byte(time.Time(t).Format(time.RFC1123)) + return b, nil +} + +func (t *timeRFC1123) UnmarshalJSON(data []byte) error { + p, err := time.Parse(rfc1123JSON, strings.ToUpper(string(data))) + *t = timeRFC1123(p) + return err +} + +func (t *timeRFC1123) UnmarshalText(data []byte) error { + p, err := time.Parse(time.RFC1123, string(data)) + *t = timeRFC1123(p) + return err +} diff --git a/sdk/storage/azfile/internal/generated/zz_time_rfc3339.go b/sdk/storage/azfile/internal/generated/zz_time_rfc3339.go new file mode 100644 index 000000000000..1ce9d621164e --- /dev/null +++ b/sdk/storage/azfile/internal/generated/zz_time_rfc3339.go @@ -0,0 +1,59 @@ +//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. +// Code generated by Microsoft (R) AutoRest Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. +// DO NOT EDIT. + +package generated + +import ( + "regexp" + "strings" + "time" +) + +const ( + utcLayoutJSON = `"2006-01-02T15:04:05.999999999"` + utcLayout = "2006-01-02T15:04:05.999999999" + rfc3339JSON = `"` + time.RFC3339Nano + `"` +) + +// Azure reports time in UTC but it doesn't include the 'Z' time zone suffix in some cases. +var tzOffsetRegex = regexp.MustCompile(`(Z|z|\+|-)(\d+:\d+)*"*$`) + +type timeRFC3339 time.Time + +func (t timeRFC3339) MarshalJSON() (json []byte, err error) { + tt := time.Time(t) + return tt.MarshalJSON() +} + +func (t timeRFC3339) MarshalText() (text []byte, err error) { + tt := time.Time(t) + return tt.MarshalText() +} + +func (t *timeRFC3339) UnmarshalJSON(data []byte) error { + layout := utcLayoutJSON + if tzOffsetRegex.Match(data) { + layout = rfc3339JSON + } + return t.Parse(layout, string(data)) +} + +func (t *timeRFC3339) UnmarshalText(data []byte) (err error) { + layout := utcLayout + if tzOffsetRegex.Match(data) { + layout = time.RFC3339Nano + } + return t.Parse(layout, string(data)) +} + +func (t *timeRFC3339) Parse(layout, value string) error { + p, err := time.Parse(layout, strings.ToUpper(value)) + *t = timeRFC3339(p) + return err +} diff --git a/sdk/storage/azfile/internal/generated/zz_xml_helper.go b/sdk/storage/azfile/internal/generated/zz_xml_helper.go new file mode 100644 index 000000000000..144ea18e1aba --- /dev/null +++ b/sdk/storage/azfile/internal/generated/zz_xml_helper.go @@ -0,0 +1,41 @@ +//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. +// Code generated by Microsoft (R) AutoRest Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. +// DO NOT EDIT. + +package generated + +import ( + "encoding/xml" + "strings" +) + +type additionalProperties map[string]*string + +// UnmarshalXML implements the xml.Unmarshaler interface for additionalProperties. +func (ap *additionalProperties) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error { + tokName := "" + for t, err := d.Token(); err == nil; t, err = d.Token() { + switch tt := t.(type) { + case xml.StartElement: + tokName = strings.ToLower(tt.Name.Local) + break + case xml.CharData: + if tokName == "" { + continue + } + if *ap == nil { + *ap = additionalProperties{} + } + s := string(tt) + (*ap)[tokName] = &s + tokName = "" + break + } + } + return nil +} diff --git a/sdk/storage/azfile/internal/shared/batch_transfer.go b/sdk/storage/azfile/internal/shared/batch_transfer.go new file mode 100644 index 000000000000..ec5541bfbb13 --- /dev/null +++ b/sdk/storage/azfile/internal/shared/batch_transfer.go @@ -0,0 +1,77 @@ +//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 shared + +import ( + "context" + "errors" +) + +// BatchTransferOptions identifies options used by doBatchTransfer. +type BatchTransferOptions struct { + TransferSize int64 + ChunkSize int64 + Concurrency uint16 + Operation func(ctx context.Context, offset int64, chunkSize int64) error + OperationName string +} + +// DoBatchTransfer helps to execute operations in a batch manner. +// Can be used by users to customize batch works (for other scenarios that the SDK does not provide) +func DoBatchTransfer(ctx context.Context, o *BatchTransferOptions) error { + if o.ChunkSize == 0 { + return errors.New("ChunkSize cannot be 0") + } + + if o.Concurrency == 0 { + o.Concurrency = 5 // default concurrency + } + + // Prepare and do parallel operations. + numChunks := uint16(((o.TransferSize - 1) / o.ChunkSize) + 1) + operationChannel := make(chan func() error, o.Concurrency) // Create the channel that release 'concurrency' goroutines concurrently + operationResponseChannel := make(chan error, numChunks) // Holds each response + ctx, cancel := context.WithCancel(ctx) + defer cancel() + + // Create the goroutines that process each operation (in parallel). + for g := uint16(0); g < o.Concurrency; g++ { + //grIndex := g + go func() { + for f := range operationChannel { + err := f() + operationResponseChannel <- err + } + }() + } + + // Add each chunk's operation to the channel. + for chunkNum := uint16(0); chunkNum < numChunks; chunkNum++ { + curChunkSize := o.ChunkSize + + if chunkNum == numChunks-1 { // Last chunk + curChunkSize = o.TransferSize - (int64(chunkNum) * o.ChunkSize) // Remove size of all transferred chunks from total + } + offset := int64(chunkNum) * o.ChunkSize + operationChannel <- func() error { + return o.Operation(ctx, offset, curChunkSize) + } + } + close(operationChannel) + + // Wait for the operations to complete. + var firstErr error = nil + for chunkNum := uint16(0); chunkNum < numChunks; chunkNum++ { + responseError := <-operationResponseChannel + // record the first error (the original error which should cause the other chunks to fail with canceled context) + if responseError != nil && firstErr == nil { + cancel() // As soon as any operation fails, cancel all remaining operation calls + firstErr = responseError + } + } + return firstErr +} diff --git a/sdk/storage/azfile/internal/shared/bytes_writer.go b/sdk/storage/azfile/internal/shared/bytes_writer.go new file mode 100644 index 000000000000..8d4d35bdeffd --- /dev/null +++ b/sdk/storage/azfile/internal/shared/bytes_writer.go @@ -0,0 +1,30 @@ +//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 shared + +import ( + "errors" +) + +type bytesWriter []byte + +func NewBytesWriter(b []byte) bytesWriter { + return b +} + +func (c bytesWriter) WriteAt(b []byte, off int64) (int, error) { + if off >= int64(len(c)) || off < 0 { + return 0, errors.New("offset value is out of range") + } + + n := copy(c[int(off):], b) + if n < len(b) { + return n, errors.New("not enough space for all bytes") + } + + return n, nil +} diff --git a/sdk/storage/azfile/internal/shared/bytes_writer_test.go b/sdk/storage/azfile/internal/shared/bytes_writer_test.go new file mode 100644 index 000000000000..5f1bc53c29ca --- /dev/null +++ b/sdk/storage/azfile/internal/shared/bytes_writer_test.go @@ -0,0 +1,37 @@ +//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 shared + +import ( + "bytes" + "testing" + + "github.com/stretchr/testify/require" +) + +func TestBytesWriter(t *testing.T) { + b := make([]byte, 10) + buffer := NewBytesWriter(b) + + count, err := buffer.WriteAt([]byte{1, 2}, 10) + require.Contains(t, err.Error(), "offset value is out of range") + require.Equal(t, count, 0) + + count, err = buffer.WriteAt([]byte{1, 2}, -1) + require.Contains(t, err.Error(), "offset value is out of range") + require.Equal(t, count, 0) + + count, err = buffer.WriteAt([]byte{1, 2}, 9) + require.Contains(t, err.Error(), "not enough space for all bytes") + require.Equal(t, count, 1) + require.Equal(t, bytes.Compare(b, []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 1}), 0) + + count, err = buffer.WriteAt([]byte{1, 2}, 8) + require.NoError(t, err) + require.Equal(t, count, 2) + require.Equal(t, bytes.Compare(b, []byte{0, 0, 0, 0, 0, 0, 0, 0, 1, 2}), 0) +} diff --git a/sdk/storage/azfile/internal/shared/section_writer.go b/sdk/storage/azfile/internal/shared/section_writer.go new file mode 100644 index 000000000000..c8528a2e3ed2 --- /dev/null +++ b/sdk/storage/azfile/internal/shared/section_writer.go @@ -0,0 +1,53 @@ +//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 shared + +import ( + "errors" + "io" +) + +type SectionWriter struct { + Count int64 + Offset int64 + Position int64 + WriterAt io.WriterAt +} + +func NewSectionWriter(c io.WriterAt, off int64, count int64) *SectionWriter { + return &SectionWriter{ + Count: count, + Offset: off, + WriterAt: c, + } +} + +func (c *SectionWriter) Write(p []byte) (int, error) { + remaining := c.Count - c.Position + + if remaining <= 0 { + return 0, errors.New("end of section reached") + } + + slice := p + + if int64(len(slice)) > remaining { + slice = slice[:remaining] + } + + n, err := c.WriterAt.WriteAt(slice, c.Offset+c.Position) + c.Position += int64(n) + if err != nil { + return n, err + } + + if len(p) > n { + return n, errors.New("not enough space for all bytes") + } + + return n, nil +} diff --git a/sdk/storage/azfile/internal/shared/section_writer_test.go b/sdk/storage/azfile/internal/shared/section_writer_test.go new file mode 100644 index 000000000000..a1cf22da410a --- /dev/null +++ b/sdk/storage/azfile/internal/shared/section_writer_test.go @@ -0,0 +1,98 @@ +//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 shared + +import ( + "bytes" + "io" + "testing" + + "github.com/stretchr/testify/require" +) + +func TestSectionWriter(t *testing.T) { + b := [10]byte{} + buffer := NewBytesWriter(b[:]) + + section := NewSectionWriter(buffer, 0, 5) + require.Equal(t, section.Count, int64(5)) + require.Equal(t, section.Offset, int64(0)) + require.Equal(t, section.Position, int64(0)) + + count, err := section.Write([]byte{1, 2, 3}) + require.NoError(t, err) + require.Equal(t, count, 3) + require.Equal(t, section.Position, int64(3)) + require.Equal(t, b, [10]byte{1, 2, 3, 0, 0, 0, 0, 0, 0, 0}) + + count, err = section.Write([]byte{4, 5, 6}) + require.Contains(t, err.Error(), "not enough space for all bytes") + require.Equal(t, count, 2) + require.Equal(t, section.Position, int64(5)) + require.Equal(t, b, [10]byte{1, 2, 3, 4, 5, 0, 0, 0, 0, 0}) + + count, err = section.Write([]byte{6, 7, 8}) + require.Contains(t, err.Error(), "end of section reached") + require.Equal(t, count, 0) + require.Equal(t, section.Position, int64(5)) + require.Equal(t, b, [10]byte{1, 2, 3, 4, 5, 0, 0, 0, 0, 0}) + + // Intentionally create a section writer which will attempt to write + // outside the bounds of the buffer. + section = NewSectionWriter(buffer, 5, 6) + require.Equal(t, section.Count, int64(6)) + require.Equal(t, section.Offset, int64(5)) + require.Equal(t, section.Position, int64(0)) + + count, err = section.Write([]byte{6, 7, 8}) + require.NoError(t, err) + require.Equal(t, count, 3) + require.Equal(t, section.Position, int64(3)) + require.Equal(t, b, [10]byte{1, 2, 3, 4, 5, 6, 7, 8, 0, 0}) + + // Attempt to write past the end of the section. Since the underlying + // buffer rejects the write it gives the same error as in the normal case. + count, err = section.Write([]byte{9, 10, 11}) + require.Contains(t, err.Error(), "not enough space for all bytes") + require.Equal(t, count, 2) + require.Equal(t, section.Position, int64(5)) + require.Equal(t, b, [10]byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}) + + // Attempt to write past the end of the buffer. In this case the buffer + // rejects the write completely since it falls completely out of bounds. + count, err = section.Write([]byte{11, 12, 13}) + require.Contains(t, err.Error(), "offset value is out of range") + require.Equal(t, count, 0) + require.Equal(t, section.Position, int64(5)) + require.Equal(t, b, [10]byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}) +} + +func TestSectionWriterCopySrcDestEmpty(t *testing.T) { + input := make([]byte, 0) + reader := bytes.NewReader(input) + + output := make([]byte, 0) + buffer := NewBytesWriter(output) + section := NewSectionWriter(buffer, 0, 0) + + count, err := io.Copy(section, reader) + require.NoError(t, err) + require.Equal(t, count, int64(0)) +} + +func TestSectionWriterCopyDestEmpty(t *testing.T) { + input := make([]byte, 10) + reader := bytes.NewReader(input) + + output := make([]byte, 0) + buffer := NewBytesWriter(output) + section := NewSectionWriter(buffer, 0, 0) + + count, err := io.Copy(section, reader) + require.Contains(t, err.Error(), "end of section reached") + require.Equal(t, count, int64(0)) +} diff --git a/sdk/storage/azfile/internal/shared/shared.go b/sdk/storage/azfile/internal/shared/shared.go new file mode 100644 index 000000000000..0b819c28ea5a --- /dev/null +++ b/sdk/storage/azfile/internal/shared/shared.go @@ -0,0 +1,226 @@ +//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 shared + +import ( + "errors" + "fmt" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/to" + "github.com/Azure/azure-sdk-for-go/sdk/internal/uuid" + "hash/crc64" + "io" + "net" + "strings" +) + +const ( + TokenScope = "https://storage.azure.com/.default" +) + +const ( + HeaderAuthorization = "Authorization" + HeaderXmsDate = "x-ms-date" + HeaderContentLength = "Content-Length" + HeaderContentEncoding = "Content-Encoding" + HeaderContentLanguage = "Content-Language" + HeaderContentType = "Content-Type" + HeaderContentMD5 = "Content-MD5" + HeaderIfModifiedSince = "If-Modified-Since" + HeaderIfMatch = "If-Match" + HeaderIfNoneMatch = "If-None-Match" + HeaderIfUnmodifiedSince = "If-Unmodified-Since" + HeaderRange = "Range" +) + +const StorageAnalyticsVersion = "1.0" + +const crc64Polynomial uint64 = 0x9A6C9329AC4BC9B5 + +var CRC64Table = crc64.MakeTable(crc64Polynomial) + +const ( + // DefaultFilePermissionString is a constant for all intents and purposes. + // Inherit inherits permissions from the parent folder (default when creating files/folders) + DefaultFilePermissionString = "inherit" + + // DefaultCurrentTimeString sets creation/last write times to now + DefaultCurrentTimeString = "now" + + // DefaultPreserveString preserves old permissions on the file/folder (default when updating properties) + DefaultPreserveString = "preserve" + + // FileAttributesNone is defaults for file attributes when creating file. + // This attribute is valid only when used alone. + FileAttributesNone = "None" + + // FileAttributesDirectory is defaults for file attributes when creating directory. + // The attribute that identifies a directory + FileAttributesDirectory = "Directory" +) + +func GetClientOptions[T any](o *T) *T { + if o == nil { + return new(T) + } + return o +} + +var errConnectionString = errors.New("connection string is either blank or malformed. The expected connection string " + + "should contain key value pairs separated by semicolons. For example 'DefaultEndpointsProtocol=https;AccountName=;" + + "AccountKey=;EndpointSuffix=core.windows.net'") + +type ParsedConnectionString struct { + ServiceURL string + AccountName string + AccountKey string +} + +func ParseConnectionString(connectionString string) (ParsedConnectionString, error) { + const ( + defaultScheme = "https" + defaultSuffix = "core.windows.net" + ) + + connStrMap := make(map[string]string) + connectionString = strings.TrimRight(connectionString, ";") + + splitString := strings.Split(connectionString, ";") + if len(splitString) == 0 { + return ParsedConnectionString{}, errConnectionString + } + for _, stringPart := range splitString { + parts := strings.SplitN(stringPart, "=", 2) + if len(parts) != 2 { + return ParsedConnectionString{}, errConnectionString + } + connStrMap[parts[0]] = parts[1] + } + + accountName := connStrMap["AccountName"] + accountKey, ok := connStrMap["AccountKey"] + if !ok { + sharedAccessSignature, ok := connStrMap["SharedAccessSignature"] + if !ok { + return ParsedConnectionString{}, errors.New("connection string missing AccountKey and SharedAccessSignature") + } + + fileEndpoint, ok := connStrMap["FileEndpoint"] + if !ok { + // We don't have a FileEndpoint, assume the default + if accountName != "" { + return ParsedConnectionString{ + ServiceURL: fmt.Sprintf("%v://%v.file.%v/?%v", defaultScheme, accountName, defaultSuffix, sharedAccessSignature), + }, nil + } else { + return ParsedConnectionString{}, errors.New("connection string missing AccountName") + } + } else { + if !strings.HasSuffix(fileEndpoint, "/") { + // add a trailing slash to be consistent with the portal + fileEndpoint += "/" + } + return ParsedConnectionString{ + ServiceURL: fmt.Sprintf("%v?%v", fileEndpoint, sharedAccessSignature), + }, nil + } + } else { + if accountName == "" { + return ParsedConnectionString{}, errors.New("connection string missing AccountName") + } + } + + protocol, ok := connStrMap["DefaultEndpointsProtocol"] + if !ok { + protocol = defaultScheme + } + + suffix, ok := connStrMap["EndpointSuffix"] + if !ok { + suffix = defaultSuffix + } + + if fileEndpoint, ok := connStrMap["FileEndpoint"]; ok { + return ParsedConnectionString{ + ServiceURL: fileEndpoint, + AccountName: accountName, + AccountKey: accountKey, + }, nil + } + + return ParsedConnectionString{ + ServiceURL: fmt.Sprintf("%v://%v.file.%v", protocol, accountName, suffix), + AccountName: accountName, + AccountKey: accountKey, + }, nil +} + +// IsIPEndpointStyle checks if URL's host is IP, in this case the storage account endpoint will be composed as: +// http(s)://IP(:port)/storageaccount/share(||container||etc)/... +// As url's Host property, host could be both host or host:port +func IsIPEndpointStyle(host string) bool { + if host == "" { + return false + } + if h, _, err := net.SplitHostPort(host); err == nil { + host = h + } + // For IPv6, there could be case where SplitHostPort fails for cannot finding port. + // In this case, eliminate the '[' and ']' in the URL. + // For details about IPv6 URL, please refer to https://tools.ietf.org/html/rfc2732 + if host[0] == '[' && host[len(host)-1] == ']' { + host = host[1 : len(host)-1] + } + return net.ParseIP(host) != nil +} + +func GenerateLeaseID(leaseID *string) (*string, error) { + if leaseID == nil { + generatedUuid, err := uuid.New() + if err != nil { + return nil, err + } + leaseID = to.Ptr(generatedUuid.String()) + } + return leaseID, nil +} + +func ValidateSeekableStreamAt0AndGetCount(body io.ReadSeeker) (int64, error) { + if body == nil { // nil body is "logically" seekable to 0 and are 0 bytes long + return 0, nil + } + + err := validateSeekableStreamAt0(body) + if err != nil { + return 0, err + } + + count, err := body.Seek(0, io.SeekEnd) + if err != nil { + return 0, errors.New("body stream must be seekable") + } + + _, err = body.Seek(0, io.SeekStart) + if err != nil { + return 0, err + } + return count, nil +} + +// return an error if body is not a valid seekable stream at 0 +func validateSeekableStreamAt0(body io.ReadSeeker) error { + if body == nil { // nil body is "logically" seekable to 0 + return nil + } + if pos, err := body.Seek(0, io.SeekCurrent); pos != 0 || err != nil { + // Help detect programmer error + if err != nil { + return errors.New("body stream must be seekable") + } + return errors.New("body stream must be set to position 0") + } + return nil +} diff --git a/sdk/storage/azfile/internal/shared/shared_test.go b/sdk/storage/azfile/internal/shared/shared_test.go new file mode 100644 index 000000000000..8bb7f9a9e655 --- /dev/null +++ b/sdk/storage/azfile/internal/shared/shared_test.go @@ -0,0 +1,135 @@ +//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 shared + +import ( + "fmt" + "testing" + + "github.com/stretchr/testify/require" +) + +func TestParseConnectionStringInvalid(t *testing.T) { + badConnectionStrings := []string{ + "", + "foobar", + "foo;bar;baz", + "foo=;bar=;", + "=", + ";", + "=;==", + "foobar=baz=foo", + } + + for _, badConnStr := range badConnectionStrings { + parsed, err := ParseConnectionString(badConnStr) + require.Error(t, err) + require.Zero(t, parsed) + } +} + +func TestParseConnectionString(t *testing.T) { + connStr := "DefaultEndpointsProtocol=https;AccountName=dummyaccount;AccountKey=secretkeykey;EndpointSuffix=core.windows.net" + parsed, err := ParseConnectionString(connStr) + require.NoError(t, err) + require.Equal(t, "https://dummyaccount.file.core.windows.net", parsed.ServiceURL) + require.Equal(t, "dummyaccount", parsed.AccountName) + require.Equal(t, "secretkeykey", parsed.AccountKey) +} + +func TestParseConnectionStringHTTP(t *testing.T) { + connStr := "DefaultEndpointsProtocol=http;AccountName=dummyaccount;AccountKey=secretkeykey;EndpointSuffix=core.windows.net" + parsed, err := ParseConnectionString(connStr) + require.NoError(t, err) + require.Equal(t, "http://dummyaccount.file.core.windows.net", parsed.ServiceURL) + require.Equal(t, "dummyaccount", parsed.AccountName) + require.Equal(t, "secretkeykey", parsed.AccountKey) +} + +func TestParseConnectionStringBasic(t *testing.T) { + connStr := "AccountName=dummyaccount;AccountKey=secretkeykey" + parsed, err := ParseConnectionString(connStr) + require.NoError(t, err) + require.Equal(t, "https://dummyaccount.file.core.windows.net", parsed.ServiceURL) + require.Equal(t, "dummyaccount", parsed.AccountName) + require.Equal(t, "secretkeykey", parsed.AccountKey) +} + +func TestParseConnectionStringCustomDomain(t *testing.T) { + connStr := "AccountName=dummyaccount;AccountKey=secretkeykey;FileEndpoint=www.mydomain.com;" + parsed, err := ParseConnectionString(connStr) + require.NoError(t, err) + require.Equal(t, "www.mydomain.com", parsed.ServiceURL) + require.Equal(t, "dummyaccount", parsed.AccountName) + require.Equal(t, "secretkeykey", parsed.AccountKey) +} + +func TestParseConnectionStringSAS(t *testing.T) { + connStr := "AccountName=dummyaccount;SharedAccessSignature=fakesharedaccesssignature;" + parsed, err := ParseConnectionString(connStr) + require.NoError(t, err) + require.Equal(t, "https://dummyaccount.file.core.windows.net/?fakesharedaccesssignature", parsed.ServiceURL) + require.Empty(t, parsed.AccountName) + require.Empty(t, parsed.AccountKey) +} + +func TestParseConnectionStringChinaCloud(t *testing.T) { + connStr := "AccountName=dummyaccountname;AccountKey=secretkeykey;DefaultEndpointsProtocol=http;EndpointSuffix=core.chinacloudapi.cn;" + parsed, err := ParseConnectionString(connStr) + require.NoError(t, err) + require.Equal(t, "http://dummyaccountname.file.core.chinacloudapi.cn", parsed.ServiceURL) + require.Equal(t, "dummyaccountname", parsed.AccountName) + require.Equal(t, "secretkeykey", parsed.AccountKey) +} + +func TestCParseConnectionStringAzurite(t *testing.T) { + connStr := "DefaultEndpointsProtocol=http;AccountName=dummyaccountname;AccountKey=secretkeykey;FileEndpoint=http://local-machine:11002/custom/account/path/faketokensignature;" + parsed, err := ParseConnectionString(connStr) + require.NoError(t, err) + require.Equal(t, "http://local-machine:11002/custom/account/path/faketokensignature", parsed.ServiceURL) + require.Equal(t, "dummyaccountname", parsed.AccountName) + require.Equal(t, "secretkeykey", parsed.AccountKey) +} + +func TestParseConnectionStringSASAndCustomDomain(t *testing.T) { + testData := []struct { + connectionStr string + parsedServiceURL string + parsedAccountName string + parsedAccountKey string + err error + }{ + { + connectionStr: "AccountName=dummyaccountname;SharedAccessSignature=fakesharedaccesssignature;FileEndpoint=http://127.0.0.1:10000/dummyaccountname;", + parsedServiceURL: "http://127.0.0.1:10000/dummyaccountname/?fakesharedaccesssignature", + }, + { + connectionStr: "BlobEndpoint=https://dummyaccountname.blob.core.windows.net/;FileEndpoint=https://dummyaccountname.file.core.windows.net/;SharedAccessSignature=fakesharedaccesssignature", + parsedServiceURL: "https://dummyaccountname.file.core.windows.net/?fakesharedaccesssignature", + }, + { + connectionStr: "BlobEndpoint=https://dummyaccountname.blob.core.windows.net;FileEndpoint=https://dummyaccountname.file.core.windows.net;SharedAccessSignature=fakesharedaccesssignature", + parsedServiceURL: "https://dummyaccountname.file.core.windows.net/?fakesharedaccesssignature", + }, + { + connectionStr: "SharedAccessSignature=fakesharedaccesssignature", + err: fmt.Errorf("connection string missing AccountName"), + }, + { + connectionStr: "DefaultEndpointsProtocol=http;AccountKey=secretkeykey;EndpointSuffix=core.windows.net", + err: fmt.Errorf("connection string missing AccountName"), + }, + } + + for _, td := range testData { + parsed, err := ParseConnectionString(td.connectionStr) + require.Equal(t, td.err, err) + require.Equal(t, td.parsedServiceURL, parsed.ServiceURL) + require.Equal(t, td.parsedAccountName, parsed.AccountName) + require.Equal(t, td.parsedAccountKey, parsed.AccountKey) + } +} diff --git a/sdk/storage/azfile/internal/testcommon/clients_auth.go b/sdk/storage/azfile/internal/testcommon/clients_auth.go new file mode 100644 index 000000000000..8e2e562116f0 --- /dev/null +++ b/sdk/storage/azfile/internal/testcommon/clients_auth.go @@ -0,0 +1,224 @@ +//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. + +// Contains common helpers for TESTS ONLY +package testcommon + +import ( + "context" + "errors" + "fmt" + "github.com/Azure/azure-sdk-for-go/sdk/azcore" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/policy" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/streaming" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/to" + "github.com/Azure/azure-sdk-for-go/sdk/azidentity" + "github.com/Azure/azure-sdk-for-go/sdk/internal/recording" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azfile/directory" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azfile/file" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azfile/service" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azfile/share" + "github.com/stretchr/testify/require" + "strings" + "testing" + "time" +) + +type TestAccountType string + +const ( + TestAccountDefault TestAccountType = "" + TestAccountSecondary TestAccountType = "SECONDARY_" + TestAccountPremium TestAccountType = "PREMIUM_" + TestAccountSoftDelete TestAccountType = "SOFT_DELETE_" +) + +const ( + DefaultEndpointSuffix = "core.windows.net/" + DefaultFileEndpointSuffix = "file.core.windows.net/" + AccountNameEnvVar = "AZURE_STORAGE_ACCOUNT_NAME" + AccountKeyEnvVar = "AZURE_STORAGE_ACCOUNT_KEY" + DefaultEndpointSuffixEnvVar = "AZURE_STORAGE_ENDPOINT_SUFFIX" +) + +const ( + FakeStorageAccount = "fakestorage" + FakeStorageURL = "https://fakestorage.file.core.windows.net" + FakeToken = "faketoken" +) + +const ( + ISO8601 = "2006-01-02T15:04:05.0000000Z07:00" +) + +var ( + SampleSDDL = `O:S-1-5-32-548G:S-1-5-21-397955417-626881126-188441444-512D:(A;;RPWPCCDCLCSWRCWDWOGA;;;S-1-0-0)` +) + +var BasicMetadata = map[string]*string{ + "foo": to.Ptr("foovalue"), + "bar": to.Ptr("barvalue"), +} + +func SetClientOptions(t *testing.T, opts *azcore.ClientOptions) { + opts.Logging.AllowedHeaders = append(opts.Logging.AllowedHeaders, "X-Request-Mismatch", "X-Request-Mismatch-Error") + + transport, err := recording.NewRecordingHTTPClient(t, nil) + require.NoError(t, err) + opts.Transport = transport +} + +func GetServiceClient(t *testing.T, accountType TestAccountType, options *service.ClientOptions) (*service.Client, error) { + if options == nil { + options = &service.ClientOptions{} + } + + SetClientOptions(t, &options.ClientOptions) + + cred, err := GetGenericSharedKeyCredential(accountType) + if err != nil { + return nil, err + } + + serviceClient, err := service.NewClientWithSharedKeyCredential("https://"+cred.AccountName()+".file.core.windows.net/", cred, options) + + return serviceClient, err +} + +func GetServiceClientNoCredential(t *testing.T, sasUrl string, options *service.ClientOptions) (*service.Client, error) { + if options == nil { + options = &service.ClientOptions{} + } + + SetClientOptions(t, &options.ClientOptions) + + serviceClient, err := service.NewClientWithNoCredential(sasUrl, options) + + return serviceClient, err +} + +func GetGenericAccountInfo(accountType TestAccountType) (string, string) { + if recording.GetRecordMode() == recording.PlaybackMode { + return FakeStorageAccount, "ZmFrZQ==" + } + accountNameEnvVar := string(accountType) + AccountNameEnvVar + accountKeyEnvVar := string(accountType) + AccountKeyEnvVar + accountName, _ := GetRequiredEnv(accountNameEnvVar) + accountKey, _ := GetRequiredEnv(accountKeyEnvVar) + return accountName, accountKey +} + +func GetGenericSharedKeyCredential(accountType TestAccountType) (*service.SharedKeyCredential, error) { + accountName, accountKey := GetGenericAccountInfo(accountType) + if accountName == "" || accountKey == "" { + return nil, errors.New(string(accountType) + AccountNameEnvVar + " and/or " + string(accountType) + AccountKeyEnvVar + " environment variables not specified.") + } + return service.NewSharedKeyCredential(accountName, accountKey) +} + +func GetGenericConnectionString(accountType TestAccountType) (*string, error) { + accountName, accountKey := GetGenericAccountInfo(accountType) + if accountName == "" || accountKey == "" { + return nil, errors.New(string(accountType) + AccountNameEnvVar + " and/or " + string(accountType) + AccountKeyEnvVar + " environment variables not specified.") + } + connectionString := fmt.Sprintf("DefaultEndpointsProtocol=https;AccountName=%s;AccountKey=%s;EndpointSuffix=core.windows.net/", + accountName, accountKey) + return &connectionString, nil +} + +type FakeCredential struct { +} + +func (c *FakeCredential) GetToken(ctx context.Context, opts policy.TokenRequestOptions) (azcore.AccessToken, error) { + return azcore.AccessToken{Token: FakeToken, ExpiresOn: time.Now().Add(time.Hour).UTC()}, nil +} + +func GetGenericTokenCredential() (azcore.TokenCredential, error) { + if recording.GetRecordMode() == recording.PlaybackMode { + return &FakeCredential{}, nil + } + return azidentity.NewDefaultAzureCredential(nil) +} + +func GetServiceClientFromConnectionString(t *testing.T, accountType TestAccountType, options *service.ClientOptions) (*service.Client, error) { + if options == nil { + options = &service.ClientOptions{} + } + SetClientOptions(t, &options.ClientOptions) + + transport, err := recording.NewRecordingHTTPClient(t, nil) + require.NoError(t, err) + options.Transport = transport + + cred, err := GetGenericConnectionString(accountType) + if err != nil { + return nil, err + } + svcClient, err := service.NewClientFromConnectionString(*cred, options) + return svcClient, err +} + +func GetShareClient(shareName string, s *service.Client) *share.Client { + return s.NewShareClient(shareName) +} + +func CreateNewShare(ctx context.Context, _require *require.Assertions, shareName string, svcClient *service.Client) *share.Client { + shareClient := GetShareClient(shareName, svcClient) + _, err := shareClient.Create(ctx, nil) + _require.NoError(err) + return shareClient +} + +func DeleteShare(ctx context.Context, _require *require.Assertions, shareClient *share.Client) { + _, err := shareClient.Delete(ctx, nil) + _require.NoError(err) +} + +func GetDirectoryClient(dirName string, s *share.Client) *directory.Client { + return s.NewDirectoryClient(dirName) +} + +func CreateNewDirectory(ctx context.Context, _require *require.Assertions, dirName string, shareClient *share.Client) *directory.Client { + dirClient := GetDirectoryClient(dirName, shareClient) + _, err := dirClient.Create(ctx, nil) + _require.NoError(err) + return dirClient +} + +func DeleteDirectory(ctx context.Context, _require *require.Assertions, dirClient *directory.Client) { + _, err := dirClient.Delete(ctx, nil) + _require.NoError(err) +} + +func GetFileClientFromShare(fileName string, shareClient *share.Client) *file.Client { + return shareClient.NewRootDirectoryClient().NewFileClient(fileName) +} + +func CreateNewFileFromShare(ctx context.Context, _require *require.Assertions, fileName string, fileSize int64, shareClient *share.Client) *file.Client { + fClient := GetFileClientFromShare(fileName, shareClient) + + _, err := fClient.Create(ctx, fileSize, nil) + _require.NoError(err) + + return fClient +} + +func CreateNewFileFromShareWithData(ctx context.Context, _require *require.Assertions, fileName string, shareClient *share.Client) *file.Client { + fClient := GetFileClientFromShare(fileName, shareClient) + + _, err := fClient.Create(ctx, int64(len(FileDefaultData)), nil) + _require.NoError(err) + + _, err = fClient.UploadRange(ctx, 0, streaming.NopCloser(strings.NewReader(FileDefaultData)), nil) + _require.NoError(err) + + return fClient +} + +func DeleteFile(ctx context.Context, _require *require.Assertions, fileClient *file.Client) { + _, err := fileClient.Delete(ctx, nil) + _require.NoError(err) +} diff --git a/sdk/storage/azfile/internal/testcommon/common.go b/sdk/storage/azfile/internal/testcommon/common.go new file mode 100644 index 000000000000..11e61800da79 --- /dev/null +++ b/sdk/storage/azfile/internal/testcommon/common.go @@ -0,0 +1,117 @@ +//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. + +// Contains common helpers for TESTS ONLY +package testcommon + +import ( + "bytes" + "errors" + "github.com/Azure/azure-sdk-for-go/sdk/azcore" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/streaming" + "github.com/Azure/azure-sdk-for-go/sdk/internal/recording" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azfile/fileerror" + "github.com/stretchr/testify/require" + "io" + "os" + "strconv" + "strings" + "testing" +) + +const ( + SharePrefix = "gos" + DirectoryPrefix = "godir" + FilePrefix = "gotestfile" + FileDefaultData = "GoFileDefaultData" +) + +func GenerateShareName(testName string) string { + return SharePrefix + GenerateEntityName(testName) +} + +func GenerateEntityName(testName string) string { + return strings.ReplaceAll(strings.ReplaceAll(strings.ToLower(testName), "/", ""), "test", "") +} + +func GenerateDirectoryName(testName string) string { + return DirectoryPrefix + GenerateEntityName(testName) +} + +func GenerateFileName(testName string) string { + return FilePrefix + GenerateEntityName(testName) +} + +const random64BString string = "2SDgZj6RkKYzJpu04sweQek4uWHO8ndPnYlZ0tnFS61hjnFZ5IkvIGGY44eKABov" + +func GenerateData(sizeInBytes int) (io.ReadSeekCloser, []byte) { + data := make([]byte, sizeInBytes) + _len := len(random64BString) + if sizeInBytes > _len { + count := sizeInBytes / _len + if sizeInBytes%_len != 0 { + count = count + 1 + } + copy(data[:], strings.Repeat(random64BString, count)) + } else { + copy(data[:], random64BString) + } + return streaming.NopCloser(bytes.NewReader(data)), data +} + +func ValidateHTTPErrorCode(_require *require.Assertions, err error, code int) { + _require.Error(err) + var responseErr *azcore.ResponseError + errors.As(err, &responseErr) + if responseErr != nil { + _require.Equal(responseErr.StatusCode, code) + } else { + _require.Equal(strings.Contains(err.Error(), strconv.Itoa(code)), true) + } +} + +func ValidateFileErrorCode(_require *require.Assertions, err error, code fileerror.Code) { + _require.Error(err) + var responseErr *azcore.ResponseError + errors.As(err, &responseErr) + if responseErr != nil { + _require.Equal(string(code), responseErr.ErrorCode) + } else { + _require.Contains(err.Error(), code) + } +} + +// GetRequiredEnv gets an environment variable by name and returns an error if it is not found +func GetRequiredEnv(name string) (string, error) { + env, ok := os.LookupEnv(name) + if ok { + return env, nil + } else { + return "", errors.New("Required environment variable not set: " + name) + } +} + +func BeforeTest(t *testing.T, suite string, test string) { + const urlRegex = `https://\S+\.file\.core\.windows\.net` + const tokenRegex = `(?:Bearer\s).*` + + require.NoError(t, recording.AddURISanitizer(FakeStorageURL, urlRegex, nil)) + require.NoError(t, recording.AddHeaderRegexSanitizer("x-ms-copy-source", FakeStorageURL, urlRegex, nil)) + require.NoError(t, recording.AddHeaderRegexSanitizer("x-ms-copy-source-authorization", FakeToken, tokenRegex, nil)) + // we freeze request IDs and timestamps to avoid creating noisy diffs + // NOTE: we can't freeze time stamps as that breaks some tests that use if-modified-since etc (maybe it can be fixed?) + //testframework.AddHeaderRegexSanitizer("X-Ms-Date", "Wed, 10 Aug 2022 23:34:14 GMT", "", nil) + require.NoError(t, recording.AddHeaderRegexSanitizer("x-ms-request-id", "00000000-0000-0000-0000-000000000000", "", nil)) + //testframework.AddHeaderRegexSanitizer("Date", "Wed, 10 Aug 2022 23:34:14 GMT", "", nil) + // TODO: more freezing + //testframework.AddBodyRegexSanitizer("RequestId:00000000-0000-0000-0000-000000000000", `RequestId:\w{8}-\w{4}-\w{4}-\w{4}-\w{12}`, nil) + //testframework.AddBodyRegexSanitizer("Time:2022-08-11T00:21:56.4562741Z", `Time:\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d*)?Z`, nil) + require.NoError(t, recording.Start(t, "sdk/storage/azfile/testdata", nil)) +} + +func AfterTest(t *testing.T, suite string, test string) { + require.NoError(t, recording.Stop(t, nil)) +} diff --git a/sdk/storage/azfile/lease/client_test.go b/sdk/storage/azfile/lease/client_test.go new file mode 100644 index 000000000000..7b90fbfa9f7f --- /dev/null +++ b/sdk/storage/azfile/lease/client_test.go @@ -0,0 +1,633 @@ +//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 lease_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/azfile/file" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azfile/internal/testcommon" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azfile/lease" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azfile/share" + "github.com/stretchr/testify/require" + "github.com/stretchr/testify/suite" + "testing" + "time" +) + +func Test(t *testing.T) { + recordMode := recording.GetRecordMode() + t.Logf("Running lease Tests in %s mode\n", recordMode) + if recordMode == recording.LiveMode { + suite.Run(t, &LeaseRecordedTestsSuite{}) + suite.Run(t, &LeaseUnrecordedTestsSuite{}) + } else if recordMode == recording.PlaybackMode { + suite.Run(t, &LeaseRecordedTestsSuite{}) + } else if recordMode == recording.RecordingMode { + suite.Run(t, &LeaseRecordedTestsSuite{}) + } +} + +func (l *LeaseRecordedTestsSuite) BeforeTest(suite string, test string) { + testcommon.BeforeTest(l.T(), suite, test) +} + +func (l *LeaseRecordedTestsSuite) AfterTest(suite string, test string) { + testcommon.AfterTest(l.T(), suite, test) +} + +func (l *LeaseUnrecordedTestsSuite) BeforeTest(suite string, test string) { + +} + +func (l *LeaseUnrecordedTestsSuite) AfterTest(suite string, test string) { + +} + +type LeaseRecordedTestsSuite struct { + suite.Suite +} + +type LeaseUnrecordedTestsSuite struct { + suite.Suite +} + +var proposedLeaseIDs = []*string{to.Ptr("c820a799-76d7-4ee2-6e15-546f19325c2c"), to.Ptr("326cc5e1-746e-4af8-4811-a50e6629a8ca")} + +func (l *LeaseRecordedTestsSuite) TestShareAcquireLease() { + _require := require.New(l.T()) + testName := l.T().Name() + + svcClient, err := testcommon.GetServiceClient(l.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + shareName := testcommon.GenerateShareName(testName) + shareClient := testcommon.CreateNewShare(context.Background(), _require, shareName, svcClient) + defer testcommon.DeleteShare(context.Background(), _require, shareClient) + + shareLeaseClient, _ := lease.NewShareClient(shareClient, &lease.ShareClientOptions{ + LeaseID: proposedLeaseIDs[0], + }) + + ctx := context.Background() + acquireLeaseResponse, err := shareLeaseClient.Acquire(ctx, int32(60), nil) + _require.NoError(err) + _require.NotNil(acquireLeaseResponse.LeaseID) + _require.EqualValues(*acquireLeaseResponse.LeaseID, *shareLeaseClient.LeaseID()) + + _, err = shareClient.Delete(ctx, nil) + _require.Error(err) + + _, err = shareLeaseClient.Release(ctx, nil) + _require.NoError(err) +} + +func (l *LeaseRecordedTestsSuite) TestNegativeShareAcquireMultipleLease() { + _require := require.New(l.T()) + testName := l.T().Name() + + svcClient, err := testcommon.GetServiceClient(l.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + shareName := testcommon.GenerateShareName(testName) + shareClient := testcommon.CreateNewShare(context.Background(), _require, shareName, svcClient) + defer testcommon.DeleteShare(context.Background(), _require, shareClient) + + shareLeaseClient0, _ := lease.NewShareClient(shareClient, &lease.ShareClientOptions{ + LeaseID: proposedLeaseIDs[0], + }) + + shareLeaseClient1, _ := lease.NewShareClient(shareClient, &lease.ShareClientOptions{ + LeaseID: proposedLeaseIDs[1], + }) + + ctx := context.Background() + acquireLeaseResponse0, err := shareLeaseClient0.Acquire(ctx, int32(60), nil) + _require.NoError(err) + _require.NotNil(acquireLeaseResponse0.LeaseID) + _require.EqualValues(*acquireLeaseResponse0.LeaseID, *shareLeaseClient0.LeaseID()) + + // acquiring lease for the second time returns LeaseAlreadyPresent error + _, err = shareLeaseClient1.Acquire(ctx, int32(60), nil) + _require.Error(err) + + _, err = shareLeaseClient0.Release(ctx, nil) + _require.NoError(err) +} + +func (l *LeaseRecordedTestsSuite) TestShareDeleteShareWithoutLeaseId() { + _require := require.New(l.T()) + testName := l.T().Name() + + svcClient, err := testcommon.GetServiceClient(l.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + shareName := testcommon.GenerateShareName(testName) + shareClient := testcommon.CreateNewShare(context.Background(), _require, shareName, svcClient) + defer testcommon.DeleteShare(context.Background(), _require, shareClient) + + shareLeaseClient, _ := lease.NewShareClient(shareClient, &lease.ShareClientOptions{ + LeaseID: proposedLeaseIDs[0], + }) + + ctx := context.Background() + acquireLeaseResponse, err := shareLeaseClient.Acquire(ctx, int32(60), nil) + _require.NoError(err) + _require.NotNil(acquireLeaseResponse.LeaseID) + _require.EqualValues(*acquireLeaseResponse.LeaseID, *shareLeaseClient.LeaseID()) + + _, err = shareClient.Delete(ctx, nil) + _require.Error(err) + + leaseID := shareLeaseClient.LeaseID() + _, err = shareClient.Delete(ctx, &share.DeleteOptions{ + LeaseAccessConditions: &share.LeaseAccessConditions{LeaseID: leaseID}, + }) + _require.NoError(err) +} + +func (l *LeaseRecordedTestsSuite) TestShareReleaseLease() { + _require := require.New(l.T()) + testName := l.T().Name() + + svcClient, err := testcommon.GetServiceClient(l.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + shareName := testcommon.GenerateShareName(testName) + shareClient := testcommon.CreateNewShare(context.Background(), _require, shareName, svcClient) + defer testcommon.DeleteShare(context.Background(), _require, shareClient) + + shareLeaseClient, _ := lease.NewShareClient(shareClient, &lease.ShareClientOptions{ + LeaseID: proposedLeaseIDs[0], + }) + + ctx := context.Background() + acquireLeaseResponse, err := shareLeaseClient.Acquire(ctx, int32(60), nil) + _require.NoError(err) + _require.NotNil(acquireLeaseResponse.LeaseID) + _require.EqualValues(*acquireLeaseResponse.LeaseID, *shareLeaseClient.LeaseID()) + + _, err = shareClient.Delete(ctx, nil) + _require.Error(err) + + _, err = shareLeaseClient.Release(ctx, nil) + _require.NoError(err) + + _, err = shareClient.Delete(ctx, nil) + _require.NoError(err) +} + +func (l *LeaseRecordedTestsSuite) TestShareRenewLease() { + _require := require.New(l.T()) + testName := l.T().Name() + + svcClient, err := testcommon.GetServiceClient(l.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + shareName := testcommon.GenerateShareName(testName) + shareClient := testcommon.CreateNewShare(context.Background(), _require, shareName, svcClient) + defer testcommon.DeleteShare(context.Background(), _require, shareClient) + + shareLeaseClient, _ := lease.NewShareClient(shareClient, &lease.ShareClientOptions{ + LeaseID: proposedLeaseIDs[0], + }) + + ctx := context.Background() + acquireLeaseResponse, err := shareLeaseClient.Acquire(ctx, int32(15), nil) + _require.NoError(err) + _require.NotNil(acquireLeaseResponse.LeaseID) + _require.EqualValues(*acquireLeaseResponse.LeaseID, *shareLeaseClient.LeaseID()) + + _, err = shareLeaseClient.Renew(ctx, nil) + _require.NoError(err) + + _, err = shareLeaseClient.Release(ctx, nil) + _require.NoError(err) +} + +func (l *LeaseRecordedTestsSuite) TestShareBreakLeaseDefault() { + _require := require.New(l.T()) + testName := l.T().Name() + + svcClient, err := testcommon.GetServiceClient(l.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + shareName := testcommon.GenerateShareName(testName) + shareClient := testcommon.CreateNewShare(context.Background(), _require, shareName, svcClient) + defer testcommon.DeleteShare(context.Background(), _require, shareClient) + + shareLeaseClient, _ := lease.NewShareClient(shareClient, &lease.ShareClientOptions{ + LeaseID: proposedLeaseIDs[0], + }) + + ctx := context.Background() + acquireLeaseResponse, err := shareLeaseClient.Acquire(ctx, int32(60), nil) + _require.NoError(err) + _require.NotNil(acquireLeaseResponse.LeaseID) + _require.EqualValues(*acquireLeaseResponse.LeaseID, *shareLeaseClient.LeaseID()) + + bResp, err := shareLeaseClient.Break(ctx, nil) + _require.NoError(err) + _require.NotNil(bResp.LeaseTime) + + _, err = shareClient.Delete(ctx, nil) + _require.Error(err) + + _, err = shareLeaseClient.Release(ctx, nil) + _require.NoError(err) +} + +func (l *LeaseRecordedTestsSuite) TestShareBreakLeaseNonDefault() { + _require := require.New(l.T()) + testName := l.T().Name() + + svcClient, err := testcommon.GetServiceClient(l.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + shareName := testcommon.GenerateShareName(testName) + shareClient := testcommon.CreateNewShare(context.Background(), _require, shareName, svcClient) + defer testcommon.DeleteShare(context.Background(), _require, shareClient) + + shareLeaseClient, _ := lease.NewShareClient(shareClient, &lease.ShareClientOptions{ + LeaseID: proposedLeaseIDs[0], + }) + + ctx := context.Background() + acquireLeaseResponse, err := shareLeaseClient.Acquire(ctx, int32(60), nil) + _require.NoError(err) + _require.NotNil(acquireLeaseResponse.LeaseID) + _require.EqualValues(*acquireLeaseResponse.LeaseID, *shareLeaseClient.LeaseID()) + + bResp, err := shareLeaseClient.Break(ctx, &lease.ShareBreakOptions{ + BreakPeriod: to.Ptr((int32)(5)), + }) + _require.NoError(err) + _require.NotNil(bResp.LeaseTime) + + _, err = shareClient.Delete(ctx, nil) + _require.Error(err) + + // wait for lease to expire + time.Sleep(6 * time.Second) + + _, err = shareClient.Delete(ctx, nil) + _require.NoError(err) +} + +func (l *LeaseRecordedTestsSuite) TestNegativeShareBreakRenewLease() { + _require := require.New(l.T()) + testName := l.T().Name() + + svcClient, err := testcommon.GetServiceClient(l.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + shareName := testcommon.GenerateShareName(testName) + shareClient := testcommon.CreateNewShare(context.Background(), _require, shareName, svcClient) + defer testcommon.DeleteShare(context.Background(), _require, shareClient) + + shareLeaseClient, _ := lease.NewShareClient(shareClient, &lease.ShareClientOptions{ + LeaseID: proposedLeaseIDs[0], + }) + + ctx := context.Background() + acquireLeaseResponse, err := shareLeaseClient.Acquire(ctx, int32(60), nil) + _require.NoError(err) + _require.NotNil(acquireLeaseResponse.LeaseID) + _require.EqualValues(*acquireLeaseResponse.LeaseID, *shareLeaseClient.LeaseID()) + + bResp, err := shareLeaseClient.Break(ctx, &lease.ShareBreakOptions{ + BreakPeriod: to.Ptr((int32)(5)), + }) + _require.NoError(err) + _require.NotNil(bResp.LeaseTime) + + // renewing broken lease returns error + _, err = shareLeaseClient.Renew(ctx, nil) + _require.Error(err) + + _, err = shareLeaseClient.Release(ctx, nil) + _require.NoError(err) +} + +func (l *LeaseRecordedTestsSuite) TestShareChangeLease() { + _require := require.New(l.T()) + testName := l.T().Name() + + svcClient, err := testcommon.GetServiceClient(l.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + shareName := testcommon.GenerateShareName(testName) + shareClient := testcommon.CreateNewShare(context.Background(), _require, shareName, svcClient) + defer testcommon.DeleteShare(context.Background(), _require, shareClient) + + shareLeaseClient, _ := lease.NewShareClient(shareClient, &lease.ShareClientOptions{ + LeaseID: proposedLeaseIDs[0], + }) + + ctx := context.Background() + acquireLeaseResponse, err := shareLeaseClient.Acquire(ctx, int32(60), nil) + _require.NoError(err) + _require.NotNil(acquireLeaseResponse.LeaseID) + _require.EqualValues(*acquireLeaseResponse.LeaseID, *shareLeaseClient.LeaseID()) + + oldLeaseID := shareLeaseClient.LeaseID() + + changeLeaseResp, err := shareLeaseClient.Change(ctx, *proposedLeaseIDs[1], nil) + _require.NoError(err) + _require.EqualValues(changeLeaseResp.LeaseID, proposedLeaseIDs[1]) + _require.EqualValues(shareLeaseClient.LeaseID(), proposedLeaseIDs[1]) + + _, err = shareClient.Delete(ctx, &share.DeleteOptions{ + LeaseAccessConditions: &share.LeaseAccessConditions{ + LeaseID: oldLeaseID, + }, + }) + _require.Error(err) + + _, err = shareLeaseClient.Renew(ctx, nil) + _require.NoError(err) + + _, err = shareLeaseClient.Release(ctx, nil) + _require.NoError(err) +} + +func (l *LeaseRecordedTestsSuite) TestFileAcquireLease() { + _require := require.New(l.T()) + testName := l.T().Name() + + svcClient, err := testcommon.GetServiceClient(l.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + shareName := testcommon.GenerateShareName(testName) + shareClient := testcommon.CreateNewShare(context.Background(), _require, shareName, svcClient) + defer testcommon.DeleteShare(context.Background(), _require, shareClient) + + ctx := context.Background() + fileName := testcommon.GenerateFileName(testName) + fileClient := shareClient.NewRootDirectoryClient().NewFileClient(fileName) + _, err = fileClient.Create(ctx, 0, nil) + _require.NoError(err) + + fileLeaseClient, err := lease.NewFileClient(fileClient, &lease.FileClientOptions{ + LeaseID: proposedLeaseIDs[0], + }) + _require.NoError(err) + + acquireLeaseResponse, err := fileLeaseClient.Acquire(ctx, nil) + _require.NoError(err) + _require.NotNil(acquireLeaseResponse.LeaseID) + _require.EqualValues(acquireLeaseResponse.LeaseID, fileLeaseClient.LeaseID()) + + _, err = fileClient.Delete(ctx, nil) + _require.Error(err) + + _, err = fileLeaseClient.Release(ctx, nil) + _require.NoError(err) +} + +func (l *LeaseRecordedTestsSuite) TestNegativeFileAcquireMultipleLease() { + _require := require.New(l.T()) + testName := l.T().Name() + + svcClient, err := testcommon.GetServiceClient(l.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + shareName := testcommon.GenerateShareName(testName) + shareClient := testcommon.CreateNewShare(context.Background(), _require, shareName, svcClient) + defer testcommon.DeleteShare(context.Background(), _require, shareClient) + + ctx := context.Background() + fileName := testcommon.GenerateFileName(testName) + fileClient := shareClient.NewRootDirectoryClient().NewFileClient(fileName) + _, err = fileClient.Create(ctx, 0, nil) + _require.NoError(err) + + fileLeaseClient0, err := lease.NewFileClient(fileClient, &lease.FileClientOptions{ + LeaseID: proposedLeaseIDs[0], + }) + _require.NoError(err) + + fileLeaseClient1, err := lease.NewFileClient(fileClient, &lease.FileClientOptions{ + LeaseID: proposedLeaseIDs[1], + }) + _require.NoError(err) + + acquireLeaseResponse, err := fileLeaseClient0.Acquire(ctx, nil) + _require.NoError(err) + _require.NotNil(acquireLeaseResponse.LeaseID) + _require.EqualValues(acquireLeaseResponse.LeaseID, fileLeaseClient0.LeaseID()) + + // acquiring lease for the second time returns LeaseAlreadyPresent error + _, err = fileLeaseClient1.Acquire(ctx, nil) + _require.Error(err) + + _, err = fileClient.Delete(ctx, nil) + _require.Error(err) + + _, err = fileLeaseClient0.Release(ctx, nil) + _require.NoError(err) +} + +func (l *LeaseRecordedTestsSuite) TestDeleteFileWithoutLeaseId() { + _require := require.New(l.T()) + testName := l.T().Name() + + svcClient, err := testcommon.GetServiceClient(l.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + shareName := testcommon.GenerateShareName(testName) + shareClient := testcommon.CreateNewShare(context.Background(), _require, shareName, svcClient) + defer testcommon.DeleteShare(context.Background(), _require, shareClient) + + ctx := context.Background() + fileName := testcommon.GenerateFileName(testName) + fileClient := shareClient.NewRootDirectoryClient().NewFileClient(fileName) + _, err = fileClient.Create(ctx, 0, nil) + _require.NoError(err) + + fileLeaseClient, err := lease.NewFileClient(fileClient, &lease.FileClientOptions{ + LeaseID: proposedLeaseIDs[0], + }) + _require.NoError(err) + + acquireLeaseResponse, err := fileLeaseClient.Acquire(ctx, nil) + _require.NoError(err) + _require.NotNil(acquireLeaseResponse.LeaseID) + _require.EqualValues(acquireLeaseResponse.LeaseID, fileLeaseClient.LeaseID()) + + _, err = fileClient.Delete(ctx, nil) + _require.Error(err) + + leaseID := fileLeaseClient.LeaseID() + _, err = fileClient.Delete(ctx, &file.DeleteOptions{ + LeaseAccessConditions: &file.LeaseAccessConditions{ + LeaseID: leaseID, + }, + }) + _require.NoError(err) +} + +func (l *LeaseRecordedTestsSuite) TestFileReleaseLease() { + _require := require.New(l.T()) + testName := l.T().Name() + + svcClient, err := testcommon.GetServiceClient(l.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + shareName := testcommon.GenerateShareName(testName) + shareClient := testcommon.CreateNewShare(context.Background(), _require, shareName, svcClient) + defer testcommon.DeleteShare(context.Background(), _require, shareClient) + + ctx := context.Background() + fileName := testcommon.GenerateFileName(testName) + fileClient := shareClient.NewRootDirectoryClient().NewFileClient(fileName) + _, err = fileClient.Create(ctx, 0, nil) + _require.NoError(err) + + fileLeaseClient, err := lease.NewFileClient(fileClient, &lease.FileClientOptions{ + LeaseID: proposedLeaseIDs[0], + }) + _require.NoError(err) + + acquireLeaseResponse, err := fileLeaseClient.Acquire(ctx, nil) + _require.NoError(err) + _require.NotNil(acquireLeaseResponse.LeaseID) + _require.EqualValues(acquireLeaseResponse.LeaseID, fileLeaseClient.LeaseID()) + + _, err = fileClient.Delete(ctx, nil) + _require.Error(err) + + _, err = fileLeaseClient.Release(ctx, nil) + _require.NoError(err) + + _, err = fileClient.Delete(ctx, nil) + _require.NoError(err) +} + +func (l *LeaseRecordedTestsSuite) TestFileChangeLease() { + _require := require.New(l.T()) + testName := l.T().Name() + + svcClient, err := testcommon.GetServiceClient(l.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + shareName := testcommon.GenerateShareName(testName) + shareClient := testcommon.CreateNewShare(context.Background(), _require, shareName, svcClient) + defer testcommon.DeleteShare(context.Background(), _require, shareClient) + + ctx := context.Background() + fileName := testcommon.GenerateFileName(testName) + fileClient := shareClient.NewRootDirectoryClient().NewFileClient(fileName) + _, err = fileClient.Create(ctx, 0, nil) + _require.NoError(err) + + fileLeaseClient, err := lease.NewFileClient(fileClient, &lease.FileClientOptions{ + LeaseID: proposedLeaseIDs[0], + }) + _require.NoError(err) + + acquireLeaseResponse, err := fileLeaseClient.Acquire(ctx, nil) + _require.NoError(err) + _require.NotNil(acquireLeaseResponse.LeaseID) + _require.Equal(*acquireLeaseResponse.LeaseID, *proposedLeaseIDs[0]) + + oldLeaseID := fileLeaseClient.LeaseID() + + changeLeaseResp, err := fileLeaseClient.Change(ctx, *proposedLeaseIDs[1], nil) + _require.NoError(err) + _require.Equal(*changeLeaseResp.LeaseID, *proposedLeaseIDs[1]) + + _, err = fileClient.Delete(ctx, &file.DeleteOptions{ + LeaseAccessConditions: &file.LeaseAccessConditions{ + LeaseID: oldLeaseID, + }, + }) + _require.Error(err) + + _, err = fileLeaseClient.Release(ctx, nil) + _require.NoError(err) +} + +func (l *LeaseRecordedTestsSuite) TestNegativeFileDeleteAfterReleaseLease() { + _require := require.New(l.T()) + testName := l.T().Name() + + svcClient, err := testcommon.GetServiceClient(l.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + shareName := testcommon.GenerateShareName(testName) + shareClient := testcommon.CreateNewShare(context.Background(), _require, shareName, svcClient) + defer testcommon.DeleteShare(context.Background(), _require, shareClient) + + ctx := context.Background() + fileName := testcommon.GenerateFileName(testName) + fileClient := shareClient.NewRootDirectoryClient().NewFileClient(fileName) + _, err = fileClient.Create(ctx, 0, nil) + _require.NoError(err) + + fileLeaseClient, err := lease.NewFileClient(fileClient, &lease.FileClientOptions{ + LeaseID: proposedLeaseIDs[0], + }) + _require.NoError(err) + + acquireLeaseResponse, err := fileLeaseClient.Acquire(ctx, nil) + _require.NoError(err) + _require.NotNil(acquireLeaseResponse.LeaseID) + _require.EqualValues(acquireLeaseResponse.LeaseID, fileLeaseClient.LeaseID()) + + _, err = fileClient.Delete(ctx, nil) + _require.Error(err) + + _, err = fileLeaseClient.Release(ctx, nil) + _require.NoError(err) + + // deleting file after its lease has expired or released returns error. + _, err = fileClient.Delete(ctx, &file.DeleteOptions{ + LeaseAccessConditions: &file.LeaseAccessConditions{ + LeaseID: fileLeaseClient.LeaseID(), + }, + }) + _require.Error(err) +} + +func (l *LeaseRecordedTestsSuite) TestFileBreakLease() { + _require := require.New(l.T()) + testName := l.T().Name() + + svcClient, err := testcommon.GetServiceClient(l.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + shareName := testcommon.GenerateShareName(testName) + shareClient := testcommon.CreateNewShare(context.Background(), _require, shareName, svcClient) + defer testcommon.DeleteShare(context.Background(), _require, shareClient) + + ctx := context.Background() + fileName := testcommon.GenerateFileName(testName) + fileClient := shareClient.NewRootDirectoryClient().NewFileClient(fileName) + _, err = fileClient.Create(ctx, 0, nil) + _require.NoError(err) + + fileLeaseClient, err := lease.NewFileClient(fileClient, &lease.FileClientOptions{ + LeaseID: proposedLeaseIDs[0], + }) + _require.NoError(err) + + acquireLeaseResponse, err := fileLeaseClient.Acquire(ctx, nil) + _require.NoError(err) + _require.NotNil(acquireLeaseResponse.LeaseID) + _require.EqualValues(acquireLeaseResponse.LeaseID, fileLeaseClient.LeaseID()) + + _, err = fileClient.Delete(ctx, nil) + _require.Error(err) + + _, err = fileLeaseClient.Break(ctx, nil) + _require.NoError(err) + + _, err = fileClient.Delete(ctx, nil) + _require.NoError(err) +} diff --git a/sdk/storage/azfile/lease/constants.go b/sdk/storage/azfile/lease/constants.go new file mode 100644 index 000000000000..3b384475deb0 --- /dev/null +++ b/sdk/storage/azfile/lease/constants.go @@ -0,0 +1,51 @@ +//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 lease + +import "github.com/Azure/azure-sdk-for-go/sdk/storage/azfile/internal/generated" + +// DurationType - When a share is leased, specifies whether the lease is of infinite or fixed duration. +type DurationType = generated.LeaseDurationType + +const ( + DurationTypeInfinite DurationType = generated.LeaseDurationTypeInfinite + DurationTypeFixed DurationType = generated.LeaseDurationTypeFixed +) + +// PossibleDurationTypeValues returns the possible values for the DurationType const type. +func PossibleDurationTypeValues() []DurationType { + return generated.PossibleLeaseDurationTypeValues() +} + +// StateType - Lease state of the share. +type StateType = generated.LeaseStateType + +const ( + StateTypeAvailable StateType = generated.LeaseStateTypeAvailable + StateTypeLeased StateType = generated.LeaseStateTypeLeased + StateTypeExpired StateType = generated.LeaseStateTypeExpired + StateTypeBreaking StateType = generated.LeaseStateTypeBreaking + StateTypeBroken StateType = generated.LeaseStateTypeBroken +) + +// PossibleStateTypeValues returns the possible values for the StateType const type. +func PossibleStateTypeValues() []StateType { + return generated.PossibleLeaseStateTypeValues() +} + +// StatusType - The current lease status of the share. +type StatusType = generated.LeaseStatusType + +const ( + StatusTypeLocked StatusType = generated.LeaseStatusTypeLocked + StatusTypeUnlocked StatusType = generated.LeaseStatusTypeUnlocked +) + +// PossibleStatusTypeValues returns the possible values for the StatusType const type. +func PossibleStatusTypeValues() []StatusType { + return generated.PossibleLeaseStatusTypeValues() +} diff --git a/sdk/storage/azfile/lease/examples_test.go b/sdk/storage/azfile/lease/examples_test.go new file mode 100644 index 000000000000..f8b61b3ba133 --- /dev/null +++ b/sdk/storage/azfile/lease/examples_test.go @@ -0,0 +1,101 @@ +//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 lease_test + +import ( + "context" + "fmt" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/to" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azfile/lease" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azfile/service" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azfile/share" + "log" + "os" +) + +func handleError(err error) { + if err != nil { + log.Fatal(err.Error()) + } +} + +// This example shows how to perform various lease operations on a share. +// The same lease operations can be performed on individual files as well. +// A lease on a share prevents it from being deleted by others, while a lease on a file +// protects it from both modifications and deletions. +func Example_lease_ShareClient_AcquireLease() { + accountName, ok := os.LookupEnv("AZURE_STORAGE_ACCOUNT_NAME") + if !ok { + panic("AZURE_STORAGE_ACCOUNT_NAME could not be found") + } + accountKey, ok := os.LookupEnv("AZURE_STORAGE_ACCOUNT_KEY") + if !ok { + panic("AZURE_STORAGE_ACCOUNT_KEY could not be found") + } + + shareName := "testshare" + shareURL := fmt.Sprintf("https://%s.file.core.windows.net/%s", accountName, shareName) + + cred, err := service.NewSharedKeyCredential(accountName, accountKey) + handleError(err) + + shareClient, err := share.NewClientWithSharedKeyCredential(shareURL, cred, nil) + handleError(err) + + // Create a unique ID for the lease + // A lease ID can be any valid GUID string format. To generate UUIDs, consider the github.com/google/uuid package + leaseID := "36b1a876-cf98-4eb2-a5c3-6d68489658ff" + shareLeaseClient, err := lease.NewShareClient(shareClient, &lease.ShareClientOptions{LeaseID: to.Ptr(leaseID)}) + handleError(err) + + // Now acquire a lease on the share. + // You can choose to pass an empty string for proposed ID so that the service automatically assigns one for you. + duration := int32(60) + acquireLeaseResponse, err := shareLeaseClient.Acquire(context.TODO(), duration, nil) + handleError(err) + fmt.Println("The share is leased for delete operations with lease ID", *acquireLeaseResponse.LeaseID) + + // The share cannot be deleted without providing the lease ID. + _, err = shareClient.Delete(context.TODO(), nil) + if err == nil { + log.Fatal("delete should have failed") + } + + fmt.Println("The share cannot be deleted while there is an active lease") + + // share can be deleted by providing the lease id + //_, err = shareClient.Delete(context.TODO(), &share.DeleteOptions{ + // LeaseAccessConditions: &share.LeaseAccessConditions{LeaseID: acquireLeaseResponse.LeaseID}, + //}) + + // We can release the lease now and the share can be deleted. + _, err = shareLeaseClient.Release(context.TODO(), nil) + handleError(err) + fmt.Println("The lease on the share is now released") + + // AcquireLease a lease again to perform other operations. + // Duration is still 60 + acquireLeaseResponse, err = shareLeaseClient.Acquire(context.TODO(), duration, nil) + handleError(err) + fmt.Println("The share is leased again with lease ID", *acquireLeaseResponse.LeaseID) + + // We can change the ID of an existing lease. + newLeaseID := "6b3e65e5-e1bb-4a3f-8b72-13e9bc9cd3bf" + changeLeaseResponse, err := shareLeaseClient.Change(context.TODO(), newLeaseID, nil) + handleError(err) + fmt.Println("The lease ID was changed to", *changeLeaseResponse.LeaseID) + + // The lease can be renewed. + renewLeaseResponse, err := shareLeaseClient.Renew(context.TODO(), nil) + handleError(err) + fmt.Println("The lease was renewed with the same ID", *renewLeaseResponse.LeaseID) + + // Finally, the lease can be broken, and we could prevent others from acquiring a lease for a period of time + _, err = shareLeaseClient.Break(context.TODO(), &lease.ShareBreakOptions{BreakPeriod: to.Ptr(int32(60))}) + handleError(err) + fmt.Println("The lease was broken, and nobody can acquire a lease for 60 seconds") +} diff --git a/sdk/storage/azfile/lease/file_client.go b/sdk/storage/azfile/lease/file_client.go new file mode 100644 index 000000000000..b1bffc781a5b --- /dev/null +++ b/sdk/storage/azfile/lease/file_client.go @@ -0,0 +1,103 @@ +//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 lease + +import ( + "context" + "errors" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azfile/file" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azfile/internal/base" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azfile/internal/generated" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azfile/internal/shared" +) + +// FileClient provides lease functionality for the underlying file client. +type FileClient struct { + fileClient *file.Client + leaseID *string +} + +// FileClientOptions contains the optional values when creating a FileClient. +type FileClientOptions struct { + // LeaseID contains a caller-provided lease ID. + LeaseID *string +} + +// NewFileClient creates a file lease client for the provided file client. +// - client - an instance of a file client +// - options - client options; pass nil to accept the default values +func NewFileClient(client *file.Client, options *FileClientOptions) (*FileClient, error) { + var leaseID *string + if options != nil { + leaseID = options.LeaseID + } + + leaseID, err := shared.GenerateLeaseID(leaseID) + if err != nil { + return nil, err + } + + return &FileClient{ + fileClient: client, + leaseID: leaseID, + }, nil +} + +func (f *FileClient) generated() *generated.FileClient { + return base.InnerClient((*base.Client[generated.FileClient])(f.fileClient)) +} + +// LeaseID returns leaseID of the client. +func (f *FileClient) LeaseID() *string { + return f.leaseID +} + +// Acquire operation can be used to request a new lease. +// For more information, see https://learn.microsoft.com/en-us/rest/api/storageservices/lease-file. +func (f *FileClient) Acquire(ctx context.Context, options *FileAcquireOptions) (FileAcquireResponse, error) { + opts := options.format(f.LeaseID()) + resp, err := f.generated().AcquireLease(ctx, (int32)(-1), opts) + return resp, err +} + +// Break operation can be used to break the lease, if the file has an active lease. Once a lease is broken, it cannot be renewed. +// For more information, see https://learn.microsoft.com/en-us/rest/api/storageservices/lease-file. +func (f *FileClient) Break(ctx context.Context, options *FileBreakOptions) (FileBreakResponse, error) { + opts, leaseAccessConditions := options.format() + resp, err := f.generated().BreakLease(ctx, opts, leaseAccessConditions) + return resp, err +} + +// Change operation can be used to change the lease ID of an active lease. +// For more information, see https://learn.microsoft.com/en-us/rest/api/storageservices/lease-file. +func (f *FileClient) Change(ctx context.Context, proposedLeaseID string, options *FileChangeOptions) (FileChangeResponse, error) { + if f.LeaseID() == nil { + return FileChangeResponse{}, errors.New("leaseID cannot be nil") + } + + opts := options.format(&proposedLeaseID) + resp, err := f.generated().ChangeLease(ctx, *f.LeaseID(), opts) + + // If lease has been changed successfully, set the leaseID in client + if err == nil { + f.leaseID = &proposedLeaseID + } + + return resp, err +} + +// Release operation can be used to free the lease if it is no longer needed so that another client may immediately acquire a lease against the file. +// For more information, see https://learn.microsoft.com/en-us/rest/api/storageservices/lease-file. +func (f *FileClient) Release(ctx context.Context, options *FileReleaseOptions) (FileReleaseResponse, error) { + if f.LeaseID() == nil { + return FileReleaseResponse{}, errors.New("leaseID cannot be nil") + } + + opts := options.format() + resp, err := f.generated().ReleaseLease(ctx, *f.LeaseID(), opts) + return resp, err +} diff --git a/sdk/storage/azfile/lease/models.go b/sdk/storage/azfile/lease/models.go new file mode 100644 index 000000000000..0de250f8aeb4 --- /dev/null +++ b/sdk/storage/azfile/lease/models.go @@ -0,0 +1,147 @@ +//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 lease + +import "github.com/Azure/azure-sdk-for-go/sdk/storage/azfile/internal/generated" + +// AccessConditions contains optional parameters to access leased entity. +type AccessConditions = generated.LeaseAccessConditions + +// FileAcquireOptions contains the optional parameters for the FileClient.Acquire method. +type FileAcquireOptions struct { + // placeholder for future options +} + +func (o *FileAcquireOptions) format(proposedLeaseID *string) *generated.FileClientAcquireLeaseOptions { + return &generated.FileClientAcquireLeaseOptions{ + ProposedLeaseID: proposedLeaseID, + } +} + +// FileBreakOptions contains the optional parameters for the FileClient.Break method. +type FileBreakOptions struct { + // AccessConditions contains optional parameters to access leased entity. + AccessConditions *AccessConditions +} + +func (o *FileBreakOptions) format() (*generated.FileClientBreakLeaseOptions, *generated.LeaseAccessConditions) { + if o == nil { + return nil, nil + } + + return nil, o.AccessConditions +} + +// FileChangeOptions contains the optional parameters for the FileClient.Change method. +type FileChangeOptions struct { + // placeholder for future options +} + +func (o *FileChangeOptions) format(proposedLeaseID *string) *generated.FileClientChangeLeaseOptions { + return &generated.FileClientChangeLeaseOptions{ + ProposedLeaseID: proposedLeaseID, + } +} + +// FileReleaseOptions contains the optional parameters for the FileClient.Release method. +type FileReleaseOptions struct { + // placeholder for future options +} + +func (o *FileReleaseOptions) format() *generated.FileClientReleaseLeaseOptions { + return nil +} + +// --------------------------------------------------------------------------------------------------------------------- + +// ShareAcquireOptions contains the optional parameters for the ShareClient.Acquire method. +type ShareAcquireOptions struct { + // The snapshot parameter is an opaque DateTime value that, when present, specifies the share snapshot to query. + ShareSnapshot *string +} + +func (o *ShareAcquireOptions) format(proposedLeaseID *string) *generated.ShareClientAcquireLeaseOptions { + opts := &generated.ShareClientAcquireLeaseOptions{ + ProposedLeaseID: proposedLeaseID, + } + if o != nil { + opts.Sharesnapshot = o.ShareSnapshot + } + return opts +} + +// ShareBreakOptions contains the optional parameters for the ShareClient.Break method. +type ShareBreakOptions struct { + // For a break operation, this is the proposed duration the lease should continue before it is broken, in seconds, between 0 and 60. This + // break period is only used if it is shorter than the time remaining on the + // lease. If longer, the time remaining on the lease is used. A new lease will not be available before the break period has + // expired, but the lease may be held for longer than the break period. If this + // header does not appear with a break operation, a fixed-duration lease breaks after the remaining lease period elapses, + // and an infinite lease breaks immediately. + BreakPeriod *int32 + // The snapshot parameter is an opaque DateTime value that, when present, specifies the share snapshot to query. + ShareSnapshot *string + // AccessConditions contains optional parameters to access leased entity. + AccessConditions *AccessConditions +} + +func (o *ShareBreakOptions) format() (*generated.ShareClientBreakLeaseOptions, *generated.LeaseAccessConditions) { + if o == nil { + return nil, nil + } + + return &generated.ShareClientBreakLeaseOptions{ + BreakPeriod: o.BreakPeriod, + Sharesnapshot: o.ShareSnapshot, + }, o.AccessConditions +} + +// ShareChangeOptions contains the optional parameters for the ShareClient.Change method. +type ShareChangeOptions struct { + // The snapshot parameter is an opaque DateTime value that, when present, specifies the share snapshot to query. + ShareSnapshot *string +} + +func (o *ShareChangeOptions) format(proposedLeaseID *string) *generated.ShareClientChangeLeaseOptions { + opts := &generated.ShareClientChangeLeaseOptions{ + ProposedLeaseID: proposedLeaseID, + } + if o != nil { + opts.Sharesnapshot = o.ShareSnapshot + } + return opts +} + +// ShareReleaseOptions contains the optional parameters for the ShareClient.Release method. +type ShareReleaseOptions struct { + // The snapshot parameter is an opaque DateTime value that, when present, specifies the share snapshot to query. + ShareSnapshot *string +} + +func (o *ShareReleaseOptions) format() *generated.ShareClientReleaseLeaseOptions { + if o == nil { + return nil + } + return &generated.ShareClientReleaseLeaseOptions{ + Sharesnapshot: o.ShareSnapshot, + } +} + +// ShareRenewOptions contains the optional parameters for the ShareClient.Renew method. +type ShareRenewOptions struct { + // The snapshot parameter is an opaque DateTime value that, when present, specifies the share snapshot to query. + ShareSnapshot *string +} + +func (o *ShareRenewOptions) format() *generated.ShareClientRenewLeaseOptions { + if o == nil { + return nil + } + return &generated.ShareClientRenewLeaseOptions{ + Sharesnapshot: o.ShareSnapshot, + } +} diff --git a/sdk/storage/azfile/lease/responses.go b/sdk/storage/azfile/lease/responses.go new file mode 100644 index 000000000000..23a5a1db3063 --- /dev/null +++ b/sdk/storage/azfile/lease/responses.go @@ -0,0 +1,36 @@ +//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 lease + +import "github.com/Azure/azure-sdk-for-go/sdk/storage/azfile/internal/generated" + +// FileAcquireResponse contains the response from method FileClient.Acquire. +type FileAcquireResponse = generated.FileClientAcquireLeaseResponse + +// FileBreakResponse contains the response from method FileClient.Break. +type FileBreakResponse = generated.FileClientBreakLeaseResponse + +// FileChangeResponse contains the response from method FileClient.Change. +type FileChangeResponse = generated.FileClientChangeLeaseResponse + +// FileReleaseResponse contains the response from method FileClient.Release. +type FileReleaseResponse = generated.FileClientReleaseLeaseResponse + +// ShareAcquireResponse contains the response from method ShareClient.Acquire. +type ShareAcquireResponse = generated.ShareClientAcquireLeaseResponse + +// ShareBreakResponse contains the response from method ShareClient.Break. +type ShareBreakResponse = generated.ShareClientBreakLeaseResponse + +// ShareChangeResponse contains the response from method ShareClient.Change. +type ShareChangeResponse = generated.ShareClientChangeLeaseResponse + +// ShareReleaseResponse contains the response from method ShareClient.Release. +type ShareReleaseResponse = generated.ShareClientReleaseLeaseResponse + +// ShareRenewResponse contains the response from method ShareClient.Renew. +type ShareRenewResponse = generated.ShareClientRenewLeaseResponse diff --git a/sdk/storage/azfile/lease/share_client.go b/sdk/storage/azfile/lease/share_client.go new file mode 100644 index 000000000000..ff4db564c57f --- /dev/null +++ b/sdk/storage/azfile/lease/share_client.go @@ -0,0 +1,116 @@ +//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 lease + +import ( + "context" + "errors" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azfile/internal/base" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azfile/internal/generated" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azfile/internal/shared" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azfile/share" +) + +// ShareClient provides lease functionality for the underlying share client. +type ShareClient struct { + shareClient *share.Client + leaseID *string +} + +// ShareClientOptions contains the optional values when creating a ShareClient. +type ShareClientOptions struct { + // LeaseID contains a caller-provided lease ID. + LeaseID *string +} + +// NewShareClient creates a share lease client for the provided share client. +// - client - an instance of a share client +// - options - client options; pass nil to accept the default values +func NewShareClient(client *share.Client, options *ShareClientOptions) (*ShareClient, error) { + var leaseID *string + if options != nil { + leaseID = options.LeaseID + } + + leaseID, err := shared.GenerateLeaseID(leaseID) + if err != nil { + return nil, err + } + + return &ShareClient{ + shareClient: client, + leaseID: leaseID, + }, nil +} + +func (s *ShareClient) generated() *generated.ShareClient { + return base.InnerClient((*base.Client[generated.ShareClient])(s.shareClient)) +} + +// LeaseID returns leaseID of the client. +func (s *ShareClient) LeaseID() *string { + return s.leaseID +} + +// Acquire operation can be used to request a new lease. +// The lease duration must be between 15 and 60 seconds, or infinite (-1). +// For more information, see https://learn.microsoft.com/en-us/rest/api/storageservices/lease-share. +func (s *ShareClient) Acquire(ctx context.Context, duration int32, options *ShareAcquireOptions) (ShareAcquireResponse, error) { + opts := options.format(s.LeaseID()) + resp, err := s.generated().AcquireLease(ctx, duration, opts) + return resp, err +} + +// Break operation can be used to break the lease, if the file share has an active lease. Once a lease is broken, it cannot be renewed. +// For more information, see https://learn.microsoft.com/en-us/rest/api/storageservices/lease-share. +func (s *ShareClient) Break(ctx context.Context, options *ShareBreakOptions) (ShareBreakResponse, error) { + opts, leaseAccessConditions := options.format() + resp, err := s.generated().BreakLease(ctx, opts, leaseAccessConditions) + return resp, err +} + +// Change operation can be used to change the lease ID of an active lease. +// For more information, see https://learn.microsoft.com/en-us/rest/api/storageservices/lease-share. +func (s *ShareClient) Change(ctx context.Context, proposedLeaseID string, options *ShareChangeOptions) (ShareChangeResponse, error) { + if s.LeaseID() == nil { + return ShareChangeResponse{}, errors.New("leaseID cannot be nil") + } + + opts := options.format(&proposedLeaseID) + resp, err := s.generated().ChangeLease(ctx, *s.LeaseID(), opts) + + // If lease has been changed successfully, set the leaseID in client + if err == nil { + s.leaseID = &proposedLeaseID + } + + return resp, err +} + +// Release operation can be used to free the lease if it is no longer needed so that another client may immediately acquire a lease against the file share. +// For more information, see https://learn.microsoft.com/en-us/rest/api/storageservices/lease-share. +func (s *ShareClient) Release(ctx context.Context, options *ShareReleaseOptions) (ShareReleaseResponse, error) { + if s.LeaseID() == nil { + return ShareReleaseResponse{}, errors.New("leaseID cannot be nil") + } + + opts := options.format() + resp, err := s.generated().ReleaseLease(ctx, *s.LeaseID(), opts) + return resp, err +} + +// Renew operation can be used to renew an existing lease. +// For more information, see https://learn.microsoft.com/en-us/rest/api/storageservices/lease-share. +func (s *ShareClient) Renew(ctx context.Context, options *ShareRenewOptions) (ShareRenewResponse, error) { + if s.LeaseID() == nil { + return ShareRenewResponse{}, errors.New("leaseID cannot be nil") + } + + opts := options.format() + resp, err := s.generated().RenewLease(ctx, *s.LeaseID(), opts) + return resp, err +} diff --git a/sdk/storage/azfile/log.go b/sdk/storage/azfile/log.go new file mode 100644 index 000000000000..f59215653531 --- /dev/null +++ b/sdk/storage/azfile/log.go @@ -0,0 +1,16 @@ +//go:build go1.18 +// +build go1.18 + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package azfile + +import ( + "github.com/Azure/azure-sdk-for-go/sdk/storage/azfile/internal/exported" +) + +const ( + // EventUpload is used for logging events related to upload operation. + EventUpload = exported.EventUpload +) diff --git a/sdk/storage/azfile/sas/account.go b/sdk/storage/azfile/sas/account.go new file mode 100644 index 000000000000..6b0c0067e811 --- /dev/null +++ b/sdk/storage/azfile/sas/account.go @@ -0,0 +1,183 @@ +//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 sas + +import ( + "bytes" + "errors" + "fmt" + "strings" + "time" + + "github.com/Azure/azure-sdk-for-go/sdk/storage/azfile/internal/exported" +) + +// SharedKeyCredential contains an account's name and its primary or secondary key. +type SharedKeyCredential = exported.SharedKeyCredential + +// AccountSignatureValues is used to generate a Shared Access Signature (SAS) for an Azure Storage account. +// For more information, see https://docs.microsoft.com/rest/api/storageservices/constructing-an-account-sas +type AccountSignatureValues struct { + Version string `param:"sv"` // If not specified, this format to SASVersion + Protocol Protocol `param:"spr"` // See the SASProtocol* constants + StartTime time.Time `param:"st"` // Not specified if IsZero + ExpiryTime time.Time `param:"se"` // Not specified if IsZero + Permissions string `param:"sp"` // Create by initializing AccountPermissions and then call String() + IPRange IPRange `param:"sip"` + ResourceTypes string `param:"srt"` // Create by initializing AccountResourceTypes and then call String() +} + +// SignWithSharedKey uses an account's shared key credential to sign this signature values to produce +// the proper SAS query parameters. +func (v AccountSignatureValues) SignWithSharedKey(sharedKeyCredential *SharedKeyCredential) (QueryParameters, error) { + // https://docs.microsoft.com/en-us/rest/api/storageservices/Constructing-an-Account-SAS + if v.ExpiryTime.IsZero() || v.Permissions == "" || v.ResourceTypes == "" { + return QueryParameters{}, errors.New("account SAS is missing at least one of these: ExpiryTime, Permissions, Service, or ResourceType") + } + if v.Version == "" { + v.Version = Version + } + perms, err := parseAccountPermissions(v.Permissions) + if err != nil { + return QueryParameters{}, err + } + v.Permissions = perms.String() + + resources, err := parseAccountResourceTypes(v.ResourceTypes) + if err != nil { + return QueryParameters{}, err + } + v.ResourceTypes = resources.String() + + startTime, expiryTime, _ := formatTimesForSigning(v.StartTime, v.ExpiryTime, time.Time{}) + + stringToSign := strings.Join([]string{ + sharedKeyCredential.AccountName(), + v.Permissions, + "f", // file service + v.ResourceTypes, + startTime, + expiryTime, + v.IPRange.String(), + string(v.Protocol), + v.Version, + ""}, // That is right, the account SAS requires a terminating extra newline + "\n") + + signature, err := exported.ComputeHMACSHA256(sharedKeyCredential, stringToSign) + if err != nil { + return QueryParameters{}, err + } + p := QueryParameters{ + // Common SAS parameters + version: v.Version, + protocol: v.Protocol, + startTime: v.StartTime, + expiryTime: v.ExpiryTime, + permissions: v.Permissions, + ipRange: v.IPRange, + + // Account-specific SAS parameters + services: "f", // will always be "f" for Azure File + resourceTypes: v.ResourceTypes, + + // Calculated SAS signature + signature: signature, + } + + return p, nil +} + +// AccountPermissions type simplifies creating the permissions string for an Azure Storage Account SAS. +// Initialize an instance of this type and then call its String method to set AccountSignatureValues' Permissions field. +type AccountPermissions struct { + Read, Write, Delete, List, Create bool +} + +// String produces the SAS permissions string for an Azure Storage account. +// Call this method to set AccountSignatureValues' Permissions field. +func (p *AccountPermissions) String() string { + var buffer bytes.Buffer + if p.Read { + buffer.WriteRune('r') + } + if p.Write { + buffer.WriteRune('w') + } + if p.Delete { + buffer.WriteRune('d') + } + if p.List { + buffer.WriteRune('l') + } + if p.Create { + buffer.WriteRune('c') + } + return buffer.String() +} + +// parseAccountPermissions initializes the AccountPermissions' fields from a string. +func parseAccountPermissions(s string) (AccountPermissions, error) { + p := AccountPermissions{} // Clear out the flags + for _, r := range s { + switch r { + case 'r': + p.Read = true + case 'w': + p.Write = true + case 'd': + p.Delete = true + case 'l': + p.List = true + case 'c': + p.Create = true + default: + return AccountPermissions{}, fmt.Errorf("invalid permission character: '%v'", r) + } + } + return p, nil +} + +// AccountResourceTypes type simplifies creating the resource types string for an Azure Storage Account SAS. +// Initialize an instance of this type and then call its String method to set AccountSignatureValues' ResourceTypes field. +type AccountResourceTypes struct { + Service, Container, Object bool +} + +// String produces the SAS resource types string for an Azure Storage account. +// Call this method to set AccountSignatureValues' ResourceTypes field. +func (rt *AccountResourceTypes) String() string { + var buffer bytes.Buffer + if rt.Service { + buffer.WriteRune('s') + } + if rt.Container { + buffer.WriteRune('c') + } + if rt.Object { + buffer.WriteRune('o') + } + return buffer.String() +} + +// parseAccountResourceTypes initializes the AccountResourceTypes' fields from a string. +func parseAccountResourceTypes(s string) (AccountResourceTypes, error) { + rt := AccountResourceTypes{} + for _, r := range s { + switch r { + case 's': + rt.Service = true + case 'c': + rt.Container = true + case 'o': + rt.Object = true + default: + return AccountResourceTypes{}, fmt.Errorf("invalid resource type character: '%v'", r) + } + } + return rt, nil +} diff --git a/sdk/storage/azfile/sas/account_test.go b/sdk/storage/azfile/sas/account_test.go new file mode 100644 index 000000000000..d22d645185ed --- /dev/null +++ b/sdk/storage/azfile/sas/account_test.go @@ -0,0 +1,124 @@ +//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 sas + +import ( + "github.com/stretchr/testify/require" + "testing" +) + +func TestAccountPermissions_String(t *testing.T) { + testdata := []struct { + input AccountPermissions + expected string + }{ + {input: AccountPermissions{Read: true}, expected: "r"}, + {input: AccountPermissions{Write: true}, expected: "w"}, + {input: AccountPermissions{Delete: true}, expected: "d"}, + {input: AccountPermissions{List: true}, expected: "l"}, + {input: AccountPermissions{Create: true}, expected: "c"}, + {input: AccountPermissions{ + Read: true, + Write: true, + Delete: true, + List: true, + Create: true, + }, expected: "rwdlc"}, + } + for _, c := range testdata { + require.Equal(t, c.expected, c.input.String()) + } +} + +func TestAccountPermissions_Parse(t *testing.T) { + testdata := []struct { + input string + expected AccountPermissions + }{ + {expected: AccountPermissions{Read: true}, input: "r"}, + {expected: AccountPermissions{Write: true}, input: "w"}, + {expected: AccountPermissions{Delete: true}, input: "d"}, + {expected: AccountPermissions{List: true}, input: "l"}, + {expected: AccountPermissions{Create: true}, input: "c"}, + {expected: AccountPermissions{ + Read: true, + Write: true, + Delete: true, + List: true, + Create: true, + }, input: "rwdlc"}, + {expected: AccountPermissions{ + Read: true, + Write: true, + Delete: true, + List: true, + Create: true, + }, input: "rcdlw"}, + } + for _, c := range testdata { + permissions, err := parseAccountPermissions(c.input) + require.Nil(t, err) + require.Equal(t, c.expected, permissions) + } +} + +func TestAccountPermissions_ParseNegative(t *testing.T) { + _, err := parseAccountPermissions("rwldcz") // Here 'z' is invalid + require.NotNil(t, err) + require.Contains(t, err.Error(), "122") +} + +func TestAccountResourceTypes_String(t *testing.T) { + testdata := []struct { + input AccountResourceTypes + expected string + }{ + {input: AccountResourceTypes{Service: true}, expected: "s"}, + {input: AccountResourceTypes{Container: true}, expected: "c"}, + {input: AccountResourceTypes{Object: true}, expected: "o"}, + {input: AccountResourceTypes{ + Service: true, + Container: true, + Object: true, + }, expected: "sco"}, + } + for _, c := range testdata { + require.Equal(t, c.expected, c.input.String()) + } +} + +func TestAccountResourceTypes_Parse(t *testing.T) { + testdata := []struct { + input string + expected AccountResourceTypes + }{ + {expected: AccountResourceTypes{Service: true}, input: "s"}, + {expected: AccountResourceTypes{Container: true}, input: "c"}, + {expected: AccountResourceTypes{Object: true}, input: "o"}, + {expected: AccountResourceTypes{ + Service: true, + Container: true, + Object: true, + }, input: "sco"}, + {expected: AccountResourceTypes{ + Service: true, + Container: true, + Object: true, + }, input: "osc"}, + } + for _, c := range testdata { + permissions, err := parseAccountResourceTypes(c.input) + require.Nil(t, err) + require.Equal(t, c.expected, permissions) + } +} + +func TestAccountResourceTypes_ParseNegative(t *testing.T) { + _, err := parseAccountResourceTypes("scoz") // Here 'z' is invalid + require.NotNil(t, err) + require.Contains(t, err.Error(), "122") +} diff --git a/sdk/storage/azfile/sas/query_params.go b/sdk/storage/azfile/sas/query_params.go new file mode 100644 index 000000000000..5bf5422d6082 --- /dev/null +++ b/sdk/storage/azfile/sas/query_params.go @@ -0,0 +1,339 @@ +//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 sas + +import ( + "errors" + "net" + "net/url" + "strings" + "time" +) + +// timeFormat represents the format of a SAS start or expiry time. Use it when formatting/parsing a time.Time. +const ( + timeFormat = "2006-01-02T15:04:05Z" // "2017-07-27T00:00:00Z" // ISO 8601 + SnapshotTimeFormat = "2006-01-02T15:04:05.0000000Z07:00" +) + +var ( + // Version is the default version encoded in the SAS token. + Version = "2020-02-10" +) + +// TimeFormats ISO 8601 format. +// Please refer to https://docs.microsoft.com/en-us/rest/api/storageservices/constructing-a-service-sas for more details. +var timeFormats = []string{"2006-01-02T15:04:05.0000000Z", timeFormat, "2006-01-02T15:04Z", "2006-01-02"} + +// Protocol indicates the http/https. +type Protocol string + +const ( + // ProtocolHTTPS can be specified for a SAS protocol. + ProtocolHTTPS Protocol = "https" + + // ProtocolHTTPSandHTTP can be specified for a SAS protocol. + ProtocolHTTPSandHTTP Protocol = "https,http" +) + +// FormatTimesForSigning converts a time.Time to a SnapshotTimeFormat string suitable for a +// Field's StartTime or ExpiryTime fields. Returns "" if value.IsZero(). +func formatTimesForSigning(startTime, expiryTime, snapshotTime time.Time) (string, string, string) { + ss := "" + if !startTime.IsZero() { + ss = formatTimeWithDefaultFormat(&startTime) + } + se := "" + if !expiryTime.IsZero() { + se = formatTimeWithDefaultFormat(&expiryTime) + } + sh := "" + if !snapshotTime.IsZero() { + sh = snapshotTime.Format(SnapshotTimeFormat) + } + return ss, se, sh +} + +// formatTimeWithDefaultFormat format time with ISO 8601 in "yyyy-MM-ddTHH:mm:ssZ". +func formatTimeWithDefaultFormat(t *time.Time) string { + return formatTime(t, timeFormat) // By default, "yyyy-MM-ddTHH:mm:ssZ" is used +} + +// formatTime format time with given format, use ISO 8601 in "yyyy-MM-ddTHH:mm:ssZ" by default. +func formatTime(t *time.Time, format string) string { + if format != "" { + return t.Format(format) + } + return t.Format(timeFormat) // By default, "yyyy-MM-ddTHH:mm:ssZ" is used +} + +// ParseTime try to parse a SAS time string. +func parseTime(val string) (t time.Time, timeFormat string, err error) { + for _, sasTimeFormat := range timeFormats { + t, err = time.Parse(sasTimeFormat, val) + if err == nil { + timeFormat = sasTimeFormat + break + } + } + + if err != nil { + err = errors.New("fail to parse time with IOS 8601 formats, please refer to https://docs.microsoft.com/en-us/rest/api/storageservices/constructing-a-service-sas for more details") + } + + return +} + +// IPRange represents a SAS IP range's start IP and (optionally) end IP. +type IPRange struct { + Start net.IP // Not specified if length = 0 + End net.IP // Not specified if length = 0 +} + +// String returns a string representation of an IPRange. +func (ipr *IPRange) String() string { + if len(ipr.Start) == 0 { + return "" + } + start := ipr.Start.String() + if len(ipr.End) == 0 { + return start + } + return start + "-" + ipr.End.String() +} + +// https://docs.microsoft.com/en-us/rest/api/storageservices/constructing-a-service-sas + +// QueryParameters object represents the components that make up an Azure Storage SAS' query parameters. +// You parse a map of query parameters into its fields by calling NewQueryParameters(). You add the components +// to a query parameter map by calling AddToValues(). +// NOTE: Changing any field requires computing a new SAS signature using a XxxSASSignatureValues type. +// This type defines the components used by all Azure Storage resources (Containers, Blobs, Files, & Queues). +type QueryParameters struct { + // All members are immutable or values so copies of this struct are goroutine-safe. + version string `param:"sv"` + services string `param:"ss"` + resourceTypes string `param:"srt"` + protocol Protocol `param:"spr"` + startTime time.Time `param:"st"` + expiryTime time.Time `param:"se"` + shareSnapshotTime time.Time `param:"sharesnapshot"` + ipRange IPRange `param:"sip"` + identifier string `param:"si"` + resource string `param:"sr"` + permissions string `param:"sp"` + signature string `param:"sig"` + cacheControl string `param:"rscc"` + contentDisposition string `param:"rscd"` + contentEncoding string `param:"rsce"` + contentLanguage string `param:"rscl"` + contentType string `param:"rsct"` + // private member used for startTime and expiryTime formatting. + stTimeFormat string + seTimeFormat string +} + +// ShareSnapshotTime returns shareSnapshotTime. +func (p *QueryParameters) ShareSnapshotTime() time.Time { + return p.shareSnapshotTime +} + +// Version returns version. +func (p *QueryParameters) Version() string { + return p.version +} + +// Services returns services. +func (p *QueryParameters) Services() string { + return p.services +} + +// ResourceTypes returns resourceTypes. +func (p *QueryParameters) ResourceTypes() string { + return p.resourceTypes +} + +// Protocol returns protocol. +func (p *QueryParameters) Protocol() Protocol { + return p.protocol +} + +// StartTime returns startTime. +func (p *QueryParameters) StartTime() time.Time { + return p.startTime +} + +// ExpiryTime returns expiryTime. +func (p *QueryParameters) ExpiryTime() time.Time { + return p.expiryTime +} + +// IPRange returns ipRange. +func (p *QueryParameters) IPRange() IPRange { + return p.ipRange +} + +// Identifier returns identifier. +func (p *QueryParameters) Identifier() string { + return p.identifier +} + +// Resource returns resource. +func (p *QueryParameters) Resource() string { + return p.resource +} + +// Permissions returns permissions. +func (p *QueryParameters) Permissions() string { + return p.permissions +} + +// Signature returns signature. +func (p *QueryParameters) Signature() string { + return p.signature +} + +// CacheControl returns cacheControl. +func (p *QueryParameters) CacheControl() string { + return p.cacheControl +} + +// ContentDisposition returns contentDisposition. +func (p *QueryParameters) ContentDisposition() string { + return p.contentDisposition +} + +// ContentEncoding returns contentEncoding. +func (p *QueryParameters) ContentEncoding() string { + return p.contentEncoding +} + +// ContentLanguage returns contentLanguage. +func (p *QueryParameters) ContentLanguage() string { + return p.contentLanguage +} + +// ContentType returns contentType. +func (p *QueryParameters) ContentType() string { + return p.contentType +} + +// Encode encodes the SAS query parameters into URL encoded form sorted by key. +func (p *QueryParameters) Encode() string { + v := url.Values{} + + if p.version != "" { + v.Add("sv", p.version) + } + if p.services != "" { + v.Add("ss", p.services) + } + if p.resourceTypes != "" { + v.Add("srt", p.resourceTypes) + } + if p.protocol != "" { + v.Add("spr", string(p.protocol)) + } + if !p.startTime.IsZero() { + v.Add("st", formatTime(&(p.startTime), p.stTimeFormat)) + } + if !p.expiryTime.IsZero() { + v.Add("se", formatTime(&(p.expiryTime), p.seTimeFormat)) + } + if len(p.ipRange.Start) > 0 { + v.Add("sip", p.ipRange.String()) + } + if p.identifier != "" { + v.Add("si", p.identifier) + } + if p.resource != "" { + v.Add("sr", p.resource) + } + if p.permissions != "" { + v.Add("sp", p.permissions) + } + if p.signature != "" { + v.Add("sig", p.signature) + } + if p.cacheControl != "" { + v.Add("rscc", p.cacheControl) + } + if p.contentDisposition != "" { + v.Add("rscd", p.contentDisposition) + } + if p.contentEncoding != "" { + v.Add("rsce", p.contentEncoding) + } + if p.contentLanguage != "" { + v.Add("rscl", p.contentLanguage) + } + if p.contentType != "" { + v.Add("rsct", p.contentType) + } + + return v.Encode() +} + +// NewQueryParameters creates and initializes a QueryParameters object based on the +// query parameter map's passed-in values. If deleteSASParametersFromValues is true, +// all SAS-related query parameters are removed from the passed-in map. If +// deleteSASParametersFromValues is false, the map passed-in map is unaltered. +func NewQueryParameters(values url.Values, deleteSASParametersFromValues bool) QueryParameters { + p := QueryParameters{} + for k, v := range values { + val := v[0] + isSASKey := true + switch strings.ToLower(k) { + case "sv": + p.version = val + case "ss": + p.services = val + case "srt": + p.resourceTypes = val + case "spr": + p.protocol = Protocol(val) + case "sharesnapshot": + p.shareSnapshotTime, _ = time.Parse(SnapshotTimeFormat, val) + case "st": + p.startTime, p.stTimeFormat, _ = parseTime(val) + case "se": + p.expiryTime, p.seTimeFormat, _ = parseTime(val) + case "sip": + dashIndex := strings.Index(val, "-") + if dashIndex == -1 { + p.ipRange.Start = net.ParseIP(val) + } else { + p.ipRange.Start = net.ParseIP(val[:dashIndex]) + p.ipRange.End = net.ParseIP(val[dashIndex+1:]) + } + case "si": + p.identifier = val + case "sr": + p.resource = val + case "sp": + p.permissions = val + case "sig": + p.signature = val + case "rscc": + p.cacheControl = val + case "rscd": + p.contentDisposition = val + case "rsce": + p.contentEncoding = val + case "rscl": + p.contentLanguage = val + case "rsct": + p.contentType = val + default: + isSASKey = false // We didn't recognize the query parameter + } + if isSASKey && deleteSASParametersFromValues { + delete(values, k) + } + } + return p +} diff --git a/sdk/storage/azfile/sas/query_params_test.go b/sdk/storage/azfile/sas/query_params_test.go new file mode 100644 index 000000000000..7d699f9c3396 --- /dev/null +++ b/sdk/storage/azfile/sas/query_params_test.go @@ -0,0 +1,211 @@ +//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 sas + +import ( + "fmt" + "net" + "net/url" + "strings" + "testing" + "time" + + "github.com/stretchr/testify/require" +) + +func TestFormatTimesForSigning(t *testing.T) { + testdata := []struct { + inputStart time.Time + inputEnd time.Time + inputSnapshot time.Time + expectedStart string + expectedEnd string + expectedSnapshot string + }{ + {expectedStart: "", expectedEnd: "", expectedSnapshot: ""}, + {inputStart: time.Date(1955, 6, 25, 22, 15, 56, 345456, time.UTC), expectedStart: "1955-06-25T22:15:56Z", expectedEnd: "", expectedSnapshot: ""}, + {inputEnd: time.Date(2023, 4, 5, 8, 50, 27, 4500, time.UTC), expectedStart: "", expectedEnd: "2023-04-05T08:50:27Z", expectedSnapshot: ""}, + {inputSnapshot: time.Date(2021, 1, 5, 22, 15, 33, 1234879, time.UTC), expectedStart: "", expectedEnd: "", expectedSnapshot: "2021-01-05T22:15:33.0012348Z"}, + { + inputStart: time.Date(1955, 6, 25, 22, 15, 56, 345456, time.UTC), + inputEnd: time.Date(2023, 4, 5, 8, 50, 27, 4500, time.UTC), + inputSnapshot: time.Date(2021, 1, 5, 22, 15, 33, 1234879, time.UTC), + expectedStart: "1955-06-25T22:15:56Z", + expectedEnd: "2023-04-05T08:50:27Z", + expectedSnapshot: "2021-01-05T22:15:33.0012348Z", + }, + } + for _, c := range testdata { + start, end, ss := formatTimesForSigning(c.inputStart, c.inputEnd, c.inputSnapshot) + require.Equal(t, c.expectedStart, start) + require.Equal(t, c.expectedEnd, end) + require.Equal(t, c.expectedSnapshot, ss) + } +} + +func TestFormatTimeWithDefaultFormat(t *testing.T) { + testdata := []struct { + input time.Time + expectedTime string + }{ + {input: time.Date(1955, 4, 5, 8, 50, 27, 4500, time.UTC), expectedTime: "1955-04-05T08:50:27Z"}, + {input: time.Date(1917, 3, 9, 16, 22, 56, 0, time.UTC), expectedTime: "1917-03-09T16:22:56Z"}, + {input: time.Date(2021, 1, 5, 22, 15, 0, 0, time.UTC), expectedTime: "2021-01-05T22:15:00Z"}, + {input: time.Date(2023, 6, 25, 0, 0, 0, 0, time.UTC), expectedTime: "2023-06-25T00:00:00Z"}, + } + for _, c := range testdata { + formattedTime := formatTimeWithDefaultFormat(&c.input) + require.Equal(t, c.expectedTime, formattedTime) + } +} + +func TestFormatTime(t *testing.T) { + testdata := []struct { + input time.Time + format string + expectedTime string + }{ + {input: time.Date(1955, 4, 5, 8, 50, 27, 4500, time.UTC), format: "2006-01-02T15:04:05.0000000Z", expectedTime: "1955-04-05T08:50:27.0000045Z"}, + {input: time.Date(1955, 4, 5, 8, 50, 27, 4500, time.UTC), format: "", expectedTime: "1955-04-05T08:50:27Z"}, + {input: time.Date(1917, 3, 9, 16, 22, 56, 0, time.UTC), format: "2006-01-02T15:04:05Z", expectedTime: "1917-03-09T16:22:56Z"}, + {input: time.Date(1917, 3, 9, 16, 22, 56, 0, time.UTC), format: "", expectedTime: "1917-03-09T16:22:56Z"}, + {input: time.Date(2021, 1, 5, 22, 15, 0, 0, time.UTC), format: "2006-01-02T15:04Z", expectedTime: "2021-01-05T22:15Z"}, + {input: time.Date(2021, 1, 5, 22, 15, 0, 0, time.UTC), format: "", expectedTime: "2021-01-05T22:15:00Z"}, + {input: time.Date(2023, 6, 25, 0, 0, 0, 0, time.UTC), format: "2006-01-02", expectedTime: "2023-06-25"}, + {input: time.Date(2023, 6, 25, 0, 0, 0, 0, time.UTC), format: "", expectedTime: "2023-06-25T00:00:00Z"}, + } + for _, c := range testdata { + formattedTime := formatTime(&c.input, c.format) + require.Equal(t, c.expectedTime, formattedTime) + } +} + +func TestParseTime(t *testing.T) { + testdata := []struct { + input string + expectedTime time.Time + expectedFormat string + }{ + {input: "1955-04-05T08:50:27.0000045Z", expectedTime: time.Date(1955, 4, 5, 8, 50, 27, 4500, time.UTC), expectedFormat: "2006-01-02T15:04:05.0000000Z"}, + {input: "1917-03-09T16:22:56Z", expectedTime: time.Date(1917, 3, 9, 16, 22, 56, 0, time.UTC), expectedFormat: "2006-01-02T15:04:05Z"}, + {input: "2021-01-05T22:15Z", expectedTime: time.Date(2021, 1, 5, 22, 15, 0, 0, time.UTC), expectedFormat: "2006-01-02T15:04Z"}, + {input: "2023-06-25", expectedTime: time.Date(2023, 6, 25, 0, 0, 0, 0, time.UTC), expectedFormat: "2006-01-02"}, + } + for _, c := range testdata { + parsedTime, format, err := parseTime(c.input) + require.Nil(t, err) + require.Equal(t, c.expectedTime, parsedTime) + require.Equal(t, c.expectedFormat, format) + } +} + +func TestParseTimeNegative(t *testing.T) { + _, _, err := parseTime("notatime") + require.Error(t, err, "fail to parse time with IOS 8601 formats, please refer to https://docs.microsoft.com/en-us/rest/api/storageservices/constructing-a-service-sas for more details") +} + +func TestIPRange_String(t *testing.T) { + testdata := []struct { + inputStart net.IP + inputEnd net.IP + expected string + }{ + {expected: ""}, + {inputStart: net.IPv4(10, 255, 0, 0), expected: "10.255.0.0"}, + {inputStart: net.IPv4(10, 255, 0, 0), inputEnd: net.IPv4(10, 255, 0, 50), expected: "10.255.0.0-10.255.0.50"}, + } + for _, c := range testdata { + var ipRange IPRange + if c.inputStart != nil { + ipRange.Start = c.inputStart + } + if c.inputEnd != nil { + ipRange.End = c.inputEnd + } + require.Equal(t, c.expected, ipRange.String()) + } +} + +func TestSAS(t *testing.T) { + // Note: This is a totally invalid fake SAS, this is just testing our ability to parse different query parameters on a SAS + const sas = "sv=2019-12-12&sr=b&st=2111-01-09T01:42:34.936Z&se=2222-03-09T01:42:34.936Z&sp=rw&sip=168.1.5.60-168.1.5.70&spr=https,http&si=myIdentifier&ss=bf&srt=s&rscc=cc&rscd=cd&rsce=ce&rscl=cl&rsct=ct&sig=clNxbtnkKSHw7f3KMEVVc4agaszoRFdbZr%2FWBmPNsrw%3D" + _url := fmt.Sprintf("https://teststorageaccount.file.core.windows.net/testshare/testpath?%s", sas) + _uri, err := url.Parse(_url) + require.NoError(t, err) + sasQueryParams := NewQueryParameters(_uri.Query(), true) + validateSAS(t, sas, sasQueryParams) +} + +func validateSAS(t *testing.T, sas string, parameters QueryParameters) { + sasCompMap := make(map[string]string) + for _, sasComp := range strings.Split(sas, "&") { + comp := strings.Split(sasComp, "=") + sasCompMap[comp[0]] = comp[1] + } + + require.Equal(t, parameters.Version(), sasCompMap["sv"]) + require.Equal(t, parameters.Services(), sasCompMap["ss"]) + require.Equal(t, parameters.ResourceTypes(), sasCompMap["srt"]) + require.Equal(t, string(parameters.Protocol()), sasCompMap["spr"]) + if _, ok := sasCompMap["st"]; ok { + startTime, _, err := parseTime(sasCompMap["st"]) + require.NoError(t, err) + require.Equal(t, parameters.StartTime(), startTime) + } + if _, ok := sasCompMap["se"]; ok { + endTime, _, err := parseTime(sasCompMap["se"]) + require.NoError(t, err) + require.Equal(t, parameters.ExpiryTime(), endTime) + } + + if _, ok := sasCompMap["sharesnapshot"]; ok { + snapshotTime, _, err := parseTime(sasCompMap["sharesnapshot"]) + require.NoError(t, err) + require.Equal(t, parameters.ShareSnapshotTime(), snapshotTime) + } + ipRange := parameters.IPRange() + require.Equal(t, ipRange.String(), sasCompMap["sip"]) + require.Equal(t, parameters.Identifier(), sasCompMap["si"]) + require.Equal(t, parameters.Resource(), sasCompMap["sr"]) + require.Equal(t, parameters.Permissions(), sasCompMap["sp"]) + + sign, err := url.QueryUnescape(sasCompMap["sig"]) + require.NoError(t, err) + + require.Equal(t, parameters.Signature(), sign) + require.Equal(t, parameters.CacheControl(), sasCompMap["rscc"]) + require.Equal(t, parameters.ContentDisposition(), sasCompMap["rscd"]) + require.Equal(t, parameters.ContentEncoding(), sasCompMap["rsce"]) + require.Equal(t, parameters.ContentLanguage(), sasCompMap["rscl"]) + require.Equal(t, parameters.ContentType(), sasCompMap["rsct"]) +} + +func TestSASInvalidQueryParameter(t *testing.T) { + // Signature is invalid below + const sas = "sv=2019-12-12&signature=clNxbtnkKSHw7f3KMEVVc4agaszoRFdbZr%2FWBmPNsrw%3D&sr=b" + _url := fmt.Sprintf("https://teststorageaccount.file.core.windows.net/testshare/testpath?%s", sas) + _uri, err := url.Parse(_url) + require.NoError(t, err) + NewQueryParameters(_uri.Query(), true) + // NewQueryParameters should not delete signature + require.Contains(t, _uri.Query(), "signature") +} + +func TestEncode(t *testing.T) { + // Note: This is a totally invalid fake SAS, this is just testing our ability to parse different query parameters on a SAS + expected := "rscc=cc&rscd=cd&rsce=ce&rscl=cl&rsct=ct&se=2222-03-09T01%3A42%3A34Z&si=myIdentifier&sig=clNxbtnkKSHw7f3KMEVVc4agaszoRFdbZr%2FWBmPNsrw%3D&sip=168.1.5.60-168.1.5.70&sp=rw&spr=https%2Chttp&sr=b&srt=sco&ss=bf&st=2111-01-09T01%3A42%3A34Z&sv=2019-12-12" + randomOrder := "se=2222-03-09T01:42:34.936Z&rsce=ce&ss=bf&si=myIdentifier&sip=168.1.5.60-168.1.5.70&rscc=cc&srt=sco&sig=clNxbtnkKSHw7f3KMEVVc4agaszoRFdbZr%2FWBmPNsrw%3D&rsct=ct&rscl=cl&sv=2019-12-12&sr=b&st=2111-01-09T01:42:34.936Z&rscd=cd&sp=rw&spr=https,http" + testdata := []string{expected, randomOrder} + + for _, sas := range testdata { + _url := fmt.Sprintf("https://teststorageaccount.file.core.windows.net/testshare/testpath?%s", sas) + _uri, err := url.Parse(_url) + require.NoError(t, err) + queryParams := NewQueryParameters(_uri.Query(), true) + require.Equal(t, expected, queryParams.Encode()) + } +} diff --git a/sdk/storage/azfile/sas/service.go b/sdk/storage/azfile/sas/service.go new file mode 100644 index 000000000000..50192f9ef58b --- /dev/null +++ b/sdk/storage/azfile/sas/service.go @@ -0,0 +1,227 @@ +//go:build go1.18 +// +build go1.18 + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package sas + +import ( + "bytes" + "errors" + "fmt" + "strings" + "time" + + "github.com/Azure/azure-sdk-for-go/sdk/storage/azfile/internal/exported" +) + +// SignatureValues is used to generate a Shared Access Signature (SAS) for an Azure Storage file or share. +// For more information on creating service sas, see https://docs.microsoft.com/rest/api/storageservices/constructing-a-service-sas +// User Delegation SAS not supported for files service +type SignatureValues struct { + Version string `param:"sv"` // If not specified, this defaults to Version + Protocol Protocol `param:"spr"` // See the Protocol* constants + StartTime time.Time `param:"st"` // Not specified if IsZero + ExpiryTime time.Time `param:"se"` // Not specified if IsZero + SnapshotTime time.Time + Permissions string `param:"sp"` // Create by initializing SharePermissions or FilePermissions and then call String() + IPRange IPRange `param:"sip"` + Identifier string `param:"si"` + ShareName string + FilePath string // Ex: "directory/FileName". Use "" to create a Share SAS and file path for File SAS. + CacheControl string // rscc + ContentDisposition string // rscd + ContentEncoding string // rsce + ContentLanguage string // rscl + ContentType string // rsct +} + +// SignWithSharedKey uses an account's SharedKeyCredential to sign this signature values to produce the proper SAS query parameters. +func (v SignatureValues) SignWithSharedKey(sharedKeyCredential *SharedKeyCredential) (QueryParameters, error) { + if v.ExpiryTime.IsZero() || v.Permissions == "" { + return QueryParameters{}, errors.New("service SAS is missing at least one of these: ExpiryTime or Permissions") + } + + resource := "s" + if v.FilePath == "" { + //Make sure the permission characters are in the correct order + perms, err := parseSharePermissions(v.Permissions) + if err != nil { + return QueryParameters{}, err + } + v.Permissions = perms.String() + } else { + resource = "f" + // Make sure the permission characters are in the correct order + perms, err := parseFilePermissions(v.Permissions) + if err != nil { + return QueryParameters{}, err + } + v.Permissions = perms.String() + } + + if v.Version == "" { + v.Version = Version + } + startTime, expiryTime, _ := formatTimesForSigning(v.StartTime, v.ExpiryTime, v.SnapshotTime) + + // String to sign: http://msdn.microsoft.com/en-us/library/azure/dn140255.aspx + stringToSign := strings.Join([]string{ + v.Permissions, + startTime, + expiryTime, + getCanonicalName(sharedKeyCredential.AccountName(), v.ShareName, v.FilePath), + v.Identifier, + v.IPRange.String(), + string(v.Protocol), + v.Version, + v.CacheControl, // rscc + v.ContentDisposition, // rscd + v.ContentEncoding, // rsce + v.ContentLanguage, // rscl + v.ContentType}, // rsct + "\n") + + signature, err := exported.ComputeHMACSHA256(sharedKeyCredential, stringToSign) + if err != nil { + return QueryParameters{}, err + } + + p := QueryParameters{ + // Common SAS parameters + version: v.Version, + protocol: v.Protocol, + startTime: v.StartTime, + expiryTime: v.ExpiryTime, + permissions: v.Permissions, + ipRange: v.IPRange, + + // Share/File-specific SAS parameters + resource: resource, + identifier: v.Identifier, + cacheControl: v.CacheControl, + contentDisposition: v.ContentDisposition, + contentEncoding: v.ContentEncoding, + contentLanguage: v.ContentLanguage, + contentType: v.ContentType, + shareSnapshotTime: v.SnapshotTime, + // Calculated SAS signature + signature: signature, + } + + return p, nil +} + +// getCanonicalName computes the canonical name for a share or file resource for SAS signing. +func getCanonicalName(account string, shareName string, filePath string) string { + // Share: "/file/account/sharename" + // File: "/file/account/sharename/filename" + // File: "/file/account/sharename/directoryname/filename" + elements := []string{"/file/", account, "/", shareName} + if filePath != "" { + dfp := strings.Replace(filePath, "\\", "/", -1) + if dfp[0] == '/' { + dfp = dfp[1:] + } + elements = append(elements, "/", dfp) + } + return strings.Join(elements, "") +} + +// SharePermissions type simplifies creating the permissions string for an Azure Storage share SAS. +// Initialize an instance of this type and then call its String method to set SignatureValues' Permissions field. +// All permissions descriptions can be found here: https://docs.microsoft.com/en-us/rest/api/storageservices/create-service-sas#permissions-for-a-share +type SharePermissions struct { + Read, Create, Write, Delete, List bool +} + +// String produces the SAS permissions string for an Azure Storage share. +// Call this method to set SignatureValues' Permissions field. +func (p *SharePermissions) String() string { + var b bytes.Buffer + if p.Read { + b.WriteRune('r') + } + if p.Create { + b.WriteRune('c') + } + if p.Write { + b.WriteRune('w') + } + if p.Delete { + b.WriteRune('d') + } + if p.List { + b.WriteRune('l') + } + return b.String() +} + +// parseSharePermissions initializes SharePermissions' fields from a string. +func parseSharePermissions(s string) (SharePermissions, error) { + p := SharePermissions{} // Clear the flags + for _, r := range s { + switch r { + case 'r': + p.Read = true + case 'c': + p.Create = true + case 'w': + p.Write = true + case 'd': + p.Delete = true + case 'l': + p.List = true + default: + return SharePermissions{}, fmt.Errorf("invalid permission: '%v'", r) + } + } + return p, nil +} + +// FilePermissions type simplifies creating the permissions string for an Azure Storage file SAS. +// Initialize an instance of this type and then call its String method to set SignatureValues' Permissions field. +// All permissions descriptions can be found here: https://docs.microsoft.com/en-us/rest/api/storageservices/create-service-sas#permissions-for-a-file +type FilePermissions struct { + Read, Create, Write, Delete bool +} + +// String produces the SAS permissions string for an Azure Storage file. +// Call this method to set SignatureValues' Permissions field. +func (p *FilePermissions) String() string { + var b bytes.Buffer + if p.Read { + b.WriteRune('r') + } + if p.Create { + b.WriteRune('c') + } + if p.Write { + b.WriteRune('w') + } + if p.Delete { + b.WriteRune('d') + } + return b.String() +} + +// parseFilePermissions initializes the FilePermissions' fields from a string. +func parseFilePermissions(s string) (FilePermissions, error) { + p := FilePermissions{} // Clear the flags + for _, r := range s { + switch r { + case 'r': + p.Read = true + case 'c': + p.Create = true + case 'w': + p.Write = true + case 'd': + p.Delete = true + default: + return FilePermissions{}, fmt.Errorf("invalid permission: '%v'", r) + } + } + return p, nil +} diff --git a/sdk/storage/azfile/sas/service_test.go b/sdk/storage/azfile/sas/service_test.go new file mode 100644 index 000000000000..dd640be0e4fc --- /dev/null +++ b/sdk/storage/azfile/sas/service_test.go @@ -0,0 +1,147 @@ +//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 sas + +import ( + "github.com/stretchr/testify/require" + "testing" +) + +func TestSharePermissions_String(t *testing.T) { + testdata := []struct { + input SharePermissions + expected string + }{ + {input: SharePermissions{Read: true}, expected: "r"}, + {input: SharePermissions{Create: true}, expected: "c"}, + {input: SharePermissions{Write: true}, expected: "w"}, + {input: SharePermissions{Delete: true}, expected: "d"}, + {input: SharePermissions{List: true}, expected: "l"}, + {input: SharePermissions{ + Read: true, + Create: true, + Write: true, + Delete: true, + List: true, + }, expected: "rcwdl"}, + } + for _, c := range testdata { + require.Equal(t, c.expected, c.input.String()) + } +} + +func TestSharePermissions_Parse(t *testing.T) { + testdata := []struct { + input string + expected SharePermissions + }{ + {expected: SharePermissions{Read: true}, input: "r"}, + {expected: SharePermissions{Create: true}, input: "c"}, + {expected: SharePermissions{Write: true}, input: "w"}, + {expected: SharePermissions{Delete: true}, input: "d"}, + {expected: SharePermissions{List: true}, input: "l"}, + {expected: SharePermissions{ + Read: true, + Create: true, + Write: true, + Delete: true, + List: true, + }, input: "rcwdl"}, + {expected: SharePermissions{ + Read: true, + Create: true, + Write: true, + Delete: true, + List: true, + }, input: "cwrdl"}, // Wrong order parses correctly + } + for _, c := range testdata { + permissions, err := parseSharePermissions(c.input) + require.Nil(t, err) + require.Equal(t, c.expected, permissions) + } +} + +func TestSharePermissions_ParseNegative(t *testing.T) { + _, err := parseSharePermissions("cwtrdl") // Here 't' is invalid + require.NotNil(t, err) + require.Contains(t, err.Error(), "116") +} + +func TestFilePermissions_String(t *testing.T) { + testdata := []struct { + input FilePermissions + expected string + }{ + {input: FilePermissions{Read: true}, expected: "r"}, + {input: FilePermissions{Create: true}, expected: "c"}, + {input: FilePermissions{Write: true}, expected: "w"}, + {input: FilePermissions{Delete: true}, expected: "d"}, + {input: FilePermissions{ + Read: true, + Create: true, + Write: true, + Delete: true, + }, expected: "rcwd"}, + } + for _, c := range testdata { + require.Equal(t, c.expected, c.input.String()) + } +} + +func TestFilePermissions_Parse(t *testing.T) { + testdata := []struct { + expected FilePermissions + input string + }{ + {expected: FilePermissions{Read: true}, input: "r"}, + {expected: FilePermissions{Create: true}, input: "c"}, + {expected: FilePermissions{Write: true}, input: "w"}, + {expected: FilePermissions{Delete: true}, input: "d"}, + {expected: FilePermissions{ + Read: true, + Create: true, + Write: true, + Delete: true, + }, input: "rcwd"}, + {expected: FilePermissions{ + Read: true, + Create: true, + Write: true, + Delete: true, + }, input: "wcrd"}, // Wrong order parses correctly + } + for _, c := range testdata { + permissions, err := parseFilePermissions(c.input) + require.Nil(t, err) + require.Equal(t, c.expected, permissions) + } +} + +func TestFilePermissions_ParseNegative(t *testing.T) { + _, err := parseFilePermissions("wcrdf") // Here 'f' is invalid + require.NotNil(t, err) + require.Contains(t, err.Error(), "102") +} + +func TestGetCanonicalName(t *testing.T) { + testdata := []struct { + inputAccount string + inputShare string + inputFilePath string + expected string + }{ + {inputAccount: "fakestorageaccount", inputShare: "fakestorageshare", expected: "/file/fakestorageaccount/fakestorageshare"}, + {inputAccount: "fakestorageaccount", inputShare: "fakestorageshare", inputFilePath: "fakestoragefile", expected: "/file/fakestorageaccount/fakestorageshare/fakestoragefile"}, + {inputAccount: "fakestorageaccount", inputShare: "fakestorageshare", inputFilePath: "fakestoragedirectory/fakestoragefile", expected: "/file/fakestorageaccount/fakestorageshare/fakestoragedirectory/fakestoragefile"}, + {inputAccount: "fakestorageaccount", inputShare: "fakestorageshare", inputFilePath: "fakestoragedirectory\\fakestoragefile", expected: "/file/fakestorageaccount/fakestorageshare/fakestoragedirectory/fakestoragefile"}, + {inputAccount: "fakestorageaccount", inputShare: "fakestorageshare", inputFilePath: "fakestoragedirectory", expected: "/file/fakestorageaccount/fakestorageshare/fakestoragedirectory"}, + } + for _, c := range testdata { + require.Equal(t, c.expected, getCanonicalName(c.inputAccount, c.inputShare, c.inputFilePath)) + } +} diff --git a/sdk/storage/azfile/sas/url_parts.go b/sdk/storage/azfile/sas/url_parts.go new file mode 100644 index 000000000000..3f741c921fd3 --- /dev/null +++ b/sdk/storage/azfile/sas/url_parts.go @@ -0,0 +1,147 @@ +//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 sas + +import ( + "github.com/Azure/azure-sdk-for-go/sdk/storage/azfile/internal/shared" + "net/url" + "strings" +) + +const ( + shareSnapshot = "sharesnapshot" +) + +// IPEndpointStyleInfo is used for IP endpoint style URL when working with Azure storage emulator. +// Ex: "https://10.132.141.33/accountname/sharename" +type IPEndpointStyleInfo struct { + AccountName string // "" if not using IP endpoint style +} + +// URLParts object represents the components that make up an Azure Storage Share/Directory/File URL. You parse an +// existing URL into its parts by calling NewFileURLParts(). You construct a URL from parts by calling URL(). +// NOTE: Changing any SAS-related field requires computing a new SAS signature. +type URLParts struct { + Scheme string // Ex: "https://" + Host string // Ex: "account.share.core.windows.net", "10.132.141.33", "10.132.141.33:80" + IPEndpointStyleInfo IPEndpointStyleInfo // Useful Parts for IP endpoint style URL. + ShareName string // Share name, Ex: "myshare" + DirectoryOrFilePath string // Path of directory or file, Ex: "mydirectory/myfile" + ShareSnapshot string // IsZero is true if not a snapshot + SAS QueryParameters + UnparsedParams string +} + +// ParseURL parses a URL initializing URLParts' fields including any SAS-related & sharesnapshot query parameters. +// Any other query parameters remain in the UnparsedParams field. +func ParseURL(u string) (URLParts, error) { + uri, err := url.Parse(u) + if err != nil { + return URLParts{}, err + } + + up := URLParts{ + Scheme: uri.Scheme, + Host: uri.Host, + } + + if uri.Path != "" { + path := uri.Path + if path[0] == '/' { + path = path[1:] + } + if shared.IsIPEndpointStyle(up.Host) { + if accountEndIndex := strings.Index(path, "/"); accountEndIndex == -1 { // Slash not found; path has account name & no share, path of directory or file + up.IPEndpointStyleInfo.AccountName = path + path = "" // no ShareName present in the URL so path should be empty + } else { + up.IPEndpointStyleInfo.AccountName = path[:accountEndIndex] // The account name is the part between the slashes + path = path[accountEndIndex+1:] + } + } + + shareEndIndex := strings.Index(path, "/") // Find the next slash (if it exists) + if shareEndIndex == -1 { // Slash not found; path has share name & no path of directory or file + up.ShareName = path + } else { // Slash found; path has share name & path of directory or file + up.ShareName = path[:shareEndIndex] + up.DirectoryOrFilePath = path[shareEndIndex+1:] + } + } + + // Convert the query parameters to a case-sensitive map & trim whitespace + paramsMap := uri.Query() + + up.ShareSnapshot = "" // Assume no snapshot + if snapshotStr, ok := caseInsensitiveValues(paramsMap).Get(shareSnapshot); ok { + up.ShareSnapshot = snapshotStr[0] + // If we recognized the query parameter, remove it from the map + delete(paramsMap, shareSnapshot) + } + + up.SAS = NewQueryParameters(paramsMap, true) + up.UnparsedParams = paramsMap.Encode() + return up, nil +} + +// String returns a URL object whose fields are initialized from the URLParts fields. The URL's RawQuery +// field contains the SAS, snapshot, and unparsed query parameters. +func (up URLParts) String() string { + path := "" + // Concatenate account name for IP endpoint style URL + if shared.IsIPEndpointStyle(up.Host) && up.IPEndpointStyleInfo.AccountName != "" { + path += "/" + up.IPEndpointStyleInfo.AccountName + } + // Concatenate share & path of directory or file (if they exist) + if up.ShareName != "" { + path += "/" + up.ShareName + if up.DirectoryOrFilePath != "" { + path += "/" + up.DirectoryOrFilePath + } + } + + rawQuery := up.UnparsedParams + + //If no snapshot is initially provided, fill it in from the SAS query properties to help the user + if up.ShareSnapshot == "" && !up.SAS.ShareSnapshotTime().IsZero() { + up.ShareSnapshot = up.SAS.ShareSnapshotTime().Format(SnapshotTimeFormat) + } + + // Concatenate share snapshot query parameter (if it exists) + if up.ShareSnapshot != "" { + if len(rawQuery) > 0 { + rawQuery += "&" + } + rawQuery += shareSnapshot + "=" + up.ShareSnapshot + } + sas := up.SAS.Encode() + if sas != "" { + if len(rawQuery) > 0 { + rawQuery += "&" + } + rawQuery += sas + } + u := url.URL{ + Scheme: up.Scheme, + Host: up.Host, + Path: path, + RawQuery: rawQuery, + } + return u.String() +} + +type caseInsensitiveValues url.Values // map[string][]string + +func (values caseInsensitiveValues) Get(key string) ([]string, bool) { + key = strings.ToLower(key) + for k, v := range values { + if strings.ToLower(k) == key { + return v, true + } + } + return []string{}, false +} diff --git a/sdk/storage/azfile/sas/url_parts_test.go b/sdk/storage/azfile/sas/url_parts_test.go new file mode 100644 index 000000000000..21691e0a7ae7 --- /dev/null +++ b/sdk/storage/azfile/sas/url_parts_test.go @@ -0,0 +1,75 @@ +//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 sas + +import ( + "fmt" + "testing" + + "github.com/stretchr/testify/require" +) + +func TestParseURLIPStyle(t *testing.T) { + urlWithIP := "https://127.0.0.1:5000/fakestorageaccount" + fileURLParts, err := ParseURL(urlWithIP) + require.NoError(t, err) + require.Equal(t, fileURLParts.Scheme, "https") + require.Equal(t, fileURLParts.Host, "127.0.0.1:5000") + require.Equal(t, fileURLParts.IPEndpointStyleInfo.AccountName, "fakestorageaccount") + + urlWithIP = "https://127.0.0.1:5000/fakestorageaccount/fakeshare" + fileURLParts, err = ParseURL(urlWithIP) + require.NoError(t, err) + require.Equal(t, fileURLParts.Scheme, "https") + require.Equal(t, fileURLParts.Host, "127.0.0.1:5000") + require.Equal(t, fileURLParts.IPEndpointStyleInfo.AccountName, "fakestorageaccount") + require.Equal(t, fileURLParts.ShareName, "fakeshare") + + urlWithIP = "https://127.0.0.1:5000/fakestorageaccount/fakeshare/fakefile" + fileURLParts, err = ParseURL(urlWithIP) + require.NoError(t, err) + require.Equal(t, fileURLParts.Scheme, "https") + require.Equal(t, fileURLParts.Host, "127.0.0.1:5000") + require.Equal(t, fileURLParts.IPEndpointStyleInfo.AccountName, "fakestorageaccount") + require.Equal(t, fileURLParts.ShareName, "fakeshare") + require.Equal(t, fileURLParts.DirectoryOrFilePath, "fakefile") +} + +func TestParseURL(t *testing.T) { + testStorageAccount := "fakestorageaccount" + host := fmt.Sprintf("%s.file.core.windows.net", testStorageAccount) + testShare := "fakeshare" + fileNames := []string{"/._.TESTT.txt", "/.gitignore/dummyfile1"} + + const sasStr = "sv=2019-12-12&sr=b&st=2111-01-09T01:42:34.936Z&se=2222-03-09T01:42:34.936Z&sp=rw&sip=168.1.5.60-168.1.5.70&spr=https,http&si=myIdentifier&ss=bf&srt=s&sig=clNxbtnkKSHw7f3KMEVVc4agaszoRFdbZr%2FWBmPNsrw%3D" + + for _, fileName := range fileNames { + sasURL := fmt.Sprintf("https://%s.file.core.windows.net/%s%s?%s", testStorageAccount, testShare, fileName, sasStr) + fileURLParts, err := ParseURL(sasURL) + require.NoError(t, err) + + require.Equal(t, fileURLParts.Scheme, "https") + require.Equal(t, fileURLParts.Host, host) + require.Equal(t, fileURLParts.ShareName, testShare) + + validateSAS(t, sasStr, fileURLParts.SAS) + } + + for _, fileName := range fileNames { + shareSnapshotID := "2011-03-09T01:42:34Z" + sasWithShareSnapshotID := "?sharesnapshot=" + shareSnapshotID + "&" + sasStr + urlWithShareSnapshot := fmt.Sprintf("https://%s.file.core.windows.net/%s%s%s", testStorageAccount, testShare, fileName, sasWithShareSnapshotID) + fileURLParts, err := ParseURL(urlWithShareSnapshot) + require.NoError(t, err) + + require.Equal(t, fileURLParts.Scheme, "https") + require.Equal(t, fileURLParts.Host, host) + require.Equal(t, fileURLParts.ShareName, testShare) + + validateSAS(t, sasStr, fileURLParts.SAS) + } +} diff --git a/sdk/storage/azfile/service/client.go b/sdk/storage/azfile/service/client.go new file mode 100644 index 000000000000..89bf5f02c5a3 --- /dev/null +++ b/sdk/storage/azfile/service/client.go @@ -0,0 +1,214 @@ +//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 service + +import ( + "context" + "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/azfile/fileerror" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azfile/internal/base" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azfile/internal/exported" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azfile/internal/generated" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azfile/internal/shared" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azfile/sas" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azfile/share" + "net/http" + "strings" + "time" +) + +// ClientOptions contains the optional parameters when creating a Client. +type ClientOptions base.ClientOptions + +// Client represents a URL to the Azure File Storage service allowing you to manipulate file shares. +type Client base.Client[generated.ServiceClient] + +// NewClientWithNoCredential creates an instance of Client with the specified values. +// This is used to anonymously access a storage account or with a shared access signature (SAS) token. +// - serviceURL - the URL of the storage account e.g. https://.file.core.windows.net/? +// - options - client options; pass nil to accept the default values +func NewClientWithNoCredential(serviceURL string, options *ClientOptions) (*Client, error) { + conOptions := shared.GetClientOptions(options) + pl := runtime.NewPipeline(exported.ModuleName, exported.ModuleVersion, runtime.PipelineOptions{}, &conOptions.ClientOptions) + + return (*Client)(base.NewServiceClient(serviceURL, pl, nil)), nil +} + +// NewClientWithSharedKeyCredential creates an instance of Client with the specified values. +// - serviceURL - the URL of the storage account e.g. https://.file.core.windows.net/ +// - cred - a SharedKeyCredential created with the matching storage account and access key +// - options - client options; pass nil to accept the default values +func NewClientWithSharedKeyCredential(serviceURL string, cred *SharedKeyCredential, options *ClientOptions) (*Client, error) { + authPolicy := exported.NewSharedKeyCredPolicy(cred) + conOptions := shared.GetClientOptions(options) + conOptions.PerRetryPolicies = append(conOptions.PerRetryPolicies, authPolicy) + pl := runtime.NewPipeline(exported.ModuleName, exported.ModuleVersion, runtime.PipelineOptions{}, &conOptions.ClientOptions) + + return (*Client)(base.NewServiceClient(serviceURL, pl, cred)), nil +} + +// NewClientFromConnectionString creates an instance of Client with the specified values. +// - connectionString - a connection string for the desired storage account +// - options - client options; pass nil to accept the default values +func NewClientFromConnectionString(connectionString string, options *ClientOptions) (*Client, error) { + parsed, err := shared.ParseConnectionString(connectionString) + if err != nil { + return nil, err + } + + if parsed.AccountKey != "" && parsed.AccountName != "" { + credential, err := exported.NewSharedKeyCredential(parsed.AccountName, parsed.AccountKey) + if err != nil { + return nil, err + } + return NewClientWithSharedKeyCredential(parsed.ServiceURL, credential, options) + } + + return NewClientWithNoCredential(parsed.ServiceURL, options) +} + +func (s *Client) generated() *generated.ServiceClient { + return base.InnerClient((*base.Client[generated.ServiceClient])(s)) +} + +func (s *Client) sharedKey() *SharedKeyCredential { + return base.SharedKey((*base.Client[generated.ServiceClient])(s)) +} + +// URL returns the URL endpoint used by the Client object. +func (s *Client) URL() string { + return s.generated().Endpoint() +} + +// NewShareClient creates a new share.Client object by concatenating shareName to the end of this Client's URL. +// The new share.Client uses the same request policy pipeline as the Client. +func (s *Client) NewShareClient(shareName string) *share.Client { + shareURL := runtime.JoinPaths(s.generated().Endpoint(), shareName) + return (*share.Client)(base.NewShareClient(shareURL, s.generated().Pipeline(), s.sharedKey())) +} + +// CreateShare is a lifecycle method to creates a new share under the specified account. +// If the share with the same name already exists, a ResourceExistsError will be raised. +// This method returns a client with which to interact with the newly created share. +// For more information see, https://learn.microsoft.com/en-us/rest/api/storageservices/create-share. +func (s *Client) CreateShare(ctx context.Context, shareName string, options *CreateShareOptions) (CreateShareResponse, error) { + shareClient := s.NewShareClient(shareName) + createShareResp, err := shareClient.Create(ctx, options) + return createShareResp, err +} + +// DeleteShare is a lifecycle method that marks the specified share for deletion. +// The share and any files contained within it are later deleted during garbage collection. +// If the share is not found, a ResourceNotFoundError will be raised. +// For more information see, https://learn.microsoft.com/en-us/rest/api/storageservices/delete-share. +func (s *Client) DeleteShare(ctx context.Context, shareName string, options *DeleteShareOptions) (DeleteShareResponse, error) { + shareClient := s.NewShareClient(shareName) + deleteShareResp, err := shareClient.Delete(ctx, options) + return deleteShareResp, err +} + +// RestoreShare restores soft-deleted share. +// Operation will only be successful if used within the specified number of days set in the delete retention policy. +// For more information see, https://learn.microsoft.com/en-us/rest/api/storageservices/restore-share. +func (s *Client) RestoreShare(ctx context.Context, deletedShareName string, deletedShareVersion string, options *RestoreShareOptions) (RestoreShareResponse, error) { + shareClient := s.NewShareClient(deletedShareName) + createShareResp, err := shareClient.Restore(ctx, deletedShareVersion, options) + return createShareResp, err +} + +// GetProperties operation gets the properties of a storage account's File service. +// For more information, see https://learn.microsoft.com/en-us/rest/api/storageservices/get-file-service-properties. +func (s *Client) GetProperties(ctx context.Context, options *GetPropertiesOptions) (GetPropertiesResponse, error) { + opts := options.format() + resp, err := s.generated().GetProperties(ctx, opts) + return resp, err +} + +// SetProperties operation sets properties for a storage account's File service endpoint. +// For more information, see https://learn.microsoft.com/en-us/rest/api/storageservices/set-file-service-properties. +func (s *Client) SetProperties(ctx context.Context, options *SetPropertiesOptions) (SetPropertiesResponse, error) { + svcProperties, o := options.format() + resp, err := s.generated().SetProperties(ctx, svcProperties, o) + return resp, err +} + +// NewListSharesPager operation returns a pager of the shares under the specified account. +// For more information, see https://learn.microsoft.com/en-us/rest/api/storageservices/list-shares +func (s *Client) NewListSharesPager(options *ListSharesOptions) *runtime.Pager[ListSharesSegmentResponse] { + listOptions := generated.ServiceClientListSharesSegmentOptions{} + if options != nil { + if options.Include.Deleted { + listOptions.Include = append(listOptions.Include, ListSharesIncludeTypeDeleted) + } + if options.Include.Metadata { + listOptions.Include = append(listOptions.Include, ListSharesIncludeTypeMetadata) + } + if options.Include.Snapshots { + listOptions.Include = append(listOptions.Include, ListSharesIncludeTypeSnapshots) + } + listOptions.Marker = options.Marker + listOptions.Maxresults = options.MaxResults + listOptions.Prefix = options.Prefix + } + + return runtime.NewPager(runtime.PagingHandler[ListSharesSegmentResponse]{ + More: func(page ListSharesSegmentResponse) bool { + return page.NextMarker != nil && len(*page.NextMarker) > 0 + }, + Fetcher: func(ctx context.Context, page *ListSharesSegmentResponse) (ListSharesSegmentResponse, error) { + var req *policy.Request + var err error + if page == nil { + req, err = s.generated().ListSharesSegmentCreateRequest(ctx, &listOptions) + } else { + listOptions.Marker = page.NextMarker + req, err = s.generated().ListSharesSegmentCreateRequest(ctx, &listOptions) + } + if err != nil { + return ListSharesSegmentResponse{}, err + } + resp, err := s.generated().Pipeline().Do(req) + if err != nil { + return ListSharesSegmentResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusOK) { + return ListSharesSegmentResponse{}, runtime.NewResponseError(resp) + } + return s.generated().ListSharesSegmentHandleResponse(resp) + }, + }) +} + +// GetSASURL is a convenience method for generating a SAS token for the currently pointed at account. +// It can only be used if the credential supplied during creation was a SharedKeyCredential. +func (s *Client) GetSASURL(resources sas.AccountResourceTypes, permissions sas.AccountPermissions, expiry time.Time, o *GetSASURLOptions) (string, error) { + if s.sharedKey() == nil { + return "", fileerror.MissingSharedKeyCredential + } + st := o.format() + qps, err := sas.AccountSignatureValues{ + Version: sas.Version, + Protocol: sas.ProtocolHTTPS, + Permissions: permissions.String(), + ResourceTypes: resources.String(), + StartTime: st, + ExpiryTime: expiry.UTC(), + }.SignWithSharedKey(s.sharedKey()) + if err != nil { + return "", err + } + + endpoint := s.URL() + if !strings.HasSuffix(endpoint, "/") { + // add a trailing slash to be consistent with the portal + endpoint += "/" + } + endpoint += "?" + qps.Encode() + + return endpoint, nil +} diff --git a/sdk/storage/azfile/service/client_test.go b/sdk/storage/azfile/service/client_test.go new file mode 100644 index 000000000000..d9c3642c4628 --- /dev/null +++ b/sdk/storage/azfile/service/client_test.go @@ -0,0 +1,454 @@ +//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 service_test + +import ( + "context" + "fmt" + "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/azfile/fileerror" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azfile/internal/testcommon" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azfile/sas" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azfile/service" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azfile/share" + "github.com/stretchr/testify/require" + "github.com/stretchr/testify/suite" + "strconv" + "testing" + "time" +) + +func Test(t *testing.T) { + recordMode := recording.GetRecordMode() + t.Logf("Running service Tests in %s mode\n", recordMode) + if recordMode == recording.LiveMode { + suite.Run(t, &ServiceRecordedTestsSuite{}) + suite.Run(t, &ServiceUnrecordedTestsSuite{}) + } else if recordMode == recording.PlaybackMode { + suite.Run(t, &ServiceRecordedTestsSuite{}) + } else if recordMode == recording.RecordingMode { + suite.Run(t, &ServiceRecordedTestsSuite{}) + } +} + +func (s *ServiceRecordedTestsSuite) BeforeTest(suite string, test string) { + testcommon.BeforeTest(s.T(), suite, test) +} + +func (s *ServiceRecordedTestsSuite) AfterTest(suite string, test string) { + testcommon.AfterTest(s.T(), suite, test) +} + +func (s *ServiceUnrecordedTestsSuite) BeforeTest(suite string, test string) { + +} + +func (s *ServiceUnrecordedTestsSuite) AfterTest(suite string, test string) { + +} + +type ServiceRecordedTestsSuite struct { + suite.Suite +} + +type ServiceUnrecordedTestsSuite struct { + suite.Suite +} + +func (s *ServiceRecordedTestsSuite) TestAccountNewServiceURLValidName() { + _require := require.New(s.T()) + + accountName, _ := testcommon.GetGenericAccountInfo(testcommon.TestAccountDefault) + _require.Greater(len(accountName), 0) + + svcClient, err := testcommon.GetServiceClient(s.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + correctURL := "https://" + accountName + "." + testcommon.DefaultFileEndpointSuffix + _require.Equal(svcClient.URL(), correctURL) +} + +func (s *ServiceRecordedTestsSuite) TestAccountNewShareURLValidName() { + _require := require.New(s.T()) + testName := s.T().Name() + + accountName, _ := testcommon.GetGenericAccountInfo(testcommon.TestAccountDefault) + _require.Greater(len(accountName), 0) + + svcClient, err := testcommon.GetServiceClient(s.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + shareName := testcommon.GenerateShareName(testName) + shareClient := svcClient.NewShareClient(shareName) + _require.NoError(err) + + correctURL := "https://" + accountName + "." + testcommon.DefaultFileEndpointSuffix + shareName + _require.Equal(shareClient.URL(), correctURL) +} + +func (s *ServiceRecordedTestsSuite) TestServiceClientFromConnectionString() { + _require := require.New(s.T()) + + svcClient, err := testcommon.GetServiceClientFromConnectionString(s.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + resp, err := svcClient.GetProperties(context.Background(), nil) + _require.NoError(err) + _require.NotNil(resp.RequestID) +} + +func (s *ServiceRecordedTestsSuite) TestAccountProperties() { + _require := require.New(s.T()) + + svcClient, err := testcommon.GetServiceClient(s.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + setPropertiesOptions := &service.SetPropertiesOptions{ + HourMetrics: &service.Metrics{ + Enabled: to.Ptr(true), + IncludeAPIs: to.Ptr(true), + RetentionPolicy: &service.RetentionPolicy{ + Enabled: to.Ptr(true), + Days: to.Ptr(int32(2)), + }, + }, + MinuteMetrics: &service.Metrics{ + Enabled: to.Ptr(true), + IncludeAPIs: to.Ptr(false), + RetentionPolicy: &service.RetentionPolicy{ + Enabled: to.Ptr(true), + Days: to.Ptr(int32(2)), + }, + }, + CORS: []*service.CORSRule{ + { + AllowedOrigins: to.Ptr("*"), + AllowedMethods: to.Ptr("PUT"), + AllowedHeaders: to.Ptr("x-ms-client-request-id"), + ExposedHeaders: to.Ptr("x-ms-*"), + MaxAgeInSeconds: to.Ptr(int32(2)), + }, + }, + } + + setPropsResp, err := svcClient.SetProperties(context.Background(), setPropertiesOptions) + _require.NoError(err) + _require.NotNil(setPropsResp.RequestID) + + time.Sleep(time.Second * 30) + + getPropsResp, err := svcClient.GetProperties(context.Background(), nil) + _require.NoError(err) + _require.NotNil(getPropsResp.RequestID) + _require.EqualValues(getPropsResp.HourMetrics.RetentionPolicy.Enabled, setPropertiesOptions.HourMetrics.RetentionPolicy.Enabled) + _require.EqualValues(getPropsResp.HourMetrics.RetentionPolicy.Days, setPropertiesOptions.HourMetrics.RetentionPolicy.Days) + _require.EqualValues(getPropsResp.MinuteMetrics.RetentionPolicy.Enabled, setPropertiesOptions.MinuteMetrics.RetentionPolicy.Enabled) + _require.EqualValues(getPropsResp.MinuteMetrics.RetentionPolicy.Days, setPropertiesOptions.MinuteMetrics.RetentionPolicy.Days) + _require.EqualValues(len(getPropsResp.CORS), len(setPropertiesOptions.CORS)) +} + +func (s *ServiceRecordedTestsSuite) TestAccountHourMetrics() { + _require := require.New(s.T()) + + svcClient, err := testcommon.GetServiceClient(s.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + setPropertiesOptions := &service.SetPropertiesOptions{ + HourMetrics: &service.Metrics{ + Enabled: to.Ptr(true), + IncludeAPIs: to.Ptr(true), + RetentionPolicy: &service.RetentionPolicy{ + Enabled: to.Ptr(true), + Days: to.Ptr(int32(5)), + }, + }, + } + _, err = svcClient.SetProperties(context.Background(), setPropertiesOptions) + _require.NoError(err) +} + +func (s *ServiceRecordedTestsSuite) TestAccountListSharesNonDefault() { + _require := require.New(s.T()) + testName := s.T().Name() + + svcClient, err := testcommon.GetServiceClient(s.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + mySharePrefix := testcommon.GenerateEntityName(testName) + pager := svcClient.NewListSharesPager(&service.ListSharesOptions{ + Prefix: to.Ptr(mySharePrefix), + }) + for pager.More() { + resp, err := pager.NextPage(context.Background()) + _require.NoError(err) + _require.NotNil(resp.Prefix) + _require.Equal(*resp.Prefix, mySharePrefix) + _require.NotNil(resp.ServiceEndpoint) + _require.NotNil(resp.Version) + _require.Len(resp.Shares, 0) + } + + shareClients := map[string]*share.Client{} + for i := 0; i < 4; i++ { + shareName := mySharePrefix + "share" + strconv.Itoa(i) + shareClients[shareName] = testcommon.CreateNewShare(context.Background(), _require, shareName, svcClient) + defer testcommon.DeleteShare(context.Background(), _require, shareClients[shareName]) + + _, err := shareClients[shareName].SetMetadata(context.Background(), &share.SetMetadataOptions{ + Metadata: testcommon.BasicMetadata, + }) + _require.NoError(err) + } + + pager = svcClient.NewListSharesPager(&service.ListSharesOptions{ + Include: service.ListSharesInclude{Metadata: true, Snapshots: true}, + Prefix: to.Ptr(mySharePrefix), + MaxResults: to.Ptr(int32(2)), + }) + + for pager.More() { + resp, err := pager.NextPage(context.Background()) + _require.NoError(err) + if len(resp.Shares) > 0 { + _require.Len(resp.Shares, 2) + } + for _, shareItem := range resp.Shares { + _require.NotNil(shareItem.Properties) + _require.NotNil(shareItem.Properties.LastModified) + _require.NotNil(shareItem.Properties.ETag) + _require.EqualValues(shareItem.Metadata, testcommon.BasicMetadata) + } + } +} + +func (s *ServiceUnrecordedTestsSuite) TestSASServiceClientRestoreShare() { + _require := require.New(s.T()) + testName := s.T().Name() + cred, _ := testcommon.GetGenericSharedKeyCredential(testcommon.TestAccountDefault) + + serviceClient, err := service.NewClientWithSharedKeyCredential(fmt.Sprintf("https://%s.file.core.windows.net/", cred.AccountName()), cred, nil) + _require.NoError(err) + + shareName := testcommon.GenerateShareName(testName) + + // Note: Always set all permissions, services, types to true to ensure order of string formed is correct. + resources := sas.AccountResourceTypes{ + Object: true, + Service: true, + Container: true, + } + permissions := sas.AccountPermissions{ + Read: true, + Write: true, + Delete: true, + List: true, + Create: true, + } + expiry := time.Now().Add(time.Hour) + sasUrl, err := serviceClient.GetSASURL(resources, permissions, expiry, nil) + _require.NoError(err) + + svcClient, err := testcommon.GetServiceClientNoCredential(s.T(), sasUrl, nil) + _require.NoError(err) + + resp, err := svcClient.GetProperties(context.Background(), nil) + _require.NoError(err) + _require.NotNil(resp.RequestID) + + // create share using account SAS + _, err = svcClient.CreateShare(context.Background(), shareName, nil) + _require.NoError(err) + + defer func() { + _, err := svcClient.DeleteShare(context.Background(), shareName, nil) + _require.NoError(err) + }() + + _, err = svcClient.DeleteShare(context.Background(), shareName, nil) + _require.NoError(err) + + // wait for share deletion + time.Sleep(60 * time.Second) + + sharesCnt := 0 + shareVersion := "" + + pager := svcClient.NewListSharesPager(&service.ListSharesOptions{ + Include: service.ListSharesInclude{Deleted: true}, + Prefix: &shareName, + }) + + for pager.More() { + resp, err := pager.NextPage(context.Background()) + _require.NoError(err) + for _, s := range resp.Shares { + if s.Deleted != nil && *s.Deleted { + _require.NotNil(s.Version) + shareVersion = *s.Version + } else { + sharesCnt++ + } + } + } + + _require.Equal(sharesCnt, 0) + _require.NotEmpty(shareVersion) + + restoreResp, err := svcClient.RestoreShare(context.Background(), shareName, shareVersion, nil) + _require.NoError(err) + _require.NotNil(restoreResp.RequestID) + + sharesCnt = 0 + pager = svcClient.NewListSharesPager(&service.ListSharesOptions{ + Prefix: &shareName, + }) + + for pager.More() { + resp, err := pager.NextPage(context.Background()) + _require.NoError(err) + sharesCnt += len(resp.Shares) + } + _require.Equal(sharesCnt, 1) +} + +func (s *ServiceRecordedTestsSuite) TestSASServiceClientNoKey() { + _require := require.New(s.T()) + accountName, _ := testcommon.GetGenericAccountInfo(testcommon.TestAccountDefault) + _require.Greater(len(accountName), 0) + + serviceClient, err := service.NewClientWithNoCredential(fmt.Sprintf("https://%s.file.core.windows.net/", accountName), nil) + _require.NoError(err) + resources := sas.AccountResourceTypes{ + Object: true, + Service: true, + Container: true, + } + permissions := sas.AccountPermissions{ + Read: true, + Write: true, + Delete: true, + List: true, + Create: true, + } + + expiry := time.Now().Add(time.Hour) + _, err = serviceClient.GetSASURL(resources, permissions, expiry, nil) + _require.Equal(err, fileerror.MissingSharedKeyCredential) +} + +func (s *ServiceRecordedTestsSuite) TestSASServiceClientSignNegative() { + _require := require.New(s.T()) + accountName, accountKey := testcommon.GetGenericAccountInfo(testcommon.TestAccountDefault) + _require.Greater(len(accountName), 0) + _require.Greater(len(accountKey), 0) + + cred, err := service.NewSharedKeyCredential(accountName, accountKey) + _require.NoError(err) + + serviceClient, err := service.NewClientWithSharedKeyCredential(fmt.Sprintf("https://%s.file.core.windows.net/", accountName), cred, nil) + _require.NoError(err) + resources := sas.AccountResourceTypes{ + Object: true, + Service: true, + Container: true, + } + permissions := sas.AccountPermissions{ + Read: true, + Write: true, + Delete: true, + List: true, + Create: true, + } + expiry := time.Time{} + + // zero expiry time + _, err = serviceClient.GetSASURL(resources, permissions, expiry, &service.GetSASURLOptions{StartTime: to.Ptr(time.Now())}) + _require.Equal(err.Error(), "account SAS is missing at least one of these: ExpiryTime, Permissions, Service, or ResourceType") + + // zero start and expiry time + _, err = serviceClient.GetSASURL(resources, permissions, expiry, &service.GetSASURLOptions{}) + _require.Equal(err.Error(), "account SAS is missing at least one of these: ExpiryTime, Permissions, Service, or ResourceType") + + // empty permissions + _, err = serviceClient.GetSASURL(sas.AccountResourceTypes{}, sas.AccountPermissions{}, expiry, nil) + _require.Equal(err.Error(), "account SAS is missing at least one of these: ExpiryTime, Permissions, Service, or ResourceType") +} + +func (s *ServiceRecordedTestsSuite) TestServiceSetPropertiesDefault() { + _require := require.New(s.T()) + + svcClient, err := testcommon.GetServiceClient(s.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + _, err = svcClient.SetProperties(context.Background(), nil) + _require.NoError(err) +} + +func (s *ServiceRecordedTestsSuite) TestServiceCreateDeleteRestoreShare() { + _require := require.New(s.T()) + testName := s.T().Name() + + svcClient, err := testcommon.GetServiceClient(s.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + shareName := testcommon.GenerateShareName(testName) + + _, err = svcClient.CreateShare(context.Background(), shareName, nil) + _require.NoError(err) + + defer func() { + _, err := svcClient.DeleteShare(context.Background(), shareName, nil) + _require.NoError(err) + }() + + _, err = svcClient.DeleteShare(context.Background(), shareName, nil) + _require.NoError(err) + + // wait for share deletion + time.Sleep(60 * time.Second) + + sharesCnt := 0 + shareVersion := "" + + pager := svcClient.NewListSharesPager(&service.ListSharesOptions{ + Include: service.ListSharesInclude{Deleted: true}, + Prefix: &shareName, + }) + + for pager.More() { + resp, err := pager.NextPage(context.Background()) + _require.NoError(err) + for _, s := range resp.Shares { + if s.Deleted != nil && *s.Deleted { + _require.NotNil(s.Version) + shareVersion = *s.Version + } else { + sharesCnt++ + } + } + } + + _require.Equal(sharesCnt, 0) + _require.NotEmpty(shareVersion) + + restoreResp, err := svcClient.RestoreShare(context.Background(), shareName, shareVersion, nil) + _require.NoError(err) + _require.NotNil(restoreResp.RequestID) + + sharesCnt = 0 + pager = svcClient.NewListSharesPager(&service.ListSharesOptions{ + Prefix: &shareName, + }) + + for pager.More() { + resp, err := pager.NextPage(context.Background()) + _require.NoError(err) + sharesCnt += len(resp.Shares) + } + _require.Equal(sharesCnt, 1) +} diff --git a/sdk/storage/azfile/service/constants.go b/sdk/storage/azfile/service/constants.go new file mode 100644 index 000000000000..a936067376b4 --- /dev/null +++ b/sdk/storage/azfile/service/constants.go @@ -0,0 +1,37 @@ +//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 service + +import "github.com/Azure/azure-sdk-for-go/sdk/storage/azfile/internal/generated" + +// ListSharesIncludeType defines values for ListSharesIncludeType +type ListSharesIncludeType = generated.ListSharesIncludeType + +const ( + ListSharesIncludeTypeSnapshots ListSharesIncludeType = generated.ListSharesIncludeTypeSnapshots + ListSharesIncludeTypeMetadata ListSharesIncludeType = generated.ListSharesIncludeTypeMetadata + ListSharesIncludeTypeDeleted ListSharesIncludeType = generated.ListSharesIncludeTypeDeleted +) + +// PossibleListSharesIncludeTypeValues returns the possible values for the ListSharesIncludeType const type. +func PossibleListSharesIncludeTypeValues() []ListSharesIncludeType { + return generated.PossibleListSharesIncludeTypeValues() +} + +// ShareRootSquash defines values for the root squashing behavior on the share when NFS is enabled. If it's not specified, the default is NoRootSquash. +type ShareRootSquash = generated.ShareRootSquash + +const ( + RootSquashNoRootSquash ShareRootSquash = generated.ShareRootSquashNoRootSquash + RootSquashRootSquash ShareRootSquash = generated.ShareRootSquashRootSquash + RootSquashAllSquash ShareRootSquash = generated.ShareRootSquashAllSquash +) + +// PossibleShareRootSquashValues returns the possible values for the RootSquash const type. +func PossibleShareRootSquashValues() []ShareRootSquash { + return generated.PossibleShareRootSquashValues() +} diff --git a/sdk/storage/azfile/service/examples_test.go b/sdk/storage/azfile/service/examples_test.go new file mode 100644 index 000000000000..bc7a2e4cd6dd --- /dev/null +++ b/sdk/storage/azfile/service/examples_test.go @@ -0,0 +1,308 @@ +//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 service_test + +import ( + "context" + "fmt" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/to" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azfile/sas" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azfile/service" + "log" + "os" + "time" +) + +func handleError(err error) { + if err != nil { + log.Fatal(err.Error()) + } +} + +func Example_service_Client_NewClient() { + accountName, ok := os.LookupEnv("AZURE_STORAGE_ACCOUNT_NAME") + if !ok { + panic("AZURE_STORAGE_ACCOUNT_NAME could not be found") + } + accountKey, ok := os.LookupEnv("AZURE_STORAGE_ACCOUNT_KEY") + if !ok { + panic("AZURE_STORAGE_ACCOUNT_KEY could not be found") + } + + serviceURL := fmt.Sprintf("https://%s.file.core.windows.net/", accountName) + + cred, err := service.NewSharedKeyCredential(accountName, accountKey) + handleError(err) + + svcClient, err := service.NewClientWithSharedKeyCredential(serviceURL, cred, nil) + handleError(err) + + fmt.Println(svcClient.URL()) +} + +func Example_service_NewClientFromConnectionString() { + // Your connection string can be obtained from the Azure Portal. + connectionString, ok := os.LookupEnv("AZURE_STORAGE_CONNECTION_STRING") + if !ok { + log.Fatal("the environment variable 'AZURE_STORAGE_CONNECTION_STRING' could not be found") + } + + svcClient, err := service.NewClientFromConnectionString(connectionString, nil) + handleError(err) + + fmt.Println(svcClient.URL()) +} + +func Example_service_Client_NewShareClient() { + accountName, ok := os.LookupEnv("AZURE_STORAGE_ACCOUNT_NAME") + if !ok { + panic("AZURE_STORAGE_ACCOUNT_NAME could not be found") + } + accountKey, ok := os.LookupEnv("AZURE_STORAGE_ACCOUNT_KEY") + if !ok { + panic("AZURE_STORAGE_ACCOUNT_KEY could not be found") + } + + serviceURL := fmt.Sprintf("https://%s.file.core.windows.net/", accountName) + + cred, err := service.NewSharedKeyCredential(accountName, accountKey) + handleError(err) + + svcClient, err := service.NewClientWithSharedKeyCredential(serviceURL, cred, nil) + handleError(err) + + shareName := "testShare" + shareClient := svcClient.NewShareClient(shareName) + + fmt.Println(shareClient.URL()) +} + +func Example_service_Client_CreateShare() { + accountName, ok := os.LookupEnv("AZURE_STORAGE_ACCOUNT_NAME") + if !ok { + panic("AZURE_STORAGE_ACCOUNT_NAME could not be found") + } + accountKey, ok := os.LookupEnv("AZURE_STORAGE_ACCOUNT_KEY") + if !ok { + panic("AZURE_STORAGE_ACCOUNT_KEY could not be found") + } + + serviceURL := fmt.Sprintf("https://%s.file.core.windows.net/", accountName) + + cred, err := service.NewSharedKeyCredential(accountName, accountKey) + handleError(err) + + svcClient, err := service.NewClientWithSharedKeyCredential(serviceURL, cred, nil) + handleError(err) + + shareName := "testShare" + _, err = svcClient.CreateShare(context.TODO(), shareName, nil) + handleError(err) + fmt.Println("Share created") +} + +func Example_service_Client_DeleteShare() { + accountName, ok := os.LookupEnv("AZURE_STORAGE_ACCOUNT_NAME") + if !ok { + panic("AZURE_STORAGE_ACCOUNT_NAME could not be found") + } + accountKey, ok := os.LookupEnv("AZURE_STORAGE_ACCOUNT_KEY") + if !ok { + panic("AZURE_STORAGE_ACCOUNT_KEY could not be found") + } + + serviceURL := fmt.Sprintf("https://%s.file.core.windows.net/", accountName) + + cred, err := service.NewSharedKeyCredential(accountName, accountKey) + handleError(err) + + svcClient, err := service.NewClientWithSharedKeyCredential(serviceURL, cred, nil) + handleError(err) + + shareName := "testShare" + _, err = svcClient.DeleteShare(context.TODO(), shareName, nil) + handleError(err) + fmt.Println("Share deleted") +} + +func Example_service_Client_RestoreShare() { + accountName, ok := os.LookupEnv("AZURE_STORAGE_ACCOUNT_NAME") + if !ok { + panic("AZURE_STORAGE_ACCOUNT_NAME could not be found") + } + accountKey, ok := os.LookupEnv("AZURE_STORAGE_ACCOUNT_KEY") + if !ok { + panic("AZURE_STORAGE_ACCOUNT_KEY could not be found") + } + + serviceURL := fmt.Sprintf("https://%s.file.core.windows.net/", accountName) + + cred, err := service.NewSharedKeyCredential(accountName, accountKey) + handleError(err) + + svcClient, err := service.NewClientWithSharedKeyCredential(serviceURL, cred, nil) + handleError(err) + + // get share version for restore operation + pager := svcClient.NewListSharesPager(&service.ListSharesOptions{ + Include: service.ListSharesInclude{Deleted: true}, // Include deleted shares in the result + }) + + for pager.More() { + resp, err := pager.NextPage(context.Background()) + handleError(err) + for _, s := range resp.Shares { + if s.Deleted != nil && *s.Deleted { + _, err = svcClient.RestoreShare(context.TODO(), *s.Name, *s.Version, nil) + handleError(err) + } + } + } +} + +func Example_service_Client_GetProperties() { + accountName, ok := os.LookupEnv("AZURE_STORAGE_ACCOUNT_NAME") + if !ok { + panic("AZURE_STORAGE_ACCOUNT_NAME could not be found") + } + accountKey, ok := os.LookupEnv("AZURE_STORAGE_ACCOUNT_KEY") + if !ok { + panic("AZURE_STORAGE_ACCOUNT_KEY could not be found") + } + + serviceURL := fmt.Sprintf("https://%s.file.core.windows.net/", accountName) + + cred, err := service.NewSharedKeyCredential(accountName, accountKey) + handleError(err) + + svcClient, err := service.NewClientWithSharedKeyCredential(serviceURL, cred, nil) + handleError(err) + + _, err = svcClient.GetProperties(context.TODO(), nil) + handleError(err) +} + +func Example_service_Client_SetProperties() { + accountName, ok := os.LookupEnv("AZURE_STORAGE_ACCOUNT_NAME") + if !ok { + panic("AZURE_STORAGE_ACCOUNT_NAME could not be found") + } + accountKey, ok := os.LookupEnv("AZURE_STORAGE_ACCOUNT_KEY") + if !ok { + panic("AZURE_STORAGE_ACCOUNT_KEY could not be found") + } + + serviceURL := fmt.Sprintf("https://%s.file.core.windows.net/", accountName) + + cred, err := service.NewSharedKeyCredential(accountName, accountKey) + handleError(err) + + svcClient, err := service.NewClientWithSharedKeyCredential(serviceURL, cred, nil) + handleError(err) + + setPropertiesOpts := service.SetPropertiesOptions{ + HourMetrics: &service.Metrics{ + Enabled: to.Ptr(true), + IncludeAPIs: to.Ptr(true), + RetentionPolicy: &service.RetentionPolicy{ + Enabled: to.Ptr(true), + Days: to.Ptr(int32(2)), + }, + }, + MinuteMetrics: &service.Metrics{ + Enabled: to.Ptr(true), + IncludeAPIs: to.Ptr(false), + RetentionPolicy: &service.RetentionPolicy{ + Enabled: to.Ptr(true), + Days: to.Ptr(int32(2)), + }, + }, + CORS: []*service.CORSRule{ + { + AllowedOrigins: to.Ptr("*"), + AllowedMethods: to.Ptr("PUT"), + AllowedHeaders: to.Ptr("x-ms-client-request-id"), + ExposedHeaders: to.Ptr("x-ms-*"), + MaxAgeInSeconds: to.Ptr(int32(2)), + }, + }, + } + _, err = svcClient.SetProperties(context.TODO(), &setPropertiesOpts) + handleError(err) +} + +func Example_service_Client_ListShares() { + accountName, ok := os.LookupEnv("AZURE_STORAGE_ACCOUNT_NAME") + if !ok { + panic("AZURE_STORAGE_ACCOUNT_NAME could not be found") + } + accountKey, ok := os.LookupEnv("AZURE_STORAGE_ACCOUNT_KEY") + if !ok { + panic("AZURE_STORAGE_ACCOUNT_KEY could not be found") + } + + serviceURL := fmt.Sprintf("https://%s.file.core.windows.net/", accountName) + + cred, err := service.NewSharedKeyCredential(accountName, accountKey) + handleError(err) + + svcClient, err := service.NewClientWithSharedKeyCredential(serviceURL, cred, nil) + handleError(err) + + pager := svcClient.NewListSharesPager(nil) + + for pager.More() { + resp, err := pager.NextPage(context.Background()) + handleError(err) + for _, s := range resp.Shares { + fmt.Println(*s.Name) + } + } +} + +func Example_service_Client_GetSASURL() { + accountName, ok := os.LookupEnv("AZURE_STORAGE_ACCOUNT_NAME") + if !ok { + panic("AZURE_STORAGE_ACCOUNT_NAME could not be found") + } + accountKey, ok := os.LookupEnv("AZURE_STORAGE_ACCOUNT_KEY") + if !ok { + panic("AZURE_STORAGE_ACCOUNT_KEY could not be found") + } + + serviceURL := fmt.Sprintf("https://%s.file.core.windows.net/", accountName) + + cred, err := service.NewSharedKeyCredential(accountName, accountKey) + handleError(err) + + svcClient, err := service.NewClientWithSharedKeyCredential(serviceURL, cred, nil) + handleError(err) + + resources := sas.AccountResourceTypes{ + Object: true, + Service: true, + Container: true, + } + permissions := sas.AccountPermissions{ + Read: true, + Write: true, + Delete: true, + List: true, + Create: true, + } + expiry := time.Now().Add(time.Hour) + sasUrl, err := svcClient.GetSASURL(resources, permissions, expiry, nil) + handleError(err) + + fmt.Println("SAS URL: ", sasUrl) + + svcSASClient, err := service.NewClientWithNoCredential(sasUrl, nil) + handleError(err) + + _, err = svcSASClient.GetProperties(context.TODO(), nil) + handleError(err) +} diff --git a/sdk/storage/azfile/service/models.go b/sdk/storage/azfile/service/models.go new file mode 100644 index 000000000000..0a529af87248 --- /dev/null +++ b/sdk/storage/azfile/service/models.go @@ -0,0 +1,171 @@ +//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 service + +import ( + "github.com/Azure/azure-sdk-for-go/sdk/azcore/to" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azfile/internal/exported" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azfile/internal/generated" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azfile/internal/shared" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azfile/share" + "time" +) + +// SharedKeyCredential contains an account's name and its primary or secondary key. +type SharedKeyCredential = exported.SharedKeyCredential + +// NewSharedKeyCredential creates an immutable SharedKeyCredential containing the +// storage account's name and either its primary or secondary key. +func NewSharedKeyCredential(accountName, accountKey string) (*SharedKeyCredential, error) { + return exported.NewSharedKeyCredential(accountName, accountKey) +} + +// CreateShareOptions contains the optional parameters for the share.Client.Create method. +type CreateShareOptions = share.CreateOptions + +// DeleteShareOptions contains the optional parameters for the share.Client.Delete method. +type DeleteShareOptions = share.DeleteOptions + +// RestoreShareOptions contains the optional parameters for the share.Client.Restore method. +type RestoreShareOptions = share.RestoreOptions + +// --------------------------------------------------------------------------------------------------------------------- + +// GetPropertiesOptions provides set of options for Client.GetProperties +type GetPropertiesOptions struct { + // placeholder for future options +} + +func (o *GetPropertiesOptions) format() *generated.ServiceClientGetPropertiesOptions { + return nil +} + +// --------------------------------------------------------------------------------------------------------------------- + +// SetPropertiesOptions provides set of options for Client.SetProperties +type SetPropertiesOptions struct { + // The set of CORS rules. + CORS []*CORSRule + + // A summary of request statistics grouped by API in hourly aggregates for files. + HourMetrics *Metrics + + // A summary of request statistics grouped by API in minute aggregates for files. + MinuteMetrics *Metrics + + // Protocol settings + Protocol *ProtocolSettings +} + +func (o *SetPropertiesOptions) format() (generated.StorageServiceProperties, *generated.ServiceClientSetPropertiesOptions) { + if o == nil { + return generated.StorageServiceProperties{}, nil + } + + formatMetrics(o.HourMetrics) + formatMetrics(o.MinuteMetrics) + + return generated.StorageServiceProperties{ + CORS: o.CORS, + HourMetrics: o.HourMetrics, + MinuteMetrics: o.MinuteMetrics, + Protocol: o.Protocol, + }, nil +} + +// update version of Storage Analytics to configure. Use 1.0 for this value. +func formatMetrics(m *Metrics) { + if m == nil { + return + } + + m.Version = to.Ptr(shared.StorageAnalyticsVersion) +} + +// StorageServiceProperties - Storage service properties. +type StorageServiceProperties = generated.StorageServiceProperties + +// CORSRule - CORS is an HTTP feature that enables a web application running under one domain to access resources in +// another domain. Web browsers implement a security restriction known as same-origin policy that +// prevents a web page from calling APIs in a different domain; CORS provides a secure way to allow one domain (the origin +// domain) to call APIs in another domain. +type CORSRule = generated.CORSRule + +// Metrics - Storage Analytics metrics for file service. +type Metrics = generated.Metrics + +// RetentionPolicy - The retention policy. +type RetentionPolicy = generated.RetentionPolicy + +// ProtocolSettings - Protocol settings +type ProtocolSettings = generated.ProtocolSettings + +// SMBSettings - Settings for SMB protocol. +type SMBSettings = generated.SMBSettings + +// SMBMultichannel - Settings for SMB multichannel +type SMBMultichannel = generated.SMBMultichannel + +// --------------------------------------------------------------------------------------------------------------------- + +// ListSharesOptions contains the optional parameters for the Client.NewListSharesPager method. +type ListSharesOptions struct { + // Include this parameter to specify one or more datasets to include in the responseBody. + Include ListSharesInclude + + // A string value that identifies the portion of the list to be returned with the next list operation. The operation returns + // a marker value within the responseBody body if the list returned was not complete. + // The marker value may then be used in a subsequent call to request the next set of list items. The marker value is opaque + // to the client. + Marker *string + + // Specifies the maximum number of entries to return. If the request does not specify maxresults, or specifies a value greater + // than 5,000, the server will return up to 5,000 items. + MaxResults *int32 + + // Filters the results to return only entries whose name begins with the specified prefix. + Prefix *string +} + +// ListSharesInclude indicates what additional information the service should return with each share. +type ListSharesInclude struct { + // Tells the service whether to return metadata for each share. + Metadata bool + + // Tells the service whether to return soft-deleted shares. + Deleted bool + + // Tells the service whether to return share snapshots. + Snapshots bool +} + +// Share - A listed Azure Storage share item. +type Share = generated.Share + +// ShareProperties - Properties of a share. +type ShareProperties = generated.ShareProperties + +// --------------------------------------------------------------------------------------------------------------------- + +// GetSASURLOptions contains the optional parameters for the Client.GetSASURL method. +type GetSASURLOptions struct { + StartTime *time.Time +} + +func (o *GetSASURLOptions) format() time.Time { + if o == nil { + return time.Time{} + } + + var st time.Time + if o.StartTime != nil { + st = o.StartTime.UTC() + } else { + st = time.Time{} + } + return st +} diff --git a/sdk/storage/azfile/service/responses.go b/sdk/storage/azfile/service/responses.go new file mode 100644 index 000000000000..fad91de63547 --- /dev/null +++ b/sdk/storage/azfile/service/responses.go @@ -0,0 +1,30 @@ +//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 service + +import "github.com/Azure/azure-sdk-for-go/sdk/storage/azfile/internal/generated" + +// CreateShareResponse contains the response from method share.Client.Create. +type CreateShareResponse = generated.ShareClientCreateResponse + +// DeleteShareResponse contains the response from method share.Client.Delete. +type DeleteShareResponse = generated.ShareClientDeleteResponse + +// RestoreShareResponse contains the response from method share.Client.Restore. +type RestoreShareResponse = generated.ShareClientRestoreResponse + +// GetPropertiesResponse contains the response from method Client.GetProperties. +type GetPropertiesResponse = generated.ServiceClientGetPropertiesResponse + +// SetPropertiesResponse contains the response from method Client.SetProperties. +type SetPropertiesResponse = generated.ServiceClientSetPropertiesResponse + +// ListSharesSegmentResponse contains the response from method Client.NewListSharesPager. +type ListSharesSegmentResponse = generated.ServiceClientListSharesSegmentResponse + +// ListSharesResponse - An enumeration of shares. +type ListSharesResponse = generated.ListSharesResponse diff --git a/sdk/storage/azfile/share/client.go b/sdk/storage/azfile/share/client.go new file mode 100644 index 000000000000..aac826a8a6c1 --- /dev/null +++ b/sdk/storage/azfile/share/client.go @@ -0,0 +1,258 @@ +//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 share + +import ( + "context" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azfile/directory" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azfile/fileerror" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azfile/internal/base" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azfile/internal/exported" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azfile/internal/generated" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azfile/internal/shared" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azfile/sas" + "net/url" + "time" +) + +// ClientOptions contains the optional parameters when creating a Client. +type ClientOptions base.ClientOptions + +// Client represents a URL to the Azure Storage share allowing you to manipulate its directories and files. +type Client base.Client[generated.ShareClient] + +// NewClientWithNoCredential creates an instance of Client with the specified values. +// This is used to anonymously access a share or with a shared access signature (SAS) token. +// - shareURL - the URL of the share e.g. https://.file.core.windows.net/share? +// - options - client options; pass nil to accept the default values +func NewClientWithNoCredential(shareURL string, options *ClientOptions) (*Client, error) { + conOptions := shared.GetClientOptions(options) + pl := runtime.NewPipeline(exported.ModuleName, exported.ModuleVersion, runtime.PipelineOptions{}, &conOptions.ClientOptions) + + return (*Client)(base.NewShareClient(shareURL, pl, nil)), nil +} + +// NewClientWithSharedKeyCredential creates an instance of Client with the specified values. +// - shareURL - the URL of the share e.g. https://.file.core.windows.net/share +// - cred - a SharedKeyCredential created with the matching share's storage account and access key +// - options - client options; pass nil to accept the default values +func NewClientWithSharedKeyCredential(shareURL string, cred *SharedKeyCredential, options *ClientOptions) (*Client, error) { + authPolicy := exported.NewSharedKeyCredPolicy(cred) + conOptions := shared.GetClientOptions(options) + conOptions.PerRetryPolicies = append(conOptions.PerRetryPolicies, authPolicy) + pl := runtime.NewPipeline(exported.ModuleName, exported.ModuleVersion, runtime.PipelineOptions{}, &conOptions.ClientOptions) + + return (*Client)(base.NewShareClient(shareURL, pl, cred)), nil +} + +// NewClientFromConnectionString creates an instance of Client with the specified values. +// - connectionString - a connection string for the desired storage account +// - shareName - the name of the share within the storage account +// - options - client options; pass nil to accept the default values +func NewClientFromConnectionString(connectionString string, shareName string, options *ClientOptions) (*Client, error) { + parsed, err := shared.ParseConnectionString(connectionString) + if err != nil { + return nil, err + } + parsed.ServiceURL = runtime.JoinPaths(parsed.ServiceURL, shareName) + + if parsed.AccountKey != "" && parsed.AccountName != "" { + credential, err := exported.NewSharedKeyCredential(parsed.AccountName, parsed.AccountKey) + if err != nil { + return nil, err + } + return NewClientWithSharedKeyCredential(parsed.ServiceURL, credential, options) + } + + return NewClientWithNoCredential(parsed.ServiceURL, options) +} + +func (s *Client) generated() *generated.ShareClient { + return base.InnerClient((*base.Client[generated.ShareClient])(s)) +} + +func (s *Client) sharedKey() *SharedKeyCredential { + return base.SharedKey((*base.Client[generated.ShareClient])(s)) +} + +// URL returns the URL endpoint used by the Client object. +func (s *Client) URL() string { + return s.generated().Endpoint() +} + +// NewDirectoryClient creates a new directory.Client object by concatenating directoryName to the end of this Client's URL. +// The new directory.Client uses the same request policy pipeline as the Client. +func (s *Client) NewDirectoryClient(directoryName string) *directory.Client { + directoryName = url.PathEscape(directoryName) + directoryURL := runtime.JoinPaths(s.URL(), directoryName) + return (*directory.Client)(base.NewDirectoryClient(directoryURL, s.generated().Pipeline(), s.sharedKey())) +} + +// NewRootDirectoryClient creates a new directory.Client object for the root of the share using the Client's URL. +// The new directory.Client uses the same request policy pipeline as the Client. +func (s *Client) NewRootDirectoryClient() *directory.Client { + rootDirURL := s.URL() + return (*directory.Client)(base.NewDirectoryClient(rootDirURL, s.generated().Pipeline(), s.sharedKey())) +} + +// WithSnapshot creates a new Client object identical to the source but with the specified share snapshot timestamp. +// Pass "" to remove the snapshot returning a URL to the base share. +func (s *Client) WithSnapshot(shareSnapshot string) (*Client, error) { + p, err := sas.ParseURL(s.URL()) + if err != nil { + return nil, err + } + p.ShareSnapshot = shareSnapshot + + return (*Client)(base.NewShareClient(p.String(), s.generated().Pipeline(), s.sharedKey())), nil +} + +// Create operation creates a new share within a storage account. If a share with the same name already exists, the operation fails. +// For more information, see https://learn.microsoft.com/en-us/rest/api/storageservices/create-share. +func (s *Client) Create(ctx context.Context, options *CreateOptions) (CreateResponse, error) { + opts := options.format() + resp, err := s.generated().Create(ctx, opts) + return resp, err +} + +// Delete operation marks the specified share for deletion. The share and any files contained within it are later deleted during garbage collection. +// For more information, see https://learn.microsoft.com/en-us/rest/api/storageservices/delete-share. +func (s *Client) Delete(ctx context.Context, options *DeleteOptions) (DeleteResponse, error) { + opts, leaseAccessConditions := options.format() + resp, err := s.generated().Delete(ctx, opts, leaseAccessConditions) + return resp, err +} + +// Restore operation restores a share that had previously been soft-deleted. +// For more information, see https://learn.microsoft.com/en-us/rest/api/storageservices/restore-share. +func (s *Client) Restore(ctx context.Context, deletedShareVersion string, options *RestoreOptions) (RestoreResponse, error) { + urlParts, err := sas.ParseURL(s.URL()) + if err != nil { + return RestoreResponse{}, err + } + + opts := &generated.ShareClientRestoreOptions{ + DeletedShareName: &urlParts.ShareName, + DeletedShareVersion: &deletedShareVersion, + } + resp, err := s.generated().Restore(ctx, opts) + return resp, err +} + +// GetProperties operation returns all user-defined metadata and system properties for the specified share or share snapshot. +// For more information, see https://learn.microsoft.com/en-us/rest/api/storageservices/get-share-properties. +func (s *Client) GetProperties(ctx context.Context, options *GetPropertiesOptions) (GetPropertiesResponse, error) { + opts, leaseAccessConditions := options.format() + resp, err := s.generated().GetProperties(ctx, opts, leaseAccessConditions) + return resp, err +} + +// SetProperties operation sets properties for the specified share. +// For more information, see https://learn.microsoft.com/en-us/rest/api/storageservices/set-share-properties. +func (s *Client) SetProperties(ctx context.Context, options *SetPropertiesOptions) (SetPropertiesResponse, error) { + opts, leaseAccessConditions := options.format() + resp, err := s.generated().SetProperties(ctx, opts, leaseAccessConditions) + return resp, err +} + +// CreateSnapshot operation creates a read-only snapshot of a share. +// For more information, see https://learn.microsoft.com/en-us/rest/api/storageservices/snapshot-share. +func (s *Client) CreateSnapshot(ctx context.Context, options *CreateSnapshotOptions) (CreateSnapshotResponse, error) { + opts := options.format() + resp, err := s.generated().CreateSnapshot(ctx, opts) + return resp, err +} + +// GetAccessPolicy operation returns information about stored access policies specified on the share. +// For more information, see https://learn.microsoft.com/en-us/rest/api/storageservices/get-share-acl. +func (s *Client) GetAccessPolicy(ctx context.Context, options *GetAccessPolicyOptions) (GetAccessPolicyResponse, error) { + opts, leaseAccessConditions := options.format() + resp, err := s.generated().GetAccessPolicy(ctx, opts, leaseAccessConditions) + return resp, err +} + +// SetAccessPolicy operation sets a stored access policy for use with shared access signatures. +// For more information, see https://learn.microsoft.com/en-us/rest/api/storageservices/set-share-acl. +func (s *Client) SetAccessPolicy(ctx context.Context, options *SetAccessPolicyOptions) (SetAccessPolicyResponse, error) { + opts, acl, leaseAccessConditions, err := options.format() + if err != nil { + return SetAccessPolicyResponse{}, err + } + + resp, err := s.generated().SetAccessPolicy(ctx, acl, opts, leaseAccessConditions) + return resp, err +} + +// CreatePermission operation creates a permission (a security descriptor) at the share level. +// The created security descriptor can be used for the files and directories in the share. +// For more information, see https://learn.microsoft.com/en-us/rest/api/storageservices/create-permission. +func (s *Client) CreatePermission(ctx context.Context, sharePermission string, options *CreatePermissionOptions) (CreatePermissionResponse, error) { + permission, opts := options.format(sharePermission) + resp, err := s.generated().CreatePermission(ctx, permission, opts) + return resp, err +} + +// GetPermission operation gets the SDDL permission string from the service using a known permission key. +// For more information, see https://learn.microsoft.com/en-us/rest/api/storageservices/get-permission. +func (s *Client) GetPermission(ctx context.Context, filePermissionKey string, options *GetPermissionOptions) (GetPermissionResponse, error) { + opts := options.format() + resp, err := s.generated().GetPermission(ctx, filePermissionKey, opts) + return resp, err +} + +// SetMetadata operation sets one or more user-defined name-value pairs for the specified share. +// For more information, see https://learn.microsoft.com/en-us/rest/api/storageservices/set-share-metadata. +func (s *Client) SetMetadata(ctx context.Context, options *SetMetadataOptions) (SetMetadataResponse, error) { + opts, leaseAccessConditions := options.format() + resp, err := s.generated().SetMetadata(ctx, opts, leaseAccessConditions) + return resp, err +} + +// GetStatistics operation retrieves statistics related to the share. +// For more information, see https://learn.microsoft.com/en-us/rest/api/storageservices/get-share-stats. +func (s *Client) GetStatistics(ctx context.Context, options *GetStatisticsOptions) (GetStatisticsResponse, error) { + opts, leaseAccessConditions := options.format() + resp, err := s.generated().GetStatistics(ctx, opts, leaseAccessConditions) + return resp, err +} + +// GetSASURL is a convenience method for generating a SAS token for the currently pointed at share. +// It can only be used if the credential supplied during creation was a SharedKeyCredential. +func (s *Client) GetSASURL(permissions sas.SharePermissions, expiry time.Time, o *GetSASURLOptions) (string, error) { + if s.sharedKey() == nil { + return "", fileerror.MissingSharedKeyCredential + } + st := o.format() + + urlParts, err := sas.ParseURL(s.URL()) + if err != nil { + return "", err + } + + t, err := time.Parse(sas.SnapshotTimeFormat, urlParts.ShareSnapshot) + if err != nil { + t = time.Time{} + } + + qps, err := sas.SignatureValues{ + Version: sas.Version, + Protocol: sas.ProtocolHTTPS, + ShareName: urlParts.ShareName, + SnapshotTime: t, + Permissions: permissions.String(), + StartTime: st, + ExpiryTime: expiry.UTC(), + }.SignWithSharedKey(s.sharedKey()) + if err != nil { + return "", err + } + + endpoint := s.URL() + "?" + qps.Encode() + + return endpoint, nil +} diff --git a/sdk/storage/azfile/share/client_test.go b/sdk/storage/azfile/share/client_test.go new file mode 100644 index 000000000000..44940a537d27 --- /dev/null +++ b/sdk/storage/azfile/share/client_test.go @@ -0,0 +1,1460 @@ +//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 share_test + +import ( + "context" + "fmt" + "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/azfile/fileerror" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azfile/internal/testcommon" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azfile/sas" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azfile/service" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azfile/share" + "github.com/stretchr/testify/require" + "github.com/stretchr/testify/suite" + "strconv" + "testing" + "time" +) + +func Test(t *testing.T) { + recordMode := recording.GetRecordMode() + t.Logf("Running share Tests in %s mode\n", recordMode) + if recordMode == recording.LiveMode { + suite.Run(t, &ShareRecordedTestsSuite{}) + suite.Run(t, &ShareUnrecordedTestsSuite{}) + } else if recordMode == recording.PlaybackMode { + suite.Run(t, &ShareRecordedTestsSuite{}) + } else if recordMode == recording.RecordingMode { + suite.Run(t, &ShareRecordedTestsSuite{}) + } +} + +func (s *ShareRecordedTestsSuite) BeforeTest(suite string, test string) { + testcommon.BeforeTest(s.T(), suite, test) +} + +func (s *ShareRecordedTestsSuite) AfterTest(suite string, test string) { + testcommon.AfterTest(s.T(), suite, test) +} + +func (s *ShareUnrecordedTestsSuite) BeforeTest(suite string, test string) { + +} + +func (s *ShareUnrecordedTestsSuite) AfterTest(suite string, test string) { + +} + +type ShareRecordedTestsSuite struct { + suite.Suite +} + +type ShareUnrecordedTestsSuite struct { + suite.Suite +} + +func (s *ShareRecordedTestsSuite) TestShareCreateRootDirectoryURL() { + _require := require.New(s.T()) + testName := s.T().Name() + + svcClient, err := testcommon.GetServiceClient(s.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + shareClient := testcommon.CreateNewShare(context.Background(), _require, testcommon.GenerateShareName(testName), svcClient) + defer testcommon.DeleteShare(context.Background(), _require, shareClient) + + rootDirClient := shareClient.NewRootDirectoryClient() + _require.Equal(shareClient.URL(), rootDirClient.URL()) +} + +func (s *ShareRecordedTestsSuite) TestShareCreateDirectoryURL() { + _require := require.New(s.T()) + testName := s.T().Name() + + accountName, _ := testcommon.GetGenericAccountInfo(testcommon.TestAccountDefault) + _require.Greater(len(accountName), 0) + + svcClient, err := testcommon.GetServiceClient(s.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + shareName, dirName := testcommon.GenerateShareName(testName), testcommon.GenerateDirectoryName(testName) + shareClient := svcClient.NewShareClient(shareName) + _require.NoError(err) + dirClient := shareClient.NewDirectoryClient(dirName) + _require.NoError(err) + + correctURL := "https://" + accountName + ".file.core.windows.net/" + shareName + "/" + dirName + _require.Equal(dirClient.URL(), correctURL) +} + +func (s *ShareRecordedTestsSuite) TestShareCreateUsingSharedKey() { + _require := require.New(s.T()) + testName := s.T().Name() + + cred, err := testcommon.GetGenericSharedKeyCredential(testcommon.TestAccountDefault) + _require.NoError(err) + + shareName := testcommon.GenerateShareName(testName) + shareURL := "https://" + cred.AccountName() + ".file.core.windows.net/" + shareName + options := &share.ClientOptions{} + testcommon.SetClientOptions(s.T(), &options.ClientOptions) + shareClient, err := share.NewClientWithSharedKeyCredential(shareURL, cred, options) + _require.NoError(err) + + resp, err := shareClient.Create(context.Background(), nil) + defer testcommon.DeleteShare(context.Background(), _require, shareClient) + + _require.NoError(err) + _require.NotNil(resp.ETag) + _require.NotNil(resp.RequestID) +} + +func (s *ShareRecordedTestsSuite) TestShareCreateUsingConnectionString() { + _require := require.New(s.T()) + testName := s.T().Name() + + connString, err := testcommon.GetGenericConnectionString(testcommon.TestAccountDefault) + _require.NoError(err) + + shareName := testcommon.GenerateShareName(testName) + options := &share.ClientOptions{} + testcommon.SetClientOptions(s.T(), &options.ClientOptions) + shareClient, err := share.NewClientFromConnectionString(*connString, shareName, options) + _require.NoError(err) + + resp, err := shareClient.Create(context.Background(), nil) + defer testcommon.DeleteShare(context.Background(), _require, shareClient) + + _require.NoError(err) + _require.NotNil(resp.ETag) + _require.NotNil(resp.RequestID) +} + +func (s *ShareUnrecordedTestsSuite) TestShareClientUsingSAS() { + _require := require.New(s.T()) + testName := s.T().Name() + + svcClient, err := testcommon.GetServiceClient(s.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + shareName := testcommon.GenerateShareName(testName) + shareClient := testcommon.CreateNewShare(context.Background(), _require, shareName, svcClient) + defer testcommon.DeleteShare(context.Background(), _require, shareClient) + + permissions := sas.SharePermissions{ + Read: true, + Write: true, + Delete: true, + List: true, + Create: true, + } + expiry := time.Now().Add(time.Hour) + + shareSASURL, err := shareClient.GetSASURL(permissions, expiry, nil) + _require.NoError(err) + + shareSASClient, err := share.NewClientWithNoCredential(shareSASURL, nil) + _require.NoError(err) + + _, err = shareSASClient.GetProperties(context.Background(), nil) + _require.Error(err) + testcommon.ValidateFileErrorCode(_require, err, fileerror.AuthorizationFailure) + + dirName1 := testcommon.GenerateDirectoryName(testName) + "1" + _, err = shareSASClient.NewDirectoryClient(dirName1).Create(context.Background(), nil) + _require.NoError(err) + + dirName2 := testcommon.GenerateDirectoryName(testName) + "2" + _, err = shareSASClient.NewDirectoryClient(dirName2).Create(context.Background(), nil) + _require.NoError(err) + + fileName1 := testcommon.GenerateFileName(testName) + "1" + _, err = shareSASClient.NewRootDirectoryClient().NewFileClient(fileName1).Create(context.Background(), 1024, nil) + _require.NoError(err) + + fileName2 := testcommon.GenerateFileName(testName) + "2" + _, err = shareSASClient.NewDirectoryClient(dirName2).NewFileClient(fileName2).Create(context.Background(), 1024, nil) + _require.NoError(err) + + dirCtr, fileCtr := 0, 0 + pager := shareSASClient.NewRootDirectoryClient().NewListFilesAndDirectoriesPager(nil) + for pager.More() { + resp, err := pager.NextPage(context.Background()) + _require.NoError(err) + dirCtr += len(resp.Segment.Directories) + fileCtr += len(resp.Segment.Files) + } + _require.Equal(dirCtr, 2) + _require.Equal(fileCtr, 1) +} + +func (s *ShareRecordedTestsSuite) TestShareCreateDeleteNonDefault() { + _require := require.New(s.T()) + testName := s.T().Name() + svcClient, err := testcommon.GetServiceClient(s.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + shareName := testcommon.GenerateShareName(testName) + shareClient := svcClient.NewShareClient(shareName) + + quota := int32(1000) + + cResp, err := shareClient.Create(context.Background(), &share.CreateOptions{ + AccessTier: to.Ptr(share.AccessTierCool), + Quota: to.Ptr(quota), + Metadata: testcommon.BasicMetadata}) + + _require.NoError(err) + _require.Equal(cResp.Date.IsZero(), false) + _require.NotNil(cResp.ETag) + _require.NotNil(cResp.LastModified) + _require.NotNil(cResp.RequestID) + _require.NotNil(cResp.Version) + + pager := svcClient.NewListSharesPager(&service.ListSharesOptions{ + Prefix: to.Ptr(shareName), + Include: service.ListSharesInclude{Metadata: true}, + }) + + for pager.More() { + resp, err := pager.NextPage(context.Background()) + _require.NoError(err) + _require.Len(resp.Shares, 1) + _require.Equal(*resp.Shares[0].Name, shareName) + _require.NotNil(resp.Shares[0].Metadata) + _require.EqualValues(resp.Shares[0].Metadata, testcommon.BasicMetadata) + _require.Equal(*resp.Shares[0].Properties.AccessTier, string(share.AccessTierCool)) + _require.Equal(*resp.Shares[0].Properties.Quota, quota) + } + + dResp, err := shareClient.Delete(context.Background(), nil) + _require.NoError(err) + _require.NotNil(dResp.Date) + _require.NotNil(dResp.RequestID) + _require.NotNil(dResp.Version) + + pager1 := svcClient.NewListSharesPager(&service.ListSharesOptions{ + Prefix: to.Ptr(shareName), + Include: service.ListSharesInclude{Metadata: true}, + }) + for pager1.More() { + resp, err := pager1.NextPage(context.Background()) + _require.NoError(err) + _require.Len(resp.Shares, 0) + } +} + +func (s *ShareRecordedTestsSuite) TestShareCreateNilMetadata() { + _require := require.New(s.T()) + testName := s.T().Name() + svcClient, err := testcommon.GetServiceClient(s.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + shareName := testcommon.GenerateShareName(testName) + shareClient := svcClient.NewShareClient(shareName) + + _, err = shareClient.Create(context.Background(), nil) + defer testcommon.DeleteShare(context.Background(), _require, shareClient) + _require.NoError(err) + + response, err := shareClient.GetProperties(context.Background(), nil) + _require.NoError(err) + _require.Len(response.Metadata, 0) +} + +func (s *ShareRecordedTestsSuite) TestShareCreateNegativeInvalidName() { + _require := require.New(s.T()) + svcClient, err := testcommon.GetServiceClient(s.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + shareClient := svcClient.NewShareClient("foo bar") + + _, err = shareClient.Create(context.Background(), nil) + + testcommon.ValidateFileErrorCode(_require, err, fileerror.InvalidResourceName) +} + +func (s *ShareRecordedTestsSuite) TestShareCreateNegativeInvalidMetadata() { + _require := require.New(s.T()) + testName := s.T().Name() + svcClient, err := testcommon.GetServiceClient(s.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + shareName := testcommon.GenerateShareName(testName) + shareClient := svcClient.NewShareClient(shareName) + + _, err = shareClient.Create(context.Background(), &share.CreateOptions{ + Metadata: map[string]*string{"!@#$%^&*()": to.Ptr("!@#$%^&*()")}, + Quota: to.Ptr(int32(0)), + }) + _require.Error(err) +} + +func (s *ShareRecordedTestsSuite) TestShareDeleteNegativeNonExistent() { + _require := require.New(s.T()) + testName := s.T().Name() + svcClient, err := testcommon.GetServiceClient(s.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + shareName := testcommon.GenerateShareName(testName) + shareClient := svcClient.NewShareClient(shareName) + + _, err = shareClient.Delete(context.Background(), nil) + testcommon.ValidateFileErrorCode(_require, err, fileerror.ShareNotFound) +} + +func (s *ShareRecordedTestsSuite) TestShareGetSetPropertiesNonDefault() { + _require := require.New(s.T()) + testName := s.T().Name() + svcClient, err := testcommon.GetServiceClient(s.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + shareName := testcommon.GenerateShareName(testName) + shareClient := testcommon.CreateNewShare(context.Background(), _require, shareName, svcClient) + defer testcommon.DeleteShare(context.Background(), _require, shareClient) + + newQuota := int32(1234) + + sResp, err := shareClient.SetProperties(context.Background(), &share.SetPropertiesOptions{ + Quota: to.Ptr(newQuota), + AccessTier: to.Ptr(share.AccessTierHot), + }) + _require.NoError(err) + _require.NotNil(sResp.ETag) + _require.Equal(sResp.LastModified.IsZero(), false) + _require.NotNil(sResp.RequestID) + _require.NotNil(sResp.Version) + _require.Equal(sResp.Date.IsZero(), false) + + props, err := shareClient.GetProperties(context.Background(), nil) + _require.NoError(err) + _require.NotNil(props.ETag) + _require.Equal(props.LastModified.IsZero(), false) + _require.NotNil(props.RequestID) + _require.NotNil(props.Version) + _require.Equal(props.Date.IsZero(), false) + _require.Equal(*props.Quota, newQuota) + _require.Equal(*props.AccessTier, string(share.AccessTierHot)) +} + +func (s *ShareRecordedTestsSuite) TestShareGetSetPropertiesDefault() { + _require := require.New(s.T()) + testName := s.T().Name() + svcClient, err := testcommon.GetServiceClient(s.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + shareName := testcommon.GenerateShareName(testName) + shareClient := testcommon.CreateNewShare(context.Background(), _require, shareName, svcClient) + defer testcommon.DeleteShare(context.Background(), _require, shareClient) + + sResp, err := shareClient.SetProperties(context.Background(), nil) + _require.NoError(err) + _require.NotNil(sResp.ETag) + _require.Equal(sResp.LastModified.IsZero(), false) + _require.NotNil(sResp.RequestID) + _require.NotNil(sResp.Version) + _require.Equal(sResp.Date.IsZero(), false) + + props, err := shareClient.GetProperties(context.Background(), nil) + _require.NoError(err) + _require.NotNil(props.ETag) + _require.Equal(props.LastModified.IsZero(), false) + _require.NotNil(props.RequestID) + _require.NotNil(props.Version) + _require.Equal(props.Date.IsZero(), false) + _require.Greater(*props.Quota, int32(0)) // When using service default quota, it could be any value +} + +func (s *ShareRecordedTestsSuite) TestShareSetQuotaNegative() { + _require := require.New(s.T()) + testName := s.T().Name() + svcClient, err := testcommon.GetServiceClient(s.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + shareName := testcommon.GenerateShareName(testName) + shareClient := testcommon.CreateNewShare(context.Background(), _require, shareName, svcClient) + defer testcommon.DeleteShare(context.Background(), _require, shareClient) + + _, err = shareClient.SetProperties(context.Background(), &share.SetPropertiesOptions{Quota: to.Ptr(int32(-1))}) + _require.Error(err) + testcommon.ValidateFileErrorCode(_require, err, fileerror.InvalidHeaderValue) +} + +func (s *ShareRecordedTestsSuite) TestShareGetPropertiesNegative() { + _require := require.New(s.T()) + testName := s.T().Name() + svcClient, err := testcommon.GetServiceClient(s.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + shareName := testcommon.GenerateShareName(testName) + shareClient := testcommon.GetShareClient(shareName, svcClient) + + _, err = shareClient.GetProperties(context.Background(), nil) + _require.Error(err) + testcommon.ValidateFileErrorCode(_require, err, fileerror.ShareNotFound) +} + +func (s *ShareRecordedTestsSuite) TestSharePutAndGetPermission() { + _require := require.New(s.T()) + testName := s.T().Name() + svcClient, err := testcommon.GetServiceClient(s.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + shareName := testcommon.GenerateShareName(testName) + shareClient := testcommon.CreateNewShare(context.Background(), _require, shareName, svcClient) + defer testcommon.DeleteShare(context.Background(), _require, shareClient) + + // Create a permission and check that it's not empty. + createResp, err := shareClient.CreatePermission(context.Background(), testcommon.SampleSDDL, nil) + _require.NoError(err) + _require.NotEqual(*createResp.FilePermissionKey, "") + + getResp, err := shareClient.GetPermission(context.Background(), *createResp.FilePermissionKey, nil) + _require.NoError(err) + // Rather than checking against the original, we check for emptiness, as Azure Files has set a nil-ness flag on SACLs + // and converted our well-known SID. + /* + Expected :string = "O:S-1-5-32-548G:S-1-5-21-397955417-626881126-188441444-512D:(A;;RPWPCCDCLCSWRCWDWOGA;;;S-1-0-0)" + Actual :string = "O:AOG:S-1-5-21-397955417-626881126-188441444-512D:(A;;CCDCLCSWRPWPRCWDWOGA;;;S-1-0-0)S:NO_ACCESS_CONTROL" + */ + _require.NotNil(getResp.Permission) + _require.NotEmpty(*getResp.Permission) +} + +func (s *ShareRecordedTestsSuite) TestShareGetSetAccessPolicyNonDefault() { + _require := require.New(s.T()) + testName := s.T().Name() + svcClient, err := testcommon.GetServiceClient(s.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + shareName := testcommon.GenerateShareName(testName) + shareClient := testcommon.CreateNewShare(context.Background(), _require, shareName, svcClient) + defer testcommon.DeleteShare(context.Background(), _require, shareClient) + + currTime, err := time.Parse(time.UnixDate, "Fri Mar 31 20:00:00 GMT 2023") + _require.NoError(err) + now := currTime.UTC().Truncate(10000 * time.Millisecond) // Enough resolution + expiryTIme := now.Add(5 * time.Minute).UTC() + pS := share.AccessPolicyPermission{ + Read: true, + Write: true, + Create: true, + Delete: true, + List: true, + } + pS2 := &share.AccessPolicyPermission{} + err = pS2.Parse("ldcwr") + _require.NoError(err) + _require.EqualValues(*pS2, pS) + + permission := pS.String() + permissions := []*share.SignedIdentifier{ + { + ID: to.Ptr("MTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTI="), + AccessPolicy: &share.AccessPolicy{ + Start: &now, + Expiry: &expiryTIme, + Permission: &permission, + }, + }} + + sResp, err := shareClient.SetAccessPolicy(context.Background(), &share.SetAccessPolicyOptions{ + ShareACL: permissions, + }) + _require.NoError(err) + _require.Equal(sResp.Date.IsZero(), false) + _require.NotNil(sResp.ETag) + _require.Equal(sResp.LastModified.IsZero(), false) + _require.NotNil(sResp.RequestID) + _require.NotNil(sResp.Version) + + gResp, err := shareClient.GetAccessPolicy(context.Background(), nil) + _require.NoError(err) + _require.Equal(gResp.Date.IsZero(), false) + _require.NotNil(gResp.ETag) + _require.Equal(gResp.LastModified.IsZero(), false) + _require.NotNil(gResp.RequestID) + _require.NotNil(gResp.Version) + _require.Len(gResp.SignedIdentifiers, 1) + _require.EqualValues(*(gResp.SignedIdentifiers[0]), *permissions[0]) +} + +func (s *ShareRecordedTestsSuite) TestShareGetSetAccessPolicyNonDefaultMultiple() { + _require := require.New(s.T()) + testName := s.T().Name() + svcClient, err := testcommon.GetServiceClient(s.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + shareName := testcommon.GenerateShareName(testName) + shareClient := testcommon.CreateNewShare(context.Background(), _require, shareName, svcClient) + defer testcommon.DeleteShare(context.Background(), _require, shareClient) + + currTime, err := time.Parse(time.UnixDate, "Fri Mar 31 20:00:00 GMT 2023") + _require.NoError(err) + now := currTime.UTC().Truncate(10000 * time.Millisecond) // Enough resolution + expiryTIme := now.Add(5 * time.Minute).UTC() + permission := share.AccessPolicyPermission{ + Read: true, + Write: true, + }.String() + + permissions := []*share.SignedIdentifier{ + { + ID: to.Ptr("MTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTI="), + AccessPolicy: &share.AccessPolicy{ + Start: &now, + Expiry: &expiryTIme, + Permission: &permission, + }, + }, + { + ID: to.Ptr("2"), + AccessPolicy: &share.AccessPolicy{ + Start: &now, + Expiry: &expiryTIme, + Permission: &permission, + }, + }} + + sResp, err := shareClient.SetAccessPolicy(context.Background(), &share.SetAccessPolicyOptions{ + ShareACL: permissions, + }) + _require.NoError(err) + _require.Equal(sResp.Date.IsZero(), false) + _require.NotNil(sResp.ETag) + _require.Equal(sResp.LastModified.IsZero(), false) + _require.NotNil(sResp.RequestID) + _require.NotNil(sResp.Version) + + gResp, err := shareClient.GetAccessPolicy(context.Background(), nil) + _require.NoError(err) + _require.Equal(gResp.Date.IsZero(), false) + _require.NotNil(gResp.ETag) + _require.Equal(gResp.LastModified.IsZero(), false) + _require.NotNil(gResp.RequestID) + _require.NotNil(gResp.Version) + _require.Len(gResp.SignedIdentifiers, 2) + _require.EqualValues(gResp.SignedIdentifiers[0], permissions[0]) + _require.EqualValues(gResp.SignedIdentifiers[1], permissions[1]) +} + +func (s *ShareRecordedTestsSuite) TestShareSetAccessPolicyMoreThanFive() { + _require := require.New(s.T()) + testName := s.T().Name() + svcClient, err := testcommon.GetServiceClient(s.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + shareName := testcommon.GenerateShareName(testName) + shareClient := testcommon.CreateNewShare(context.Background(), _require, shareName, svcClient) + defer testcommon.DeleteShare(context.Background(), _require, shareClient) + + currTime, err := time.Parse(time.UnixDate, "Fri Mar 31 20:00:00 GMT 2023") + _require.NoError(err) + now := currTime.UTC().Truncate(10000 * time.Millisecond) // Enough resolution + expiryTIme := now.Add(5 * time.Minute).UTC() + permission := share.AccessPolicyPermission{ + Read: true, + Create: true, + Write: true, + Delete: true, + List: true, + }.String() + + var permissions []*share.SignedIdentifier + for i := 0; i <= len(permission); i++ { + p := permission + if i < len(permission) { + p = string(permission[i]) + } + permissions = append(permissions, &share.SignedIdentifier{ + ID: to.Ptr(fmt.Sprintf("%v", i)), + AccessPolicy: &share.AccessPolicy{ + Start: &now, + Expiry: &expiryTIme, + Permission: &p, + }, + }) + } + _require.Len(permissions, 6) + + _, err = shareClient.SetAccessPolicy(context.Background(), &share.SetAccessPolicyOptions{ + ShareACL: permissions, + }) + _require.Error(err) + testcommon.ValidateFileErrorCode(_require, err, fileerror.InvalidXMLDocument) +} + +func (s *ShareRecordedTestsSuite) TestShareGetSetAccessPolicyDefault() { + _require := require.New(s.T()) + testName := s.T().Name() + svcClient, err := testcommon.GetServiceClient(s.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + shareName := testcommon.GenerateShareName(testName) + shareClient := testcommon.CreateNewShare(context.Background(), _require, shareName, svcClient) + defer testcommon.DeleteShare(context.Background(), _require, shareClient) + + sResp, err := shareClient.SetAccessPolicy(context.Background(), nil) + _require.NoError(err) + _require.Equal(sResp.Date.IsZero(), false) + _require.NotNil(sResp.ETag) + _require.Equal(sResp.LastModified.IsZero(), false) + _require.NotNil(sResp.RequestID) + _require.NotNil(sResp.Version) + + gResp, err := shareClient.GetAccessPolicy(context.Background(), nil) + _require.NoError(err) + _require.Equal(gResp.Date.IsZero(), false) + _require.NotNil(gResp.ETag) + _require.Equal(gResp.LastModified.IsZero(), false) + _require.NotNil(gResp.RequestID) + _require.NotNil(gResp.Version) + _require.Len(gResp.SignedIdentifiers, 0) +} + +func (s *ShareRecordedTestsSuite) TestShareGetAccessPolicyNegative() { + _require := require.New(s.T()) + testName := s.T().Name() + svcClient, err := testcommon.GetServiceClient(s.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + shareName := testcommon.GenerateShareName(testName) + shareClient := testcommon.GetShareClient(shareName, svcClient) + + _, err = shareClient.GetAccessPolicy(context.Background(), nil) + _require.Error(err) + testcommon.ValidateFileErrorCode(_require, err, fileerror.ShareNotFound) +} + +func (s *ShareRecordedTestsSuite) TestShareSetAccessPolicyNonDefaultDeleteAndModifyACL() { + _require := require.New(s.T()) + testName := s.T().Name() + svcClient, err := testcommon.GetServiceClient(s.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + shareName := testcommon.GenerateShareName(testName) + shareClient := testcommon.CreateNewShare(context.Background(), _require, shareName, svcClient) + defer testcommon.DeleteShare(context.Background(), _require, shareClient) + + currTime, err := time.Parse(time.UnixDate, "Thu Mar 30 20:00:00 GMT 2023") + _require.NoError(err) + start := currTime.UTC().Truncate(10000 * time.Millisecond) + expiry := start.Add(5 * time.Minute).UTC() + accessPermission := share.AccessPolicyPermission{List: true}.String() + permissions := make([]*share.SignedIdentifier, 2) + for i := 0; i < 2; i++ { + permissions[i] = &share.SignedIdentifier{ + ID: to.Ptr("000" + strconv.Itoa(i)), + AccessPolicy: &share.AccessPolicy{ + Start: &start, + Expiry: &expiry, + Permission: &accessPermission, + }, + } + } + + _, err = shareClient.SetAccessPolicy(context.Background(), &share.SetAccessPolicyOptions{ + ShareACL: permissions, + }) + _require.NoError(err) + + resp, err := shareClient.GetAccessPolicy(context.Background(), nil) + _require.NoError(err) + _require.Len(resp.SignedIdentifiers, len(permissions)) + _require.EqualValues(resp.SignedIdentifiers, permissions) + + permissions = resp.SignedIdentifiers[:1] // Delete the second policy by removing it from the slice + permissions[0].ID = to.Ptr("0004") // Modify the remaining policy which is at index 0 in the new slice + _, err = shareClient.SetAccessPolicy(context.Background(), &share.SetAccessPolicyOptions{ + ShareACL: permissions, + }) + _require.NoError(err) + + resp, err = shareClient.GetAccessPolicy(context.Background(), nil) + _require.NoError(err) + _require.Len(resp.SignedIdentifiers, 1) + _require.EqualValues(resp.SignedIdentifiers, permissions) +} + +func (s *ShareRecordedTestsSuite) TestShareSetAccessPolicyDeleteAllPolicies() { + _require := require.New(s.T()) + testName := s.T().Name() + svcClient, err := testcommon.GetServiceClient(s.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + shareName := testcommon.GenerateShareName(testName) + shareClient := testcommon.CreateNewShare(context.Background(), _require, shareName, svcClient) + defer testcommon.DeleteShare(context.Background(), _require, shareClient) + + currTime, err := time.Parse(time.UnixDate, "Fri Mar 31 20:00:00 GMT 2023") + _require.NoError(err) + start := currTime.UTC() + expiry := start.Add(5 * time.Minute).UTC() + accessPermission := share.AccessPolicyPermission{List: true}.String() + permissions := make([]*share.SignedIdentifier, 2) + for i := 0; i < 2; i++ { + permissions[i] = &share.SignedIdentifier{ + ID: to.Ptr("000" + strconv.Itoa(i)), + AccessPolicy: &share.AccessPolicy{ + Start: &start, + Expiry: &expiry, + Permission: &accessPermission, + }, + } + } + + _, err = shareClient.SetAccessPolicy(context.Background(), &share.SetAccessPolicyOptions{ + ShareACL: permissions, + }) + _require.NoError(err) + + resp1, err := shareClient.GetAccessPolicy(context.Background(), nil) + _require.NoError(err) + _require.Len(resp1.SignedIdentifiers, 2) + + _, err = shareClient.SetAccessPolicy(context.Background(), nil) + _require.NoError(err) + + resp2, err := shareClient.GetAccessPolicy(context.Background(), nil) + _require.NoError(err) + _require.Len(resp2.SignedIdentifiers, 0) +} + +func (s *ShareRecordedTestsSuite) TestShareSetPermissionsNegativeInvalidPolicyTimes() { + _require := require.New(s.T()) + testName := s.T().Name() + svcClient, err := testcommon.GetServiceClient(s.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + shareName := testcommon.GenerateShareName(testName) + shareClient := testcommon.CreateNewShare(context.Background(), _require, shareName, svcClient) + defer testcommon.DeleteShare(context.Background(), _require, shareClient) + + // Swap start and expiry + currTime, err := time.Parse(time.UnixDate, "Fri Mar 31 20:00:00 GMT 2023") + _require.NoError(err) + expiry := currTime.UTC() + start := expiry.Add(5 * time.Minute).UTC() + accessPermission := share.AccessPolicyPermission{List: true}.String() + permissions := make([]*share.SignedIdentifier, 2) + for i := 0; i < 2; i++ { + permissions[i] = &share.SignedIdentifier{ + ID: to.Ptr("000" + strconv.Itoa(i)), + AccessPolicy: &share.AccessPolicy{ + Start: &start, + Expiry: &expiry, + Permission: &accessPermission, + }, + } + } + + _, err = shareClient.SetAccessPolicy(context.Background(), &share.SetAccessPolicyOptions{ + ShareACL: permissions, + }) + _require.NoError(err) + + resp, err := shareClient.GetAccessPolicy(context.Background(), nil) + _require.NoError(err) + _require.Len(resp.SignedIdentifiers, len(permissions)) + _require.EqualValues(resp.SignedIdentifiers, permissions) +} + +// SignedIdentifier ID too long +func (s *ShareRecordedTestsSuite) TestShareSetPermissionsNegative() { + _require := require.New(s.T()) + testName := s.T().Name() + svcClient, err := testcommon.GetServiceClient(s.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + shareName := testcommon.GenerateShareName(testName) + shareClient := testcommon.CreateNewShare(context.Background(), _require, shareName, svcClient) + defer testcommon.DeleteShare(context.Background(), _require, shareClient) + + id := "" + for i := 0; i < 65; i++ { + id += "a" + } + currTime, err := time.Parse(time.UnixDate, "Wed Mar 29 20:00:00 GMT 2023") + _require.NoError(err) + expiry := currTime.UTC() + start := expiry.Add(5 * time.Minute).UTC() + accessPermission := share.AccessPolicyPermission{List: true}.String() + permissions := make([]*share.SignedIdentifier, 2) + for i := 0; i < 2; i++ { + permissions[i] = &share.SignedIdentifier{ + ID: to.Ptr(id), + AccessPolicy: &share.AccessPolicy{ + Start: &start, + Expiry: &expiry, + Permission: &accessPermission, + }, + } + } + + _, err = shareClient.SetAccessPolicy(context.Background(), &share.SetAccessPolicyOptions{ + ShareACL: permissions, + }) + _require.Error(err) + testcommon.ValidateFileErrorCode(_require, err, fileerror.InvalidXMLDocument) +} + +func (s *ShareRecordedTestsSuite) TestShareGetSetMetadataDefault() { + _require := require.New(s.T()) + testName := s.T().Name() + svcClient, err := testcommon.GetServiceClient(s.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + shareName := testcommon.GenerateShareName(testName) + shareClient := testcommon.CreateNewShare(context.Background(), _require, shareName, svcClient) + defer testcommon.DeleteShare(context.Background(), _require, shareClient) + + sResp, err := shareClient.SetMetadata(context.Background(), &share.SetMetadataOptions{ + Metadata: map[string]*string{}, + }) + _require.NoError(err) + _require.Equal(sResp.Date.IsZero(), false) + _require.NotNil(sResp.ETag) + _require.Equal(sResp.LastModified.IsZero(), false) + _require.NotNil(sResp.RequestID) + _require.NotNil(sResp.Version) + + gResp, err := shareClient.GetProperties(context.Background(), nil) + _require.NoError(err) + _require.Equal(gResp.Date.IsZero(), false) + _require.NotNil(gResp.ETag) + _require.Equal(gResp.LastModified.IsZero(), false) + _require.NotNil(gResp.RequestID) + _require.NotNil(gResp.Version) + _require.Len(gResp.Metadata, 0) +} + +func (s *ShareRecordedTestsSuite) TestShareGetSetMetadataNonDefault() { + _require := require.New(s.T()) + testName := s.T().Name() + svcClient, err := testcommon.GetServiceClient(s.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + shareName := testcommon.GenerateShareName(testName) + shareClient := testcommon.CreateNewShare(context.Background(), _require, shareName, svcClient) + defer testcommon.DeleteShare(context.Background(), _require, shareClient) + + md := map[string]*string{ + "Foo": to.Ptr("FooValuE"), + "Bar": to.Ptr("bArvaLue"), + } + sResp, err := shareClient.SetMetadata(context.Background(), &share.SetMetadataOptions{ + Metadata: md, + }) + _require.NoError(err) + _require.Equal(sResp.Date.IsZero(), false) + _require.NotNil(sResp.ETag) + _require.Equal(sResp.LastModified.IsZero(), false) + _require.NotNil(sResp.RequestID) + _require.NotNil(sResp.Version) + + gResp, err := shareClient.GetProperties(context.Background(), nil) + _require.NoError(err) + _require.Equal(gResp.Date.IsZero(), false) + _require.NotNil(gResp.ETag) + _require.Equal(gResp.LastModified.IsZero(), false) + _require.NotNil(gResp.RequestID) + _require.NotNil(gResp.Version) + _require.EqualValues(gResp.Metadata, md) +} + +func (s *ShareRecordedTestsSuite) TestShareSetMetadataNegative() { + _require := require.New(s.T()) + testName := s.T().Name() + svcClient, err := testcommon.GetServiceClient(s.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + shareName := testcommon.GenerateShareName(testName) + shareClient := testcommon.CreateNewShare(context.Background(), _require, shareName, svcClient) + defer testcommon.DeleteShare(context.Background(), _require, shareClient) + + md := map[string]*string{ + "!@#$%^&*()": to.Ptr("!@#$%^&*()"), + } + _, err = shareClient.SetMetadata(context.Background(), &share.SetMetadataOptions{ + Metadata: md, + }) + _require.Error(err) +} + +func (s *ShareRecordedTestsSuite) TestShareGetStats() { + _require := require.New(s.T()) + testName := s.T().Name() + svcClient, err := testcommon.GetServiceClient(s.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + shareName := testcommon.GenerateShareName(testName) + shareClient := testcommon.CreateNewShare(context.Background(), _require, shareName, svcClient) + defer testcommon.DeleteShare(context.Background(), _require, shareClient) + + newQuota := int32(300) + + // In order to test and get LastModified property. + _, err = shareClient.SetProperties(context.Background(), &share.SetPropertiesOptions{Quota: to.Ptr(newQuota)}) + _require.NoError(err) + + gResp, err := shareClient.GetStatistics(context.Background(), nil) + _require.NoError(err) + _require.Equal(gResp.Date.IsZero(), false) + // _require.NotEqual(*gResp.ETag, "") // TODO: The ETag would be "" + // _require.Equal(gResp.LastModified.IsZero(), false) // TODO: Even share is once updated, no LastModified would be returned. + _require.NotNil(gResp.RequestID) + _require.NotNil(gResp.Version) + _require.Equal(*gResp.ShareUsageBytes, int64(0)) +} + +func (s *ShareRecordedTestsSuite) TestShareGetStatsNegative() { + _require := require.New(s.T()) + testName := s.T().Name() + svcClient, err := testcommon.GetServiceClient(s.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + shareName := testcommon.GenerateShareName(testName) + shareClient := testcommon.GetShareClient(shareName, svcClient) + + _, err = shareClient.GetStatistics(context.Background(), nil) + _require.Error(err) + testcommon.ValidateFileErrorCode(_require, err, fileerror.ShareNotFound) +} + +func (s *ShareRecordedTestsSuite) TestSetAndGetStatistics() { + _require := require.New(s.T()) + testName := s.T().Name() + svcClient, err := testcommon.GetServiceClient(s.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + shareName := testcommon.GenerateShareName(testName) + shareClient := testcommon.GetShareClient(shareName, svcClient) + + _, err = shareClient.Create(context.Background(), &share.CreateOptions{Quota: to.Ptr(int32(1024))}) + _require.NoError(err) + defer testcommon.DeleteShare(context.Background(), _require, shareClient) + + dirClient := shareClient.NewDirectoryClient("testdir") + _, err = dirClient.Create(context.Background(), nil) + _require.NoError(err) + + fileClient := dirClient.NewFileClient("testfile") + _, err = fileClient.Create(context.Background(), int64(1024*1024*1024*1024), nil) + _require.NoError(err) + + getStats, err := shareClient.GetStatistics(context.Background(), nil) + _require.NoError(err) + _require.Equal(*getStats.ShareUsageBytes, int64(1024*1024*1024*1024)) +} + +func deleteShare(ctx context.Context, _require *require.Assertions, shareClient *share.Client, o *share.DeleteOptions) { + _, err := shareClient.Delete(ctx, o) + _require.NoError(err) +} + +func (s *ShareRecordedTestsSuite) TestShareCreateSnapshotNonDefault() { + _require := require.New(s.T()) + testName := s.T().Name() + svcClient, err := testcommon.GetServiceClient(s.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + shareName := testcommon.GenerateShareName(testName) + shareClient := testcommon.CreateNewShare(context.Background(), _require, shareName, svcClient) + defer deleteShare(context.Background(), _require, shareClient, &share.DeleteOptions{DeleteSnapshots: to.Ptr(share.DeleteSnapshotsOptionTypeInclude)}) + + cResp, err := shareClient.CreateSnapshot(context.Background(), &share.CreateSnapshotOptions{Metadata: testcommon.BasicMetadata}) + _require.NoError(err) + _require.Equal(cResp.Date.IsZero(), false) + _require.NotNil(cResp.ETag) + _require.NotEqual(*cResp.ETag, "") + _require.Equal(cResp.LastModified.IsZero(), false) + _require.NotNil(cResp.RequestID) + _require.NotNil(cResp.Version) + _require.NotNil(cResp.Snapshot) + _require.NotEqual(*cResp.Snapshot, "") + + cSnapshot := *cResp.Snapshot + + pager := svcClient.NewListSharesPager(&service.ListSharesOptions{ + Include: service.ListSharesInclude{Metadata: true, Snapshots: true}, + Prefix: &shareName, + }) + + foundSnapshot := false + for pager.More() { + lResp, err := pager.NextPage(context.Background()) + _require.NoError(err) + _require.Len(lResp.Shares, 2) + + for _, s := range lResp.Shares { + if s.Snapshot != nil { + foundSnapshot = true + _require.Equal(*s.Snapshot, cSnapshot) + _require.NotNil(s.Metadata) + _require.EqualValues(s.Metadata, testcommon.BasicMetadata) + } else { + _require.Len(s.Metadata, 0) + } + } + } + _require.True(foundSnapshot) +} + +func (s *ShareUnrecordedTestsSuite) TestShareCreateSnapshotDefault() { + _require := require.New(s.T()) + testName := s.T().Name() + + cred, err := testcommon.GetGenericSharedKeyCredential(testcommon.TestAccountDefault) + _require.NoError(err) + + svcClient, err := testcommon.GetServiceClient(s.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + shareName := testcommon.GenerateShareName(testName) + shareClient := svcClient.NewShareClient(shareName) + + _, err = shareClient.Create(context.Background(), nil) + _require.NoError(err) + defer deleteShare(context.Background(), _require, shareClient, &share.DeleteOptions{DeleteSnapshots: to.Ptr(share.DeleteSnapshotsOptionTypeInclude)}) + + // create a file in the base share. + dirClient := shareClient.NewRootDirectoryClient() + _require.NoError(err) + + fClient := dirClient.NewFileClient("myfile") + _, err = fClient.Create(context.Background(), 0, nil) + _require.NoError(err) + + // Create share snapshot, the snapshot contains the create file. + snapshotShare, err := shareClient.CreateSnapshot(context.Background(), nil) + _require.NoError(err) + + // Delete file in base share. + _, err = fClient.Delete(context.Background(), nil) + _require.NoError(err) + + // To produce a share SAS (as opposed to a file SAS), assign to FilePermissions using + // ShareSASPermissions and make sure the DirectoryAndFilePath field is "" (the default). + perms := sas.SharePermissions{Read: true, Write: true} + + // Restore file from share snapshot. + // Create a SAS. + sasQueryParams, err := sas.SignatureValues{ + Protocol: sas.ProtocolHTTPS, // Users MUST use HTTPS (not HTTP) + ExpiryTime: time.Now().UTC().Add(48 * time.Hour), // 48-hours before expiration + ShareName: shareName, + Permissions: perms.String(), + }.SignWithSharedKey(cred) + _require.NoError(err) + + // Build a file snapshot URL. + fileParts, err := sas.ParseURL(fClient.URL()) + _require.NoError(err) + fileParts.ShareSnapshot = *snapshotShare.Snapshot + fileParts.SAS = sasQueryParams + sourceURL := fileParts.String() + + // Before restore + _, err = fClient.GetProperties(context.Background(), nil) + _require.Error(err) + testcommon.ValidateFileErrorCode(_require, err, fileerror.ResourceNotFound) + + // Do restore. + _, err = fClient.StartCopyFromURL(context.Background(), sourceURL, nil) + _require.NoError(err) + + time.Sleep(2 * time.Second) + + // After restore + _, err = fClient.GetProperties(context.Background(), nil) + _require.NoError(err) + + _, err = shareClient.Delete(context.Background(), &share.DeleteOptions{ + ShareSnapshot: snapshotShare.Snapshot, + }) + _require.NoError(err) +} + +func (s *ShareRecordedTestsSuite) TestShareCreateSnapshotNegativeShareNotExist() { + _require := require.New(s.T()) + testName := s.T().Name() + svcClient, err := testcommon.GetServiceClient(s.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + shareName := testcommon.GenerateShareName(testName) + shareClient := testcommon.GetShareClient(shareName, svcClient) + + _, err = shareClient.CreateSnapshot(context.Background(), &share.CreateSnapshotOptions{Metadata: map[string]*string{}}) + _require.Error(err) + testcommon.ValidateFileErrorCode(_require, err, fileerror.ShareNotFound) +} + +func (s *ShareRecordedTestsSuite) TestShareDeleteSnapshot() { + _require := require.New(s.T()) + testName := s.T().Name() + svcClient, err := testcommon.GetServiceClient(s.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + shareName := testcommon.GenerateShareName(testName) + shareClient := testcommon.CreateNewShare(context.Background(), _require, shareName, svcClient) + defer deleteShare(context.Background(), _require, shareClient, &share.DeleteOptions{DeleteSnapshots: to.Ptr(share.DeleteSnapshotsOptionTypeInclude)}) + + resp1, err := shareClient.CreateSnapshot(context.Background(), nil) + _require.NoError(err) + _require.NotNil(resp1.Snapshot) + _require.NotEmpty(*resp1.Snapshot) + + resp2, err := shareClient.CreateSnapshot(context.Background(), nil) + _require.NoError(err) + _require.NotNil(resp2.Snapshot) + _require.NotEmpty(*resp2.Snapshot) + + pager := svcClient.NewListSharesPager(&service.ListSharesOptions{ + Include: service.ListSharesInclude{Snapshots: true}, + Prefix: &shareName, + }) + + snapshotsCtr := 0 + for pager.More() { + lResp, err := pager.NextPage(context.Background()) + _require.NoError(err) + _require.Len(lResp.Shares, 3) // 2 snapshots and 1 share + + for _, s := range lResp.Shares { + if s.Snapshot != nil { + snapshotsCtr++ + } + } + } + _require.Equal(snapshotsCtr, 2) + + snapClient, err := shareClient.WithSnapshot(*resp1.Snapshot) + _require.NoError(err) + + _, err = snapClient.Delete(context.Background(), nil) + _require.NoError(err) + + pager = svcClient.NewListSharesPager(&service.ListSharesOptions{ + Include: service.ListSharesInclude{Snapshots: true}, + Prefix: &shareName, + }) + + snapshotsCtr = 0 + for pager.More() { + lResp, err := pager.NextPage(context.Background()) + _require.NoError(err) + _require.Len(lResp.Shares, 2) + + for _, s := range lResp.Shares { + if s.Snapshot != nil { + snapshotsCtr++ + _require.Equal(*s.Snapshot, *resp2.Snapshot) + } + } + } + _require.Equal(snapshotsCtr, 1) +} + +func (s *ShareRecordedTestsSuite) TestShareCreateSnapshotNegativeMetadataInvalid() { + _require := require.New(s.T()) + testName := s.T().Name() + svcClient, err := testcommon.GetServiceClient(s.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + shareName := testcommon.GenerateShareName(testName) + shareClient := testcommon.CreateNewShare(context.Background(), _require, shareName, svcClient) + defer testcommon.DeleteShare(context.Background(), _require, shareClient) + + _, err = shareClient.CreateSnapshot(context.Background(), &share.CreateSnapshotOptions{Metadata: map[string]*string{"!@#$%^&*()": to.Ptr("!@#$%^&*()")}}) + _require.Error(err) +} + +func (s *ShareRecordedTestsSuite) TestShareCreateSnapshotNegativeSnapshotOfSnapshot() { + _require := require.New(s.T()) + testName := s.T().Name() + svcClient, err := testcommon.GetServiceClient(s.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + shareName := testcommon.GenerateShareName(testName) + shareClient := testcommon.CreateNewShare(context.Background(), _require, shareName, svcClient) + defer deleteShare(context.Background(), _require, shareClient, &share.DeleteOptions{DeleteSnapshots: to.Ptr(share.DeleteSnapshotsOptionTypeInclude)}) + + snapTime, err := time.Parse(time.UnixDate, "Fri Mar 31 20:00:00 GMT 2023") + _require.NoError(err) + + snapshotClient, err := shareClient.WithSnapshot(snapTime.UTC().String()) + _require.NoError(err) + + cResp, err := snapshotClient.CreateSnapshot(context.Background(), nil) + _require.NoError(err) //Note: this would not fail, snapshot would be ignored. + _require.NotNil(cResp) + _require.NotEmpty(*cResp.Snapshot) + + snapshotRecursiveClient, err := shareClient.WithSnapshot(*cResp.Snapshot) + _require.NoError(err) + _, err = snapshotRecursiveClient.CreateSnapshot(context.Background(), nil) + _require.NoError(err) //Note: this would not fail, snapshot would be ignored. +} + +func (s *ShareRecordedTestsSuite) TestShareDeleteSnapshotsInclude() { + _require := require.New(s.T()) + testName := s.T().Name() + svcClient, err := testcommon.GetServiceClient(s.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + shareName := testcommon.GenerateShareName(testName) + shareClient := testcommon.CreateNewShare(context.Background(), _require, shareName, svcClient) + + _, err = shareClient.CreateSnapshot(context.Background(), nil) + _require.NoError(err) + + pager := svcClient.NewListSharesPager(&service.ListSharesOptions{ + Include: service.ListSharesInclude{Snapshots: true}, + Prefix: &shareName, + }) + + for pager.More() { + resp, err := pager.NextPage(context.Background()) + _require.NoError(err) + _require.Len(resp.Shares, 2) + } + + _, err = shareClient.Delete(context.Background(), &share.DeleteOptions{DeleteSnapshots: to.Ptr(share.DeleteSnapshotsOptionTypeInclude)}) + _require.NoError(err) + + pager = svcClient.NewListSharesPager(&service.ListSharesOptions{ + Include: service.ListSharesInclude{Snapshots: true}, + Prefix: &shareName, + }) + + for pager.More() { + resp, err := pager.NextPage(context.Background()) + _require.NoError(err) + _require.Len(resp.Shares, 0) + } +} + +func (s *ShareRecordedTestsSuite) TestShareDeleteSnapshotsNoneWithSnapshots() { + _require := require.New(s.T()) + testName := s.T().Name() + svcClient, err := testcommon.GetServiceClient(s.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + shareName := testcommon.GenerateShareName(testName) + shareClient := testcommon.CreateNewShare(context.Background(), _require, shareName, svcClient) + defer deleteShare(context.Background(), _require, shareClient, &share.DeleteOptions{DeleteSnapshots: to.Ptr(share.DeleteSnapshotsOptionTypeInclude)}) + + _, err = shareClient.CreateSnapshot(context.Background(), nil) + _require.NoError(err) + + _, err = shareClient.Delete(context.Background(), nil) + _require.Error(err) + testcommon.ValidateFileErrorCode(_require, err, fileerror.ShareHasSnapshots) +} + +func (s *ShareRecordedTestsSuite) TestShareRestoreSuccess() { + _require := require.New(s.T()) + testName := s.T().Name() + svcClient, err := testcommon.GetServiceClient(s.T(), testcommon.TestAccountSoftDelete, nil) + _require.NoError(err) + + shareName := testcommon.GenerateShareName(testName) + shareClient := testcommon.CreateNewShare(context.Background(), _require, shareName, svcClient) + defer testcommon.DeleteShare(context.Background(), _require, shareClient) + + _, err = shareClient.Delete(context.Background(), nil) + _require.NoError(err) + + // wait for share deletion + time.Sleep(60 * time.Second) + + pager := svcClient.NewListSharesPager(&service.ListSharesOptions{ + Include: service.ListSharesInclude{Deleted: true}, + Prefix: &shareName, + }) + + shareVersion := "" + shareCtr := 0 + for pager.More() { + resp, err := pager.NextPage(context.Background()) + _require.NoError(err) + + for _, s := range resp.Shares { + if s.Deleted != nil && *s.Deleted { + shareVersion = *s.Version + } else { + shareCtr++ + } + } + } + _require.NotEmpty(shareVersion) + _require.Equal(shareCtr, 0) + + rResp, err := shareClient.Restore(context.Background(), shareVersion, nil) + _require.NoError(err) + _require.NotNil(rResp.ETag) + _require.NotNil(rResp.RequestID) + _require.NotNil(rResp.Version) + + pager = svcClient.NewListSharesPager(&service.ListSharesOptions{ + Prefix: &shareName, + }) + + shareCtr = 0 + for pager.More() { + resp, err := pager.NextPage(context.Background()) + _require.NoError(err) + shareCtr += len(resp.Shares) + } + _require.Equal(shareCtr, 1) +} + +func (s *ShareRecordedTestsSuite) TestShareRestoreFailures() { + _require := require.New(s.T()) + testName := s.T().Name() + svcClient, err := testcommon.GetServiceClient(s.T(), testcommon.TestAccountSoftDelete, nil) + _require.NoError(err) + + shareName := testcommon.GenerateShareName(testName) + shareClient := testcommon.CreateNewShare(context.Background(), _require, shareName, svcClient) + defer testcommon.DeleteShare(context.Background(), _require, shareClient) + + _, err = shareClient.Restore(context.Background(), "", nil) + _require.Error(err) + testcommon.ValidateFileErrorCode(_require, err, fileerror.MissingRequiredHeader) +} + +func (s *ShareRecordedTestsSuite) TestShareRestoreWithSnapshotsAgain() { + _require := require.New(s.T()) + testName := s.T().Name() + svcClient, err := testcommon.GetServiceClient(s.T(), testcommon.TestAccountSoftDelete, nil) + _require.NoError(err) + + shareName := testcommon.GenerateShareName(testName) + shareClient := testcommon.CreateNewShare(context.Background(), _require, shareName, svcClient) + defer deleteShare(context.Background(), _require, shareClient, &share.DeleteOptions{DeleteSnapshots: to.Ptr(share.DeleteSnapshotsOptionTypeInclude)}) + + cResp, err := shareClient.CreateSnapshot(context.Background(), nil) + _require.NoError(err) + _require.NotNil(cResp.Snapshot) + + _, err = shareClient.Delete(context.Background(), &share.DeleteOptions{ + DeleteSnapshots: to.Ptr(share.DeleteSnapshotsOptionTypeInclude), + }) + _require.NoError(err) + + // wait for share deletion + time.Sleep(60 * time.Second) + + pager := svcClient.NewListSharesPager(&service.ListSharesOptions{ + Include: service.ListSharesInclude{Deleted: true}, + Prefix: &shareName, + }) + + shareVersion := "" + shareCtr := 0 + for pager.More() { + resp, err := pager.NextPage(context.Background()) + _require.NoError(err) + + for _, s := range resp.Shares { + if s.Deleted != nil && *s.Deleted { + shareVersion = *s.Version + } else { + shareCtr++ + } + } + } + _require.NotEmpty(shareVersion) + _require.Equal(shareCtr, 0) + + rResp, err := shareClient.Restore(context.Background(), shareVersion, nil) + _require.NoError(err) + _require.NotNil(rResp.ETag) + _require.NotNil(rResp.RequestID) + _require.NotNil(rResp.Version) + + pager = svcClient.NewListSharesPager(&service.ListSharesOptions{ + Include: service.ListSharesInclude{Snapshots: true}, + Prefix: &shareName, + }) + + shareCtr = 0 + for pager.More() { + resp, err := pager.NextPage(context.Background()) + _require.NoError(err) + shareCtr += len(resp.Shares) + for _, s := range resp.Shares { + if s.Snapshot != nil { + _require.Equal(*s.Snapshot, *cResp.Snapshot) + } + } + } + _require.Equal(shareCtr, 2) // 1 share and 1 snapshot +} + +func (s *ShareRecordedTestsSuite) TestSASShareClientNoKey() { + _require := require.New(s.T()) + accountName, _ := testcommon.GetGenericAccountInfo(testcommon.TestAccountDefault) + _require.Greater(len(accountName), 0) + + testName := s.T().Name() + shareName := testcommon.GenerateShareName(testName) + shareClient, err := share.NewClientWithNoCredential(fmt.Sprintf("https://%s.file.core.windows.net/%v", accountName, shareName), nil) + _require.NoError(err) + + permissions := sas.SharePermissions{ + Read: true, + Write: true, + Delete: true, + List: true, + Create: true, + } + expiry := time.Now().Add(time.Hour) + + _, err = shareClient.GetSASURL(permissions, expiry, nil) + _require.Equal(err, fileerror.MissingSharedKeyCredential) +} + +func (s *ShareRecordedTestsSuite) TestSASShareClientSignNegative() { + _require := require.New(s.T()) + accountName, accountKey := testcommon.GetGenericAccountInfo(testcommon.TestAccountDefault) + _require.Greater(len(accountName), 0) + _require.Greater(len(accountKey), 0) + + cred, err := share.NewSharedKeyCredential(accountName, accountKey) + _require.NoError(err) + + testName := s.T().Name() + shareName := testcommon.GenerateShareName(testName) + shareClient, err := share.NewClientWithSharedKeyCredential(fmt.Sprintf("https://%s.file.core.windows.net/%v", accountName, shareName), cred, nil) + _require.NoError(err) + + permissions := sas.SharePermissions{ + Read: true, + Write: true, + Delete: true, + List: true, + Create: true, + } + expiry := time.Time{} + + // zero expiry time + _, err = shareClient.GetSASURL(permissions, expiry, &share.GetSASURLOptions{StartTime: to.Ptr(time.Now())}) + _require.Equal(err.Error(), "service SAS is missing at least one of these: ExpiryTime or Permissions") + + // zero start and expiry time + _, err = shareClient.GetSASURL(permissions, expiry, &share.GetSASURLOptions{}) + _require.Equal(err.Error(), "service SAS is missing at least one of these: ExpiryTime or Permissions") + + // empty permissions + _, err = shareClient.GetSASURL(sas.SharePermissions{}, expiry, nil) + _require.Equal(err.Error(), "service SAS is missing at least one of these: ExpiryTime or Permissions") +} diff --git a/sdk/storage/azfile/share/constants.go b/sdk/storage/azfile/share/constants.go new file mode 100644 index 000000000000..231ab9e27e09 --- /dev/null +++ b/sdk/storage/azfile/share/constants.go @@ -0,0 +1,50 @@ +//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 share + +import "github.com/Azure/azure-sdk-for-go/sdk/storage/azfile/internal/generated" + +// AccessTier defines values for the access tier of the share. +type AccessTier = generated.ShareAccessTier + +const ( + AccessTierCool AccessTier = generated.ShareAccessTierCool + AccessTierHot AccessTier = generated.ShareAccessTierHot + AccessTierTransactionOptimized AccessTier = generated.ShareAccessTierTransactionOptimized +) + +// PossibleAccessTierValues returns the possible values for the AccessTier const type. +func PossibleAccessTierValues() []AccessTier { + return generated.PossibleShareAccessTierValues() +} + +// RootSquash defines values for the root squashing behavior on the share when NFS is enabled. If it's not specified, the default is NoRootSquash. +type RootSquash = generated.ShareRootSquash + +const ( + RootSquashNoRootSquash RootSquash = generated.ShareRootSquashNoRootSquash + RootSquashRootSquash RootSquash = generated.ShareRootSquashRootSquash + RootSquashAllSquash RootSquash = generated.ShareRootSquashAllSquash +) + +// PossibleRootSquashValues returns the possible values for the RootSquash const type. +func PossibleRootSquashValues() []RootSquash { + return generated.PossibleShareRootSquashValues() +} + +// DeleteSnapshotsOptionType defines values for DeleteSnapshotsOptionType +type DeleteSnapshotsOptionType = generated.DeleteSnapshotsOptionType + +const ( + DeleteSnapshotsOptionTypeInclude DeleteSnapshotsOptionType = generated.DeleteSnapshotsOptionTypeInclude + DeleteSnapshotsOptionTypeIncludeLeased DeleteSnapshotsOptionType = generated.DeleteSnapshotsOptionTypeIncludeLeased +) + +// PossibleDeleteSnapshotsOptionTypeValues returns the possible values for the DeleteSnapshotsOptionType const type. +func PossibleDeleteSnapshotsOptionTypeValues() []DeleteSnapshotsOptionType { + return generated.PossibleDeleteSnapshotsOptionTypeValues() +} diff --git a/sdk/storage/azfile/share/examples_test.go b/sdk/storage/azfile/share/examples_test.go new file mode 100644 index 000000000000..bb4739e9b151 --- /dev/null +++ b/sdk/storage/azfile/share/examples_test.go @@ -0,0 +1,464 @@ +//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 share_test + +import ( + "context" + "fmt" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/to" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azfile/sas" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azfile/service" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azfile/share" + "log" + "os" + "time" +) + +func handleError(err error) { + if err != nil { + log.Fatal(err.Error()) + } +} + +func Example_share_Client_NewClient() { + accountName, ok := os.LookupEnv("AZURE_STORAGE_ACCOUNT_NAME") + if !ok { + panic("AZURE_STORAGE_ACCOUNT_NAME could not be found") + } + accountKey, ok := os.LookupEnv("AZURE_STORAGE_ACCOUNT_KEY") + if !ok { + panic("AZURE_STORAGE_ACCOUNT_KEY could not be found") + } + + shareName := "testshare" + shareURL := fmt.Sprintf("https://%s.file.core.windows.net/%s", accountName, shareName) + + cred, err := service.NewSharedKeyCredential(accountName, accountKey) + handleError(err) + + shareClient, err := share.NewClientWithSharedKeyCredential(shareURL, cred, nil) + handleError(err) + + fmt.Println(shareClient.URL()) +} + +func Example_share_Client_NewClientFromConnectionString() { + // Your connection string can be obtained from the Azure Portal. + connectionString, ok := os.LookupEnv("AZURE_STORAGE_CONNECTION_STRING") + if !ok { + log.Fatal("the environment variable 'AZURE_STORAGE_CONNECTION_STRING' could not be found") + } + + shareName := "testshare" + shareClient, err := share.NewClientFromConnectionString(connectionString, shareName, nil) + handleError(err) + + fmt.Println(shareClient.URL()) +} + +func Example_share_Client_NewDirectoryClient() { + accountName, ok := os.LookupEnv("AZURE_STORAGE_ACCOUNT_NAME") + if !ok { + panic("AZURE_STORAGE_ACCOUNT_NAME could not be found") + } + accountKey, ok := os.LookupEnv("AZURE_STORAGE_ACCOUNT_KEY") + if !ok { + panic("AZURE_STORAGE_ACCOUNT_KEY could not be found") + } + + shareName := "testshare" + shareURL := fmt.Sprintf("https://%s.file.core.windows.net/%s", accountName, shareName) + + cred, err := service.NewSharedKeyCredential(accountName, accountKey) + handleError(err) + + shareClient, err := share.NewClientWithSharedKeyCredential(shareURL, cred, nil) + handleError(err) + + dirName := "testdirectory" + dirClient := shareClient.NewDirectoryClient(dirName) + + fmt.Println(dirClient.URL()) +} + +func Example_share_Client_NewRootDirectoryClient() { + accountName, ok := os.LookupEnv("AZURE_STORAGE_ACCOUNT_NAME") + if !ok { + panic("AZURE_STORAGE_ACCOUNT_NAME could not be found") + } + accountKey, ok := os.LookupEnv("AZURE_STORAGE_ACCOUNT_KEY") + if !ok { + panic("AZURE_STORAGE_ACCOUNT_KEY could not be found") + } + + shareName := "testshare" + shareURL := fmt.Sprintf("https://%s.file.core.windows.net/%s", accountName, shareName) + + cred, err := service.NewSharedKeyCredential(accountName, accountKey) + handleError(err) + + shareClient, err := share.NewClientWithSharedKeyCredential(shareURL, cred, nil) + handleError(err) + + dirClient := shareClient.NewRootDirectoryClient() + + fmt.Println(dirClient.URL()) +} + +func Example_share_Client_CreateSnapshot() { + accountName, ok := os.LookupEnv("AZURE_STORAGE_ACCOUNT_NAME") + if !ok { + panic("AZURE_STORAGE_ACCOUNT_NAME could not be found") + } + accountKey, ok := os.LookupEnv("AZURE_STORAGE_ACCOUNT_KEY") + if !ok { + panic("AZURE_STORAGE_ACCOUNT_KEY could not be found") + } + + shareName := "testshare" + shareURL := fmt.Sprintf("https://%s.file.core.windows.net/%s", accountName, shareName) + + cred, err := service.NewSharedKeyCredential(accountName, accountKey) + handleError(err) + + shareClient, err := share.NewClientWithSharedKeyCredential(shareURL, cred, nil) + handleError(err) + + snapResp, err := shareClient.CreateSnapshot(context.TODO(), nil) + handleError(err) + shareSnapshot := *snapResp.Snapshot + + snapshotShareClient, err := shareClient.WithSnapshot(shareSnapshot) + handleError(err) + + fmt.Println(snapshotShareClient.URL()) + + _, err = snapshotShareClient.GetProperties(context.TODO(), nil) + handleError(err) +} + +func Example_share_Client_Create() { + accountName, ok := os.LookupEnv("AZURE_STORAGE_ACCOUNT_NAME") + if !ok { + panic("AZURE_STORAGE_ACCOUNT_NAME could not be found") + } + accountKey, ok := os.LookupEnv("AZURE_STORAGE_ACCOUNT_KEY") + if !ok { + panic("AZURE_STORAGE_ACCOUNT_KEY could not be found") + } + + shareName := "testshare" + shareURL := fmt.Sprintf("https://%s.file.core.windows.net/%s", accountName, shareName) + + cred, err := service.NewSharedKeyCredential(accountName, accountKey) + handleError(err) + + shareClient, err := share.NewClientWithSharedKeyCredential(shareURL, cred, nil) + handleError(err) + + _, err = shareClient.Create(context.TODO(), nil) + handleError(err) +} + +func Example_share_Client_Delete() { + accountName, ok := os.LookupEnv("AZURE_STORAGE_ACCOUNT_NAME") + if !ok { + panic("AZURE_STORAGE_ACCOUNT_NAME could not be found") + } + accountKey, ok := os.LookupEnv("AZURE_STORAGE_ACCOUNT_KEY") + if !ok { + panic("AZURE_STORAGE_ACCOUNT_KEY could not be found") + } + + shareName := "testshare" + shareURL := fmt.Sprintf("https://%s.file.core.windows.net/%s", accountName, shareName) + + cred, err := service.NewSharedKeyCredential(accountName, accountKey) + handleError(err) + + shareClient, err := share.NewClientWithSharedKeyCredential(shareURL, cred, nil) + handleError(err) + + _, err = shareClient.Delete(context.TODO(), nil) + handleError(err) +} + +func Example_share_Client_Restore() { + accountName, ok := os.LookupEnv("AZURE_STORAGE_ACCOUNT_NAME") + if !ok { + panic("AZURE_STORAGE_ACCOUNT_NAME could not be found") + } + accountKey, ok := os.LookupEnv("AZURE_STORAGE_ACCOUNT_KEY") + if !ok { + panic("AZURE_STORAGE_ACCOUNT_KEY could not be found") + } + + shareName := "testshare" + serviceURL := fmt.Sprintf("https://%s.file.core.windows.net/", accountName) + + cred, err := service.NewSharedKeyCredential(accountName, accountKey) + handleError(err) + + svcClient, err := service.NewClientWithSharedKeyCredential(serviceURL, cred, nil) + handleError(err) + + shareClient := svcClient.NewShareClient(shareName) + + // get share version for restore operation + pager := svcClient.NewListSharesPager(&service.ListSharesOptions{ + Include: service.ListSharesInclude{Deleted: true}, // Include deleted shares in the result + }) + + for pager.More() { + resp, err := pager.NextPage(context.Background()) + handleError(err) + for _, s := range resp.Shares { + if s.Deleted != nil && *s.Deleted { + _, err = shareClient.Restore(context.TODO(), *s.Version, nil) + handleError(err) + } + } + } +} + +func Example_share_Client_GetProperties() { + accountName, ok := os.LookupEnv("AZURE_STORAGE_ACCOUNT_NAME") + if !ok { + panic("AZURE_STORAGE_ACCOUNT_NAME could not be found") + } + accountKey, ok := os.LookupEnv("AZURE_STORAGE_ACCOUNT_KEY") + if !ok { + panic("AZURE_STORAGE_ACCOUNT_KEY could not be found") + } + + shareName := "testshare" + shareURL := fmt.Sprintf("https://%s.file.core.windows.net/%s", accountName, shareName) + + cred, err := service.NewSharedKeyCredential(accountName, accountKey) + handleError(err) + + shareClient, err := share.NewClientWithSharedKeyCredential(shareURL, cred, nil) + handleError(err) + + _, err = shareClient.GetProperties(context.TODO(), nil) + handleError(err) +} + +func Example_share_Client_SetProperties() { + accountName, ok := os.LookupEnv("AZURE_STORAGE_ACCOUNT_NAME") + if !ok { + panic("AZURE_STORAGE_ACCOUNT_NAME could not be found") + } + accountKey, ok := os.LookupEnv("AZURE_STORAGE_ACCOUNT_KEY") + if !ok { + panic("AZURE_STORAGE_ACCOUNT_KEY could not be found") + } + + shareName := "testshare" + shareURL := fmt.Sprintf("https://%s.file.core.windows.net/%s", accountName, shareName) + + cred, err := service.NewSharedKeyCredential(accountName, accountKey) + handleError(err) + + shareClient, err := share.NewClientWithSharedKeyCredential(shareURL, cred, nil) + handleError(err) + + _, err = shareClient.SetProperties(context.TODO(), &share.SetPropertiesOptions{ + Quota: to.Ptr(int32(1000)), + AccessTier: to.Ptr(share.AccessTierHot), + }) + handleError(err) +} + +func Example_share_Client_AccessPolicy() { + accountName, ok := os.LookupEnv("AZURE_STORAGE_ACCOUNT_NAME") + if !ok { + panic("AZURE_STORAGE_ACCOUNT_NAME could not be found") + } + accountKey, ok := os.LookupEnv("AZURE_STORAGE_ACCOUNT_KEY") + if !ok { + panic("AZURE_STORAGE_ACCOUNT_KEY could not be found") + } + + shareName := "testshare" + shareURL := fmt.Sprintf("https://%s.file.core.windows.net/%s", accountName, shareName) + + cred, err := service.NewSharedKeyCredential(accountName, accountKey) + handleError(err) + + shareClient, err := share.NewClientWithSharedKeyCredential(shareURL, cred, nil) + handleError(err) + + permission := share.AccessPolicyPermission{Read: true, Write: true, Create: true, Delete: true, List: true}.String() + permissions := []*share.SignedIdentifier{ + { + ID: to.Ptr("1"), + AccessPolicy: &share.AccessPolicy{ + Start: to.Ptr(time.Now()), + Expiry: to.Ptr(time.Now().Add(time.Hour)), + Permission: &permission, + }, + }} + + _, err = shareClient.SetAccessPolicy(context.TODO(), &share.SetAccessPolicyOptions{ + ShareACL: permissions, + }) + handleError(err) + + resp, err := shareClient.GetAccessPolicy(context.TODO(), nil) + handleError(err) + + fmt.Println(*resp.SignedIdentifiers[0].AccessPolicy.Permission) +} + +func Example_share_Client_CreateGetPermission() { + accountName, ok := os.LookupEnv("AZURE_STORAGE_ACCOUNT_NAME") + if !ok { + panic("AZURE_STORAGE_ACCOUNT_NAME could not be found") + } + accountKey, ok := os.LookupEnv("AZURE_STORAGE_ACCOUNT_KEY") + if !ok { + panic("AZURE_STORAGE_ACCOUNT_KEY could not be found") + } + + shareName := "testshare" + shareURL := fmt.Sprintf("https://%s.file.core.windows.net/%s", accountName, shareName) + + cred, err := service.NewSharedKeyCredential(accountName, accountKey) + handleError(err) + + shareClient, err := share.NewClientWithSharedKeyCredential(shareURL, cred, nil) + handleError(err) + + testSDDL := `O:S-1-5-32-548G:S-1-5-21-397955417-626881126-188441444-512D:(A;;RPWPCCDCLCSWRCWDWOGA;;;S-1-0-0)` + createResp, err := shareClient.CreatePermission(context.TODO(), testSDDL, nil) + handleError(err) + + getResp, err := shareClient.GetPermission(context.TODO(), *createResp.FilePermissionKey, nil) + handleError(err) + fmt.Println(*getResp.Permission) +} + +func Example_share_Client_SetMetadata() { + accountName, ok := os.LookupEnv("AZURE_STORAGE_ACCOUNT_NAME") + if !ok { + panic("AZURE_STORAGE_ACCOUNT_NAME could not be found") + } + accountKey, ok := os.LookupEnv("AZURE_STORAGE_ACCOUNT_KEY") + if !ok { + panic("AZURE_STORAGE_ACCOUNT_KEY could not be found") + } + + shareName := "testshare" + shareURL := fmt.Sprintf("https://%s.file.core.windows.net/%s", accountName, shareName) + + cred, err := service.NewSharedKeyCredential(accountName, accountKey) + handleError(err) + + shareClient, err := share.NewClientWithSharedKeyCredential(shareURL, cred, nil) + handleError(err) + + md := map[string]*string{ + "Foo": to.Ptr("FooValuE"), + "Bar": to.Ptr("bArvaLue"), + } + _, err = shareClient.SetMetadata(context.TODO(), &share.SetMetadataOptions{ + Metadata: md, + }) + handleError(err) + + resp, err := shareClient.GetProperties(context.TODO(), nil) + handleError(err) + for k, v := range resp.Metadata { + fmt.Printf("%v : %v\n", k, *v) + } +} + +func Example_share_Client_GetStatistics() { + accountName, ok := os.LookupEnv("AZURE_STORAGE_ACCOUNT_NAME") + if !ok { + panic("AZURE_STORAGE_ACCOUNT_NAME could not be found") + } + accountKey, ok := os.LookupEnv("AZURE_STORAGE_ACCOUNT_KEY") + if !ok { + panic("AZURE_STORAGE_ACCOUNT_KEY could not be found") + } + + shareName := "testshare" + shareURL := fmt.Sprintf("https://%s.file.core.windows.net/%s", accountName, shareName) + + cred, err := service.NewSharedKeyCredential(accountName, accountKey) + handleError(err) + + shareClient, err := share.NewClientWithSharedKeyCredential(shareURL, cred, nil) + handleError(err) + + getStats, err := shareClient.GetStatistics(context.Background(), nil) + handleError(err) + fmt.Println(*getStats.ShareUsageBytes) +} + +func Example_share_Client_GetSASURL() { + accountName, ok := os.LookupEnv("AZURE_STORAGE_ACCOUNT_NAME") + if !ok { + panic("AZURE_STORAGE_ACCOUNT_NAME could not be found") + } + accountKey, ok := os.LookupEnv("AZURE_STORAGE_ACCOUNT_KEY") + if !ok { + panic("AZURE_STORAGE_ACCOUNT_KEY could not be found") + } + + shareName := "testshare" + shareURL := fmt.Sprintf("https://%s.file.core.windows.net/%s", accountName, shareName) + + cred, err := service.NewSharedKeyCredential(accountName, accountKey) + handleError(err) + + shareClient, err := share.NewClientWithSharedKeyCredential(shareURL, cred, nil) + handleError(err) + + permissions := sas.SharePermissions{ + Read: true, + Write: true, + Delete: true, + List: true, + Create: true, + } + expiry := time.Now().Add(time.Hour) + + shareSASURL, err := shareClient.GetSASURL(permissions, expiry, nil) + handleError(err) + + fmt.Println("SAS URL: ", shareSASURL) + + shareSASClient, err := share.NewClientWithNoCredential(shareSASURL, nil) + handleError(err) + + var dirs, files []string + pager := shareSASClient.NewRootDirectoryClient().NewListFilesAndDirectoriesPager(nil) + for pager.More() { + resp, err := pager.NextPage(context.Background()) + handleError(err) + + for _, d := range resp.Segment.Directories { + dirs = append(dirs, *d.Name) + } + for _, f := range resp.Segment.Files { + files = append(files, *f.Name) + } + } + + fmt.Println("Directories:") + for _, d := range dirs { + fmt.Println(d) + } + + fmt.Println("Files:") + for _, f := range files { + fmt.Println(f) + } +} diff --git a/sdk/storage/azfile/share/models.go b/sdk/storage/azfile/share/models.go new file mode 100644 index 000000000000..5b200ce9429b --- /dev/null +++ b/sdk/storage/azfile/share/models.go @@ -0,0 +1,312 @@ +//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 share + +import ( + "github.com/Azure/azure-sdk-for-go/sdk/storage/azfile/internal/exported" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azfile/internal/generated" + "time" +) + +// SharedKeyCredential contains an account's name and its primary or secondary key. +type SharedKeyCredential = exported.SharedKeyCredential + +// NewSharedKeyCredential creates an immutable SharedKeyCredential containing the +// storage account's name and either its primary or secondary key. +func NewSharedKeyCredential(accountName, accountKey string) (*SharedKeyCredential, error) { + return exported.NewSharedKeyCredential(accountName, accountKey) +} + +// --------------------------------------------------------------------------------------------------------------------- + +// CreateOptions contains the optional parameters for the Client.Create method. +type CreateOptions struct { + // Specifies the access tier of the share. + AccessTier *AccessTier + // Protocols to enable on the share. + EnabledProtocols *string + // A name-value pair to associate with a file storage object. + Metadata map[string]*string + // Specifies the maximum size of the share, in gigabytes. + Quota *int32 + // Root squash to set on the share. Only valid for NFS shares. + RootSquash *RootSquash +} + +func (o *CreateOptions) format() *generated.ShareClientCreateOptions { + if o == nil { + return nil + } + + return &generated.ShareClientCreateOptions{ + AccessTier: o.AccessTier, + EnabledProtocols: o.EnabledProtocols, + Metadata: o.Metadata, + Quota: o.Quota, + RootSquash: o.RootSquash, + } +} + +// --------------------------------------------------------------------------------------------------------------------- + +// DeleteOptions contains the optional parameters for the Client.Delete method. +type DeleteOptions struct { + // Specifies the option include to delete the base share and all of its snapshots. + DeleteSnapshots *DeleteSnapshotsOptionType + // The snapshot parameter is an opaque DateTime value that, when present, specifies the share snapshot to query. + ShareSnapshot *string + // LeaseAccessConditions contains optional parameters to access leased entity. + LeaseAccessConditions *LeaseAccessConditions +} + +func (o *DeleteOptions) format() (*generated.ShareClientDeleteOptions, *LeaseAccessConditions) { + if o == nil { + return nil, nil + } + + return &generated.ShareClientDeleteOptions{ + DeleteSnapshots: o.DeleteSnapshots, + Sharesnapshot: o.ShareSnapshot, + }, o.LeaseAccessConditions +} + +// LeaseAccessConditions contains optional parameters to access leased entity. +type LeaseAccessConditions = generated.LeaseAccessConditions + +// --------------------------------------------------------------------------------------------------------------------- + +// RestoreOptions contains the optional parameters for the Client.Restore method. +type RestoreOptions struct { + // placeholder for future options +} + +// --------------------------------------------------------------------------------------------------------------------- + +// GetPropertiesOptions contains the optional parameters for the Client.GetProperties method. +type GetPropertiesOptions struct { + // The snapshot parameter is an opaque DateTime value that, when present, specifies the share snapshot to query. + ShareSnapshot *string + // LeaseAccessConditions contains optional parameters to access leased entity. + LeaseAccessConditions *LeaseAccessConditions +} + +func (o *GetPropertiesOptions) format() (*generated.ShareClientGetPropertiesOptions, *LeaseAccessConditions) { + if o == nil { + return nil, nil + } + + return &generated.ShareClientGetPropertiesOptions{ + Sharesnapshot: o.ShareSnapshot, + }, o.LeaseAccessConditions +} + +// --------------------------------------------------------------------------------------------------------------------- + +// SetPropertiesOptions contains the optional parameters for the Client.SetProperties method. +type SetPropertiesOptions struct { + // Specifies the access tier of the share. + AccessTier *AccessTier + // Specifies the maximum size of the share, in gigabytes. + Quota *int32 + // Root squash to set on the share. Only valid for NFS shares. + RootSquash *RootSquash + // LeaseAccessConditions contains optional parameters to access leased entity. + LeaseAccessConditions *LeaseAccessConditions +} + +func (o *SetPropertiesOptions) format() (*generated.ShareClientSetPropertiesOptions, *LeaseAccessConditions) { + if o == nil { + return nil, nil + } + + return &generated.ShareClientSetPropertiesOptions{ + AccessTier: o.AccessTier, + Quota: o.Quota, + RootSquash: o.RootSquash, + }, o.LeaseAccessConditions +} + +// --------------------------------------------------------------------------------------------------------------------- + +// CreateSnapshotOptions contains the optional parameters for the Client.CreateSnapshot method. +type CreateSnapshotOptions struct { + // A name-value pair to associate with a file storage object. + Metadata map[string]*string +} + +func (o *CreateSnapshotOptions) format() *generated.ShareClientCreateSnapshotOptions { + if o == nil { + return nil + } + + return &generated.ShareClientCreateSnapshotOptions{ + Metadata: o.Metadata, + } +} + +// --------------------------------------------------------------------------------------------------------------------- + +// GetAccessPolicyOptions contains the optional parameters for the Client.GetAccessPolicy method. +type GetAccessPolicyOptions struct { + // LeaseAccessConditions contains optional parameters to access leased entity. + LeaseAccessConditions *LeaseAccessConditions +} + +func (o *GetAccessPolicyOptions) format() (*generated.ShareClientGetAccessPolicyOptions, *LeaseAccessConditions) { + if o == nil { + return nil, nil + } + + return nil, o.LeaseAccessConditions +} + +// SignedIdentifier - Signed identifier. +type SignedIdentifier = generated.SignedIdentifier + +// AccessPolicy - An Access policy. +type AccessPolicy = generated.AccessPolicy + +// AccessPolicyPermission type simplifies creating the permissions string for a share's access policy. +// Initialize an instance of this type and then call its String method to set AccessPolicy's permission field. +type AccessPolicyPermission = exported.AccessPolicyPermission + +// --------------------------------------------------------------------------------------------------------------------- + +// SetAccessPolicyOptions contains the optional parameters for the Client.SetAccessPolicy method. +type SetAccessPolicyOptions struct { + // Specifies the ACL for the share. + ShareACL []*SignedIdentifier + // LeaseAccessConditions contains optional parameters to access leased entity. + LeaseAccessConditions *LeaseAccessConditions +} + +func (o *SetAccessPolicyOptions) format() (*generated.ShareClientSetAccessPolicyOptions, []*SignedIdentifier, *LeaseAccessConditions, error) { + if o == nil { + return nil, nil, nil, nil + } + + if o.ShareACL != nil { + for _, si := range o.ShareACL { + err := formatTime(si) + if err != nil { + return nil, nil, nil, err + } + } + } + + return nil, o.ShareACL, o.LeaseAccessConditions, nil +} + +func formatTime(si *SignedIdentifier) error { + if si.AccessPolicy == nil { + return nil + } + + if si.AccessPolicy.Start != nil { + st, err := time.Parse(time.RFC3339, si.AccessPolicy.Start.UTC().Format(time.RFC3339)) + if err != nil { + return err + } + si.AccessPolicy.Start = &st + } + if si.AccessPolicy.Expiry != nil { + et, err := time.Parse(time.RFC3339, si.AccessPolicy.Expiry.UTC().Format(time.RFC3339)) + if err != nil { + return err + } + si.AccessPolicy.Expiry = &et + } + + return nil +} + +// --------------------------------------------------------------------------------------------------------------------- + +// CreatePermissionOptions contains the optional parameters for the Client.CreatePermission method. +type CreatePermissionOptions struct { + // placeholder for future options +} + +func (o *CreatePermissionOptions) format(sharePermission string) (Permission, *generated.ShareClientCreatePermissionOptions) { + return Permission{ + Permission: &sharePermission, + }, nil +} + +// Permission - A permission (a security descriptor) at the share level. +type Permission = generated.SharePermission + +// --------------------------------------------------------------------------------------------------------------------- + +// GetPermissionOptions contains the optional parameters for the Client.GetPermission method. +type GetPermissionOptions struct { + // placeholder for future options +} + +func (o *GetPermissionOptions) format() *generated.ShareClientGetPermissionOptions { + return nil +} + +// --------------------------------------------------------------------------------------------------------------------- + +// SetMetadataOptions contains the optional parameters for the Client.SetMetadata method. +type SetMetadataOptions struct { + // A name-value pair to associate with a file storage object. + Metadata map[string]*string + // LeaseAccessConditions contains optional parameters to access leased entity. + LeaseAccessConditions *LeaseAccessConditions +} + +func (o *SetMetadataOptions) format() (*generated.ShareClientSetMetadataOptions, *LeaseAccessConditions) { + if o == nil { + return nil, nil + } + + return &generated.ShareClientSetMetadataOptions{ + Metadata: o.Metadata, + }, o.LeaseAccessConditions +} + +// --------------------------------------------------------------------------------------------------------------------- + +// GetStatisticsOptions contains the optional parameters for the Client.GetStatistics method. +type GetStatisticsOptions struct { + // LeaseAccessConditions contains optional parameters to access leased entity. + LeaseAccessConditions *LeaseAccessConditions +} + +func (o *GetStatisticsOptions) format() (*generated.ShareClientGetStatisticsOptions, *LeaseAccessConditions) { + if o == nil { + return nil, nil + } + + return nil, o.LeaseAccessConditions +} + +// Stats - Stats for the share. +type Stats = generated.ShareStats + +// --------------------------------------------------------------------------------------------------------------------- + +// GetSASURLOptions contains the optional parameters for the Client.GetSASURL method. +type GetSASURLOptions struct { + StartTime *time.Time +} + +func (o *GetSASURLOptions) format() time.Time { + if o == nil { + return time.Time{} + } + + var st time.Time + if o.StartTime != nil { + st = o.StartTime.UTC() + } else { + st = time.Time{} + } + return st +} diff --git a/sdk/storage/azfile/share/responses.go b/sdk/storage/azfile/share/responses.go new file mode 100644 index 000000000000..2932e7ec93a9 --- /dev/null +++ b/sdk/storage/azfile/share/responses.go @@ -0,0 +1,45 @@ +//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 share + +import "github.com/Azure/azure-sdk-for-go/sdk/storage/azfile/internal/generated" + +// CreateResponse contains the response from method Client.Create. +type CreateResponse = generated.ShareClientCreateResponse + +// DeleteResponse contains the response from method Client.Delete. +type DeleteResponse = generated.ShareClientDeleteResponse + +// RestoreResponse contains the response from method Client.Restore. +type RestoreResponse = generated.ShareClientRestoreResponse + +// GetPropertiesResponse contains the response from method Client.GetProperties. +type GetPropertiesResponse = generated.ShareClientGetPropertiesResponse + +// SetPropertiesResponse contains the response from method Client.SetProperties. +type SetPropertiesResponse = generated.ShareClientSetPropertiesResponse + +// CreateSnapshotResponse contains the response from method Client.CreateSnapshot. +type CreateSnapshotResponse = generated.ShareClientCreateSnapshotResponse + +// GetAccessPolicyResponse contains the response from method Client.GetAccessPolicy. +type GetAccessPolicyResponse = generated.ShareClientGetAccessPolicyResponse + +// SetAccessPolicyResponse contains the response from method Client.SetAccessPolicy. +type SetAccessPolicyResponse = generated.ShareClientSetAccessPolicyResponse + +// CreatePermissionResponse contains the response from method Client.CreatePermission. +type CreatePermissionResponse = generated.ShareClientCreatePermissionResponse + +// GetPermissionResponse contains the response from method Client.GetPermission. +type GetPermissionResponse = generated.ShareClientGetPermissionResponse + +// SetMetadataResponse contains the response from method Client.SetMetadata. +type SetMetadataResponse = generated.ShareClientSetMetadataResponse + +// GetStatisticsResponse contains the response from method Client.GetStatistics. +type GetStatisticsResponse = generated.ShareClientGetStatisticsResponse diff --git a/sdk/storage/azfile/test-resources.json b/sdk/storage/azfile/test-resources.json new file mode 100644 index 000000000000..c6259f7ab02f --- /dev/null +++ b/sdk/storage/azfile/test-resources.json @@ -0,0 +1,579 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "baseName": { + "type": "String" + }, + "tenantId": { + "type": "string", + "defaultValue": "72f988bf-86f1-41af-91ab-2d7cd011db47", + "metadata": { + "description": "The tenant ID to which the application and resources belong." + } + }, + "testApplicationOid": { + "type": "string", + "metadata": { + "description": "The principal to assign the role to. This is application object id." + } + } + }, + "variables": { + "mgmtApiVersion": "2022-09-01", + "authorizationApiVersion": "2018-09-01-preview", + "blobDataContributorRoleId": "[concat('/subscriptions/', subscription().subscriptionId, '/providers/Microsoft.Authorization/roleDefinitions/ba92f5b4-2d11-453d-a403-e96b0029c9fe')]", + "contributorRoleId": "[concat('/subscriptions/', subscription().subscriptionId, '/providers/Microsoft.Authorization/roleDefinitions/b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "blobDataOwnerRoleId": "[concat('/subscriptions/', subscription().subscriptionId, '/providers/Microsoft.Authorization/roleDefinitions/b7e6dc6d-f1e8-4753-8033-0f276bb0955b')]", + "primaryAccountName": "[concat(parameters('baseName'), 'prim')]", + "immutableAccountName": "[concat(parameters('baseName'), 'imm')]", + "primaryEncryptionScopeName": "encryptionScope", + "primaryEncryptionScope": "[concat(parameters('baseName'), 'prim', concat('/', variables('primaryEncryptionScopeName')))]", + "secondaryAccountName": "[concat(parameters('baseName'), 'sec')]", + "premiumAccountName": "[concat(parameters('baseName'), 'prem')]", + "dataLakeAccountName": "[concat(parameters('baseName'), 'dtlk')]", + "softDeleteAccountName": "[concat(parameters('baseName'), 'sftdl')]", + "premiumFileAccountName": "[concat(parameters('baseName'), 'pfile')]", + "webjobsPrimaryAccountName": "[concat(parameters('baseName'), 'wjprim')]", + "webjobsSecondaryAccountName": "[concat(parameters('baseName'), 'wjsec')]", + "location": "[resourceGroup().location]", + "resourceGroupName": "[resourceGroup().name]", + "subscriptionId": "[subscription().subscriptionId]", + "encryption": { + "services": { + "file": { + "enabled": true + }, + "blob": { + "enabled": true + } + }, + "keySource": "Microsoft.Storage" + }, + "networkAcls": { + "bypass": "AzureServices", + "virtualNetworkRules": [], + "ipRules": [], + "defaultAction": "Allow" + } + }, + "resources": [ + { + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "[variables('authorizationApiVersion')]", + "name": "[guid(concat('dataContributorRoleId', resourceGroup().id))]", + "properties": { + "roleDefinitionId": "[variables('blobDataContributorRoleId')]", + "principalId": "[parameters('testApplicationOid')]" + } + }, + { + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "[variables('authorizationApiVersion')]", + "name": "[guid(concat('contributorRoleId', resourceGroup().id))]", + "properties": { + "roleDefinitionId": "[variables('contributorRoleId')]", + "principalId": "[parameters('testApplicationOid')]" + } + }, + { + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "[variables('authorizationApiVersion')]", + "name": "[guid(concat('blobDataOwnerRoleId', resourceGroup().id))]", + "properties": { + "roleDefinitionId": "[variables('blobDataOwnerRoleId')]", + "principalId": "[parameters('testApplicationOid')]" + } + }, + { + "type": "Microsoft.Storage/storageAccounts", + "apiVersion": "[variables('mgmtApiVersion')]", + "name": "[variables('primaryAccountName')]", + "location": "[variables('location')]", + "sku": { + "name": "Standard_RAGRS", + "tier": "Standard" + }, + "kind": "StorageV2", + "properties": { + "networkAcls": "[variables('networkAcls')]", + "supportsHttpsTrafficOnly": true, + "encryption": "[variables('encryption')]", + "accessTier": "Hot" + } + }, + { + "type": "Microsoft.Storage/storageAccounts/blobServices", + "apiVersion": "[variables('mgmtApiVersion')]", + "name": "[concat(variables('primaryAccountName'), '/default')]", + "properties": { + "isVersioningEnabled": true, + "lastAccessTimeTrackingPolicy": { + "enable": true, + "name": "AccessTimeTracking", + "trackingGranularityInDays": 1, + "blobType": [ + "blockBlob" + ] + } + }, + "dependsOn": [ + "[variables('primaryAccountName')]" + ] + }, + { + "type": "Microsoft.Storage/storageAccounts", + "apiVersion": "[variables('mgmtApiVersion')]", + "name": "[variables('immutableAccountName')]", + "location": "[variables('location')]", + "sku": { + "name": "Standard_RAGRS", + "tier": "Standard" + }, + "kind": "StorageV2", + "properties": { + "networkAcls": "[variables('networkAcls')]", + "supportsHttpsTrafficOnly": true, + "encryption": "[variables('encryption')]", + "accessTier": "Hot", + "immutableStorageWithVersioning": { + "enabled": true + } + } + }, + { + "type": "Microsoft.Storage/storageAccounts/blobServices", + "apiVersion": "[variables('mgmtApiVersion')]", + "name": "[concat(variables('immutableAccountName'), '/default')]", + "properties": { + "isVersioningEnabled": true, + "lastAccessTimeTrackingPolicy": { + "enable": true, + "name": "AccessTimeTracking", + "trackingGranularityInDays": 1, + "blobType": [ + "blockBlob" + ] + } + }, + "dependsOn": [ + "[variables('immutableAccountName')]" + ] + }, + { + "type": "Microsoft.Storage/storageAccounts/encryptionScopes", + "apiVersion": "[variables('mgmtApiVersion')]", + "name": "[variables('primaryEncryptionScope')]", + "properties": { + "source": "Microsoft.Storage", + "state": "Enabled" + }, + "dependsOn": [ + "[variables('primaryAccountName')]" + ] + }, + { + "type": "Microsoft.Storage/storageAccounts", + "apiVersion": "[variables('mgmtApiVersion')]", + "name": "[variables('secondaryAccountName')]", + "location": "[variables('location')]", + "sku": { + "name": "Standard_RAGRS", + "tier": "Standard" + }, + "kind": "StorageV2", + "properties": { + "networkAcls": "[variables('networkAcls')]", + "supportsHttpsTrafficOnly": true, + "encryption": "[variables('encryption')]", + "accessTier": "Hot" + } + }, + { + "type": "Microsoft.Storage/storageAccounts", + "apiVersion": "[variables('mgmtApiVersion')]", + "name": "[variables('premiumAccountName')]", + "location": "[variables('location')]", + "sku": { + "name": "Premium_LRS", + "tier": "Premium" + }, + "kind": "StorageV2", + "properties": { + "networkAcls": "[variables('networkAcls')]", + "supportsHttpsTrafficOnly": true, + "encryption": "[variables('encryption')]", + "accessTier": "Hot" + } + }, + { + "type": "Microsoft.Storage/storageAccounts", + "apiVersion": "[variables('mgmtApiVersion')]", + "name": "[variables('dataLakeAccountName')]", + "location": "[variables('location')]", + "sku": { + "name": "Standard_RAGRS", + "tier": "Standard" + }, + "kind": "StorageV2", + "properties": { + "isHnsEnabled": true, + "networkAcls": "[variables('networkAcls')]", + "supportsHttpsTrafficOnly": true, + "encryption": "[variables('encryption')]", + "accessTier": "Hot" + } + }, + { + "type": "Microsoft.Storage/storageAccounts/blobServices", + "apiVersion": "[variables('mgmtApiVersion')]", + "name": "[concat(variables('dataLakeAccountName'), '/default')]", + "properties": { + "containerDeleteRetentionPolicy": { + "enabled": true, + "days": 1 + } + }, + "dependsOn": [ + "[variables('dataLakeAccountName')]" + ] + }, + { + "type": "Microsoft.Storage/storageAccounts", + "apiVersion": "[variables('mgmtApiVersion')]", + "name": "[variables('softDeleteAccountName')]", + "location": "[variables('location')]", + "sku": { + "name": "Standard_RAGRS", + "tier": "Standard" + }, + "kind": "StorageV2", + "properties": { + "networkAcls": "[variables('networkAcls')]", + "supportsHttpsTrafficOnly": true, + "encryption": "[variables('encryption')]", + "accessTier": "Hot" + } + }, + { + "type": "Microsoft.Storage/storageAccounts/blobServices", + "apiVersion": "[variables('mgmtApiVersion')]", + "name": "[concat(variables('softDeleteAccountName'), '/default')]", + "properties": { + "isVersioningEnabled": true, + "deleteRetentionPolicy": { + "allowPermanentDelete": true, + "enabled": true, + "days": 1 + }, + "containerDeleteRetentionPolicy": { + "enabled": true, + "days": 1 + } + }, + "dependsOn": [ + "[variables('softDeleteAccountName')]" + ] + }, + { + "type": "Microsoft.Storage/storageAccounts/fileServices", + "apiVersion": "[variables('mgmtApiVersion')]", + "name": "[concat(variables('softDeleteAccountName'), '/default')]", + "properties": { + "shareDeleteRetentionPolicy": { + "enabled": true, + "days": 1 + } + }, + "dependsOn": [ + "[variables('softDeleteAccountName')]" + ] + }, + { + "type": "Microsoft.Storage/storageAccounts", + "apiVersion": "[variables('mgmtApiVersion')]", + "name": "[variables('premiumFileAccountName')]", + "location": "[variables('location')]", + "sku": { + "name": "Premium_LRS", + "tier": "Premium" + }, + "kind": "FileStorage", + "properties": { + "networkAcls": "[variables('networkAcls')]", + "supportsHttpsTrafficOnly": true, + "encryption": "[variables('encryption')]", + "accessTier": "Hot" + } + }, + { + "type": "Microsoft.Storage/storageAccounts", + "apiVersion": "[variables('mgmtApiVersion')]", + "name": "[variables('webjobsPrimaryAccountName')]", + "location": "[variables('location')]", + "sku": { + "name": "Standard_RAGRS", + "tier": "Standard" + }, + "kind": "StorageV2", + "properties": { + "networkAcls": "[variables('networkAcls')]", + "supportsHttpsTrafficOnly": true, + "encryption": "[variables('encryption')]", + "accessTier": "Hot" + } + }, + { + "type": "Microsoft.Storage/storageAccounts", + "apiVersion": "[variables('mgmtApiVersion')]", + "name": "[variables('webjobsSecondaryAccountName')]", + "location": "[variables('location')]", + "sku": { + "name": "Standard_RAGRS", + "tier": "Standard" + }, + "kind": "StorageV2", + "properties": { + "networkAcls": "[variables('networkAcls')]", + "supportsHttpsTrafficOnly": true, + "encryption": "[variables('encryption')]", + "accessTier": "Hot" + } + } + ], + "functions": [ + { + "namespace": "url", + "members": { + "serviceEndpointSuffix": { + "parameters": [ + { + "name": "endpoint", + "type": "string" + } + ], + "output": { + "type": "string", + "value": "[substring(parameters('endpoint'), add(indexOf(parameters('endpoint'), '.'),1), sub(length(parameters('endpoint')), add(indexOf(parameters('endpoint'), '.'),2)))]" + } + } + } + }, + { + "namespace": "connectionString", + "members": { + "create": { + "parameters": [ + { + "name": "accountName", + "type": "string" + }, + { + "name": "accountKey", + "type": "string" + }, + { + "name": "blobEndpoint", + "type": "string" + }, + { + "name": "queueEndpoint", + "type": "string" + }, + { + "name": "fileEndpoint", + "type": "string" + }, + { + "name": "tableEndpoint", + "type": "string" + } + ], + "output": { + "type": "string", + "value": "[concat('DefaultEndpointsProtocol=https;AccountName=', parameters('accountName'), ';AccountKey=', parameters('accountKey'), ';BlobEndpoint=', parameters('blobEndpoint'), ';QueueEndpoint=', parameters('queueEndpoint'), ';FileEndpoint=', parameters('fileEndpoint'), ';TableEndpoint=', parameters('tableEndpoint'))]" + } + } + } + } + ], + "outputs": { + "AZURE_STORAGE_ACCOUNT_NAME": { + "type": "string", + "value": "[variables('primaryAccountName')]" + }, + "AZURE_STORAGE_ACCOUNT_KEY": { + "type": "string", + "value": "[listKeys(resourceId('Microsoft.Storage/storageAccounts', variables('primaryAccountName')), variables('mgmtApiVersion')).keys[0].value]" + }, + "PRIMARY_STORAGE_ACCOUNT_BLOB_ENDPOINT_SUFFIX": { + "type": "string", + "value": "[url.serviceEndpointSuffix(reference(resourceId('Microsoft.Storage/storageAccounts', variables('primaryAccountName')), variables('mgmtApiVersion')).primaryEndpoints.blob)]" + }, + "PRIMARY_STORAGE_ACCOUNT_FILE_ENDPOINT_SUFFIX": { + "type": "string", + "value": "[url.serviceEndpointSuffix(reference(resourceId('Microsoft.Storage/storageAccounts', variables('primaryAccountName')), variables('mgmtApiVersion')).primaryEndpoints.file)]" + }, + "PRIMARY_STORAGE_ACCOUNT_QUEUE_ENDPOINT_SUFFIX": { + "type": "string", + "value": "[url.serviceEndpointSuffix(reference(resourceId('Microsoft.Storage/storageAccounts', variables('primaryAccountName')), variables('mgmtApiVersion')).primaryEndpoints.queue)]" + }, + "PRIMARY_STORAGE_ACCOUNT_TABLE_ENDPOINT_SUFFIX": { + "type": "string", + "value": "[url.serviceEndpointSuffix(reference(resourceId('Microsoft.Storage/storageAccounts', variables('primaryAccountName')), variables('mgmtApiVersion')).primaryEndpoints.table)]" + }, + "SECONDARY_AZURE_STORAGE_ACCOUNT_NAME": { + "type": "string", + "value": "[variables('secondaryAccountName')]" + }, + "SECONDARY_AZURE_STORAGE_ACCOUNT_KEY": { + "type": "string", + "value": "[listKeys(resourceId('Microsoft.Storage/storageAccounts', variables('secondaryAccountName')), variables('mgmtApiVersion')).keys[0].value]" + }, + "SECONDARY_STORAGE_ACCOUNT_BLOB_ENDPOINT_SUFFIX": { + "type": "string", + "value": "[url.serviceEndpointSuffix(reference(resourceId('Microsoft.Storage/storageAccounts', variables('secondaryAccountName')), variables('mgmtApiVersion')).primaryEndpoints.blob)]" + }, + "SECONDARY_STORAGE_ACCOUNT_FILE_ENDPOINT_SUFFIX": { + "type": "string", + "value": "[url.serviceEndpointSuffix(reference(resourceId('Microsoft.Storage/storageAccounts', variables('secondaryAccountName')), variables('mgmtApiVersion')).primaryEndpoints.file)]" + }, + "SECONDARY_STORAGE_ACCOUNT_QUEUE_ENDPOINT_SUFFIX": { + "type": "string", + "value": "[url.serviceEndpointSuffix(reference(resourceId('Microsoft.Storage/storageAccounts', variables('secondaryAccountName')), variables('mgmtApiVersion')).primaryEndpoints.queue)]" + }, + "SECONDARY_STORAGE_ACCOUNT_TABLE_ENDPOINT_SUFFIX": { + "type": "string", + "value": "[url.serviceEndpointSuffix(reference(resourceId('Microsoft.Storage/storageAccounts', variables('secondaryAccountName')), variables('mgmtApiVersion')).primaryEndpoints.table)]" + }, + "BLOB_STORAGE_ACCOUNT_NAME": { + "type": "string", + "value": "[variables('secondaryAccountName')]" + }, + "BLOB_STORAGE_ACCOUNT_KEY": { + "type": "string", + "value": "[listKeys(resourceId('Microsoft.Storage/storageAccounts', variables('secondaryAccountName')), variables('mgmtApiVersion')).keys[0].value]" + }, + "PREMIUM_AZURE_STORAGE_ACCOUNT_NAME": { + "type": "string", + "value": "[variables('premiumAccountName')]" + }, + "PREMIUM_AZURE_STORAGE_ACCOUNT_KEY": { + "type": "string", + "value": "[listKeys(resourceId('Microsoft.Storage/storageAccounts', variables('premiumAccountName')), variables('mgmtApiVersion')).keys[0].value]" + }, + "PREMIUM_STORAGE_ACCOUNT_BLOB_ENDPOINT_SUFFIX": { + "type": "string", + "value": "[url.serviceEndpointSuffix(reference(resourceId('Microsoft.Storage/storageAccounts', variables('premiumAccountName')), variables('mgmtApiVersion')).primaryEndpoints.blob)]" + }, + "DATALAKE_AZURE_STORAGE_ACCOUNT_NAME": { + "type": "string", + "value": "[variables('dataLakeAccountName')]" + }, + "DATALAKE_AZURE_STORAGE_ACCOUNT_KEY": { + "type": "string", + "value": "[listKeys(resourceId('Microsoft.Storage/storageAccounts', variables('dataLakeAccountName')), variables('mgmtApiVersion')).keys[0].value]" + }, + "DATALAKE_STORAGE_ACCOUNT_BLOB_ENDPOINT_SUFFIX": { + "type": "string", + "value": "[url.serviceEndpointSuffix(reference(resourceId('Microsoft.Storage/storageAccounts', variables('dataLakeAccountName')), variables('mgmtApiVersion')).primaryEndpoints.blob)]" + }, + "DATALAKE_STORAGE_ACCOUNT_FILE_ENDPOINT_SUFFIX": { + "type": "string", + "value": "[url.serviceEndpointSuffix(reference(resourceId('Microsoft.Storage/storageAccounts', variables('dataLakeAccountName')), variables('mgmtApiVersion')).primaryEndpoints.file)]" + }, + "DATALAKE_STORAGE_ACCOUNT_QUEUE_ENDPOINT_SUFFIX": { + "type": "string", + "value": "[url.serviceEndpointSuffix(reference(resourceId('Microsoft.Storage/storageAccounts', variables('dataLakeAccountName')), variables('mgmtApiVersion')).primaryEndpoints.queue)]" + }, + "DATALAKE_STORAGE_ACCOUNT_TABLE_ENDPOINT_SUFFIX": { + "type": "string", + "value": "[url.serviceEndpointSuffix(reference(resourceId('Microsoft.Storage/storageAccounts', variables('dataLakeAccountName')), variables('mgmtApiVersion')).primaryEndpoints.table)]" + }, + "IMMUTABLE_AZURE_STORAGE_ACCOUNT_NAME": { + "type": "string", + "value": "[variables('immutableAccountName')]" + }, + "IMMUTABLE_AZURE_STORAGE_ACCOUNT_KEY": { + "type": "string", + "value": "[listKeys(resourceId('Microsoft.Storage/storageAccounts', variables('immutableAccountName')), variables('mgmtApiVersion')).keys[0].value]" + }, + "IMMUTABLE_AZURE_STORAGE_ACCOUNT_BLOB_ENDPOINT_SUFFIX": { + "type": "string", + "value": "[url.serviceEndpointSuffix(reference(resourceId('Microsoft.Storage/storageAccounts', variables('immutableAccountName')), variables('mgmtApiVersion')).primaryEndpoints.blob)]" + }, + "IMMUTABLE_STORAGE_ACCOUNT_FILE_ENDPOINT_SUFFIX": { + "type": "string", + "value": "[url.serviceEndpointSuffix(reference(resourceId('Microsoft.Storage/storageAccounts', variables('immutableAccountName')), variables('mgmtApiVersion')).primaryEndpoints.file)]" + }, + "IMMUTABLE_AZURE_STORAGE_ACCOUNT_QUEUE_ENDPOINT_SUFFIX": { + "type": "string", + "value": "[url.serviceEndpointSuffix(reference(resourceId('Microsoft.Storage/storageAccounts', variables('immutableAccountName')), variables('mgmtApiVersion')).primaryEndpoints.queue)]" + }, + "IMMUTABLE_AZURE_STORAGE_ACCOUNT_TABLE_ENDPOINT_SUFFIX": { + "type": "string", + "value": "[url.serviceEndpointSuffix(reference(resourceId('Microsoft.Storage/storageAccounts', variables('immutableAccountName')), variables('mgmtApiVersion')).primaryEndpoints.table)]" + }, + "SOFT_DELETE_AZURE_STORAGE_ACCOUNT_NAME": { + "type": "string", + "value": "[variables('softDeleteAccountName')]" + }, + "SOFT_DELETE_AZURE_STORAGE_ACCOUNT_KEY": { + "type": "string", + "value": "[listKeys(resourceId('Microsoft.Storage/storageAccounts', variables('softDeleteAccountName')), variables('mgmtApiVersion')).keys[0].value]" + }, + "SOFT_DELETE_AZURE_STORAGE_ACCOUNT_BLOB_ENDPOINT_SUFFIX": { + "type": "string", + "value": "[url.serviceEndpointSuffix(reference(resourceId('Microsoft.Storage/storageAccounts', variables('softDeleteAccountName')), variables('mgmtApiVersion')).primaryEndpoints.blob)]" + }, + "SOFT_DELETE_AZURE_STORAGE_ACCOUNT_FILE_ENDPOINT_SUFFIX": { + "type": "string", + "value": "[url.serviceEndpointSuffix(reference(resourceId('Microsoft.Storage/storageAccounts', variables('softDeleteAccountName')), variables('mgmtApiVersion')).primaryEndpoints.file)]" + }, + "SOFT_DELETE_AZURE_STORAGE_ACCOUNT_QUEUE_ENDPOINT_SUFFIX": { + "type": "string", + "value": "[url.serviceEndpointSuffix(reference(resourceId('Microsoft.Storage/storageAccounts', variables('softDeleteAccountName')), variables('mgmtApiVersion')).primaryEndpoints.queue)]" + }, + "SOFT_DELETE_AZURE_STORAGE_ACCOUNT_TABLE_ENDPOINT_SUFFIX": { + "type": "string", + "value": "[url.serviceEndpointSuffix(reference(resourceId('Microsoft.Storage/storageAccounts', variables('softDeleteAccountName')), variables('mgmtApiVersion')).primaryEndpoints.table)]" + }, + "PREMIUM_FILE_STORAGE_ACCOUNT_NAME": { + "type": "string", + "value": "[variables('premiumFileAccountName')]" + }, + "PREMIUM_FILE_STORAGE_ACCOUNT_KEY": { + "type": "string", + "value": "[listKeys(resourceId('Microsoft.Storage/storageAccounts', variables('premiumFileAccountName')), variables('mgmtApiVersion')).keys[0].value]" + }, + "PREMIUM_FILE_STORAGE_ACCOUNT_FILE_ENDPOINT_SUFFIX": { + "type": "string", + "value": "[url.serviceEndpointSuffix(reference(resourceId('Microsoft.Storage/storageAccounts', variables('premiumFileAccountName')), variables('mgmtApiVersion')).primaryEndpoints.file)]" + }, + "AZUREWEBJOBSSTORAGE": { + "type": "string", + "value": "[connectionString.create(variables('webjobsPrimaryAccountName'), listKeys(resourceId('Microsoft.Storage/storageAccounts', variables('webjobsPrimaryAccountName')), variables('mgmtApiVersion')).keys[0].value, reference(resourceId('Microsoft.Storage/storageAccounts', variables('webjobsPrimaryAccountName')), variables('mgmtApiVersion')).primaryEndpoints.blob, reference(resourceId('Microsoft.Storage/storageAccounts', variables('webjobsPrimaryAccountName')), variables('mgmtApiVersion')).primaryEndpoints.queue, reference(resourceId('Microsoft.Storage/storageAccounts', variables('webjobsPrimaryAccountName')), variables('mgmtApiVersion')).primaryEndpoints.file, reference(resourceId('Microsoft.Storage/storageAccounts', variables('webjobsPrimaryAccountName')), variables('mgmtApiVersion')).primaryEndpoints.table)]" + }, + "AZUREWEBJOBSSECONDARYSTORAGE": { + "type": "string", + "value": "[connectionString.create(variables('webjobsSecondaryAccountName'), listKeys(resourceId('Microsoft.Storage/storageAccounts', variables('webjobsSecondaryAccountName')), variables('mgmtApiVersion')).keys[0].value, reference(resourceId('Microsoft.Storage/storageAccounts', variables('webjobsSecondaryAccountName')), variables('mgmtApiVersion')).primaryEndpoints.blob, reference(resourceId('Microsoft.Storage/storageAccounts', variables('webjobsSecondaryAccountName')), variables('mgmtApiVersion')).primaryEndpoints.queue, reference(resourceId('Microsoft.Storage/storageAccounts', variables('webjobsSecondaryAccountName')), variables('mgmtApiVersion')).primaryEndpoints.file, reference(resourceId('Microsoft.Storage/storageAccounts', variables('webjobsSecondaryAccountName')), variables('mgmtApiVersion')).primaryEndpoints.table)]" + }, + "RESOURCE_GROUP_NAME": { + "type": "string", + "value": "[variables('resourceGroupName')]" + }, + "SUBSCRIPTION_ID": { + "type": "string", + "value": "[variables('subscriptionId')]" + }, + "LOCATION": { + "type": "string", + "value": "[variables('location')]" + }, + "AZURE_STORAGE_ENCRYPTION_SCOPE": { + "type": "string", + "value": "[variables('primaryEncryptionScopeName')]" + } + } + } + \ No newline at end of file diff --git a/sdk/storage/azqueue/CHANGELOG.md b/sdk/storage/azqueue/CHANGELOG.md index 81127f99b819..af4b82990e16 100644 --- a/sdk/storage/azqueue/CHANGELOG.md +++ b/sdk/storage/azqueue/CHANGELOG.md @@ -1,14 +1,11 @@ ## Release History -### 0.1.1 (Unreleased) +### 1.0.0 (2023-05-09) -#### Features Added - -#### Breaking Changes +### Features Added -#### Bugs Fixed +* This is the initial GA release of the `azqueue` library -#### Other Changes ### 0.1.0 (2023-02-15) diff --git a/sdk/storage/azqueue/README.md b/sdk/storage/azqueue/README.md index 57b55f321701..0877f9ae7637 100644 --- a/sdk/storage/azqueue/README.md +++ b/sdk/storage/azqueue/README.md @@ -204,15 +204,14 @@ Get started with our [Queue samples][samples]. They contain complete examples o See the [Storage CONTRIBUTING.md][storage_contrib] for details on building, testing, and contributing to this library. -This project welcomes contributions and suggestions. Most contributions require -you to agree to a Contributor License Agreement (CLA) declaring that you have -the right to, and actually do, grant us the rights to use your contribution. For -details, visit [cla.microsoft.com][cla]. +This project welcomes contributions and suggestions. Most contributions require you to agree to a [Contributor License Agreement (CLA)][cla] declaring that you have the right to, and actually do, grant us the rights to use your contribution. + +If you'd like to contribute to this library, please read the [contributing guide] [contributing_guide] to learn more about how to build and test the code. + +When you submit a pull request, a CLA-bot will automatically determine whether you need to provide a CLA and decorate the PR appropriately (e.g., label, comment). Simply follow the instructions provided by the bot. You will only need to do this once across all repos using our CLA. + +This project has adopted the [Microsoft Open Source Code of Conduct][coc]. For more information, see the [Code of Conduct FAQ][coc_faq] or contact [opencode@microsoft.com][coc_contact] with any additional questions or comments. -This project has adopted the [Microsoft Open Source Code of Conduct][coc]. -For more information see the [Code of Conduct FAQ][coc_faq] -or contact [opencode@microsoft.com][coc_contact] with any -additional questions or comments. [source]: https://github.com/Azure/azure-sdk-for-go/tree/main/sdk/storage/azqueue @@ -235,7 +234,8 @@ additional questions or comments. [sas]: https://github.com/Azure/azure-sdk-for-go/tree/main/sdk/storage/azqueue/sas [service]: https://github.com/Azure/azure-sdk-for-go/tree/main/sdk/storage/azqueue/service_client.go [storage_contrib]: https://github.com/Azure/azure-sdk-for-go/blob/main/CONTRIBUTING.md +[contributing_guide]: https://github.com/Azure/azure-sdk-for-go/blob/main/CONTRIBUTING.md [cla]: https://cla.microsoft.com [coc]: https://opensource.microsoft.com/codeofconduct/ [coc_faq]: https://opensource.microsoft.com/codeofconduct/faq/ -[coc_contact]: mailto:opencode@microsoft.com +[coc_contact]: mailto:opencode@microsoft.com \ No newline at end of file diff --git a/sdk/storage/azqueue/internal/exported/version.go b/sdk/storage/azqueue/internal/exported/version.go index 9ad8cee51fad..abf66d142113 100644 --- a/sdk/storage/azqueue/internal/exported/version.go +++ b/sdk/storage/azqueue/internal/exported/version.go @@ -8,5 +8,5 @@ package exported const ( ModuleName = "azqueue" - ModuleVersion = "v0.1.1" + ModuleVersion = "v1.0.0" ) From bcd2b4871d158add7e4abcf8836d54c487cfad3f Mon Sep 17 00:00:00 2001 From: Tamer Sherif <69483382+tasherif-msft@users.noreply.github.com> Date: Mon, 12 Jun 2023 10:21:49 -0700 Subject: [PATCH 03/16] AzDatalake APIView (#20757) * Enable gocritic during linting (#20715) Enabled gocritic's evalOrder to catch dependencies on undefined behavior on return statements. Updated to latest version of golangci-lint. Fixed issue in azblob flagged by latest linter. * Cosmos DB: Enable merge support (#20716) * Adding header and value * Wiring and tests * format * Fixing value * change log * [azservicebus, azeventhubs] Stress test and logging improvement (#20710) Logging improvements: * Updating the logging to print more tracing information (per-link) in prep for the bigger release coming up. * Trimming out some of the verbose logging, seeing if I can get it a bit more reasonable. Stress tests: * Add a timestamp to the log name we generate and also default to append, not overwrite. * Use 0.5 cores, 0.5GB as our baseline. Some pods use more and I'll tune them more later. * update proxy version (#20712) Co-authored-by: Scott Beddall * Return an error when you try to send a message that's too large. (#20721) This now works just like the message batch - you'll get an ErrMessageTooLarge if you attempt to send a message that's too large for the link's configured size. NOTE: there's a patch to `internal/go-amqp/Sender.go` to match what's in go-amqp's main so it returns a programmatically useful error when the message is too large. Fixes #20647 * Changes in test that is failing in pipeline (#20693) * [azservicebus, azeventhubs] Treat 'entity full' as a fatal error (#20722) When the remote entity is full we get a resource-limit-exceeded condition. This isn't something we should keep retrying on and it's best to just abort and let the user know immediately, rather than hoping it might eventually clear out. This affected both Event Hubs and Service Bus. Fixes #20647 * [azservicebus/azeventhubs] Redirect stderr and stdout to tee (#20726) * Update changelog with latest features (#20730) * Update changelog with latest features Prepare for upcoming release. * bump minor version * pass along the artifact name so we can override it later (#20732) Co-authored-by: scbedd <45376673+scbedd@users.noreply.github.com> * [azeventhubs] Fixing checkpoint store race condition (#20727) The checkpoint store wasn't guarding against multiple owners claiming for the first time - fixing this by using IfNoneMatch Fixes #20717 * Fix azidentity troubleshooting guide link (#20736) * [Release] sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/0.1.0 (#20437) * [Release] sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/0.1.0 generation from spec commit: 85fb4ac6f8bfefd179e6c2632976a154b5c9ff04 * client factory * fix * fix * update * add sdk/resourcemanager/postgresql/armpostgresql live test (#20685) * add sdk/resourcemanager/postgresql/armpostgresql live test * update assets.json * set subscriptionId default value * format * add sdk/resourcemanager/eventhub/armeventhub live test (#20686) * add sdk/resourcemanager/eventhub/armeventhub live test * update assets * add sdk/resourcemanager/compute/armcompute live test (#20048) * add sdk/resourcemanager/compute/armcompute live test * skus filter * fix subscriptionId default value * fix * gofmt * update recording * sdk/resourcemanager/network/armnetwork live test (#20331) * sdk/resourcemanager/network/armnetwork live test * update subscriptionId default value * update recording * add sdk/resourcemanager/cosmos/armcosmos live test (#20705) * add sdk/resourcemanager/cosmos/armcosmos live test * update assets.json * update assets.json * update assets.json * update assets.json * Increment package version after release of azcore (#20740) * [azeventhubs] Improperly resetting etag in the checkpoint store (#20737) We shouldn't be resetting the etag to nil - it's what we use to enforce a "single winner" when doing ownership claims. The bug here was two-fold: I had bad logic in my previous claim ownership, which I fixed in a previous PR, but we need to reflect that same constraint properly in our in-memory checkpoint store for these tests. * Eng workflows sync and branch cleanup additions (#20743) Co-authored-by: James Suplizio * [azeventhubs] Latest start position can also be inclusive (ie, get the latest message) (#20744) * Update GitHubEventProcessor version and remove pull_request_review procesing (#20751) Co-authored-by: James Suplizio * Rename DisableAuthorityValidationAndInstanceDiscovery (#20746) * added basic fs methods * corrections * fix (#20707) * AzFile (#20739) * azfile: Fixing connection string parsing logic (#20798) * Fixing connection string parse logic * Update README * [azadmin] fix flaky test (#20758) * fix flaky test * charles suggestion * Prepare azidentity v1.3.0 for release (#20756) * Fix broken podman link (#20801) Co-authored-by: Wes Haggard * [azquery] update doc comments (#20755) * update doc comments * update statistics and visualization generation * prep-for-release * Fixed contribution section (#20752) Co-authored-by: Bob Tabor * [azeventhubs,azservicebus] Some API cleanup, renames (#20754) * Adding options to UpdateCheckpoint(), just for future potential expansion * Make Offset an int64, not a *int64 (it's not optional, it'll always come back with ReceivedEvents) * Adding more logging into the checkpoint store. * Point all imports at the production go-amqp * Add supporting features to enable distributed tracing (#20301) (#20708) * Add supporting features to enable distributed tracing This includes new internal pipeline policies and other supporting types. See the changelog for a full description. Added some missing doc comments. * fix linter issue * add net.peer.name trace attribute sequence custom HTTP header policy before logging policy. sequence logging policy after HTTP trace policy. keep body download policy at the end. * add span for iterating over pages * Restore ARM CAE support for azcore beta (#20657) This reverts commit 902097226ff3fe2fc6c3e7fc50d3478350253614. * Upgrade to stable azcore (#20808) * Increment package version after release of data/azcosmos (#20807) * Updating changelog (#20810) * Add fake package to azcore (#20711) * Add fake package to azcore This is the supporting infrastructure for the generated SDK fakes. * fix doc comment * Updating CHANGELOG.md (#20809) * changelog (#20811) * Increment package version after release of storage/azfile (#20813) * Update changelog (azblob) (#20815) * Updating CHANGELOG.md * Update the changelog with correct version * [azquery] migration guide (#20742) * migration guide * Charles feedback * Richard feedback --------- Co-authored-by: Charles Lowell <10964656+chlowell@users.noreply.github.com> * Increment package version after release of monitor/azquery (#20820) * [keyvault] prep for release (#20819) * prep for release * perf tests * update date * more models * changed generated code and added more models * added client files * regenrated and added more models * file and dir clients setup * combined into one package * added listing methods * separated clients * added additional clients * clean up on path client * more cleanup * more models for file client * cleanup * regenerated using new autorest * more models for fs * cleanup imports * further cleanup * lease acc conditions fixes * lease acc conditions fixes * rename methods return type * added lease * cleanup * cleanup * cleanup * added go version * feedback and cleanup * feedback and cleanup * move path to internal and create common * moved access helpers to internal * make access conditions common * cleanup * handled feedback * cleanup * conn string parsing --------- Co-authored-by: Joel Hendrix Co-authored-by: Matias Quaranta Co-authored-by: Richard Park <51494936+richardpark-msft@users.noreply.github.com> Co-authored-by: Azure SDK Bot <53356347+azure-sdk@users.noreply.github.com> Co-authored-by: Scott Beddall Co-authored-by: siminsavani-msft <77068571+siminsavani-msft@users.noreply.github.com> Co-authored-by: scbedd <45376673+scbedd@users.noreply.github.com> Co-authored-by: Charles Lowell <10964656+chlowell@users.noreply.github.com> Co-authored-by: Peng Jiahui <46921893+Alancere@users.noreply.github.com> Co-authored-by: James Suplizio Co-authored-by: Sourav Gupta <98318303+souravgupta-msft@users.noreply.github.com> Co-authored-by: gracewilcox <43627800+gracewilcox@users.noreply.github.com> Co-authored-by: Wes Haggard Co-authored-by: Bob Tabor Co-authored-by: Bob Tabor --- sdk/storage/azdatalake/common.go | 31 +++ sdk/storage/azdatalake/directory/client.go | 72 ++++++ sdk/storage/azdatalake/directory/constants.go | 35 +++ sdk/storage/azdatalake/directory/models.go | 136 ++++++++++ sdk/storage/azdatalake/directory/responses.go | 45 ++++ sdk/storage/azdatalake/file/client.go | 100 ++++++++ sdk/storage/azdatalake/file/constants.go | 42 ++++ sdk/storage/azdatalake/file/models.go | 157 ++++++++++++ sdk/storage/azdatalake/file/responses.go | 48 ++++ sdk/storage/azdatalake/filesystem/client.go | 115 +++++++++ .../azdatalake/filesystem/constants.go | 17 ++ sdk/storage/azdatalake/filesystem/models.go | 142 +++++++++++ .../azdatalake/filesystem/responses.go | 39 +++ sdk/storage/azdatalake/go.mod | 21 +- sdk/storage/azdatalake/go.sum | 38 ++- .../azdatalake/internal/base/clients.go | 24 ++ .../internal/exported/access_policy.go | 67 +++++ .../azdatalake/internal/exported/exported.go | 33 +++ .../internal/exported/set_expiry.go | 71 ++++++ .../exported/shared_key_credential.go | 218 ++++++++++++++++ .../azdatalake/internal/exported/version.go | 12 + .../azdatalake/internal/generated/autorest.md | 155 +++++++++++- .../internal/generated/filesystem_client.go | 23 ++ .../internal/generated/path_client.go | 17 ++ .../internal/generated/service_client.go | 17 ++ .../internal/generated/zz_constants.go | 50 +++- .../generated/zz_filesystem_client.go | 40 ++- .../internal/generated/zz_models.go | 97 ++++--- .../internal/generated/zz_path_client.go | 172 +++++++------ .../internal/generated/zz_response_types.go | 33 +-- .../internal/generated/zz_service_client.go | 19 +- .../azdatalake/internal/path/client.go | 71 ++++++ .../azdatalake/internal/path/constants.go | 43 ++++ .../azdatalake/internal/path/models.go | 227 +++++++++++++++++ .../azdatalake/internal/path/responses.go | 42 ++++ .../internal/shared/access_conditions.go | 56 +++++ .../internal/shared/bytes_writer.go | 30 +++ .../internal/shared/challenge_policy.go | 113 +++++++++ .../internal/shared/section_writer.go | 53 ++++ .../azdatalake/internal/shared/shared.go | 236 ++++++++++++++++++ sdk/storage/azdatalake/lease/constants.go | 51 ++++ .../azdatalake/lease/filesystem_client.go | 81 ++++++ sdk/storage/azdatalake/lease/models.go | 173 +++++++++++++ sdk/storage/azdatalake/lease/path_client.go | 82 ++++++ sdk/storage/azdatalake/lease/responses.go | 39 +++ sdk/storage/azdatalake/service/client.go | 113 +++++++++ sdk/storage/azdatalake/service/models.go | 98 ++++++++ sdk/storage/azdatalake/service/responses.go | 30 +++ 48 files changed, 3435 insertions(+), 189 deletions(-) create mode 100644 sdk/storage/azdatalake/common.go create mode 100644 sdk/storage/azdatalake/directory/client.go create mode 100644 sdk/storage/azdatalake/directory/constants.go create mode 100644 sdk/storage/azdatalake/directory/models.go create mode 100644 sdk/storage/azdatalake/directory/responses.go create mode 100644 sdk/storage/azdatalake/file/client.go create mode 100644 sdk/storage/azdatalake/file/constants.go create mode 100644 sdk/storage/azdatalake/file/models.go create mode 100644 sdk/storage/azdatalake/file/responses.go create mode 100644 sdk/storage/azdatalake/filesystem/client.go create mode 100644 sdk/storage/azdatalake/filesystem/constants.go create mode 100644 sdk/storage/azdatalake/filesystem/models.go create mode 100644 sdk/storage/azdatalake/filesystem/responses.go create mode 100644 sdk/storage/azdatalake/internal/base/clients.go create mode 100644 sdk/storage/azdatalake/internal/exported/access_policy.go create mode 100644 sdk/storage/azdatalake/internal/exported/exported.go create mode 100644 sdk/storage/azdatalake/internal/exported/set_expiry.go create mode 100644 sdk/storage/azdatalake/internal/exported/shared_key_credential.go create mode 100644 sdk/storage/azdatalake/internal/exported/version.go create mode 100644 sdk/storage/azdatalake/internal/generated/filesystem_client.go create mode 100644 sdk/storage/azdatalake/internal/generated/path_client.go create mode 100644 sdk/storage/azdatalake/internal/generated/service_client.go create mode 100644 sdk/storage/azdatalake/internal/path/client.go create mode 100644 sdk/storage/azdatalake/internal/path/constants.go create mode 100644 sdk/storage/azdatalake/internal/path/models.go create mode 100644 sdk/storage/azdatalake/internal/path/responses.go create mode 100644 sdk/storage/azdatalake/internal/shared/access_conditions.go create mode 100644 sdk/storage/azdatalake/internal/shared/bytes_writer.go create mode 100644 sdk/storage/azdatalake/internal/shared/challenge_policy.go create mode 100644 sdk/storage/azdatalake/internal/shared/section_writer.go create mode 100644 sdk/storage/azdatalake/internal/shared/shared.go create mode 100644 sdk/storage/azdatalake/lease/constants.go create mode 100644 sdk/storage/azdatalake/lease/filesystem_client.go create mode 100644 sdk/storage/azdatalake/lease/models.go create mode 100644 sdk/storage/azdatalake/lease/path_client.go create mode 100644 sdk/storage/azdatalake/lease/responses.go create mode 100644 sdk/storage/azdatalake/service/client.go create mode 100644 sdk/storage/azdatalake/service/models.go create mode 100644 sdk/storage/azdatalake/service/responses.go diff --git a/sdk/storage/azdatalake/common.go b/sdk/storage/azdatalake/common.go new file mode 100644 index 000000000000..32a7862e8256 --- /dev/null +++ b/sdk/storage/azdatalake/common.go @@ -0,0 +1,31 @@ +//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 azdatalake + +import ( + "github.com/Azure/azure-sdk-for-go/sdk/azcore" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/internal/generated" +) + +// ClientOptions contains the optional parameters when creating a Client. +type ClientOptions struct { + azcore.ClientOptions +} + +const SnapshotTimeFormat = "2006-01-02T15:04:05.0000000Z07:00" + +// AccessConditions identifies container-specific access conditions which you optionally set. +type AccessConditions struct { + ModifiedAccessConditions *ModifiedAccessConditions + LeaseAccessConditions *LeaseAccessConditions +} + +// LeaseAccessConditions contains optional parameters to access leased entity. +type LeaseAccessConditions = generated.LeaseAccessConditions + +// ModifiedAccessConditions contains a group of parameters for specifying access conditions. +type ModifiedAccessConditions = generated.ModifiedAccessConditions diff --git a/sdk/storage/azdatalake/directory/client.go b/sdk/storage/azdatalake/directory/client.go new file mode 100644 index 000000000000..f376ad4ec7b8 --- /dev/null +++ b/sdk/storage/azdatalake/directory/client.go @@ -0,0 +1,72 @@ +//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 + +import ( + "context" + "github.com/Azure/azure-sdk-for-go/sdk/azcore" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/internal/path" +) + +// Client represents a URL to the Azure Datalake Storage service allowing you to manipulate datalake directories. +type Client struct { + path.Client +} + +// NewClient creates an instance of Client with the specified values. +// - serviceURL - the URL of the storage account e.g. https://.dfs.core.windows.net/ +// - cred - an Azure AD credential, typically obtained via the azidentity module +// - options - client options; pass nil to accept the default values +func NewClient(serviceURL string, cred azcore.TokenCredential, options *azdatalake.ClientOptions) (*Client, error) { + return nil, nil +} + +// NewClientWithNoCredential creates an instance of Client with the specified values. +// This is used to anonymously access a storage account or with a shared access signature (SAS) token. +// - serviceURL - the URL of the storage account e.g. https://.dfs.core.windows.net/? +// - options - client options; pass nil to accept the default values +func NewClientWithNoCredential(serviceURL string, options *azdatalake.ClientOptions) (*Client, error) { + return nil, nil +} + +// NewClientWithSharedKeyCredential creates an instance of Client with the specified values. +// - serviceURL - the URL of the storage account e.g. https://.dfs.core.windows.net/ +// - cred - a SharedKeyCredential created with the matching storage account and access key +// - options - client options; pass nil to accept the default values +func NewClientWithSharedKeyCredential(serviceURL string, cred *SharedKeyCredential, options *azdatalake.ClientOptions) (*Client, error) { + return nil, nil +} + +// NewClientFromConnectionString creates an instance of Client with the specified values. +// - connectionString - a connection string for the desired storage account +// - options - client options; pass nil to accept the default values +func NewClientFromConnectionString(connectionString string, options *azdatalake.ClientOptions) (*Client, error) { + return nil, nil +} + +// Create creates a new directory (dfs1). +func (d *Client) Create(ctx context.Context, options *CreateOptions) (CreateResponse, error) { + return CreateResponse{}, nil +} + +// Delete removes the directory (dfs1). +func (d *Client) Delete(ctx context.Context, options *DeleteOptions) (DeleteResponse, error) { + //TODO: pass recursive = true + return DeleteResponse{}, nil +} + +// GetProperties returns the properties of the directory (blob3). #TODO: we may just move this method to path client +func (d *Client) GetProperties(ctx context.Context, options *GetPropertiesOptions) (GetPropertiesResponse, error) { + // TODO: format blob response to path response + return GetPropertiesResponse{}, nil +} + +// Rename renames the directory (dfs1). +func (d *Client) Rename(ctx context.Context, newName string, options *RenameOptions) (RenameResponse, error) { + return RenameResponse{}, nil +} diff --git a/sdk/storage/azdatalake/directory/constants.go b/sdk/storage/azdatalake/directory/constants.go new file mode 100644 index 000000000000..70e675e9f10a --- /dev/null +++ b/sdk/storage/azdatalake/directory/constants.go @@ -0,0 +1,35 @@ +//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 + +import ( + "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/internal/path" +) + +// RenameMode defines the rename mode for RenameDirectory +type RenameMode = path.RenameMode + +const ( + RenameModeLegacy RenameMode = path.RenameModeLegacy + RenameModePosix RenameMode = path.RenameModePosix +) + +// SetAccessControlRecursiveMode defines the set access control recursive mode for SetAccessControlRecursive +type SetAccessControlRecursiveMode = path.SetAccessControlRecursiveMode + +const ( + SetAccessControlRecursiveModeSet SetAccessControlRecursiveMode = path.SetAccessControlRecursiveModeSet + SetAccessControlRecursiveModeModify SetAccessControlRecursiveMode = path.SetAccessControlRecursiveModeModify + SetAccessControlRecursiveModeRemove SetAccessControlRecursiveMode = path.SetAccessControlRecursiveModeRemove +) + +type EncryptionAlgorithmType = path.EncryptionAlgorithmType + +const ( + EncryptionAlgorithmTypeNone EncryptionAlgorithmType = path.EncryptionAlgorithmTypeNone + EncryptionAlgorithmTypeAES256 EncryptionAlgorithmType = path.EncryptionAlgorithmTypeAES256 +) diff --git a/sdk/storage/azdatalake/directory/models.go b/sdk/storage/azdatalake/directory/models.go new file mode 100644 index 000000000000..4be9c742e337 --- /dev/null +++ b/sdk/storage/azdatalake/directory/models.go @@ -0,0 +1,136 @@ +//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 + +import ( + "github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/blob" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake" + "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" + "time" +) + +// CreateOptions contains the optional parameters when calling the Create operation. dfs endpoint +type CreateOptions struct { + // AccessConditions contains parameters for accessing the file. + AccessConditions *azdatalake.AccessConditions + // Metadata is a map of name-value pairs to associate with the file storage object. + Metadata map[string]*string + // CPKInfo contains a group of parameters for client provided encryption key. + CPKInfo *CPKInfo + // HTTPHeaders contains the HTTP headers for path operations. + HTTPHeaders *HTTPHeaders + //PathExpiryOptions *ExpiryOptions + // LeaseDuration specifies the duration of the lease. + LeaseDuration *time.Duration + // ProposedLeaseID specifies the proposed lease ID for the file. + ProposedLeaseID *string + // Permissions is the octal representation of the permissions for user, group and mask. + Permissions *string + // Umask is the umask for the file. + Umask *string + // Owner is the owner of the file. + Owner *string + // Group is the owning group of the file. + Group *string + // ACL is the access control list for the file. + 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 + leaseAccessConditions, modifiedAccessConditions := shared.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, + } + return leaseAccessConditions, modifiedAccessConditions, httpHeaders, nil +} + +// DeleteOptions contains the optional parameters when calling the Delete operation. dfs endpoint +type DeleteOptions struct { + // AccessConditions specifies parameters for accessing the directory + AccessConditions *azdatalake.AccessConditions +} + +func (o *DeleteOptions) format() (*generated.LeaseAccessConditions, *generated.ModifiedAccessConditions, error) { + leaseAccessConditions, modifiedAccessConditions := shared.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 *azdatalake.AccessConditions +} + +// GetPropertiesOptions contains the optional parameters for the Client.GetProperties method +type GetPropertiesOptions struct { + AccessConditions *azdatalake.AccessConditions + CPKInfo *CPKInfo +} + +func (o *GetPropertiesOptions) format() *blob.GetPropertiesOptions { + if o == nil { + return nil + } + accessConditions := shared.FormatBlobAccessConditions(o.AccessConditions) + return &blob.GetPropertiesOptions{ + AccessConditions: accessConditions, + CPKInfo: &blob.CPKInfo{ + EncryptionKey: o.CPKInfo.EncryptionKey, + EncryptionAlgorithm: o.CPKInfo.EncryptionAlgorithm, + EncryptionKeySHA256: o.CPKInfo.EncryptionKeySHA256, + }, + } +} + +// ===================================== PATH IMPORTS =========================================== + +// CPKInfo contains a group of parameters for client provided encryption key. +type CPKInfo = path.CPKInfo + +// CPKScopeInfo contains a group of parameters for client provided encryption scope. +type CPKScopeInfo = path.CPKScopeInfo + +// HTTPHeaders contains the HTTP headers for path operations. +type HTTPHeaders = path.HTTPHeaders + +// SourceModifiedAccessConditions identifies the source path access conditions. +type SourceModifiedAccessConditions = path.SourceModifiedAccessConditions + +// SetAccessControlOptions contains the optional parameters when calling the SetAccessControl operation. +type SetAccessControlOptions = path.SetAccessControlOptions + +// GetAccessControlOptions contains the optional parameters when calling the GetAccessControl operation. +type GetAccessControlOptions = path.GetAccessControlOptions + +// SetAccessControlRecursiveOptions contains the optional parameters when calling the SetAccessControlRecursive operation. +type SetAccessControlRecursiveOptions = path.SetAccessControlRecursiveOptions + +// SetMetadataOptions contains the optional parameters when calling the SetMetadata operation. +type SetMetadataOptions = path.SetMetadataOptions + +// SetHTTPHeadersOptions contains the optional parameters when calling the SetHTTPHeaders operation. +type SetHTTPHeadersOptions = path.SetHTTPHeadersOptions + +// RemoveAccessControlRecursiveOptions contains the optional parameters when calling the RemoveAccessControlRecursive operation. +type RemoveAccessControlRecursiveOptions = path.RemoveAccessControlRecursiveOptions + +// UpdateAccessControlRecursiveOptions contains the optional parameters when calling the UpdateAccessControlRecursive operation. +type UpdateAccessControlRecursiveOptions = path.UpdateAccessControlRecursiveOptions + +// SharedKeyCredential contains an account's name and its primary or secondary key. +type SharedKeyCredential = exported.SharedKeyCredential diff --git a/sdk/storage/azdatalake/directory/responses.go b/sdk/storage/azdatalake/directory/responses.go new file mode 100644 index 000000000000..19a975c5a384 --- /dev/null +++ b/sdk/storage/azdatalake/directory/responses.go @@ -0,0 +1,45 @@ +//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 + +import ( + "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/internal/generated" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/internal/path" +) + +// CreateResponse contains the response fields for the Create operation. +type CreateResponse = generated.PathClientCreateResponse + +// DeleteResponse contains the response fields for the Delete operation. +type DeleteResponse = generated.PathClientDeleteResponse + +// SetAccessControlResponse contains the response fields for the SetAccessControl operation. +type SetAccessControlResponse = path.SetAccessControlResponse + +// SetAccessControlRecursiveResponse contains the response fields for the SetAccessControlRecursive operation. +type SetAccessControlRecursiveResponse = path.SetAccessControlRecursiveResponse + +// UpdateAccessControlRecursiveResponse contains the response fields for the UpdateAccessControlRecursive operation. +type UpdateAccessControlRecursiveResponse = path.SetAccessControlRecursiveResponse + +// RemoveAccessControlRecursiveResponse contains the response fields for the RemoveAccessControlRecursive operation. +type RemoveAccessControlRecursiveResponse = path.SetAccessControlRecursiveResponse + +// GetPropertiesResponse contains the response fields for the GetProperties operation. +type GetPropertiesResponse = path.GetPropertiesResponse + +// SetMetadataResponse contains the response fields for the SetMetadata operation. +type SetMetadataResponse = path.SetMetadataResponse + +// SetHTTPHeadersResponse contains the response fields for the SetHTTPHeaders operation. +type SetHTTPHeadersResponse = path.SetHTTPHeadersResponse + +// RenameResponse contains the response fields for the Rename operation. +type RenameResponse = path.CreateResponse + +// GetAccessControlResponse contains the response fields for the GetAccessControl operation. +type GetAccessControlResponse = path.GetAccessControlResponse diff --git a/sdk/storage/azdatalake/file/client.go b/sdk/storage/azdatalake/file/client.go new file mode 100644 index 000000000000..84e9b64ca4ae --- /dev/null +++ b/sdk/storage/azdatalake/file/client.go @@ -0,0 +1,100 @@ +//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 file + +import ( + "context" + "github.com/Azure/azure-sdk-for-go/sdk/azcore" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/internal/path" +) + +// Client represents a URL to the Azure Datalake Storage service allowing you to manipulate files. +type Client struct { + path.Client +} + +// NewClient creates an instance of Client with the specified values. +// - serviceURL - the URL of the storage account e.g. https://.file.core.windows.net/ +// - cred - an Azure AD credential, typically obtained via the azidentity module +// - options - client options; pass nil to accept the default values +func NewClient(serviceURL string, cred azcore.TokenCredential, options *azdatalake.ClientOptions) (*Client, error) { + return nil, nil +} + +// NewClientWithNoCredential creates an instance of Client with the specified values. +// This is used to anonymously access a storage account or with a shared access signature (SAS) token. +// - serviceURL - the URL of the storage account e.g. https://.file.core.windows.net/? +// - options - client options; pass nil to accept the default values +func NewClientWithNoCredential(serviceURL string, options *azdatalake.ClientOptions) (*Client, error) { + return nil, nil +} + +// NewClientWithSharedKeyCredential creates an instance of Client with the specified values. +// - serviceURL - the URL of the storage account e.g. https://.file.core.windows.net/ +// - cred - a SharedKeyCredential created with the matching storage account and access key +// - options - client options; pass nil to accept the default values +func NewClientWithSharedKeyCredential(serviceURL string, cred *SharedKeyCredential, options *azdatalake.ClientOptions) (*Client, error) { + return nil, nil +} + +// NewClientFromConnectionString creates an instance of Client with the specified values. +// - connectionString - a connection string for the desired storage account +// - options - client options; pass nil to accept the default values +func NewClientFromConnectionString(connectionString string, options *azdatalake.ClientOptions) (*Client, error) { + return nil, nil +} + +// Create creates a new file (dfs1). +func (f *Client) Create(ctx context.Context, options *CreateOptions) (CreateResponse, error) { + // TODO: format for options should be able to handle the access conditions parameter correctly + return CreateResponse{}, nil +} + +// Delete deletes a file (dfs1). +func (f *Client) Delete(ctx context.Context, options *DeleteOptions) (DeleteResponse, error) { + // TODO: recursive set to false when calling generated code + return DeleteResponse{}, nil +} + +// GetProperties gets the properties of a file (blob3) +func (f *Client) GetProperties(ctx context.Context, options *GetPropertiesOptions) (GetPropertiesResponse, error) { + // TODO: format blob response to path response + return GetPropertiesResponse{}, nil +} + +// Rename renames a file (dfs1). +func (f *Client) Rename(ctx context.Context, newName string, options *RenameOptions) (RenameResponse, error) { + return RenameResponse{}, nil +} + +// SetExpiry operation sets an expiry time on an existing file. +func (f *Client) SetExpiry(ctx context.Context, expiryType ExpiryType, o *SetExpiryOptions) (SetExpiryResponse, error) { + // TODO: consider using the blob client set expiry + // TODO: call methods in set_expiry.go + return SetExpiryResponse{}, nil +} + +// Upload uploads data to a file. +func (f *Client) Upload(ctx context.Context) { + +} + +// Append appends data to a file. +func (f *Client) Append(ctx context.Context) { + +} + +// Flush flushes previous uploaded data to a file. +func (f *Client) Flush(ctx context.Context) { + +} + +// Download downloads data from a file. +func (f *Client) Download(ctx context.Context) { + +} diff --git a/sdk/storage/azdatalake/file/constants.go b/sdk/storage/azdatalake/file/constants.go new file mode 100644 index 000000000000..5ce02ebff960 --- /dev/null +++ b/sdk/storage/azdatalake/file/constants.go @@ -0,0 +1,42 @@ +//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 file + +import ( + "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/internal/path" +) + +type ResourceType = path.ResourceType + +// TODO: consider the possibility of not exposing this and just pass it under the hood +const ( + ResourceTypeFile ResourceType = path.ResourceTypeFile + ResourceTypeDirectory ResourceType = path.ResourceTypeDirectory +) + +type RenameMode = path.RenameMode + +// TODO: consider the possibility of not exposing this and just pass it under the hood +const ( + RenameModeLegacy RenameMode = path.RenameModeLegacy + RenameModePosix RenameMode = path.RenameModePosix +) + +type SetAccessControlRecursiveMode = path.SetAccessControlRecursiveMode + +const ( + SetAccessControlRecursiveModeSet SetAccessControlRecursiveMode = path.SetAccessControlRecursiveModeSet + SetAccessControlRecursiveModeModify SetAccessControlRecursiveMode = path.SetAccessControlRecursiveModeModify + SetAccessControlRecursiveModeRemove SetAccessControlRecursiveMode = path.SetAccessControlRecursiveModeRemove +) + +type EncryptionAlgorithmType = path.EncryptionAlgorithmType + +const ( + EncryptionAlgorithmTypeNone EncryptionAlgorithmType = path.EncryptionAlgorithmTypeNone + EncryptionAlgorithmTypeAES256 EncryptionAlgorithmType = path.EncryptionAlgorithmTypeAES256 +) diff --git a/sdk/storage/azdatalake/file/models.go b/sdk/storage/azdatalake/file/models.go new file mode 100644 index 000000000000..f45f6041b50b --- /dev/null +++ b/sdk/storage/azdatalake/file/models.go @@ -0,0 +1,157 @@ +//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 file + +import ( + "github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/blob" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake" + "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" + "time" +) + +// CreateOptions contains the optional parameters when calling the Create operation. dfs endpoint. TODO: Design formatter +type CreateOptions struct { + // AccessConditions contains parameters for accessing the file. + AccessConditions *azdatalake.AccessConditions + // Metadata is a map of name-value pairs to associate with the file storage object. + Metadata map[string]*string + // CPKInfo contains a group of parameters for client provided encryption key. + CPKInfo CPKInfo + // HTTPHeaders contains the HTTP headers for path operations. + HTTPHeaders HTTPHeaders + //PathExpiryOptions *ExpiryOptions + // ExpiresOn specifies the time that the file will expire. + ExpiresOn *time.Time + // LeaseDuration specifies the duration of the lease. + LeaseDuration *time.Duration + // ProposedLeaseID specifies the proposed lease ID for the file. + ProposedLeaseID *string + // Permissions is the octal representation of the permissions for user, group and mask. + Permissions *string + // Umask is the umask for the file. + Umask *string + // Owner is the owner of the file. + Owner *string + // Group is the owning group of the file. + Group *string + // ACL is the access control list for the file. + 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 + leaseAccessConditions, modifiedAccessConditions := shared.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, + } + return leaseAccessConditions, modifiedAccessConditions, httpHeaders, nil +} + +// DeleteOptions contains the optional parameters when calling the Delete operation. dfs endpoint +type DeleteOptions struct { + // AccessConditions contains parameters for accessing the file. + AccessConditions *azdatalake.AccessConditions +} + +func (o *DeleteOptions) format() (*generated.LeaseAccessConditions, *generated.ModifiedAccessConditions, error) { + leaseAccessConditions, modifiedAccessConditions := shared.FormatPathAccessConditions(o.AccessConditions) + return leaseAccessConditions, modifiedAccessConditions, nil +} + +// RenameOptions contains the optional parameters when calling the Rename operation. TODO: Design formatter +type RenameOptions struct { + // SourceModifiedAccessConditions identifies the source path access conditions. + SourceModifiedAccessConditions *SourceModifiedAccessConditions + // AccessConditions contains parameters for accessing the file. + AccessConditions *azdatalake.AccessConditions +} + +// GetPropertiesOptions contains the optional parameters for the Client.GetProperties method +type GetPropertiesOptions struct { + AccessConditions *azdatalake.AccessConditions + CPKInfo *CPKInfo +} + +func (o *GetPropertiesOptions) format() *blob.GetPropertiesOptions { + if o == nil { + return nil + } + accessConditions := shared.FormatBlobAccessConditions(o.AccessConditions) + return &blob.GetPropertiesOptions{ + AccessConditions: accessConditions, + CPKInfo: &blob.CPKInfo{ + EncryptionKey: o.CPKInfo.EncryptionKey, + EncryptionAlgorithm: o.CPKInfo.EncryptionAlgorithm, + EncryptionKeySHA256: o.CPKInfo.EncryptionKeySHA256, + }, + } +} + +// ===================================== PATH IMPORTS =========================================== + +// CPKInfo contains a group of parameters for client provided encryption key. +type CPKInfo = path.CPKInfo + +// CPKScopeInfo contains a group of parameters for client provided encryption scope. +type CPKScopeInfo = path.CPKScopeInfo + +// HTTPHeaders contains the HTTP headers for path operations. +type HTTPHeaders = path.HTTPHeaders + +// SourceModifiedAccessConditions identifies the source path access conditions. +type SourceModifiedAccessConditions = path.SourceModifiedAccessConditions + +// SetAccessControlOptions contains the optional parameters when calling the SetAccessControl operation. +type SetAccessControlOptions = path.SetAccessControlOptions + +// GetAccessControlOptions contains the optional parameters when calling the GetAccessControl operation. +type GetAccessControlOptions = path.GetAccessControlOptions + +// SetAccessControlRecursiveOptions contains the optional parameters when calling the SetAccessControlRecursive operation. +type SetAccessControlRecursiveOptions = path.SetAccessControlRecursiveOptions + +// SetMetadataOptions contains the optional parameters when calling the SetMetadata operation. +type SetMetadataOptions = path.SetMetadataOptions + +// SetHTTPHeadersOptions contains the optional parameters when calling the SetHTTPHeaders operation. +type SetHTTPHeadersOptions = path.SetHTTPHeadersOptions + +// RemoveAccessControlRecursiveOptions contains the optional parameters when calling the RemoveAccessControlRecursive operation. +type RemoveAccessControlRecursiveOptions = path.RemoveAccessControlRecursiveOptions + +// UpdateAccessControlRecursiveOptions contains the optional parameters when calling the UpdateAccessControlRecursive operation. +type UpdateAccessControlRecursiveOptions = path.UpdateAccessControlRecursiveOptions + +// ExpiryType defines values for ExpiryType. +type ExpiryType = exported.ExpiryType + +// ExpiryTypeAbsolute defines the absolute time for the expiry. +type ExpiryTypeAbsolute = exported.ExpiryTypeAbsolute + +// ExpiryTypeRelativeToNow defines the duration relative to now for the expiry. +type ExpiryTypeRelativeToNow = exported.ExpiryTypeRelativeToNow + +// ExpiryTypeRelativeToCreation defines the duration relative to creation for the expiry. +type ExpiryTypeRelativeToCreation = exported.ExpiryTypeRelativeToCreation + +// ExpiryTypeNever defines that will be set to never expire. +type ExpiryTypeNever = exported.ExpiryTypeNever + +// SetExpiryOptions contains the optional parameters for the Client.SetExpiry method. +type SetExpiryOptions = exported.SetExpiryOptions + +// SharedKeyCredential contains an account's name and its primary or secondary key. +type SharedKeyCredential = exported.SharedKeyCredential diff --git a/sdk/storage/azdatalake/file/responses.go b/sdk/storage/azdatalake/file/responses.go new file mode 100644 index 000000000000..8543eaf3902a --- /dev/null +++ b/sdk/storage/azdatalake/file/responses.go @@ -0,0 +1,48 @@ +//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 file + +import ( + "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/internal/generated" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/internal/path" +) + +// SetExpiryResponse contains the response fields for the SetExpiry operation. +type SetExpiryResponse = generated.PathClientSetExpiryResponse + +// CreateResponse contains the response fields for the Create operation. +type CreateResponse = generated.PathClientCreateResponse + +// DeleteResponse contains the response fields for the Delete operation. +type DeleteResponse = generated.PathClientDeleteResponse + +// SetAccessControlResponse contains the response fields for the SetAccessControl operation. +type SetAccessControlResponse = path.SetAccessControlResponse + +// SetAccessControlRecursiveResponse contains the response fields for the SetAccessControlRecursive operation. +type SetAccessControlRecursiveResponse = path.SetAccessControlRecursiveResponse + +// UpdateAccessControlRecursiveResponse contains the response fields for the UpdateAccessControlRecursive operation. +type UpdateAccessControlRecursiveResponse = path.SetAccessControlRecursiveResponse + +// RemoveAccessControlRecursiveResponse contains the response fields for the RemoveAccessControlRecursive operation. +type RemoveAccessControlRecursiveResponse = path.SetAccessControlRecursiveResponse + +// GetPropertiesResponse contains the response fields for the GetProperties operation. +type GetPropertiesResponse = path.GetPropertiesResponse + +// SetMetadataResponse contains the response fields for the SetMetadata operation. +type SetMetadataResponse = path.SetMetadataResponse + +// SetHTTPHeadersResponse contains the response fields for the SetHTTPHeaders operation. +type SetHTTPHeadersResponse = path.SetHTTPHeadersResponse + +// RenameResponse contains the response fields for the Rename operation. +type RenameResponse = path.CreateResponse + +// GetAccessControlResponse contains the response fields for the GetAccessControl operation. +type GetAccessControlResponse = path.GetAccessControlResponse diff --git a/sdk/storage/azdatalake/filesystem/client.go b/sdk/storage/azdatalake/filesystem/client.go new file mode 100644 index 000000000000..ae2cbdb536d2 --- /dev/null +++ b/sdk/storage/azdatalake/filesystem/client.go @@ -0,0 +1,115 @@ +//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 filesystem + +import ( + "context" + "github.com/Azure/azure-sdk-for-go/sdk/azcore" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake" + "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" +) + +// Client represents a URL to the Azure Datalake Storage service allowing you to manipulate filesystems. +type Client base.Client[generated.FileSystemClient] + +// NewClient creates an instance of Client with the specified values. +// - serviceURL - the URL of the storage account e.g. https://.file.core.windows.net/ +// - cred - an Azure AD credential, typically obtained via the azidentity module +// - options - client options; pass nil to accept the default values +func NewClient(serviceURL string, cred azcore.TokenCredential, options *azdatalake.ClientOptions) (*Client, error) { + return nil, nil +} + +// NewClientWithNoCredential creates an instance of Client with the specified values. +// This is used to anonymously access a storage account or with a shared access signature (SAS) token. +// - serviceURL - the URL of the storage account e.g. https://.file.core.windows.net/? +// - options - client options; pass nil to accept the default values +func NewClientWithNoCredential(serviceURL string, options *azdatalake.ClientOptions) (*Client, error) { + return nil, nil +} + +// NewClientWithSharedKeyCredential creates an instance of Client with the specified values. +// - serviceURL - the URL of the storage account e.g. https://.file.core.windows.net/ +// - cred - a SharedKeyCredential created with the matching storage account and access key +// - options - client options; pass nil to accept the default values +func NewClientWithSharedKeyCredential(serviceURL string, cred *SharedKeyCredential, options *azdatalake.ClientOptions) (*Client, error) { + return nil, nil +} + +// NewClientFromConnectionString creates an instance of Client with the specified values. +// - connectionString - a connection string for the desired storage account +// - options - client options; pass nil to accept the default values +func NewClientFromConnectionString(connectionString string, options *azdatalake.ClientOptions) (*Client, error) { + return nil, nil +} + +func (fs *Client) generated() *generated.FileSystemClient { + return base.InnerClient((*base.Client[generated.FileSystemClient])(fs)) +} + +func (fs *Client) sharedKey() *exported.SharedKeyCredential { + return base.SharedKey((*base.Client[generated.FileSystemClient])(fs)) +} + +// URL returns the URL endpoint used by the Client object. +func (fs *Client) URL() string { + return "s.generated().Endpoint()" +} + +// Create creates a new filesystem under the specified account. (blob3). +func (fs *Client) Create(ctx context.Context, options *CreateOptions) (CreateResponse, error) { + return CreateResponse{}, nil +} + +// Delete deletes the specified filesystem and any files or directories it contains. (blob3). +func (fs *Client) Delete(ctx context.Context, options *DeleteOptions) (DeleteResponse, error) { + return DeleteResponse{}, nil +} + +// GetProperties returns all user-defined metadata, standard HTTP properties, and system properties for the filesystem. (blob3). +func (fs *Client) GetProperties(ctx context.Context, options *GetPropertiesOptions) (GetPropertiesResponse, error) { + // TODO: format blob response to fs response + return GetPropertiesResponse{}, nil +} + +// SetMetadata sets one or more user-defined name-value pairs for the specified filesystem. (blob3). +func (fs *Client) SetMetadata(ctx context.Context, options *SetMetadataOptions) (SetMetadataResponse, error) { + return SetMetadataResponse{}, nil +} + +// SetAccessPolicy sets the permissions for the specified filesystem or the files and directories under it. (blob3). +func (fs *Client) SetAccessPolicy(ctx context.Context, options *SetAccessPolicyOptions) (SetAccessPolicyResponse, error) { + return SetAccessPolicyResponse{}, nil +} + +// GetAccessPolicy returns the permissions for the specified filesystem or the files and directories under it. (blob3). +func (fs *Client) GetAccessPolicy(ctx context.Context, options *GetAccessPolicyOptions) (GetAccessPolicyResponse, error) { + return GetAccessPolicyResponse{}, nil +} + +// UndeletePath restores the specified path that was previously deleted. (dfs op/blob2). +func (fs *Client) UndeletePath(ctx context.Context, path string, options *UndeletePathOptions) (UndeletePathResponse, error) { + return UndeletePathResponse{}, nil +} + +// NewListPathsPager operation returns a pager of the shares under the specified account. (dfs1) +// For more information, see https://learn.microsoft.com/en-us/rest/api/storageservices/list-shares +func (fs *Client) NewListPathsPager(recursive bool, options *ListPathsOptions) *runtime.Pager[ListPathsSegmentResponse] { + //TODO: look into possibility of using blob endpoint like list deleted paths is + //TODO: will use ListPathsCreateRequest + return nil +} + +// NewListDeletedPathsPager operation returns a pager of the shares under the specified account. (dfs op/blob2). +// For more information, see https://learn.microsoft.com/en-us/rest/api/storageservices/list-shares +func (fs *Client) NewListDeletedPathsPager(options *ListDeletedPathsOptions) *runtime.Pager[ListDeletedPathsSegmentResponse] { + //TODO: will use ListBlobHierarchySegmentCreateRequest + return nil +} diff --git a/sdk/storage/azdatalake/filesystem/constants.go b/sdk/storage/azdatalake/filesystem/constants.go new file mode 100644 index 000000000000..3e0c373b87a1 --- /dev/null +++ b/sdk/storage/azdatalake/filesystem/constants.go @@ -0,0 +1,17 @@ +//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 filesystem + +import "github.com/Azure/azure-sdk-for-go/sdk/storage/azblob" + +// PublicAccessType defines values for AccessType - private (default) or file or filesystem. +type PublicAccessType = azblob.PublicAccessType + +const ( + File PublicAccessType = azblob.PublicAccessTypeBlob + Filesystem PublicAccessType = azblob.PublicAccessTypeContainer +) diff --git a/sdk/storage/azdatalake/filesystem/models.go b/sdk/storage/azdatalake/filesystem/models.go new file mode 100644 index 000000000000..ebb1946ec388 --- /dev/null +++ b/sdk/storage/azdatalake/filesystem/models.go @@ -0,0 +1,142 @@ +//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 filesystem + +import ( + "github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/container" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/internal/exported" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/internal/shared" +) + +// SetAccessPolicyOptions provides set of configurations for Filesystem.SetAccessPolicy operation. +type SetAccessPolicyOptions struct { + // Specifies whether data in the filesystem may be accessed publicly and the level of access. + // If this header is not included in the request, filesystem data is private to the account owner. + Access *PublicAccessType + AccessConditions *azdatalake.AccessConditions + FilesystemACL []*SignedIdentifier +} + +func (o *SetAccessPolicyOptions) format() *container.SetAccessPolicyOptions { + return &container.SetAccessPolicyOptions{ + Access: o.Access, + AccessConditions: shared.FormatContainerAccessConditions(o.AccessConditions), + ContainerACL: o.FilesystemACL, + } +} + +// CreateOptions contains the optional parameters for the Client.Create method. +type CreateOptions struct { + // Specifies whether data in the filesystem may be accessed publicly and the level of access. + Access *PublicAccessType + + // Optional. Specifies a user-defined name-value pair associated with the filesystem. + Metadata map[string]*string + + // Optional. Specifies the encryption scope settings to set on the filesystem. + CPKScopeInfo *CPKScopeInfo +} + +func (o *CreateOptions) format() *container.CreateOptions { + return &container.CreateOptions{ + Access: o.Access, + Metadata: o.Metadata, + CPKScopeInfo: o.CPKScopeInfo, + } +} + +// DeleteOptions contains the optional parameters for the Client.Delete method. +type DeleteOptions struct { + AccessConditions *azdatalake.AccessConditions +} + +func (o *DeleteOptions) format() *container.DeleteOptions { + return &container.DeleteOptions{ + AccessConditions: shared.FormatContainerAccessConditions(o.AccessConditions), + } +} + +// GetPropertiesOptions contains the optional parameters for the FilesystemClient.GetProperties method. +type GetPropertiesOptions struct { + LeaseAccessConditions *azdatalake.LeaseAccessConditions +} + +func (o *GetPropertiesOptions) format() *container.GetPropertiesOptions { + return &container.GetPropertiesOptions{ + LeaseAccessConditions: &container.LeaseAccessConditions{ + LeaseID: o.LeaseAccessConditions.LeaseID, + }, + } +} + +// SetMetadataOptions contains the optional parameters for the Client.SetMetadata method. +type SetMetadataOptions struct { + Metadata map[string]*string + AccessConditions *azdatalake.AccessConditions +} + +func (o *SetMetadataOptions) format() *container.SetMetadataOptions { + return &container.SetMetadataOptions{ + Metadata: o.Metadata, + LeaseAccessConditions: &container.LeaseAccessConditions{ + LeaseID: o.AccessConditions.LeaseAccessConditions.LeaseID, + }, + ModifiedAccessConditions: &container.ModifiedAccessConditions{ + IfMatch: o.AccessConditions.ModifiedAccessConditions.IfMatch, + IfNoneMatch: o.AccessConditions.ModifiedAccessConditions.IfNoneMatch, + IfModifiedSince: o.AccessConditions.ModifiedAccessConditions.IfModifiedSince, + IfUnmodifiedSince: o.AccessConditions.ModifiedAccessConditions.IfUnmodifiedSince, + }, + } +} + +// GetAccessPolicyOptions contains the optional parameters for the Client.GetAccessPolicy method. +type GetAccessPolicyOptions struct { + LeaseAccessConditions *azdatalake.LeaseAccessConditions +} + +func (o *GetAccessPolicyOptions) format() *container.GetAccessPolicyOptions { + return &container.GetAccessPolicyOptions{ + LeaseAccessConditions: &container.LeaseAccessConditions{ + LeaseID: o.LeaseAccessConditions.LeaseID, + }, + } +} + +// CPKScopeInfo contains a group of parameters for the FilesystemClient.Create method. +type CPKScopeInfo = container.CPKScopeInfo + +// AccessPolicy - An Access policy. +type AccessPolicy = container.AccessPolicy + +// SignedIdentifier - signed identifier. +type SignedIdentifier = container.SignedIdentifier + +// ListPathsOptions contains the optional parameters for the Filesystem.ListPaths operation. +type ListPathsOptions struct { + Marker *string + MaxResults *int32 + Prefix *string + Upn *bool +} + +// ListDeletedPathsOptions contains the optional parameters for the Filesystem.ListDeletedPaths operation. PLACEHOLDER +type ListDeletedPathsOptions struct { + Marker *string + MaxResults *int32 + Prefix *string + Upn *bool +} + +// UndeletePathOptions contains the optional parameters for the Filesystem.UndeletePath operation. +type UndeletePathOptions struct { + // placeholder +} + +// SharedKeyCredential contains an account's name and its primary or secondary key. +type SharedKeyCredential = exported.SharedKeyCredential diff --git a/sdk/storage/azdatalake/filesystem/responses.go b/sdk/storage/azdatalake/filesystem/responses.go new file mode 100644 index 000000000000..06b9d8b78a86 --- /dev/null +++ b/sdk/storage/azdatalake/filesystem/responses.go @@ -0,0 +1,39 @@ +//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 filesystem + +import ( + "github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/container" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/internal/generated" +) + +// CreateResponse contains the response from method FilesystemClient.Create. +type CreateResponse = container.CreateResponse + +// DeleteResponse contains the response from method FilesystemClient.Delete. +type DeleteResponse = container.DeleteResponse + +// SetMetadataResponse contains the response from method FilesystemClient.SetMetadata. +type SetMetadataResponse = container.SetMetadataResponse + +// SetAccessPolicyResponse contains the response from method FilesystemClient.SetAccessPolicy. +type SetAccessPolicyResponse = container.SetAccessPolicyResponse + +// GetAccessPolicyResponse contains the response from method FilesystemClient.GetAccessPolicy. +type GetAccessPolicyResponse = container.GetAccessPolicyResponse + +// GetPropertiesResponse contains the response from method FilesystemClient.GetProperties. +type GetPropertiesResponse = generated.FileSystemClientGetPropertiesResponse + +// ListPathsSegmentResponse contains the response from method FilesystemClient.ListPathsSegment. +type ListPathsSegmentResponse = generated.FileSystemClientListPathsResponse + +// ListDeletedPathsSegmentResponse contains the response from method FilesystemClient.ListPathsSegment. +type ListDeletedPathsSegmentResponse = generated.FileSystemClientListBlobHierarchySegmentResponse + +// UndeletePathResponse contains the response from method FilesystemClient.UndeletePath. +type UndeletePathResponse = generated.PathClientUndeleteResponse diff --git a/sdk/storage/azdatalake/go.mod b/sdk/storage/azdatalake/go.mod index dfd718eb5e06..6fc071bf6038 100644 --- a/sdk/storage/azdatalake/go.mod +++ b/sdk/storage/azdatalake/go.mod @@ -1,11 +1,26 @@ module github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake -go 1.19 +go 1.18 -require github.com/Azure/azure-sdk-for-go/sdk/azcore v1.5.0 +require ( + github.com/Azure/azure-sdk-for-go/sdk/azcore v1.5.0 + github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.1.0 + github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0 + github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.0.0 + github.com/stretchr/testify v1.7.1 +) require ( - github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0 // indirect + github.com/AzureAD/microsoft-authentication-library-for-go v0.5.1 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/golang-jwt/jwt v3.2.1+incompatible // indirect + github.com/google/uuid v1.1.1 // indirect + github.com/kylelemons/godebug v1.1.0 // indirect + github.com/pkg/browser v0.0.0-20210115035449-ce105d075bb4 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect + golang.org/x/crypto v0.0.0-20220511200225-c6db032c6c88 // indirect golang.org/x/net v0.8.0 // indirect + golang.org/x/sys v0.6.0 // indirect golang.org/x/text v0.8.0 // indirect + gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect ) diff --git a/sdk/storage/azdatalake/go.sum b/sdk/storage/azdatalake/go.sum index 5b3d1f6c33e0..44c525ae55ed 100644 --- a/sdk/storage/azdatalake/go.sum +++ b/sdk/storage/azdatalake/go.sum @@ -1,12 +1,44 @@ github.com/Azure/azure-sdk-for-go/sdk/azcore v1.5.0 h1:xGLAFFd9D3iLGxYiUGPdITSzsFmU1K8VtfuUHWAoN7M= github.com/Azure/azure-sdk-for-go/sdk/azcore v1.5.0/go.mod h1:bjGvMhVMb+EEm3VRNQawDMUyMMjo+S5ewNjflkep/0Q= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.1.0 h1:QkAcEIAKbNL4KoFr4SathZPhDhF4mVwpBMFlYjyAqy8= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.1.0/go.mod h1:bhXu1AjYL+wutSL/kpSq6s7733q2Rb0yuot9Zgfqa/0= github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0 h1:sXr+ck84g/ZlZUOZiNELInmMgOsuGwdjjVkEIde0OtY= github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0/go.mod h1:okt5dMMTOFjX/aovMlrjvvXoPMBVSPzk9185BT0+eZM= -github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= +github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.0.0 h1:u/LLAOFgsMv7HmNL4Qufg58y+qElGOt5qv0z1mURkRY= +github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.0.0/go.mod h1:2e8rMJtl2+2j+HXbTBwnyGpm5Nou7KhvSfxOq8JpTag= +github.com/AzureAD/microsoft-authentication-library-for-go v0.5.1 h1:BWe8a+f/t+7KY7zH2mqygeUD0t8hNFXe08p1Pb3/jKE= +github.com/AzureAD/microsoft-authentication-library-for-go v0.5.1/go.mod h1:Vt9sXTKwMyGcOxSmLDMnGPgqsUg7m8pe215qMLrDXw4= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/dnaeon/go-vcr v1.1.0 h1:ReYa/UBrRyQdant9B4fNHGoCNKw6qh6P0fsdGmZpR7c= +github.com/golang-jwt/jwt v3.2.1+incompatible h1:73Z+4BJcrTC+KczS6WvTPvRGOp1WmfEP4Q1lOd9Z/+c= +github.com/golang-jwt/jwt v3.2.1+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I= +github.com/golang-jwt/jwt/v4 v4.2.0 h1:besgBTC8w8HjP6NzQdxwKH9Z5oQMZ24ThTrHp3cZ8eU= +github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY= +github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= +github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= +github.com/montanaflynn/stats v0.6.6/go.mod h1:etXPPgVO6n31NxCd9KQUMvCM+ve0ruNzt6R8Bnaayow= +github.com/pkg/browser v0.0.0-20210115035449-ce105d075bb4 h1:Qj1ukM4GlMWXNdMBuXcXfz/Kw9s1qm0CLY32QxuSImI= +github.com/pkg/browser v0.0.0-20210115035449-ce105d075bb4/go.mod h1:N6UoU20jOqggOuDwUaBQpluzLNDqif3kq9z2wpdYEfQ= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= -github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +golang.org/x/crypto v0.0.0-20220511200225-c6db032c6c88 h1:Tgea0cVUD0ivh5ADBX4WwuI12DUd2to3nCYe2eayMIw= +golang.org/x/crypto v0.0.0-20220511200225-c6db032c6c88/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/net v0.8.0 h1:Zrh2ngAOFYneWTAIAPethzeaQLuHwhuBkuV6ZiRnUaQ= golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= +golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.6.0 h1:MVltZSvRTcU2ljQOhs94SXPftV6DCNnZViHeQps87pQ= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/text v0.8.0 h1:57P1ETyNKtuIjB4SRd15iJxuhj8Gc416Y78H3qgMh68= golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo= +gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/sdk/storage/azdatalake/internal/base/clients.go b/sdk/storage/azdatalake/internal/base/clients.go new file mode 100644 index 000000000000..40c909a17596 --- /dev/null +++ b/sdk/storage/azdatalake/internal/base/clients.go @@ -0,0 +1,24 @@ +//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 base + +import ( + "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/internal/exported" +) + +type Client[T any] struct { + inner *T + sharedKey *exported.SharedKeyCredential +} + +func InnerClient[T any](client *Client[T]) *T { + return client.inner +} + +func SharedKey[T any](client *Client[T]) *exported.SharedKeyCredential { + return client.sharedKey +} diff --git a/sdk/storage/azdatalake/internal/exported/access_policy.go b/sdk/storage/azdatalake/internal/exported/access_policy.go new file mode 100644 index 000000000000..14c293cf6569 --- /dev/null +++ b/sdk/storage/azdatalake/internal/exported/access_policy.go @@ -0,0 +1,67 @@ +//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 exported + +import ( + "bytes" + "fmt" +) + +// AccessPolicyPermission type simplifies creating the permissions string for a container's access policy. +// Initialize an instance of this type and then call its String method to set AccessPolicy's Permission field. +type AccessPolicyPermission struct { + Read, Add, Create, Write, Delete, List bool +} + +// String produces the access policy permission string for an Azure Storage container. +// Call this method to set AccessPolicy's Permission field. +func (p *AccessPolicyPermission) String() string { + var b bytes.Buffer + if p.Read { + b.WriteRune('r') + } + if p.Add { + b.WriteRune('a') + } + if p.Create { + b.WriteRune('c') + } + if p.Write { + b.WriteRune('w') + } + if p.Delete { + b.WriteRune('d') + } + if p.List { + b.WriteRune('l') + } + return b.String() +} + +// Parse initializes the AccessPolicyPermission's fields from a string. +func (p *AccessPolicyPermission) Parse(s string) error { + *p = AccessPolicyPermission{} // Clear the flags + for _, r := range s { + switch r { + case 'r': + p.Read = true + case 'a': + p.Add = true + case 'c': + p.Create = true + case 'w': + p.Write = true + case 'd': + p.Delete = true + case 'l': + p.List = true + default: + return fmt.Errorf("invalid permission: '%v'", r) + } + } + return nil +} diff --git a/sdk/storage/azdatalake/internal/exported/exported.go b/sdk/storage/azdatalake/internal/exported/exported.go new file mode 100644 index 000000000000..9bc1ca47df84 --- /dev/null +++ b/sdk/storage/azdatalake/internal/exported/exported.go @@ -0,0 +1,33 @@ +//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 exported + +import ( + "fmt" + "strconv" +) + +// 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 +} + +// FormatHTTPRange converts an HTTPRange to its string format. +func FormatHTTPRange(r HTTPRange) *string { + if r.Offset == 0 && r.Count == 0 { + return nil // No specified range + } + endOffset := "" // if count == CountToEnd (0) + if r.Count > 0 { + endOffset = strconv.FormatInt((r.Offset+r.Count)-1, 10) + } + dataRange := fmt.Sprintf("bytes=%v-%s", r.Offset, endOffset) + return &dataRange +} diff --git a/sdk/storage/azdatalake/internal/exported/set_expiry.go b/sdk/storage/azdatalake/internal/exported/set_expiry.go new file mode 100644 index 000000000000..041dd8ba60c0 --- /dev/null +++ b/sdk/storage/azdatalake/internal/exported/set_expiry.go @@ -0,0 +1,71 @@ +//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 exported + +import ( + "net/http" + "strconv" + "time" + + "github.com/Azure/azure-sdk-for-go/sdk/azcore/to" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/internal/generated" +) + +// ExpiryType defines values for ExpiryType +type ExpiryType interface { + Format(o *SetExpiryOptions) (generated.ExpiryOptions, *generated.PathClientSetExpiryOptions) + notPubliclyImplementable() +} + +// ExpiryTypeAbsolute defines the absolute time for the blob expiry +type ExpiryTypeAbsolute time.Time + +// ExpiryTypeRelativeToNow defines the duration relative to now for the blob expiry +type ExpiryTypeRelativeToNow time.Duration + +// ExpiryTypeRelativeToCreation defines the duration relative to creation for the blob expiry +type ExpiryTypeRelativeToCreation time.Duration + +// ExpiryTypeNever defines that the blob will be set to never expire +type ExpiryTypeNever struct { + // empty struct since NeverExpire expiry type does not require expiry time +} + +// SetExpiryOptions contains the optional parameters for the Client.SetExpiry method. +type SetExpiryOptions struct { + // placeholder for future options +} + +func (e ExpiryTypeAbsolute) Format(o *SetExpiryOptions) (generated.ExpiryOptions, *generated.PathClientSetExpiryOptions) { + return generated.ExpiryOptionsAbsolute, &generated.PathClientSetExpiryOptions{ + ExpiresOn: to.Ptr(time.Time(e).UTC().Format(http.TimeFormat)), + } +} + +func (e ExpiryTypeAbsolute) notPubliclyImplementable() {} + +func (e ExpiryTypeRelativeToNow) Format(o *SetExpiryOptions) (generated.ExpiryOptions, *generated.PathClientSetExpiryOptions) { + return generated.ExpiryOptionsRelativeToNow, &generated.PathClientSetExpiryOptions{ + ExpiresOn: to.Ptr(strconv.FormatInt(time.Duration(e).Milliseconds(), 10)), + } +} + +func (e ExpiryTypeRelativeToNow) notPubliclyImplementable() {} + +func (e ExpiryTypeRelativeToCreation) Format(o *SetExpiryOptions) (generated.ExpiryOptions, *generated.PathClientSetExpiryOptions) { + return generated.ExpiryOptionsRelativeToCreation, &generated.PathClientSetExpiryOptions{ + ExpiresOn: to.Ptr(strconv.FormatInt(time.Duration(e).Milliseconds(), 10)), + } +} + +func (e ExpiryTypeRelativeToCreation) notPubliclyImplementable() {} + +func (e ExpiryTypeNever) Format(o *SetExpiryOptions) (generated.ExpiryOptions, *generated.PathClientSetExpiryOptions) { + return generated.ExpiryOptionsNeverExpire, nil +} + +func (e ExpiryTypeNever) notPubliclyImplementable() {} diff --git a/sdk/storage/azdatalake/internal/exported/shared_key_credential.go b/sdk/storage/azdatalake/internal/exported/shared_key_credential.go new file mode 100644 index 000000000000..01934a0f14de --- /dev/null +++ b/sdk/storage/azdatalake/internal/exported/shared_key_credential.go @@ -0,0 +1,218 @@ +//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 exported + +import ( + "bytes" + "crypto/hmac" + "crypto/sha256" + "encoding/base64" + "fmt" + "net/http" + "net/url" + "sort" + "strings" + "sync/atomic" + "time" + + azlog "github.com/Azure/azure-sdk-for-go/sdk/azcore/log" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/policy" + "github.com/Azure/azure-sdk-for-go/sdk/internal/log" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/internal/shared" +) + +// NewSharedKeyCredential creates an immutable SharedKeyCredential containing the +// storage account's name and either its primary or secondary key. +func NewSharedKeyCredential(accountName string, accountKey string) (*SharedKeyCredential, error) { + c := SharedKeyCredential{accountName: accountName} + if err := c.SetAccountKey(accountKey); err != nil { + return nil, err + } + return &c, nil +} + +// SharedKeyCredential contains an account's name and its primary or secondary key. +type SharedKeyCredential struct { + // Only the NewSharedKeyCredential method should set these; all other methods should treat them as read-only + accountName string + accountKey atomic.Value // []byte +} + +// AccountName returns the Storage account's name. +func (c *SharedKeyCredential) AccountName() string { + return c.accountName +} + +// SetAccountKey replaces the existing account key with the specified account key. +func (c *SharedKeyCredential) SetAccountKey(accountKey string) error { + _bytes, err := base64.StdEncoding.DecodeString(accountKey) + if err != nil { + return fmt.Errorf("decode account key: %w", err) + } + c.accountKey.Store(_bytes) + return nil +} + +// ComputeHMACSHA256 generates a hash signature for an HTTP request or for a SAS. +func (c *SharedKeyCredential) computeHMACSHA256(message string) (string, error) { + h := hmac.New(sha256.New, c.accountKey.Load().([]byte)) + _, err := h.Write([]byte(message)) + return base64.StdEncoding.EncodeToString(h.Sum(nil)), err +} + +func (c *SharedKeyCredential) buildStringToSign(req *http.Request) (string, error) { + // https://docs.microsoft.com/en-us/rest/api/storageservices/authentication-for-the-azure-storage-services + headers := req.Header + contentLength := getHeader(shared.HeaderContentLength, headers) + if contentLength == "0" { + contentLength = "" + } + + canonicalizedResource, err := c.buildCanonicalizedResource(req.URL) + if err != nil { + return "", err + } + + stringToSign := strings.Join([]string{ + req.Method, + getHeader(shared.HeaderContentEncoding, headers), + getHeader(shared.HeaderContentLanguage, headers), + contentLength, + getHeader(shared.HeaderContentMD5, headers), + getHeader(shared.HeaderContentType, headers), + "", // Empty date because x-ms-date is expected (as per web page above) + getHeader(shared.HeaderIfModifiedSince, headers), + getHeader(shared.HeaderIfMatch, headers), + getHeader(shared.HeaderIfNoneMatch, headers), + getHeader(shared.HeaderIfUnmodifiedSince, headers), + getHeader(shared.HeaderRange, headers), + c.buildCanonicalizedHeader(headers), + canonicalizedResource, + }, "\n") + return stringToSign, nil +} + +func getHeader(key string, headers map[string][]string) string { + if headers == nil { + return "" + } + if v, ok := headers[key]; ok { + if len(v) > 0 { + return v[0] + } + } + + return "" +} + +func (c *SharedKeyCredential) buildCanonicalizedHeader(headers http.Header) string { + cm := map[string][]string{} + for k, v := range headers { + headerName := strings.TrimSpace(strings.ToLower(k)) + if strings.HasPrefix(headerName, "x-ms-") { + cm[headerName] = v // NOTE: the value must not have any whitespace around it. + } + } + if len(cm) == 0 { + return "" + } + + keys := make([]string, 0, len(cm)) + for key := range cm { + keys = append(keys, key) + } + sort.Strings(keys) + ch := bytes.NewBufferString("") + for i, key := range keys { + if i > 0 { + ch.WriteRune('\n') + } + ch.WriteString(key) + ch.WriteRune(':') + ch.WriteString(strings.Join(cm[key], ",")) + } + return ch.String() +} + +func (c *SharedKeyCredential) buildCanonicalizedResource(u *url.URL) (string, error) { + // https://docs.microsoft.com/en-us/rest/api/storageservices/authentication-for-the-azure-storage-services + cr := bytes.NewBufferString("/") + cr.WriteString(c.accountName) + + if len(u.Path) > 0 { + // Any portion of the CanonicalizedResource string that is derived from + // the resource's URI should be encoded exactly as it is in the URI. + // -- https://msdn.microsoft.com/en-gb/library/azure/dd179428.aspx + cr.WriteString(u.EscapedPath()) + } else { + // a slash is required to indicate the root path + cr.WriteString("/") + } + + // params is a map[string][]string; param name is key; params values is []string + params, err := url.ParseQuery(u.RawQuery) // Returns URL decoded values + if err != nil { + return "", fmt.Errorf("failed to parse query params: %w", err) + } + + if len(params) > 0 { // There is at least 1 query parameter + var paramNames []string // We use this to sort the parameter key names + for paramName := range params { + paramNames = append(paramNames, paramName) // paramNames must be lowercase + } + sort.Strings(paramNames) + + for _, paramName := range paramNames { + paramValues := params[paramName] + sort.Strings(paramValues) + + // Join the sorted key values separated by ',' + // Then prepend "keyName:"; then add this string to the buffer + cr.WriteString("\n" + paramName + ":" + strings.Join(paramValues, ",")) + } + } + return cr.String(), nil +} + +// ComputeHMACSHA256 is a helper for computing the signed string outside of this package. +func ComputeHMACSHA256(cred *SharedKeyCredential, message string) (string, error) { + return cred.computeHMACSHA256(message) +} + +// the following content isn't actually exported but must live +// next to SharedKeyCredential as it uses its unexported methods + +type SharedKeyCredPolicy struct { + cred *SharedKeyCredential +} + +func NewSharedKeyCredPolicy(cred *SharedKeyCredential) *SharedKeyCredPolicy { + return &SharedKeyCredPolicy{cred: cred} +} + +func (s *SharedKeyCredPolicy) Do(req *policy.Request) (*http.Response, error) { + if d := getHeader(shared.HeaderXmsDate, req.Raw().Header); d == "" { + req.Raw().Header.Set(shared.HeaderXmsDate, time.Now().UTC().Format(http.TimeFormat)) + } + stringToSign, err := s.cred.buildStringToSign(req.Raw()) + if err != nil { + return nil, err + } + signature, err := s.cred.computeHMACSHA256(stringToSign) + if err != nil { + return nil, err + } + authHeader := strings.Join([]string{"SharedKey ", s.cred.AccountName(), ":", signature}, "") + req.Raw().Header.Set(shared.HeaderAuthorization, authHeader) + + response, err := req.Next() + if err != nil && response != nil && response.StatusCode == http.StatusForbidden { + // Service failed to authenticate request, log it + log.Write(azlog.EventResponse, "===== HTTP Forbidden status, String-to-Sign:\n"+stringToSign+"\n===============================\n") + } + return response, err +} diff --git a/sdk/storage/azdatalake/internal/exported/version.go b/sdk/storage/azdatalake/internal/exported/version.go new file mode 100644 index 000000000000..b570e4653d73 --- /dev/null +++ b/sdk/storage/azdatalake/internal/exported/version.go @@ -0,0 +1,12 @@ +//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 exported + +const ( + ModuleName = "azdatalake" + ModuleVersion = "v0.1.0" +) diff --git a/sdk/storage/azdatalake/internal/generated/autorest.md b/sdk/storage/azdatalake/internal/generated/autorest.md index 9a83369f048b..e5184eb7f1df 100644 --- a/sdk/storage/azdatalake/internal/generated/autorest.md +++ b/sdk/storage/azdatalake/internal/generated/autorest.md @@ -7,7 +7,7 @@ go: true clear-output-folder: false version: "^3.0.0" license-header: MICROSOFT_MIT_NO_VERSION -input-file: "https://raw.githubusercontent.com/Azure/azure-rest-api-specs/main/specification/storage/data-plane/Microsoft.StorageDataLake/preview/2020-10-02/DataLakeStorage.json" +input-file: "https://raw.githubusercontent.com/Azure/azure-rest-api-specs/main/specification/storage/data-plane/Azure.Storage.Files.DataLake/preview/2020-10-02/DataLakeStorage.json" credential-scope: "https://storage.azure.com/.default" output-folder: ../generated file-prefix: "zz_" @@ -19,7 +19,7 @@ modelerfour: seal-single-value-enum-by-default: true lenient-model-deduplication: true export-clients: true -use: "@autorest/go@4.0.0-preview.45" +use: "@autorest/go@4.0.0-preview.49" ``` ### Remove Filesystem and PathName from parameter list since they are not needed @@ -78,4 +78,153 @@ directive: 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(`); -``` \ No newline at end of file +``` + +### Fix EncryptionAlgorithm + +``` yaml +directive: +- from: swagger-document + where: $.parameters + transform: > + delete $.EncryptionAlgorithm.enum; + $.EncryptionAlgorithm.enum = [ + "None", + "AES256" + ]; +``` + +### Clean up some const type names so they don't stutter + +``` yaml +directive: +- from: swagger-document + where: $.parameters['PathExpiryOptions'] + transform: > + $["x-ms-enum"].name = "ExpiryOptions"; + $["x-ms-client-name"].name = "ExpiryOptions"; + +``` + +### use azcore.ETag + +``` yaml +directive: +- from: zz_models.go + where: $ + transform: >- + return $. + replace(/import "time"/, `import (\n\t"time"\n\t"github.com/Azure/azure-sdk-for-go/sdk/azcore"\n)`). + replace(/Etag\s+\*string/g, `ETag *azcore.ETag`). + replace(/IfMatch\s+\*string/g, `IfMatch *azcore.ETag`). + replace(/IfNoneMatch\s+\*string/g, `IfNoneMatch *azcore.ETag`). + replace(/SourceIfMatch\s+\*string/g, `SourceIfMatch *azcore.ETag`). + replace(/SourceIfNoneMatch\s+\*string/g, `SourceIfNoneMatch *azcore.ETag`); + +- from: zz_response_types.go + where: $ + transform: >- + return $. + replace(/"time"/, `"time"\n\t"github.com/Azure/azure-sdk-for-go/sdk/azcore"`). + replace(/ETag\s+\*string/g, `ETag *azcore.ETag`); + +- from: + - zz_filesystem_client.go + - zz_path_client.go + where: $ + transform: >- + return $. + replace(/"github\.com\/Azure\/azure\-sdk\-for\-go\/sdk\/azcore\/policy"/, `"github.com/Azure/azure-sdk-for-go/sdk/azcore"\n\t"github.com/Azure/azure-sdk-for-go/sdk/azcore/policy"`). + replace(/result\.ETag\s+=\s+&val/g, `result.ETag = (*azcore.ETag)(&val)`). + replace(/\*modifiedAccessConditions.IfMatch/g, `string(*modifiedAccessConditions.IfMatch)`). + replace(/\*modifiedAccessConditions.IfNoneMatch/g, `string(*modifiedAccessConditions.IfNoneMatch)`). + replace(/\*sourceModifiedAccessConditions.SourceIfMatch/g, `string(*sourceModifiedAccessConditions.SourceIfMatch)`). + replace(/\*sourceModifiedAccessConditions.SourceIfNoneMatch/g, `string(*sourceModifiedAccessConditions.SourceIfNoneMatch)`); + +``` + +### Fix up x-ms-content-crc64 header response name + +``` yaml +directive: +- from: swagger-document + where: $.x-ms-paths.*.*.responses.*.headers.x-ms-content-crc64 + transform: > + $["x-ms-client-name"] = "ContentCRC64" +``` + +### Updating encoding URL, Golang adds '+' which disrupts encoding with service + +``` yaml +directive: + - from: zz_service_client.go + where: $ + transform: >- + return $. + replace(/req.Raw\(\).URL.RawQuery \= reqQP.Encode\(\)/, `req.Raw().URL.RawQuery = strings.Replace(reqQP.Encode(), "+", "%20", -1)`) +``` + +### Change `Duration` parameter in leases to be required + +``` yaml +directive: +- from: swagger-document + where: $.parameters.LeaseDuration + transform: > + $.required = true; +``` + +### Change CPK acronym to be all caps + +``` yaml +directive: + - from: source-file-go + where: $ + transform: >- + return $. + replace(/Cpk/g, "CPK"); +``` + +### Change CORS acronym to be all caps + +``` yaml +directive: + - from: source-file-go + where: $ + transform: >- + return $. + replace(/Cors/g, "CORS"); +``` + +### Change cors xml to be correct + +``` yaml +directive: + - from: source-file-go + where: $ + transform: >- + return $. + replace(/xml:"CORS>CORSRule"/g, "xml:\"Cors>CorsRule\""); +``` + +### Convert time to GMT for If-Modified-Since and If-Unmodified-Since request headers + +``` yaml +directive: +- from: + - zz_filesystem_client.go + - zz_path.go + where: $ + transform: >- + return $. + replace (/req\.Raw\(\)\.Header\[\"If-Modified-Since\"\]\s+=\s+\[\]string\{modifiedAccessConditions\.IfModifiedSince\.Format\(time\.RFC1123\)\}/g, + `req.Raw().Header["If-Modified-Since"] = []string{(*modifiedAccessConditions.IfModifiedSince).In(gmt).Format(time.RFC1123)}`). + replace (/req\.Raw\(\)\.Header\[\"If-Unmodified-Since\"\]\s+=\s+\[\]string\{modifiedAccessConditions\.IfUnmodifiedSince\.Format\(time\.RFC1123\)\}/g, + `req.Raw().Header["If-Unmodified-Since"] = []string{(*modifiedAccessConditions.IfUnmodifiedSince).In(gmt).Format(time.RFC1123)}`). + replace (/req\.Raw\(\)\.Header\[\"x-ms-source-if-modified-since\"\]\s+=\s+\[\]string\{sourceModifiedAccessConditions\.SourceIfModifiedSince\.Format\(time\.RFC1123\)\}/g, + `req.Raw().Header["x-ms-source-if-modified-since"] = []string{(*sourceModifiedAccessConditions.SourceIfModifiedSince).In(gmt).Format(time.RFC1123)}`). + replace (/req\.Raw\(\)\.Header\[\"x-ms-source-if-unmodified-since\"\]\s+=\s+\[\]string\{sourceModifiedAccessConditions\.SourceIfUnmodifiedSince\.Format\(time\.RFC1123\)\}/g, + `req.Raw().Header["x-ms-source-if-unmodified-since"] = []string{(*sourceModifiedAccessConditions.SourceIfUnmodifiedSince).In(gmt).Format(time.RFC1123)}`). + replace (/req\.Raw\(\)\.Header\[\"x-ms-immutability-policy-until-date\"\]\s+=\s+\[\]string\{options\.ImmutabilityPolicyExpiry\.Format\(time\.RFC1123\)\}/g, + `req.Raw().Header["x-ms-immutability-policy-until-date"] = []string{(*options.ImmutabilityPolicyExpiry).In(gmt).Format(time.RFC1123)}`); + diff --git a/sdk/storage/azdatalake/internal/generated/filesystem_client.go b/sdk/storage/azdatalake/internal/generated/filesystem_client.go new file mode 100644 index 000000000000..27c60f60cbcb --- /dev/null +++ b/sdk/storage/azdatalake/internal/generated/filesystem_client.go @@ -0,0 +1,23 @@ +//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 generated + +import ( + "github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime" + "time" +) + +func (client *FileSystemClient) Endpoint() string { + return client.endpoint +} + +func (client *FileSystemClient) Pipeline() runtime.Pipeline { + return client.internal.Pipeline() +} + +// used to convert times from UTC to GMT before sending across the wire +var gmt = time.FixedZone("GMT", 0) diff --git a/sdk/storage/azdatalake/internal/generated/path_client.go b/sdk/storage/azdatalake/internal/generated/path_client.go new file mode 100644 index 000000000000..3de3766c9850 --- /dev/null +++ b/sdk/storage/azdatalake/internal/generated/path_client.go @@ -0,0 +1,17 @@ +//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 generated + +import "github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime" + +func (client *PathClient) Endpoint() string { + return client.endpoint +} + +func (client *PathClient) Pipeline() runtime.Pipeline { + return client.internal.Pipeline() +} diff --git a/sdk/storage/azdatalake/internal/generated/service_client.go b/sdk/storage/azdatalake/internal/generated/service_client.go new file mode 100644 index 000000000000..22f11c20a9fd --- /dev/null +++ b/sdk/storage/azdatalake/internal/generated/service_client.go @@ -0,0 +1,17 @@ +//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 generated + +import "github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime" + +func (client *ServiceClient) Endpoint() string { + return client.endpoint +} + +func (client *ServiceClient) Pipeline() runtime.Pipeline { + return client.internal.Pipeline() +} diff --git a/sdk/storage/azdatalake/internal/generated/zz_constants.go b/sdk/storage/azdatalake/internal/generated/zz_constants.go index ce7c1ce6f3b9..bfb6f9ceee76 100644 --- a/sdk/storage/azdatalake/internal/generated/zz_constants.go +++ b/sdk/storage/azdatalake/internal/generated/zz_constants.go @@ -9,6 +9,40 @@ package generated +type EncryptionAlgorithmType string + +const ( + EncryptionAlgorithmTypeAES256 EncryptionAlgorithmType = "AES256" + EncryptionAlgorithmTypeNone EncryptionAlgorithmType = "None" +) + +// PossibleEncryptionAlgorithmTypeValues returns the possible values for the EncryptionAlgorithmType const type. +func PossibleEncryptionAlgorithmTypeValues() []EncryptionAlgorithmType { + return []EncryptionAlgorithmType{ + EncryptionAlgorithmTypeAES256, + EncryptionAlgorithmTypeNone, + } +} + +type ExpiryOptions string + +const ( + ExpiryOptionsAbsolute ExpiryOptions = "Absolute" + ExpiryOptionsNeverExpire ExpiryOptions = "NeverExpire" + ExpiryOptionsRelativeToCreation ExpiryOptions = "RelativeToCreation" + ExpiryOptionsRelativeToNow ExpiryOptions = "RelativeToNow" +) + +// PossibleExpiryOptionsValues returns the possible values for the ExpiryOptions const type. +func PossibleExpiryOptionsValues() []ExpiryOptions { + return []ExpiryOptions{ + ExpiryOptionsAbsolute, + ExpiryOptionsNeverExpire, + ExpiryOptionsRelativeToCreation, + ExpiryOptionsRelativeToNow, + } +} + type ListBlobsIncludeItem string const ( @@ -16,9 +50,9 @@ const ( ListBlobsIncludeItemDeleted ListBlobsIncludeItem = "deleted" ListBlobsIncludeItemMetadata ListBlobsIncludeItem = "metadata" ListBlobsIncludeItemSnapshots ListBlobsIncludeItem = "snapshots" + ListBlobsIncludeItemTags ListBlobsIncludeItem = "tags" ListBlobsIncludeItemUncommittedblobs ListBlobsIncludeItem = "uncommittedblobs" ListBlobsIncludeItemVersions ListBlobsIncludeItem = "versions" - ListBlobsIncludeItemTags ListBlobsIncludeItem = "tags" ) // PossibleListBlobsIncludeItemValues returns the possible values for the ListBlobsIncludeItem const type. @@ -28,9 +62,9 @@ func PossibleListBlobsIncludeItemValues() []ListBlobsIncludeItem { ListBlobsIncludeItemDeleted, ListBlobsIncludeItemMetadata, ListBlobsIncludeItemSnapshots, + ListBlobsIncludeItemTags, ListBlobsIncludeItemUncommittedblobs, ListBlobsIncludeItemVersions, - ListBlobsIncludeItemTags, } } @@ -74,8 +108,8 @@ const ( PathLeaseActionAcquire PathLeaseAction = "acquire" PathLeaseActionBreak PathLeaseAction = "break" PathLeaseActionChange PathLeaseAction = "change" - PathLeaseActionRenew PathLeaseAction = "renew" PathLeaseActionRelease PathLeaseAction = "release" + PathLeaseActionRenew PathLeaseAction = "renew" ) // PossiblePathLeaseActionValues returns the possible values for the PathLeaseAction const type. @@ -84,8 +118,8 @@ func PossiblePathLeaseActionValues() []PathLeaseAction { PathLeaseActionAcquire, PathLeaseActionBreak, PathLeaseActionChange, - PathLeaseActionRenew, PathLeaseActionRelease, + PathLeaseActionRenew, } } @@ -122,17 +156,17 @@ func PossiblePathResourceTypeValues() []PathResourceType { type PathSetAccessControlRecursiveMode string const ( - PathSetAccessControlRecursiveModeSet PathSetAccessControlRecursiveMode = "set" PathSetAccessControlRecursiveModeModify PathSetAccessControlRecursiveMode = "modify" PathSetAccessControlRecursiveModeRemove PathSetAccessControlRecursiveMode = "remove" + PathSetAccessControlRecursiveModeSet PathSetAccessControlRecursiveMode = "set" ) // PossiblePathSetAccessControlRecursiveModeValues returns the possible values for the PathSetAccessControlRecursiveMode const type. func PossiblePathSetAccessControlRecursiveModeValues() []PathSetAccessControlRecursiveMode { return []PathSetAccessControlRecursiveMode{ - PathSetAccessControlRecursiveModeSet, PathSetAccessControlRecursiveModeModify, PathSetAccessControlRecursiveModeRemove, + PathSetAccessControlRecursiveModeSet, } } @@ -141,9 +175,9 @@ type PathUpdateAction string const ( PathUpdateActionAppend PathUpdateAction = "append" PathUpdateActionFlush PathUpdateAction = "flush" - PathUpdateActionSetProperties PathUpdateAction = "setProperties" PathUpdateActionSetAccessControl PathUpdateAction = "setAccessControl" PathUpdateActionSetAccessControlRecursive PathUpdateAction = "setAccessControlRecursive" + PathUpdateActionSetProperties PathUpdateAction = "setProperties" ) // PossiblePathUpdateActionValues returns the possible values for the PathUpdateAction const type. @@ -151,8 +185,8 @@ func PossiblePathUpdateActionValues() []PathUpdateAction { return []PathUpdateAction{ PathUpdateActionAppend, PathUpdateActionFlush, - PathUpdateActionSetProperties, PathUpdateActionSetAccessControl, PathUpdateActionSetAccessControlRecursive, + PathUpdateActionSetProperties, } } diff --git a/sdk/storage/azdatalake/internal/generated/zz_filesystem_client.go b/sdk/storage/azdatalake/internal/generated/zz_filesystem_client.go index 900c08f05fa0..99894e0fc566 100644 --- a/sdk/storage/azdatalake/internal/generated/zz_filesystem_client.go +++ b/sdk/storage/azdatalake/internal/generated/zz_filesystem_client.go @@ -12,6 +12,7 @@ package generated import ( "context" "fmt" + "github.com/Azure/azure-sdk-for-go/sdk/azcore" "github.com/Azure/azure-sdk-for-go/sdk/azcore/policy" "github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime" "net/http" @@ -21,21 +22,10 @@ import ( ) // FileSystemClient contains the methods for the FileSystem group. -// Don't use this type directly, use NewFileSystemClient() instead. +// Don't use this type directly, use a constructor function instead. type FileSystemClient struct { + internal *azcore.Client endpoint string - pl runtime.Pipeline -} - -// NewFileSystemClient creates a new instance of FileSystemClient with the specified values. -// - endpoint - The URL of the service account, container, or blob that is the target of the desired operation. -// - pl - the pipeline used for sending requests and handling responses. -func NewFileSystemClient(endpoint string, pl runtime.Pipeline) *FileSystemClient { - client := &FileSystemClient{ - endpoint: endpoint, - pl: pl, - } - return client } // Create - Create a FileSystem rooted at the specified location. If the FileSystem already exists, the operation fails. This @@ -49,7 +39,7 @@ func (client *FileSystemClient) Create(ctx context.Context, options *FileSystemC if err != nil { return FileSystemClientCreateResponse{}, err } - resp, err := client.pl.Do(req) + resp, err := client.internal.Pipeline().Do(req) if err != nil { return FileSystemClientCreateResponse{}, err } @@ -93,7 +83,7 @@ func (client *FileSystemClient) createHandleResponse(resp *http.Response) (FileS result.Date = &date } if val := resp.Header.Get("ETag"); val != "" { - result.ETag = &val + result.ETag = (*azcore.ETag)(&val) } if val := resp.Header.Get("Last-Modified"); val != "" { lastModified, err := time.Parse(time.RFC1123, val) @@ -133,7 +123,7 @@ func (client *FileSystemClient) Delete(ctx context.Context, options *FileSystemC if err != nil { return FileSystemClientDeleteResponse{}, err } - resp, err := client.pl.Do(req) + resp, err := client.internal.Pipeline().Do(req) if err != nil { return FileSystemClientDeleteResponse{}, err } @@ -160,10 +150,10 @@ func (client *FileSystemClient) deleteCreateRequest(ctx context.Context, options } req.Raw().Header["x-ms-version"] = []string{"2020-10-02"} if modifiedAccessConditions != nil && modifiedAccessConditions.IfModifiedSince != nil { - req.Raw().Header["If-Modified-Since"] = []string{modifiedAccessConditions.IfModifiedSince.Format(time.RFC1123)} + req.Raw().Header["If-Modified-Since"] = []string{(*modifiedAccessConditions.IfModifiedSince).In(gmt).Format(time.RFC1123)} } if modifiedAccessConditions != nil && modifiedAccessConditions.IfUnmodifiedSince != nil { - req.Raw().Header["If-Unmodified-Since"] = []string{modifiedAccessConditions.IfUnmodifiedSince.Format(time.RFC1123)} + req.Raw().Header["If-Unmodified-Since"] = []string{(*modifiedAccessConditions.IfUnmodifiedSince).In(gmt).Format(time.RFC1123)} } req.Raw().Header["Accept"] = []string{"application/json"} return req, nil @@ -199,7 +189,7 @@ func (client *FileSystemClient) GetProperties(ctx context.Context, options *File if err != nil { return FileSystemClientGetPropertiesResponse{}, err } - resp, err := client.pl.Do(req) + resp, err := client.internal.Pipeline().Do(req) if err != nil { return FileSystemClientGetPropertiesResponse{}, err } @@ -240,7 +230,7 @@ func (client *FileSystemClient) getPropertiesHandleResponse(resp *http.Response) result.Date = &date } if val := resp.Header.Get("ETag"); val != "" { - result.ETag = &val + result.ETag = (*azcore.ETag)(&val) } if val := resp.Header.Get("Last-Modified"); val != "" { lastModified, err := time.Parse(time.RFC1123, val) @@ -388,7 +378,7 @@ func (client *FileSystemClient) ListPathsHandleResponse(resp *http.Response) (Fi result.Date = &date } if val := resp.Header.Get("ETag"); val != "" { - result.ETag = &val + result.ETag = (*azcore.ETag)(&val) } if val := resp.Header.Get("Last-Modified"); val != "" { lastModified, err := time.Parse(time.RFC1123, val) @@ -427,7 +417,7 @@ func (client *FileSystemClient) SetProperties(ctx context.Context, options *File if err != nil { return FileSystemClientSetPropertiesResponse{}, err } - resp, err := client.pl.Do(req) + resp, err := client.internal.Pipeline().Do(req) if err != nil { return FileSystemClientSetPropertiesResponse{}, err } @@ -457,10 +447,10 @@ func (client *FileSystemClient) setPropertiesCreateRequest(ctx context.Context, req.Raw().Header["x-ms-properties"] = []string{*options.Properties} } if modifiedAccessConditions != nil && modifiedAccessConditions.IfModifiedSince != nil { - req.Raw().Header["If-Modified-Since"] = []string{modifiedAccessConditions.IfModifiedSince.Format(time.RFC1123)} + req.Raw().Header["If-Modified-Since"] = []string{(*modifiedAccessConditions.IfModifiedSince).In(gmt).Format(time.RFC1123)} } if modifiedAccessConditions != nil && modifiedAccessConditions.IfUnmodifiedSince != nil { - req.Raw().Header["If-Unmodified-Since"] = []string{modifiedAccessConditions.IfUnmodifiedSince.Format(time.RFC1123)} + req.Raw().Header["If-Unmodified-Since"] = []string{(*modifiedAccessConditions.IfUnmodifiedSince).In(gmt).Format(time.RFC1123)} } req.Raw().Header["Accept"] = []string{"application/json"} return req, nil @@ -477,7 +467,7 @@ func (client *FileSystemClient) setPropertiesHandleResponse(resp *http.Response) result.Date = &date } if val := resp.Header.Get("ETag"); val != "" { - result.ETag = &val + result.ETag = (*azcore.ETag)(&val) } if val := resp.Header.Get("Last-Modified"); val != "" { lastModified, err := time.Parse(time.RFC1123, val) diff --git a/sdk/storage/azdatalake/internal/generated/zz_models.go b/sdk/storage/azdatalake/internal/generated/zz_models.go index 1edd40a69a4a..b9c912bcd46b 100644 --- a/sdk/storage/azdatalake/internal/generated/zz_models.go +++ b/sdk/storage/azdatalake/internal/generated/zz_models.go @@ -9,12 +9,15 @@ package generated -import "time" +import ( + "github.com/Azure/azure-sdk-for-go/sdk/azcore" + "time" +) type ACLFailedEntry struct { - ErrorMessage *string `json:"errorMessage,omitempty"` - Name *string `json:"name,omitempty"` - Type *string `json:"type,omitempty"` + ErrorMessage *string + Name *string + Type *string } type BlobHierarchyListSegment struct { @@ -49,7 +52,7 @@ type BlobPrefix struct { // BlobPropertiesInternal - Properties of a blob type BlobPropertiesInternal struct { // REQUIRED - Etag *string `xml:"Etag"` + ETag *azcore.ETag `xml:"Etag"` // REQUIRED LastModified *time.Time `xml:"Last-Modified"` @@ -87,11 +90,11 @@ type BlobPropertiesInternal struct { TagCount *int32 `xml:"TagCount"` } -// CpkInfo contains a group of parameters for the PathClient.Create method. -type CpkInfo struct { +// CPKInfo contains a group of parameters for the PathClient.Create method. +type CPKInfo struct { // The algorithm used to produce the encryption key hash. Currently, the only accepted value is "AES256". Must be provided - // if the x-ms-encryption-key header is provided.. Specifying any value will set the value to AES256. - EncryptionAlgorithm *string + // if the x-ms-encryption-key header is provided. + EncryptionAlgorithm *EncryptionAlgorithmType // Optional. Specifies the encryption key to use to encrypt the data provided in the request. If not specified, encryption // is performed with the root account encryption key. For more information, see // Encryption at Rest for Azure Storage Services. @@ -101,9 +104,9 @@ type CpkInfo struct { } type FileSystem struct { - ETag *string `json:"eTag,omitempty"` - LastModified *string `json:"lastModified,omitempty"` - Name *string `json:"name,omitempty"` + ETag *string + LastModified *string + Name *string } // FileSystemClientCreateOptions contains the optional parameters for the FileSystemClient.Create method. @@ -218,7 +221,7 @@ type FileSystemClientSetPropertiesOptions struct { } type FileSystemList struct { - Filesystems []*FileSystem `json:"filesystems,omitempty"` + Filesystems []*FileSystem } // LeaseAccessConditions contains a group of parameters for the PathClient.Create method. @@ -247,29 +250,29 @@ type ListBlobsHierarchySegmentResponse struct { // ModifiedAccessConditions contains a group of parameters for the FileSystemClient.SetProperties method. type ModifiedAccessConditions struct { // Specify an ETag value to operate only on blobs with a matching value. - IfMatch *string + IfMatch *azcore.ETag // Specify this header value to operate only on a blob if it has been modified since the specified date/time. IfModifiedSince *time.Time // Specify an ETag value to operate only on blobs without a matching value. - IfNoneMatch *string + IfNoneMatch *azcore.ETag // Specify this header value to operate only on a blob if it has not been modified since the specified date/time. IfUnmodifiedSince *time.Time } type Path struct { - ContentLength *int64 `json:"contentLength,omitempty"` - CreationTime *string `json:"creationTime,omitempty"` - ETag *string `json:"eTag,omitempty"` + ContentLength *int64 + CreationTime *string + ETag *string // The name of the encryption scope under which the blob is encrypted. - EncryptionScope *string `json:"EncryptionScope,omitempty"` - ExpiryTime *string `json:"expiryTime,omitempty"` - Group *string `json:"group,omitempty"` - IsDirectory *bool `json:"isDirectory,omitempty"` - LastModified *string `json:"lastModified,omitempty"` - Name *string `json:"name,omitempty"` - Owner *string `json:"owner,omitempty"` - Permissions *string `json:"permissions,omitempty"` + EncryptionScope *string + ExpiryTime *string + Group *string + IsDirectory *bool + LastModified *string + Name *string + Owner *string + Permissions *string } // PathClientAppendDataOptions contains the optional parameters for the PathClient.AppendData method. @@ -297,14 +300,29 @@ type PathClientAppendDataOptions struct { // PathClientCreateOptions contains the optional parameters for the PathClient.Create method. type PathClientCreateOptions struct { + // Sets POSIX access control rights on files and directories. The value is a comma-separated list of access control entries. + // Each access control entry (ACE) consists of a scope, a type, a user or group + // identifier, and permissions in the format "[scope:][type]:[id]:[permissions]". + ACL *string // Optional. When deleting a directory, the number of paths that are deleted with each invocation is limited. If the number // of paths to be deleted exceeds this limit, a continuation token is returned in // this response header. When a continuation token is returned in the response, it must be specified in a subsequent invocation // of the delete operation to continue deleting the directory. Continuation *string + // The time to set the blob to expiry + ExpiresOn *string + // Required. Indicates mode of the expiry time + ExpiryOptions *PathExpiryOptions + // Optional. The owning group of the blob or directory. + Group *string + // The lease duration is required to acquire a lease, and specifies the duration of the lease in seconds. The lease duration + // must be between 15 and 60 seconds or -1 for infinite lease. + LeaseDuration *int64 // Optional. Valid only when namespace is enabled. This parameter determines the behavior of the rename operation. The value // must be "legacy" or "posix", and the default value will be "posix". Mode *PathRenameMode + // Optional. The owner of the blob or directory. + Owner *string // Optional and only valid if Hierarchical Namespace is enabled for the account. Sets POSIX access permissions for the file // owner, the file owning group, and others. Each class may be granted read, // write, or execute permission. The sticky bit is also supported. Both symbolic (rwxrw-rw-) and 4-digit octal notation (e.g. @@ -317,6 +335,10 @@ type PathClientCreateOptions struct { // header is omitted. To merge new and existing properties, first get all existing properties and the current E-Tag, then // make a conditional request with the E-Tag and include values for all properties. Properties *string + // Proposed lease ID, in a GUID string format. The Blob service returns 400 (Invalid request) if the proposed lease ID is + // not in the correct format. See Guid Constructor (String) for a list of valid GUID + // string formats. + ProposedLeaseID *string // An optional file or directory to be renamed. The value must have the following format: "/{filesystem}/{path}". If "x-ms-properties" // is specified, the properties will overwrite the existing properties; // otherwise, the existing properties will be preserved. This value must be a URL percent-encoded string. Note that the string @@ -430,9 +452,6 @@ type PathClientLeaseOptions struct { // The lease break period duration is optional to break a lease, and specifies the break period of the lease in seconds. The // lease break duration must be between 0 and 60 seconds. XMSLeaseBreakPeriod *int32 - // The lease duration is required to acquire a lease, and specifies the duration of the lease in seconds. The lease duration - // must be between 15 and 60 seconds or -1 for infinite lease. - XMSLeaseDuration *int32 } // PathClientReadOptions contains the optional parameters for the PathClient.Read method. @@ -622,7 +641,7 @@ type PathHTTPHeaders struct { } type PathList struct { - Paths []*Path `json:"paths,omitempty"` + Paths []*Path } // ServiceClientListFileSystemsOptions contains the optional parameters for the ServiceClient.NewListFileSystemsPager method. @@ -646,34 +665,34 @@ type ServiceClientListFileSystemsOptions struct { } type SetAccessControlRecursiveResponse struct { - DirectoriesSuccessful *int32 `json:"directoriesSuccessful,omitempty"` - FailedEntries []*ACLFailedEntry `json:"failedEntries,omitempty"` - FailureCount *int32 `json:"failureCount,omitempty"` - FilesSuccessful *int32 `json:"filesSuccessful,omitempty"` + DirectoriesSuccessful *int32 + FailedEntries []*ACLFailedEntry + FailureCount *int32 + FilesSuccessful *int32 } // SourceModifiedAccessConditions contains a group of parameters for the PathClient.Create method. type SourceModifiedAccessConditions struct { // Specify an ETag value to operate only on blobs with a matching value. - SourceIfMatch *string + SourceIfMatch *azcore.ETag // Specify this header value to operate only on a blob if it has been modified since the specified date/time. SourceIfModifiedSince *time.Time // Specify an ETag value to operate only on blobs without a matching value. - SourceIfNoneMatch *string + SourceIfNoneMatch *azcore.ETag // Specify this header value to operate only on a blob if it has not been modified since the specified date/time. SourceIfUnmodifiedSince *time.Time } type StorageError struct { // The service error response object. - Error *StorageErrorError `json:"error,omitempty"` + Error *StorageErrorError } // StorageErrorError - The service error response object. type StorageErrorError struct { // The service error code. - Code *string `json:"Code,omitempty"` + Code *string // The service error message. - Message *string `json:"Message,omitempty"` + Message *string } diff --git a/sdk/storage/azdatalake/internal/generated/zz_path_client.go b/sdk/storage/azdatalake/internal/generated/zz_path_client.go index 876f13e3f14d..4f3c3b3ba19f 100644 --- a/sdk/storage/azdatalake/internal/generated/zz_path_client.go +++ b/sdk/storage/azdatalake/internal/generated/zz_path_client.go @@ -12,6 +12,7 @@ package generated import ( "context" "encoding/base64" + "github.com/Azure/azure-sdk-for-go/sdk/azcore" "github.com/Azure/azure-sdk-for-go/sdk/azcore/policy" "github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime" "io" @@ -21,21 +22,11 @@ import ( ) // PathClient contains the methods for the Path group. -// Don't use this type directly, use NewPathClient() instead. +// Don't use this type directly, use a constructor function instead. type PathClient struct { - endpoint string - pl runtime.Pipeline -} - -// NewPathClient creates a new instance of PathClient with the specified values. -// - endpoint - The URL of the service account, container, or blob that is the target of the desired operation. -// - pl - the pipeline used for sending requests and handling responses. -func NewPathClient(endpoint string, pl runtime.Pipeline) *PathClient { - client := &PathClient{ - endpoint: endpoint, - pl: pl, - } - return client + internal *azcore.Client + endpoint string + xmsLeaseDuration int32 } // AppendData - Append data to the file. @@ -46,13 +37,13 @@ func NewPathClient(endpoint string, pl runtime.Pipeline) *PathClient { // - options - PathClientAppendDataOptions contains the optional parameters for the PathClient.AppendData method. // - PathHTTPHeaders - PathHTTPHeaders contains a group of parameters for the PathClient.Create method. // - LeaseAccessConditions - LeaseAccessConditions contains a group of parameters for the PathClient.Create method. -// - CpkInfo - CpkInfo contains a group of parameters for the PathClient.Create method. -func (client *PathClient) AppendData(ctx context.Context, body io.ReadSeekCloser, options *PathClientAppendDataOptions, pathHTTPHeaders *PathHTTPHeaders, leaseAccessConditions *LeaseAccessConditions, cpkInfo *CpkInfo) (PathClientAppendDataResponse, error) { +// - CPKInfo - CPKInfo contains a group of parameters for the PathClient.Create method. +func (client *PathClient) AppendData(ctx context.Context, body io.ReadSeekCloser, options *PathClientAppendDataOptions, pathHTTPHeaders *PathHTTPHeaders, leaseAccessConditions *LeaseAccessConditions, cpkInfo *CPKInfo) (PathClientAppendDataResponse, error) { req, err := client.appendDataCreateRequest(ctx, body, options, pathHTTPHeaders, leaseAccessConditions, cpkInfo) if err != nil { return PathClientAppendDataResponse{}, err } - resp, err := client.pl.Do(req) + resp, err := client.internal.Pipeline().Do(req) if err != nil { return PathClientAppendDataResponse{}, err } @@ -63,7 +54,7 @@ func (client *PathClient) AppendData(ctx context.Context, body io.ReadSeekCloser } // appendDataCreateRequest creates the AppendData request. -func (client *PathClient) appendDataCreateRequest(ctx context.Context, body io.ReadSeekCloser, options *PathClientAppendDataOptions, pathHTTPHeaders *PathHTTPHeaders, leaseAccessConditions *LeaseAccessConditions, cpkInfo *CpkInfo) (*policy.Request, error) { +func (client *PathClient) appendDataCreateRequest(ctx context.Context, body io.ReadSeekCloser, options *PathClientAppendDataOptions, pathHTTPHeaders *PathHTTPHeaders, leaseAccessConditions *LeaseAccessConditions, cpkInfo *CPKInfo) (*policy.Request, error) { req, err := runtime.NewRequest(ctx, http.MethodPatch, client.endpoint) if err != nil { return nil, err @@ -100,10 +91,13 @@ func (client *PathClient) appendDataCreateRequest(ctx context.Context, body io.R req.Raw().Header["x-ms-encryption-key-sha256"] = []string{*cpkInfo.EncryptionKeySHA256} } if cpkInfo != nil && cpkInfo.EncryptionAlgorithm != nil { - req.Raw().Header["x-ms-encryption-algorithm"] = []string{"AES256"} + req.Raw().Header["x-ms-encryption-algorithm"] = []string{string(*cpkInfo.EncryptionAlgorithm)} } req.Raw().Header["Accept"] = []string{"application/json"} - return req, req.SetBody(body, "application/json") + if err := req.SetBody(body, "application/json"); err != nil { + return nil, err + } + return req, nil } // appendDataHandleResponse handles the AppendData response. @@ -126,7 +120,7 @@ func (client *PathClient) appendDataHandleResponse(resp *http.Response) (PathCli result.Version = &val } if val := resp.Header.Get("ETag"); val != "" { - result.ETag = &val + result.ETag = (*azcore.ETag)(&val) } if val := resp.Header.Get("Content-MD5"); val != "" { contentMD5, err := base64.StdEncoding.DecodeString(val) @@ -136,11 +130,11 @@ func (client *PathClient) appendDataHandleResponse(resp *http.Response) (PathCli result.ContentMD5 = contentMD5 } if val := resp.Header.Get("x-ms-content-crc64"); val != "" { - xMSContentCRC64, err := base64.StdEncoding.DecodeString(val) + contentCRC64, err := base64.StdEncoding.DecodeString(val) if err != nil { return PathClientAppendDataResponse{}, err } - result.XMSContentCRC64 = xMSContentCRC64 + result.ContentCRC64 = contentCRC64 } if val := resp.Header.Get("x-ms-request-server-encrypted"); val != "" { isServerEncrypted, err := strconv.ParseBool(val) @@ -171,13 +165,13 @@ func (client *PathClient) appendDataHandleResponse(resp *http.Response) (PathCli // method. // - SourceModifiedAccessConditions - SourceModifiedAccessConditions contains a group of parameters for the PathClient.Create // method. -// - CpkInfo - CpkInfo contains a group of parameters for the PathClient.Create method. -func (client *PathClient) Create(ctx context.Context, options *PathClientCreateOptions, pathHTTPHeaders *PathHTTPHeaders, leaseAccessConditions *LeaseAccessConditions, modifiedAccessConditions *ModifiedAccessConditions, sourceModifiedAccessConditions *SourceModifiedAccessConditions, cpkInfo *CpkInfo) (PathClientCreateResponse, error) { +// - CPKInfo - CPKInfo contains a group of parameters for the PathClient.Create method. +func (client *PathClient) Create(ctx context.Context, options *PathClientCreateOptions, pathHTTPHeaders *PathHTTPHeaders, leaseAccessConditions *LeaseAccessConditions, modifiedAccessConditions *ModifiedAccessConditions, sourceModifiedAccessConditions *SourceModifiedAccessConditions, cpkInfo *CPKInfo) (PathClientCreateResponse, error) { req, err := client.createCreateRequest(ctx, options, pathHTTPHeaders, leaseAccessConditions, modifiedAccessConditions, sourceModifiedAccessConditions, cpkInfo) if err != nil { return PathClientCreateResponse{}, err } - resp, err := client.pl.Do(req) + resp, err := client.internal.Pipeline().Do(req) if err != nil { return PathClientCreateResponse{}, err } @@ -188,7 +182,7 @@ func (client *PathClient) Create(ctx context.Context, options *PathClientCreateO } // createCreateRequest creates the Create request. -func (client *PathClient) createCreateRequest(ctx context.Context, options *PathClientCreateOptions, pathHTTPHeaders *PathHTTPHeaders, leaseAccessConditions *LeaseAccessConditions, modifiedAccessConditions *ModifiedAccessConditions, sourceModifiedAccessConditions *SourceModifiedAccessConditions, cpkInfo *CpkInfo) (*policy.Request, error) { +func (client *PathClient) createCreateRequest(ctx context.Context, options *PathClientCreateOptions, pathHTTPHeaders *PathHTTPHeaders, leaseAccessConditions *LeaseAccessConditions, modifiedAccessConditions *ModifiedAccessConditions, sourceModifiedAccessConditions *SourceModifiedAccessConditions, cpkInfo *CPKInfo) (*policy.Request, error) { req, err := runtime.NewRequest(ctx, http.MethodPut, client.endpoint) if err != nil { return nil, err @@ -245,10 +239,10 @@ func (client *PathClient) createCreateRequest(ctx context.Context, options *Path req.Raw().Header["x-ms-umask"] = []string{*options.Umask} } if modifiedAccessConditions != nil && modifiedAccessConditions.IfMatch != nil { - req.Raw().Header["If-Match"] = []string{*modifiedAccessConditions.IfMatch} + req.Raw().Header["If-Match"] = []string{string(*modifiedAccessConditions.IfMatch)} } if modifiedAccessConditions != nil && modifiedAccessConditions.IfNoneMatch != nil { - req.Raw().Header["If-None-Match"] = []string{*modifiedAccessConditions.IfNoneMatch} + req.Raw().Header["If-None-Match"] = []string{string(*modifiedAccessConditions.IfNoneMatch)} } if modifiedAccessConditions != nil && modifiedAccessConditions.IfModifiedSince != nil { req.Raw().Header["If-Modified-Since"] = []string{modifiedAccessConditions.IfModifiedSince.Format(time.RFC1123)} @@ -257,10 +251,10 @@ func (client *PathClient) createCreateRequest(ctx context.Context, options *Path req.Raw().Header["If-Unmodified-Since"] = []string{modifiedAccessConditions.IfUnmodifiedSince.Format(time.RFC1123)} } if sourceModifiedAccessConditions != nil && sourceModifiedAccessConditions.SourceIfMatch != nil { - req.Raw().Header["x-ms-source-if-match"] = []string{*sourceModifiedAccessConditions.SourceIfMatch} + req.Raw().Header["x-ms-source-if-match"] = []string{string(*sourceModifiedAccessConditions.SourceIfMatch)} } if sourceModifiedAccessConditions != nil && sourceModifiedAccessConditions.SourceIfNoneMatch != nil { - req.Raw().Header["x-ms-source-if-none-match"] = []string{*sourceModifiedAccessConditions.SourceIfNoneMatch} + req.Raw().Header["x-ms-source-if-none-match"] = []string{string(*sourceModifiedAccessConditions.SourceIfNoneMatch)} } if sourceModifiedAccessConditions != nil && sourceModifiedAccessConditions.SourceIfModifiedSince != nil { req.Raw().Header["x-ms-source-if-modified-since"] = []string{sourceModifiedAccessConditions.SourceIfModifiedSince.Format(time.RFC1123)} @@ -275,7 +269,28 @@ func (client *PathClient) createCreateRequest(ctx context.Context, options *Path req.Raw().Header["x-ms-encryption-key-sha256"] = []string{*cpkInfo.EncryptionKeySHA256} } if cpkInfo != nil && cpkInfo.EncryptionAlgorithm != nil { - req.Raw().Header["x-ms-encryption-algorithm"] = []string{"AES256"} + req.Raw().Header["x-ms-encryption-algorithm"] = []string{string(*cpkInfo.EncryptionAlgorithm)} + } + if options != nil && options.Owner != nil { + req.Raw().Header["x-ms-owner"] = []string{*options.Owner} + } + if options != nil && options.Group != nil { + req.Raw().Header["x-ms-group"] = []string{*options.Group} + } + if options != nil && options.ACL != nil { + req.Raw().Header["x-ms-acl"] = []string{*options.ACL} + } + if options != nil && options.ProposedLeaseID != nil { + req.Raw().Header["x-ms-proposed-lease-id"] = []string{*options.ProposedLeaseID} + } + if options != nil && options.LeaseDuration != nil { + req.Raw().Header["x-ms-lease-duration"] = []string{strconv.FormatInt(*options.LeaseDuration, 10)} + } + if options != nil && options.ExpiryOptions != nil { + req.Raw().Header["x-ms-expiry-option"] = []string{string(*options.ExpiryOptions)} + } + if options != nil && options.ExpiresOn != nil { + req.Raw().Header["x-ms-expiry-time"] = []string{*options.ExpiresOn} } req.Raw().Header["Accept"] = []string{"application/json"} return req, nil @@ -292,7 +307,7 @@ func (client *PathClient) createHandleResponse(resp *http.Response) (PathClientC result.Date = &date } if val := resp.Header.Get("ETag"); val != "" { - result.ETag = &val + result.ETag = (*azcore.ETag)(&val) } if val := resp.Header.Get("Last-Modified"); val != "" { lastModified, err := time.Parse(time.RFC1123, val) @@ -345,7 +360,7 @@ func (client *PathClient) Delete(ctx context.Context, options *PathClientDeleteO if err != nil { return PathClientDeleteResponse{}, err } - resp, err := client.pl.Do(req) + resp, err := client.internal.Pipeline().Do(req) if err != nil { return PathClientDeleteResponse{}, err } @@ -380,10 +395,10 @@ func (client *PathClient) deleteCreateRequest(ctx context.Context, options *Path req.Raw().Header["x-ms-lease-id"] = []string{*leaseAccessConditions.LeaseID} } if modifiedAccessConditions != nil && modifiedAccessConditions.IfMatch != nil { - req.Raw().Header["If-Match"] = []string{*modifiedAccessConditions.IfMatch} + req.Raw().Header["If-Match"] = []string{string(*modifiedAccessConditions.IfMatch)} } if modifiedAccessConditions != nil && modifiedAccessConditions.IfNoneMatch != nil { - req.Raw().Header["If-None-Match"] = []string{*modifiedAccessConditions.IfNoneMatch} + req.Raw().Header["If-None-Match"] = []string{string(*modifiedAccessConditions.IfNoneMatch)} } if modifiedAccessConditions != nil && modifiedAccessConditions.IfModifiedSince != nil { req.Raw().Header["If-Modified-Since"] = []string{modifiedAccessConditions.IfModifiedSince.Format(time.RFC1123)} @@ -429,13 +444,13 @@ func (client *PathClient) deleteHandleResponse(resp *http.Response) (PathClientD // - LeaseAccessConditions - LeaseAccessConditions contains a group of parameters for the PathClient.Create method. // - ModifiedAccessConditions - ModifiedAccessConditions contains a group of parameters for the FileSystemClient.SetProperties // method. -// - CpkInfo - CpkInfo contains a group of parameters for the PathClient.Create method. -func (client *PathClient) FlushData(ctx context.Context, options *PathClientFlushDataOptions, pathHTTPHeaders *PathHTTPHeaders, leaseAccessConditions *LeaseAccessConditions, modifiedAccessConditions *ModifiedAccessConditions, cpkInfo *CpkInfo) (PathClientFlushDataResponse, error) { +// - CPKInfo - CPKInfo contains a group of parameters for the PathClient.Create method. +func (client *PathClient) FlushData(ctx context.Context, options *PathClientFlushDataOptions, pathHTTPHeaders *PathHTTPHeaders, leaseAccessConditions *LeaseAccessConditions, modifiedAccessConditions *ModifiedAccessConditions, cpkInfo *CPKInfo) (PathClientFlushDataResponse, error) { req, err := client.flushDataCreateRequest(ctx, options, pathHTTPHeaders, leaseAccessConditions, modifiedAccessConditions, cpkInfo) if err != nil { return PathClientFlushDataResponse{}, err } - resp, err := client.pl.Do(req) + resp, err := client.internal.Pipeline().Do(req) if err != nil { return PathClientFlushDataResponse{}, err } @@ -446,7 +461,7 @@ func (client *PathClient) FlushData(ctx context.Context, options *PathClientFlus } // flushDataCreateRequest creates the FlushData request. -func (client *PathClient) flushDataCreateRequest(ctx context.Context, options *PathClientFlushDataOptions, pathHTTPHeaders *PathHTTPHeaders, leaseAccessConditions *LeaseAccessConditions, modifiedAccessConditions *ModifiedAccessConditions, cpkInfo *CpkInfo) (*policy.Request, error) { +func (client *PathClient) flushDataCreateRequest(ctx context.Context, options *PathClientFlushDataOptions, pathHTTPHeaders *PathHTTPHeaders, leaseAccessConditions *LeaseAccessConditions, modifiedAccessConditions *ModifiedAccessConditions, cpkInfo *CPKInfo) (*policy.Request, error) { req, err := runtime.NewRequest(ctx, http.MethodPatch, client.endpoint) if err != nil { return nil, err @@ -491,10 +506,10 @@ func (client *PathClient) flushDataCreateRequest(ctx context.Context, options *P req.Raw().Header["x-ms-content-language"] = []string{*pathHTTPHeaders.ContentLanguage} } if modifiedAccessConditions != nil && modifiedAccessConditions.IfMatch != nil { - req.Raw().Header["If-Match"] = []string{*modifiedAccessConditions.IfMatch} + req.Raw().Header["If-Match"] = []string{string(*modifiedAccessConditions.IfMatch)} } if modifiedAccessConditions != nil && modifiedAccessConditions.IfNoneMatch != nil { - req.Raw().Header["If-None-Match"] = []string{*modifiedAccessConditions.IfNoneMatch} + req.Raw().Header["If-None-Match"] = []string{string(*modifiedAccessConditions.IfNoneMatch)} } if modifiedAccessConditions != nil && modifiedAccessConditions.IfModifiedSince != nil { req.Raw().Header["If-Modified-Since"] = []string{modifiedAccessConditions.IfModifiedSince.Format(time.RFC1123)} @@ -513,7 +528,7 @@ func (client *PathClient) flushDataCreateRequest(ctx context.Context, options *P req.Raw().Header["x-ms-encryption-key-sha256"] = []string{*cpkInfo.EncryptionKeySHA256} } if cpkInfo != nil && cpkInfo.EncryptionAlgorithm != nil { - req.Raw().Header["x-ms-encryption-algorithm"] = []string{"AES256"} + req.Raw().Header["x-ms-encryption-algorithm"] = []string{string(*cpkInfo.EncryptionAlgorithm)} } req.Raw().Header["Accept"] = []string{"application/json"} return req, nil @@ -530,7 +545,7 @@ func (client *PathClient) flushDataHandleResponse(resp *http.Response) (PathClie result.Date = &date } if val := resp.Header.Get("ETag"); val != "" { - result.ETag = &val + result.ETag = (*azcore.ETag)(&val) } if val := resp.Header.Get("Last-Modified"); val != "" { lastModified, err := time.Parse(time.RFC1123, val) @@ -585,7 +600,7 @@ func (client *PathClient) GetProperties(ctx context.Context, options *PathClient if err != nil { return PathClientGetPropertiesResponse{}, err } - resp, err := client.pl.Do(req) + resp, err := client.internal.Pipeline().Do(req) if err != nil { return PathClientGetPropertiesResponse{}, err } @@ -620,10 +635,10 @@ func (client *PathClient) getPropertiesCreateRequest(ctx context.Context, option req.Raw().Header["x-ms-lease-id"] = []string{*leaseAccessConditions.LeaseID} } if modifiedAccessConditions != nil && modifiedAccessConditions.IfMatch != nil { - req.Raw().Header["If-Match"] = []string{*modifiedAccessConditions.IfMatch} + req.Raw().Header["If-Match"] = []string{string(*modifiedAccessConditions.IfMatch)} } if modifiedAccessConditions != nil && modifiedAccessConditions.IfNoneMatch != nil { - req.Raw().Header["If-None-Match"] = []string{*modifiedAccessConditions.IfNoneMatch} + req.Raw().Header["If-None-Match"] = []string{string(*modifiedAccessConditions.IfNoneMatch)} } if modifiedAccessConditions != nil && modifiedAccessConditions.IfModifiedSince != nil { req.Raw().Header["If-Modified-Since"] = []string{modifiedAccessConditions.IfModifiedSince.Format(time.RFC1123)} @@ -677,7 +692,7 @@ func (client *PathClient) getPropertiesHandleResponse(resp *http.Response) (Path result.Date = &date } if val := resp.Header.Get("ETag"); val != "" { - result.ETag = &val + result.ETag = (*azcore.ETag)(&val) } if val := resp.Header.Get("Last-Modified"); val != "" { lastModified, err := time.Parse(time.RFC1123, val) @@ -746,7 +761,7 @@ func (client *PathClient) Lease(ctx context.Context, xmsLeaseAction PathLeaseAct if err != nil { return PathClientLeaseResponse{}, err } - resp, err := client.pl.Do(req) + resp, err := client.internal.Pipeline().Do(req) if err != nil { return PathClientLeaseResponse{}, err } @@ -772,9 +787,7 @@ func (client *PathClient) leaseCreateRequest(ctx context.Context, xmsLeaseAction } req.Raw().Header["x-ms-version"] = []string{"2020-10-02"} req.Raw().Header["x-ms-lease-action"] = []string{string(xmsLeaseAction)} - if options != nil && options.XMSLeaseDuration != nil { - req.Raw().Header["x-ms-lease-duration"] = []string{strconv.FormatInt(int64(*options.XMSLeaseDuration), 10)} - } + req.Raw().Header["x-ms-lease-duration"] = []string{strconv.FormatInt(int64(client.xmsLeaseDuration), 10)} if options != nil && options.XMSLeaseBreakPeriod != nil { req.Raw().Header["x-ms-lease-break-period"] = []string{strconv.FormatInt(int64(*options.XMSLeaseBreakPeriod), 10)} } @@ -785,10 +798,10 @@ func (client *PathClient) leaseCreateRequest(ctx context.Context, xmsLeaseAction req.Raw().Header["x-ms-proposed-lease-id"] = []string{*options.ProposedLeaseID} } if modifiedAccessConditions != nil && modifiedAccessConditions.IfMatch != nil { - req.Raw().Header["If-Match"] = []string{*modifiedAccessConditions.IfMatch} + req.Raw().Header["If-Match"] = []string{string(*modifiedAccessConditions.IfMatch)} } if modifiedAccessConditions != nil && modifiedAccessConditions.IfNoneMatch != nil { - req.Raw().Header["If-None-Match"] = []string{*modifiedAccessConditions.IfNoneMatch} + req.Raw().Header["If-None-Match"] = []string{string(*modifiedAccessConditions.IfNoneMatch)} } if modifiedAccessConditions != nil && modifiedAccessConditions.IfModifiedSince != nil { req.Raw().Header["If-Modified-Since"] = []string{modifiedAccessConditions.IfModifiedSince.Format(time.RFC1123)} @@ -811,7 +824,7 @@ func (client *PathClient) leaseHandleResponse(resp *http.Response) (PathClientLe result.Date = &date } if val := resp.Header.Get("ETag"); val != "" { - result.ETag = &val + result.ETag = (*azcore.ETag)(&val) } if val := resp.Header.Get("Last-Modified"); val != "" { lastModified, err := time.Parse(time.RFC1123, val) @@ -845,13 +858,13 @@ func (client *PathClient) leaseHandleResponse(resp *http.Response) (PathClientLe // - LeaseAccessConditions - LeaseAccessConditions contains a group of parameters for the PathClient.Create method. // - ModifiedAccessConditions - ModifiedAccessConditions contains a group of parameters for the FileSystemClient.SetProperties // method. -// - CpkInfo - CpkInfo contains a group of parameters for the PathClient.Create method. -func (client *PathClient) Read(ctx context.Context, options *PathClientReadOptions, leaseAccessConditions *LeaseAccessConditions, modifiedAccessConditions *ModifiedAccessConditions, cpkInfo *CpkInfo) (PathClientReadResponse, error) { +// - CPKInfo - CPKInfo contains a group of parameters for the PathClient.Create method. +func (client *PathClient) Read(ctx context.Context, options *PathClientReadOptions, leaseAccessConditions *LeaseAccessConditions, modifiedAccessConditions *ModifiedAccessConditions, cpkInfo *CPKInfo) (PathClientReadResponse, error) { req, err := client.readCreateRequest(ctx, options, leaseAccessConditions, modifiedAccessConditions, cpkInfo) if err != nil { return PathClientReadResponse{}, err } - resp, err := client.pl.Do(req) + resp, err := client.internal.Pipeline().Do(req) if err != nil { return PathClientReadResponse{}, err } @@ -862,7 +875,7 @@ func (client *PathClient) Read(ctx context.Context, options *PathClientReadOptio } // readCreateRequest creates the Read request. -func (client *PathClient) readCreateRequest(ctx context.Context, options *PathClientReadOptions, leaseAccessConditions *LeaseAccessConditions, modifiedAccessConditions *ModifiedAccessConditions, cpkInfo *CpkInfo) (*policy.Request, error) { +func (client *PathClient) readCreateRequest(ctx context.Context, options *PathClientReadOptions, leaseAccessConditions *LeaseAccessConditions, modifiedAccessConditions *ModifiedAccessConditions, cpkInfo *CPKInfo) (*policy.Request, error) { req, err := runtime.NewRequest(ctx, http.MethodGet, client.endpoint) if err != nil { return nil, err @@ -887,10 +900,10 @@ func (client *PathClient) readCreateRequest(ctx context.Context, options *PathCl req.Raw().Header["x-ms-range-get-content-md5"] = []string{strconv.FormatBool(*options.XMSRangeGetContentMD5)} } if modifiedAccessConditions != nil && modifiedAccessConditions.IfMatch != nil { - req.Raw().Header["If-Match"] = []string{*modifiedAccessConditions.IfMatch} + req.Raw().Header["If-Match"] = []string{string(*modifiedAccessConditions.IfMatch)} } if modifiedAccessConditions != nil && modifiedAccessConditions.IfNoneMatch != nil { - req.Raw().Header["If-None-Match"] = []string{*modifiedAccessConditions.IfNoneMatch} + req.Raw().Header["If-None-Match"] = []string{string(*modifiedAccessConditions.IfNoneMatch)} } if modifiedAccessConditions != nil && modifiedAccessConditions.IfModifiedSince != nil { req.Raw().Header["If-Modified-Since"] = []string{modifiedAccessConditions.IfModifiedSince.Format(time.RFC1123)} @@ -905,7 +918,7 @@ func (client *PathClient) readCreateRequest(ctx context.Context, options *PathCl req.Raw().Header["x-ms-encryption-key-sha256"] = []string{*cpkInfo.EncryptionKeySHA256} } if cpkInfo != nil && cpkInfo.EncryptionAlgorithm != nil { - req.Raw().Header["x-ms-encryption-algorithm"] = []string{"AES256"} + req.Raw().Header["x-ms-encryption-algorithm"] = []string{string(*cpkInfo.EncryptionAlgorithm)} } req.Raw().Header["Accept"] = []string{"application/json"} return req, nil @@ -953,7 +966,7 @@ func (client *PathClient) readHandleResponse(resp *http.Response) (PathClientRea result.Date = &date } if val := resp.Header.Get("ETag"); val != "" { - result.ETag = &val + result.ETag = (*azcore.ETag)(&val) } if val := resp.Header.Get("Last-Modified"); val != "" { lastModified, err := time.Parse(time.RFC1123, val) @@ -1012,7 +1025,7 @@ func (client *PathClient) SetAccessControl(ctx context.Context, options *PathCli if err != nil { return PathClientSetAccessControlResponse{}, err } - resp, err := client.pl.Do(req) + resp, err := client.internal.Pipeline().Do(req) if err != nil { return PathClientSetAccessControlResponse{}, err } @@ -1050,10 +1063,10 @@ func (client *PathClient) setAccessControlCreateRequest(ctx context.Context, opt req.Raw().Header["x-ms-acl"] = []string{*options.ACL} } if modifiedAccessConditions != nil && modifiedAccessConditions.IfMatch != nil { - req.Raw().Header["If-Match"] = []string{*modifiedAccessConditions.IfMatch} + req.Raw().Header["If-Match"] = []string{string(*modifiedAccessConditions.IfMatch)} } if modifiedAccessConditions != nil && modifiedAccessConditions.IfNoneMatch != nil { - req.Raw().Header["If-None-Match"] = []string{*modifiedAccessConditions.IfNoneMatch} + req.Raw().Header["If-None-Match"] = []string{string(*modifiedAccessConditions.IfNoneMatch)} } if modifiedAccessConditions != nil && modifiedAccessConditions.IfModifiedSince != nil { req.Raw().Header["If-Modified-Since"] = []string{modifiedAccessConditions.IfModifiedSince.Format(time.RFC1123)} @@ -1080,7 +1093,7 @@ func (client *PathClient) setAccessControlHandleResponse(resp *http.Response) (P result.Date = &date } if val := resp.Header.Get("ETag"); val != "" { - result.ETag = &val + result.ETag = (*azcore.ETag)(&val) } if val := resp.Header.Get("Last-Modified"); val != "" { lastModified, err := time.Parse(time.RFC1123, val) @@ -1115,7 +1128,7 @@ func (client *PathClient) SetAccessControlRecursive(ctx context.Context, mode Pa if err != nil { return PathClientSetAccessControlRecursiveResponse{}, err } - resp, err := client.pl.Do(req) + resp, err := client.internal.Pipeline().Do(req) if err != nil { return PathClientSetAccessControlRecursiveResponse{}, err } @@ -1192,12 +1205,12 @@ func (client *PathClient) setAccessControlRecursiveHandleResponse(resp *http.Res // Generated from API version 2020-10-02 // - expiryOptions - Required. Indicates mode of the expiry time // - options - PathClientSetExpiryOptions contains the optional parameters for the PathClient.SetExpiry method. -func (client *PathClient) SetExpiry(ctx context.Context, expiryOptions PathExpiryOptions, options *PathClientSetExpiryOptions) (PathClientSetExpiryResponse, error) { +func (client *PathClient) SetExpiry(ctx context.Context, expiryOptions ExpiryOptions, options *PathClientSetExpiryOptions) (PathClientSetExpiryResponse, error) { req, err := client.setExpiryCreateRequest(ctx, expiryOptions, options) if err != nil { return PathClientSetExpiryResponse{}, err } - resp, err := client.pl.Do(req) + resp, err := client.internal.Pipeline().Do(req) if err != nil { return PathClientSetExpiryResponse{}, err } @@ -1208,7 +1221,7 @@ func (client *PathClient) SetExpiry(ctx context.Context, expiryOptions PathExpir } // setExpiryCreateRequest creates the SetExpiry request. -func (client *PathClient) setExpiryCreateRequest(ctx context.Context, expiryOptions PathExpiryOptions, options *PathClientSetExpiryOptions) (*policy.Request, error) { +func (client *PathClient) setExpiryCreateRequest(ctx context.Context, expiryOptions ExpiryOptions, options *PathClientSetExpiryOptions) (*policy.Request, error) { req, err := runtime.NewRequest(ctx, http.MethodPut, client.endpoint) if err != nil { return nil, err @@ -1235,7 +1248,7 @@ func (client *PathClient) setExpiryCreateRequest(ctx context.Context, expiryOpti func (client *PathClient) setExpiryHandleResponse(resp *http.Response) (PathClientSetExpiryResponse, error) { result := PathClientSetExpiryResponse{} if val := resp.Header.Get("ETag"); val != "" { - result.ETag = &val + result.ETag = (*azcore.ETag)(&val) } if val := resp.Header.Get("Last-Modified"); val != "" { lastModified, err := time.Parse(time.RFC1123, val) @@ -1273,7 +1286,7 @@ func (client *PathClient) Undelete(ctx context.Context, options *PathClientUndel if err != nil { return PathClientUndeleteResponse{}, err } - resp, err := client.pl.Do(req) + resp, err := client.internal.Pipeline().Do(req) if err != nil { return PathClientUndeleteResponse{}, err } @@ -1360,7 +1373,7 @@ func (client *PathClient) Update(ctx context.Context, action PathUpdateAction, m if err != nil { return PathClientUpdateResponse{}, err } - resp, err := client.pl.Do(req) + resp, err := client.internal.Pipeline().Do(req) if err != nil { return PathClientUpdateResponse{}, err } @@ -1445,10 +1458,10 @@ func (client *PathClient) updateCreateRequest(ctx context.Context, action PathUp req.Raw().Header["x-ms-acl"] = []string{*options.ACL} } if modifiedAccessConditions != nil && modifiedAccessConditions.IfMatch != nil { - req.Raw().Header["If-Match"] = []string{*modifiedAccessConditions.IfMatch} + req.Raw().Header["If-Match"] = []string{string(*modifiedAccessConditions.IfMatch)} } if modifiedAccessConditions != nil && modifiedAccessConditions.IfNoneMatch != nil { - req.Raw().Header["If-None-Match"] = []string{*modifiedAccessConditions.IfNoneMatch} + req.Raw().Header["If-None-Match"] = []string{string(*modifiedAccessConditions.IfNoneMatch)} } if modifiedAccessConditions != nil && modifiedAccessConditions.IfModifiedSince != nil { req.Raw().Header["If-Modified-Since"] = []string{modifiedAccessConditions.IfModifiedSince.Format(time.RFC1123)} @@ -1457,7 +1470,10 @@ func (client *PathClient) updateCreateRequest(ctx context.Context, action PathUp req.Raw().Header["If-Unmodified-Since"] = []string{modifiedAccessConditions.IfUnmodifiedSince.Format(time.RFC1123)} } req.Raw().Header["Accept"] = []string{"application/json"} - return req, req.SetBody(body, "application/octet-stream") + if err := req.SetBody(body, "application/octet-stream"); err != nil { + return nil, err + } + return req, nil } // updateHandleResponse handles the Update response. @@ -1471,7 +1487,7 @@ func (client *PathClient) updateHandleResponse(resp *http.Response) (PathClientU result.Date = &date } if val := resp.Header.Get("ETag"); val != "" { - result.ETag = &val + result.ETag = (*azcore.ETag)(&val) } if val := resp.Header.Get("Last-Modified"); val != "" { lastModified, err := time.Parse(time.RFC1123, val) diff --git a/sdk/storage/azdatalake/internal/generated/zz_response_types.go b/sdk/storage/azdatalake/internal/generated/zz_response_types.go index e95f5035e654..0c55d6312788 100644 --- a/sdk/storage/azdatalake/internal/generated/zz_response_types.go +++ b/sdk/storage/azdatalake/internal/generated/zz_response_types.go @@ -10,6 +10,7 @@ package generated import ( + "github.com/Azure/azure-sdk-for-go/sdk/azcore" "io" "time" ) @@ -23,7 +24,7 @@ type FileSystemClientCreateResponse struct { Date *time.Time // ETag contains the information returned from the ETag header response. - ETag *string + ETag *azcore.ETag // LastModified contains the information returned from the Last-Modified header response. LastModified *time.Time @@ -53,7 +54,7 @@ type FileSystemClientGetPropertiesResponse struct { Date *time.Time // ETag contains the information returned from the ETag header response. - ETag *string + ETag *azcore.ETag // LastModified contains the information returned from the Last-Modified header response. LastModified *time.Time @@ -100,7 +101,7 @@ type FileSystemClientListPathsResponse struct { Date *time.Time // ETag contains the information returned from the ETag header response. - ETag *string + ETag *azcore.ETag // LastModified contains the information returned from the Last-Modified header response. LastModified *time.Time @@ -118,7 +119,7 @@ type FileSystemClientSetPropertiesResponse struct { Date *time.Time // ETag contains the information returned from the ETag header response. - ETag *string + ETag *azcore.ETag // LastModified contains the information returned from the Last-Modified header response. LastModified *time.Time @@ -135,6 +136,9 @@ type PathClientAppendDataResponse struct { // ClientRequestID contains the information returned from the x-ms-client-request-id header response. ClientRequestID *string + // ContentCRC64 contains the information returned from the x-ms-content-crc64 header response. + ContentCRC64 []byte + // ContentMD5 contains the information returned from the Content-MD5 header response. ContentMD5 []byte @@ -142,7 +146,7 @@ type PathClientAppendDataResponse struct { Date *time.Time // ETag contains the information returned from the ETag header response. - ETag *string + ETag *azcore.ETag // EncryptionKeySHA256 contains the information returned from the x-ms-encryption-key-sha256 header response. EncryptionKeySHA256 *string @@ -155,9 +159,6 @@ type PathClientAppendDataResponse struct { // Version contains the information returned from the x-ms-version header response. Version *string - - // XMSContentCRC64 contains the information returned from the x-ms-content-crc64 header response. - XMSContentCRC64 []byte } // PathClientCreateResponse contains the response from method PathClient.Create. @@ -172,7 +173,7 @@ type PathClientCreateResponse struct { Date *time.Time // ETag contains the information returned from the ETag header response. - ETag *string + ETag *azcore.ETag // EncryptionKeySHA256 contains the information returned from the x-ms-encryption-key-sha256 header response. EncryptionKeySHA256 *string @@ -220,7 +221,7 @@ type PathClientFlushDataResponse struct { Date *time.Time // ETag contains the information returned from the ETag header response. - ETag *string + ETag *azcore.ETag // EncryptionKeySHA256 contains the information returned from the x-ms-encryption-key-sha256 header response. EncryptionKeySHA256 *string @@ -274,7 +275,7 @@ type PathClientGetPropertiesResponse struct { Date *time.Time // ETag contains the information returned from the ETag header response. - ETag *string + ETag *azcore.ETag // Group contains the information returned from the x-ms-group header response. Group *string @@ -316,7 +317,7 @@ type PathClientLeaseResponse struct { Date *time.Time // ETag contains the information returned from the ETag header response. - ETag *string + ETag *azcore.ETag // LastModified contains the information returned from the Last-Modified header response. LastModified *time.Time @@ -370,7 +371,7 @@ type PathClientReadResponse struct { Date *time.Time // ETag contains the information returned from the ETag header response. - ETag *string + ETag *azcore.ETag // EncryptionKeySHA256 contains the information returned from the x-ms-encryption-key-sha256 header response. EncryptionKeySHA256 *string @@ -434,7 +435,7 @@ type PathClientSetAccessControlResponse struct { Date *time.Time // ETag contains the information returned from the ETag header response. - ETag *string + ETag *azcore.ETag // LastModified contains the information returned from the Last-Modified header response. LastModified *time.Time @@ -455,7 +456,7 @@ type PathClientSetExpiryResponse struct { Date *time.Time // ETag contains the information returned from the ETag header response. - ETag *string + ETag *azcore.ETag // LastModified contains the information returned from the Last-Modified header response. LastModified *time.Time @@ -519,7 +520,7 @@ type PathClientUpdateResponse struct { Date *time.Time // ETag contains the information returned from the ETag header response. - ETag *string + ETag *azcore.ETag // LastModified contains the information returned from the Last-Modified header response. LastModified *time.Time diff --git a/sdk/storage/azdatalake/internal/generated/zz_service_client.go b/sdk/storage/azdatalake/internal/generated/zz_service_client.go index 40654cbdefbe..f4322dd4f3fd 100644 --- a/sdk/storage/azdatalake/internal/generated/zz_service_client.go +++ b/sdk/storage/azdatalake/internal/generated/zz_service_client.go @@ -11,29 +11,20 @@ package generated import ( "context" + "github.com/Azure/azure-sdk-for-go/sdk/azcore" "github.com/Azure/azure-sdk-for-go/sdk/azcore/policy" "github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime" "net/http" "strconv" + "strings" "time" ) // ServiceClient contains the methods for the Service group. -// Don't use this type directly, use NewServiceClient() instead. +// Don't use this type directly, use a constructor function instead. type ServiceClient struct { + internal *azcore.Client endpoint string - pl runtime.Pipeline -} - -// NewServiceClient creates a new instance of ServiceClient with the specified values. -// - endpoint - The URL of the service account, container, or blob that is the target of the desired operation. -// - pl - the pipeline used for sending requests and handling responses. -func NewServiceClient(endpoint string, pl runtime.Pipeline) *ServiceClient { - client := &ServiceClient{ - endpoint: endpoint, - pl: pl, - } - return client } // NewListFileSystemsPager - List filesystems and their properties in given account. @@ -62,7 +53,7 @@ func (client *FileSystemClient) ListFileSystemsCreateRequest(ctx context.Context if options != nil && options.Timeout != nil { reqQP.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) } - req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().URL.RawQuery = strings.Replace(reqQP.Encode(), "+", "%20", -1) if options != nil && options.RequestID != nil { req.Raw().Header["x-ms-client-request-id"] = []string{*options.RequestID} } diff --git a/sdk/storage/azdatalake/internal/path/client.go b/sdk/storage/azdatalake/internal/path/client.go new file mode 100644 index 000000000000..bfeab81bcbcc --- /dev/null +++ b/sdk/storage/azdatalake/internal/path/client.go @@ -0,0 +1,71 @@ +//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 path + +import ( + "context" + "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" +) + +// Client represents a URL to the Azure Datalake Storage service allowing you to manipulate paths. +type Client base.Client[generated.PathClient] + +func (p *Client) generated() *generated.PathClient { + return base.InnerClient((*base.Client[generated.PathClient])(p)) +} + +func (p *Client) sharedKey() *exported.SharedKeyCredential { + return base.SharedKey((*base.Client[generated.PathClient])(p)) +} + +// URL returns the URL endpoint used by the Client object. +func (p *Client) URL() string { + return "s.generated().Endpoint()" +} + +// SetAccessControl sets the owner, owning group, and permissions for a file or directory (dfs1). +func (p *Client) SetAccessControl(ctx context.Context, options *SetAccessControlOptions) (SetAccessControlResponse, error) { + return SetAccessControlResponse{}, nil +} + +// SetAccessControlRecursive sets the owner, owning group, and permissions for a file or directory (dfs1). +func (p *Client) SetAccessControlRecursive(ctx context.Context, options *SetAccessControlRecursiveOptions) (SetAccessControlRecursiveResponse, error) { + // TODO explicitly pass SetAccessControlRecursiveMode + return SetAccessControlRecursiveResponse{}, nil +} + +// UpdateAccessControlRecursive updates the owner, owning group, and permissions for a file or directory (dfs1). +func (p *Client) UpdateAccessControlRecursive(ctx context.Context, options *UpdateAccessControlRecursiveOptions) (UpdateAccessControlRecursiveResponse, error) { + // TODO explicitly pass SetAccessControlRecursiveMode + return SetAccessControlRecursiveResponse{}, nil +} + +// GetAccessControl gets the owner, owning group, and permissions for a file or directory (dfs1). +func (p *Client) GetAccessControl(ctx context.Context, options *GetAccessControlOptions) (GetAccessControlResponse, error) { + return GetAccessControlResponse{}, nil +} + +// RemoveAccessControlRecursive removes the owner, owning group, and permissions for a file or directory (dfs1). +func (p *Client) RemoveAccessControlRecursive(ctx context.Context, options *RemoveAccessControlRecursiveOptions) (RemoveAccessControlRecursiveResponse, error) { + // TODO explicitly pass SetAccessControlRecursiveMode + return SetAccessControlRecursiveResponse{}, nil +} + +// SetMetadata sets the metadata for a file or directory (blob3). +func (p *Client) SetMetadata(ctx context.Context, options *SetMetadataOptions) (SetMetadataResponse, error) { + // TODO: call directly into blob + return SetMetadataResponse{}, nil +} + +// SetHTTPHeaders sets the HTTP headers for a file or directory (blob3). +func (p *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 +} diff --git a/sdk/storage/azdatalake/internal/path/constants.go b/sdk/storage/azdatalake/internal/path/constants.go new file mode 100644 index 000000000000..d2d11defca1c --- /dev/null +++ b/sdk/storage/azdatalake/internal/path/constants.go @@ -0,0 +1,43 @@ +//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 path + +import ( + "github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/blob" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/internal/generated" +) + +type ResourceType = generated.PathResourceType + +// TODO: consider the possibility of not exposing this and just pass it under the hood +const ( + ResourceTypeFile ResourceType = generated.PathResourceTypeFile + ResourceTypeDirectory ResourceType = generated.PathResourceTypeDirectory +) + +type RenameMode = generated.PathRenameMode + +// TODO: consider the possibility of not exposing this and just pass it under the hood +const ( + RenameModeLegacy RenameMode = generated.PathRenameModeLegacy + RenameModePosix RenameMode = generated.PathRenameModePosix +) + +type SetAccessControlRecursiveMode = generated.PathSetAccessControlRecursiveMode + +const ( + SetAccessControlRecursiveModeSet SetAccessControlRecursiveMode = generated.PathSetAccessControlRecursiveModeSet + SetAccessControlRecursiveModeModify SetAccessControlRecursiveMode = generated.PathSetAccessControlRecursiveModeModify + SetAccessControlRecursiveModeRemove SetAccessControlRecursiveMode = generated.PathSetAccessControlRecursiveModeRemove +) + +type EncryptionAlgorithmType = blob.EncryptionAlgorithmType + +const ( + EncryptionAlgorithmTypeNone EncryptionAlgorithmType = blob.EncryptionAlgorithmTypeNone + EncryptionAlgorithmTypeAES256 EncryptionAlgorithmType = blob.EncryptionAlgorithmTypeAES256 +) diff --git a/sdk/storage/azdatalake/internal/path/models.go b/sdk/storage/azdatalake/internal/path/models.go new file mode 100644 index 000000000000..75cca62c85c8 --- /dev/null +++ b/sdk/storage/azdatalake/internal/path/models.go @@ -0,0 +1,227 @@ +//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 path + +import ( + "github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/blob" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/internal/generated" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/internal/shared" +) + +// SetAccessControlOptions contains the optional parameters when calling the SetAccessControl operation. dfs endpoint +type SetAccessControlOptions struct { + // Owner is the owner of the path. + Owner *string + // Group is the owning group of the path. + Group *string + // ACL is the access control list for the path. + ACL *string + // Permissions is the octal representation of the permissions for user, group and mask. + Permissions *string + // AccessConditions contains parameters for accessing the path. + AccessConditions *azdatalake.AccessConditions +} + +func (o *SetAccessControlOptions) format() (*generated.PathClientSetAccessControlOptions, *generated.LeaseAccessConditions, *generated.ModifiedAccessConditions, error) { + if o == nil { + return nil, nil, nil, nil + } + // call path formatter since we're hitting dfs in this operation + leaseAccessConditions, modifiedAccessConditions := shared.FormatPathAccessConditions(o.AccessConditions) + return &generated.PathClientSetAccessControlOptions{ + Owner: o.Owner, + Group: o.Group, + ACL: o.ACL, + Permissions: o.Permissions, + }, leaseAccessConditions, modifiedAccessConditions, nil +} + +// GetAccessControlOptions contains the optional parameters when calling the GetAccessControl operation. +type GetAccessControlOptions struct { + // UPN is the user principal name. + UPN *bool + // AccessConditions contains parameters for accessing the path. + AccessConditions *azdatalake.AccessConditions +} + +func (o *GetAccessControlOptions) format() (*generated.PathClientGetPropertiesOptions, *generated.LeaseAccessConditions, *generated.ModifiedAccessConditions, error) { + action := generated.PathGetPropertiesActionGetAccessControl + if o == nil { + return &generated.PathClientGetPropertiesOptions{ + Action: &action, + }, nil, nil, nil + } + // call path formatter since we're hitting dfs in this operation + leaseAccessConditions, modifiedAccessConditions := shared.FormatPathAccessConditions(o.AccessConditions) + return &generated.PathClientGetPropertiesOptions{ + Upn: o.UPN, + Action: &action, + }, leaseAccessConditions, modifiedAccessConditions, nil +} + +// 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 + // 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 +} + +// 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 +} + +func (o *UpdateAccessControlRecursiveOptions) format() (*generated.PathClientSetAccessControlRecursiveOptions, error) { + // TODO: design formatter - similar to SetAccessControlRecursiveOptions + return nil, nil +} + +// 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 +} + +// SetHTTPHeadersOptions contains the optional parameters for the Client.SetHTTPHeaders method. +type SetHTTPHeadersOptions struct { + AccessConditions *azdatalake.AccessConditions +} + +func (o *SetHTTPHeadersOptions) format() *blob.SetHTTPHeadersOptions { + if o == nil { + return nil + } + accessConditions := shared.FormatBlobAccessConditions(o.AccessConditions) + return &blob.SetHTTPHeadersOptions{ + AccessConditions: accessConditions, + } +} + +// HTTPHeaders contains the HTTP headers for path operations. +type HTTPHeaders struct { + // Optional. Sets the path's cache control. If specified, this property is stored with the path and returned with a read request. + CacheControl *string + // Optional. Sets the path's Content-Disposition header. + ContentDisposition *string + // Optional. Sets the path's content encoding. If specified, this property is stored with the blobpath and returned with a read + // request. + ContentEncoding *string + // Optional. Set the path's content language. If specified, this property is stored with the path and returned with a read + // request. + ContentLanguage *string + // Specify the transactional md5 for the body, to be validated by the service. + ContentMD5 []byte + // Optional. Sets the path's content type. If specified, this property is stored with the path and returned with a read request. + ContentType *string +} + +func (o *HTTPHeaders) formatBlobHTTPHeaders() (*blob.HTTPHeaders, error) { + if o == nil { + return nil, nil + } + opts := blob.HTTPHeaders{ + BlobCacheControl: o.CacheControl, + BlobContentDisposition: o.ContentDisposition, + BlobContentEncoding: o.ContentEncoding, + BlobContentLanguage: o.ContentLanguage, + BlobContentMD5: o.ContentMD5, + BlobContentType: o.ContentType, + } + return &opts, nil +} + +func (o *HTTPHeaders) formatPathHTTPHeaders() (*generated.PathHTTPHeaders, error) { + // TODO: will be used for file related ops, like append + if o == nil { + return nil, nil + } + opts := generated.PathHTTPHeaders{ + CacheControl: o.CacheControl, + ContentDisposition: o.ContentDisposition, + ContentEncoding: o.ContentEncoding, + ContentLanguage: o.ContentLanguage, + ContentMD5: o.ContentMD5, + ContentType: o.ContentType, + TransactionalContentHash: o.ContentMD5, + } + return &opts, nil +} + +// SetMetadataOptions provides set of configurations for Set Metadata on path operation +type SetMetadataOptions struct { + AccessConditions *azdatalake.AccessConditions + CPKInfo *CPKInfo + CPKScopeInfo *CPKScopeInfo +} + +func (o *SetMetadataOptions) format() *blob.SetMetadataOptions { + if o == nil { + return nil + } + accessConditions := shared.FormatBlobAccessConditions(o.AccessConditions) + return &blob.SetMetadataOptions{ + AccessConditions: accessConditions, + CPKInfo: &blob.CPKInfo{ + EncryptionKey: o.CPKInfo.EncryptionKey, + EncryptionAlgorithm: o.CPKInfo.EncryptionAlgorithm, + EncryptionKeySHA256: o.CPKInfo.EncryptionKeySHA256, + }, + CPKScopeInfo: &blob.CPKScopeInfo{ + EncryptionScope: o.CPKScopeInfo.EncryptionScope, + }, + } +} + +// CPKInfo contains a group of parameters for the PathClient.Download method. +type CPKInfo struct { + EncryptionAlgorithm *EncryptionAlgorithmType + EncryptionKey *string + EncryptionKeySHA256 *string +} + +// CPKScopeInfo contains a group of parameters for the PathClient.SetMetadata method. +type CPKScopeInfo struct { + EncryptionScope *string +} + +// SourceModifiedAccessConditions identifies the source path access conditions. +type SourceModifiedAccessConditions = generated.SourceModifiedAccessConditions diff --git a/sdk/storage/azdatalake/internal/path/responses.go b/sdk/storage/azdatalake/internal/path/responses.go new file mode 100644 index 000000000000..e61078ead210 --- /dev/null +++ b/sdk/storage/azdatalake/internal/path/responses.go @@ -0,0 +1,42 @@ +//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 path + +import ( + "github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/blob" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/internal/generated" +) + +// CreateResponse contains the response fields for the Create operation. +type CreateResponse = generated.PathClientCreateResponse + +// DeleteResponse contains the response fields for the Delete operation. +type DeleteResponse = generated.PathClientDeleteResponse + +// SetAccessControlResponse contains the response fields for the SetAccessControl operation. +type SetAccessControlResponse = generated.PathClientSetAccessControlResponse + +// SetAccessControlRecursiveResponse contains the response fields for the SetAccessControlRecursive operation. +type SetAccessControlRecursiveResponse = generated.PathClientSetAccessControlRecursiveResponse + +// UpdateAccessControlRecursiveResponse contains the response fields for the UpdateAccessControlRecursive operation. +type UpdateAccessControlRecursiveResponse = generated.PathClientSetAccessControlRecursiveResponse + +// RemoveAccessControlRecursiveResponse contains the response fields for the RemoveAccessControlRecursive operation. +type RemoveAccessControlRecursiveResponse = generated.PathClientSetAccessControlRecursiveResponse + +// GetAccessControlResponse contains the response fields for the GetAccessControl operation. +type GetAccessControlResponse = generated.PathClientGetPropertiesResponse + +// GetPropertiesResponse contains the response fields for the GetProperties operation. +type GetPropertiesResponse = generated.PathClientGetPropertiesResponse + +// SetMetadataResponse contains the response fields for the SetMetadata operation. +type SetMetadataResponse = blob.SetMetadataResponse + +// SetHTTPHeadersResponse contains the response fields for the SetHTTPHeaders operation. +type SetHTTPHeadersResponse = blob.SetHTTPHeadersResponse diff --git a/sdk/storage/azdatalake/internal/shared/access_conditions.go b/sdk/storage/azdatalake/internal/shared/access_conditions.go new file mode 100644 index 000000000000..a51de4518f6b --- /dev/null +++ b/sdk/storage/azdatalake/internal/shared/access_conditions.go @@ -0,0 +1,56 @@ +package shared + +import ( + "github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/blob" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/container" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/internal/generated" +) + +// FormatContainerAccessConditions formats FilesystemAccessConditions into container's LeaseAccessConditions and ModifiedAccessConditions. +func FormatContainerAccessConditions(b *azdatalake.AccessConditions) *container.AccessConditions { + if b == nil { + return nil + } + return &container.AccessConditions{ + LeaseAccessConditions: &container.LeaseAccessConditions{ + LeaseID: b.LeaseAccessConditions.LeaseID, + }, + ModifiedAccessConditions: &container.ModifiedAccessConditions{ + IfMatch: b.ModifiedAccessConditions.IfMatch, + IfNoneMatch: b.ModifiedAccessConditions.IfNoneMatch, + IfModifiedSince: b.ModifiedAccessConditions.IfModifiedSince, + IfUnmodifiedSince: b.ModifiedAccessConditions.IfUnmodifiedSince, + }, + } +} + +// FormatPathAccessConditions formats PathAccessConditions into path's LeaseAccessConditions and ModifiedAccessConditions. +func FormatPathAccessConditions(p *azdatalake.AccessConditions) (*generated.LeaseAccessConditions, *generated.ModifiedAccessConditions) { + if p == nil { + return nil, nil + } + return &generated.LeaseAccessConditions{ + LeaseID: p.LeaseAccessConditions.LeaseID, + }, &generated.ModifiedAccessConditions{ + IfMatch: p.ModifiedAccessConditions.IfMatch, + IfNoneMatch: p.ModifiedAccessConditions.IfNoneMatch, + IfModifiedSince: p.ModifiedAccessConditions.IfModifiedSince, + IfUnmodifiedSince: p.ModifiedAccessConditions.IfUnmodifiedSince, + } +} + +// FormatBlobAccessConditions formats PathAccessConditions into blob's LeaseAccessConditions and ModifiedAccessConditions. +func FormatBlobAccessConditions(p *azdatalake.AccessConditions) *blob.AccessConditions { + if p == nil { + return nil + } + return &blob.AccessConditions{LeaseAccessConditions: &blob.LeaseAccessConditions{ + LeaseID: p.LeaseAccessConditions.LeaseID, + }, ModifiedAccessConditions: &blob.ModifiedAccessConditions{ + IfMatch: p.ModifiedAccessConditions.IfMatch, + IfNoneMatch: p.ModifiedAccessConditions.IfNoneMatch, + IfModifiedSince: p.ModifiedAccessConditions.IfModifiedSince, + IfUnmodifiedSince: p.ModifiedAccessConditions.IfUnmodifiedSince, + }} +} diff --git a/sdk/storage/azdatalake/internal/shared/bytes_writer.go b/sdk/storage/azdatalake/internal/shared/bytes_writer.go new file mode 100644 index 000000000000..8d4d35bdeffd --- /dev/null +++ b/sdk/storage/azdatalake/internal/shared/bytes_writer.go @@ -0,0 +1,30 @@ +//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 shared + +import ( + "errors" +) + +type bytesWriter []byte + +func NewBytesWriter(b []byte) bytesWriter { + return b +} + +func (c bytesWriter) WriteAt(b []byte, off int64) (int, error) { + if off >= int64(len(c)) || off < 0 { + return 0, errors.New("offset value is out of range") + } + + n := copy(c[int(off):], b) + if n < len(b) { + return n, errors.New("not enough space for all bytes") + } + + return n, nil +} diff --git a/sdk/storage/azdatalake/internal/shared/challenge_policy.go b/sdk/storage/azdatalake/internal/shared/challenge_policy.go new file mode 100644 index 000000000000..e7c8e9213d80 --- /dev/null +++ b/sdk/storage/azdatalake/internal/shared/challenge_policy.go @@ -0,0 +1,113 @@ +//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 shared + +import ( + "errors" + "github.com/Azure/azure-sdk-for-go/sdk/azcore" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/policy" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime" + "net/http" + "strings" +) + +type storageAuthorizer struct { + scopes []string + tenantID string +} + +func NewStorageChallengePolicy(cred azcore.TokenCredential) policy.Policy { + s := storageAuthorizer{scopes: []string{TokenScope}} + return runtime.NewBearerTokenPolicy(cred, []string{TokenScope}, &policy.BearerTokenOptions{ + AuthorizationHandler: policy.AuthorizationHandler{ + OnRequest: s.onRequest, + OnChallenge: s.onChallenge, + }, + }) +} + +func (s *storageAuthorizer) onRequest(req *policy.Request, authNZ func(policy.TokenRequestOptions) error) error { + return authNZ(policy.TokenRequestOptions{Scopes: s.scopes}) +} + +func (s *storageAuthorizer) onChallenge(req *policy.Request, resp *http.Response, authNZ func(policy.TokenRequestOptions) error) error { + // parse the challenge + err := s.parseChallenge(resp) + if err != nil { + return err + } + // TODO: Set tenantID when policy.TokenRequestOptions supports it. https://github.com/Azure/azure-sdk-for-go/issues/19841 + return authNZ(policy.TokenRequestOptions{Scopes: s.scopes}) +} + +type challengePolicyError struct { + err error +} + +func (c *challengePolicyError) Error() string { + return c.err.Error() +} + +func (*challengePolicyError) NonRetriable() { + // marker method +} + +func (c *challengePolicyError) Unwrap() error { + return c.err +} + +// parses Tenant ID from auth challenge +// https://login.microsoftonline.com/00000000-0000-0000-0000-000000000000/oauth2/authorize +func parseTenant(url string) string { + if url == "" { + return "" + } + parts := strings.Split(url, "/") + if len(parts) >= 3 { + tenant := parts[3] + tenant = strings.ReplaceAll(tenant, ",", "") + return tenant + } else { + return "" + } +} + +func (s *storageAuthorizer) parseChallenge(resp *http.Response) error { + authHeader := resp.Header.Get("WWW-Authenticate") + if authHeader == "" { + return &challengePolicyError{err: errors.New("response has no WWW-Authenticate header for challenge authentication")} + } + + // Strip down to auth and resource + // Format is "Bearer authorization_uri=\"\" resource_id=\"\"" + authHeader = strings.ReplaceAll(authHeader, "Bearer ", "") + + parts := strings.Split(authHeader, " ") + + vals := map[string]string{} + for _, part := range parts { + subParts := strings.Split(part, "=") + if len(subParts) == 2 { + stripped := strings.ReplaceAll(subParts[1], "\"", "") + stripped = strings.TrimSuffix(stripped, ",") + vals[subParts[0]] = stripped + } + } + + s.tenantID = parseTenant(vals["authorization_uri"]) + + scope := vals["resource_id"] + if scope == "" { + return &challengePolicyError{err: errors.New("could not find a valid resource in the WWW-Authenticate header")} + } + + if !strings.HasSuffix(scope, "/.default") { + scope += "/.default" + } + s.scopes = []string{scope} + return nil +} diff --git a/sdk/storage/azdatalake/internal/shared/section_writer.go b/sdk/storage/azdatalake/internal/shared/section_writer.go new file mode 100644 index 000000000000..c8528a2e3ed2 --- /dev/null +++ b/sdk/storage/azdatalake/internal/shared/section_writer.go @@ -0,0 +1,53 @@ +//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 shared + +import ( + "errors" + "io" +) + +type SectionWriter struct { + Count int64 + Offset int64 + Position int64 + WriterAt io.WriterAt +} + +func NewSectionWriter(c io.WriterAt, off int64, count int64) *SectionWriter { + return &SectionWriter{ + Count: count, + Offset: off, + WriterAt: c, + } +} + +func (c *SectionWriter) Write(p []byte) (int, error) { + remaining := c.Count - c.Position + + if remaining <= 0 { + return 0, errors.New("end of section reached") + } + + slice := p + + if int64(len(slice)) > remaining { + slice = slice[:remaining] + } + + n, err := c.WriterAt.WriteAt(slice, c.Offset+c.Position) + c.Position += int64(n) + if err != nil { + return n, err + } + + if len(p) > n { + return n, errors.New("not enough space for all bytes") + } + + return n, nil +} diff --git a/sdk/storage/azdatalake/internal/shared/shared.go b/sdk/storage/azdatalake/internal/shared/shared.go new file mode 100644 index 000000000000..d94f84deb8a6 --- /dev/null +++ b/sdk/storage/azdatalake/internal/shared/shared.go @@ -0,0 +1,236 @@ +//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 shared + +import ( + "errors" + "fmt" + "hash/crc64" + "io" + "net" + "net/url" + "strconv" + "strings" + + "github.com/Azure/azure-sdk-for-go/sdk/azcore/to" + "github.com/Azure/azure-sdk-for-go/sdk/internal/uuid" +) + +const ( + TokenScope = "https://storage.azure.com/.default" +) + +const ( + HeaderAuthorization = "Authorization" + HeaderXmsDate = "x-ms-date" + HeaderContentLength = "Content-Length" + HeaderContentEncoding = "Content-Encoding" + HeaderContentLanguage = "Content-Language" + HeaderContentType = "Content-Type" + HeaderContentMD5 = "Content-MD5" + HeaderIfModifiedSince = "If-Modified-Since" + HeaderIfMatch = "If-Match" + HeaderIfNoneMatch = "If-None-Match" + HeaderIfUnmodifiedSince = "If-Unmodified-Since" + HeaderRange = "Range" + HeaderXmsVersion = "x-ms-version" + HeaderXmsRequestID = "x-ms-request-id" +) + +const crc64Polynomial uint64 = 0x9A6C9329AC4BC9B5 + +var CRC64Table = crc64.MakeTable(crc64Polynomial) + +// CopyOptions returns a zero-value T if opts is nil. +// If opts is not nil, a copy is made and its address returned. +func CopyOptions[T any](opts *T) *T { + if opts == nil { + return new(T) + } + cp := *opts + return &cp +} + +var errConnectionString = errors.New("connection string is either blank or malformed. The expected connection string " + + "should contain key value pairs separated by semicolons. For example 'DefaultEndpointsProtocol=https;AccountName=;" + + "AccountKey=;EndpointSuffix=core.windows.net'") + +type ParsedConnectionString struct { + ServiceURL string + AccountName string + AccountKey string +} + +func ParseConnectionString(connectionString string) (ParsedConnectionString, error) { + const ( + defaultScheme = "https" + defaultSuffix = "core.windows.net" + ) + + connStrMap := make(map[string]string) + connectionString = strings.TrimRight(connectionString, ";") + + splitString := strings.Split(connectionString, ";") + if len(splitString) == 0 { + return ParsedConnectionString{}, errConnectionString + } + for _, stringPart := range splitString { + parts := strings.SplitN(stringPart, "=", 2) + if len(parts) != 2 { + return ParsedConnectionString{}, errConnectionString + } + connStrMap[parts[0]] = parts[1] + } + + protocol, ok := connStrMap["DefaultEndpointsProtocol"] + if !ok { + protocol = defaultScheme + } + + suffix, ok := connStrMap["EndpointSuffix"] + if !ok { + suffix = defaultSuffix + } + + blobEndpoint, has_blobEndpoint := connStrMap["BlobEndpoint"] + accountName, has_accountName := connStrMap["AccountName"] + + var serviceURL string + if has_blobEndpoint { + serviceURL = blobEndpoint + } else if has_accountName { + serviceURL = fmt.Sprintf("%v://%v.blob.%v", protocol, accountName, suffix) + } else { + return ParsedConnectionString{}, errors.New("connection string needs either AccountName or BlobEndpoint") + } + + if !strings.HasSuffix(serviceURL, "/") { + // add a trailing slash to be consistent with the portal + serviceURL += "/" + } + + accountKey, has_accountKey := connStrMap["AccountKey"] + sharedAccessSignature, has_sharedAccessSignature := connStrMap["SharedAccessSignature"] + + if has_accountName && has_accountKey { + return ParsedConnectionString{ + ServiceURL: serviceURL, + AccountName: accountName, + AccountKey: accountKey, + }, nil + } else if has_sharedAccessSignature { + return ParsedConnectionString{ + ServiceURL: fmt.Sprintf("%v?%v", serviceURL, sharedAccessSignature), + }, nil + } else { + return ParsedConnectionString{}, errors.New("connection string needs either AccountKey or SharedAccessSignature") + } + +} + +func SerializeBlobTagsToStrPtr(tagsMap map[string]string) *string { + if len(tagsMap) == 0 { + return nil + } + tags := make([]string, 0) + for key, val := range tagsMap { + tags = append(tags, url.QueryEscape(key)+"="+url.QueryEscape(val)) + } + blobTagsString := strings.Join(tags, "&") + return &blobTagsString +} + +func ValidateSeekableStreamAt0AndGetCount(body io.ReadSeeker) (int64, error) { + if body == nil { // nil body's are "logically" seekable to 0 and are 0 bytes long + return 0, nil + } + + err := validateSeekableStreamAt0(body) + if err != nil { + return 0, err + } + + count, err := body.Seek(0, io.SeekEnd) + if err != nil { + return 0, errors.New("body stream must be seekable") + } + + _, err = body.Seek(0, io.SeekStart) + if err != nil { + return 0, err + } + return count, nil +} + +// return an error if body is not a valid seekable stream at 0 +func validateSeekableStreamAt0(body io.ReadSeeker) error { + if body == nil { // nil body's are "logically" seekable to 0 + return nil + } + if pos, err := body.Seek(0, io.SeekCurrent); pos != 0 || err != nil { + // Help detect programmer error + if err != nil { + return errors.New("body stream must be seekable") + } + return errors.New("body stream must be set to position 0") + } + return nil +} + +func RangeToString(offset, count int64) string { + return "bytes=" + strconv.FormatInt(offset, 10) + "-" + strconv.FormatInt(offset+count-1, 10) +} + +type nopCloser struct { + io.ReadSeeker +} + +func (n nopCloser) Close() error { + return nil +} + +// NopCloser returns a ReadSeekCloser with a no-op close method wrapping the provided io.ReadSeeker. +func NopCloser(rs io.ReadSeeker) io.ReadSeekCloser { + return nopCloser{rs} +} + +func GenerateLeaseID(leaseID *string) (*string, error) { + if leaseID == nil { + generatedUuid, err := uuid.New() + if err != nil { + return nil, err + } + leaseID = to.Ptr(generatedUuid.String()) + } + return leaseID, nil +} + +func GetClientOptions[T any](o *T) *T { + if o == nil { + return new(T) + } + return o +} + +// IsIPEndpointStyle checkes if URL's host is IP, in this case the storage account endpoint will be composed as: +// http(s)://IP(:port)/storageaccount/container/... +// As url's Host property, host could be both host or host:port +func IsIPEndpointStyle(host string) bool { + if host == "" { + return false + } + if h, _, err := net.SplitHostPort(host); err == nil { + host = h + } + // For IPv6, there could be case where SplitHostPort fails for cannot finding port. + // In this case, eliminate the '[' and ']' in the URL. + // For details about IPv6 URL, please refer to https://tools.ietf.org/html/rfc2732 + if host[0] == '[' && host[len(host)-1] == ']' { + host = host[1 : len(host)-1] + } + return net.ParseIP(host) != nil +} diff --git a/sdk/storage/azdatalake/lease/constants.go b/sdk/storage/azdatalake/lease/constants.go new file mode 100644 index 000000000000..04df4d58e7b1 --- /dev/null +++ b/sdk/storage/azdatalake/lease/constants.go @@ -0,0 +1,51 @@ +//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 lease + +import "github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/lease" + +// StatusType defines values for StatusType +type StatusType = lease.StatusType + +const ( + StatusTypeLocked StatusType = lease.StatusTypeLocked + StatusTypeUnlocked StatusType = lease.StatusTypeUnlocked +) + +// PossibleStatusTypeValues returns the possible values for the StatusType const type. +func PossibleStatusTypeValues() []StatusType { + return lease.PossibleStatusTypeValues() +} + +// DurationType defines values for DurationType +type DurationType = lease.DurationType + +const ( + DurationTypeInfinite DurationType = lease.DurationTypeInfinite + DurationTypeFixed DurationType = lease.DurationTypeFixed +) + +// PossibleDurationTypeValues returns the possible values for the DurationType const type. +func PossibleDurationTypeValues() []DurationType { + return lease.PossibleDurationTypeValues() +} + +// StateType defines values for StateType +type StateType = lease.StateType + +const ( + StateTypeAvailable StateType = lease.StateTypeAvailable + StateTypeLeased StateType = lease.StateTypeLeased + StateTypeExpired StateType = lease.StateTypeExpired + StateTypeBreaking StateType = lease.StateTypeBreaking + StateTypeBroken StateType = lease.StateTypeBroken +) + +// PossibleStateTypeValues returns the possible values for the StateType const type. +func PossibleStateTypeValues() []StateType { + return lease.PossibleStateTypeValues() +} diff --git a/sdk/storage/azdatalake/lease/filesystem_client.go b/sdk/storage/azdatalake/lease/filesystem_client.go new file mode 100644 index 000000000000..e2c5100a859e --- /dev/null +++ b/sdk/storage/azdatalake/lease/filesystem_client.go @@ -0,0 +1,81 @@ +//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 lease + +import ( + "context" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/lease" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/filesystem" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/internal/base" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/internal/generated" +) + +// FilesystemClient provides lease functionality for the underlying filesystem client. +type FilesystemClient struct { + filesystemClient *filesystem.Client + leaseID *string + containerClient *lease.ContainerClient +} + +// FilesystemClientOptions contains the optional values when creating a FilesystemClient. +type FilesystemClientOptions struct { + // LeaseID contains a caller-provided lease ID. + LeaseID *string +} + +func (c *FilesystemClient) generated() *generated.FileSystemClient { + return base.InnerClient((*base.Client[generated.FileSystemClient])(c.filesystemClient)) +} + +// NewFilesystemClient creates a filesystem lease client for the provided filesystem client. +// - client - an instance of a filesystem client +// - options - client options; pass nil to accept the default values +func NewFilesystemClient(client *filesystem.Client, options *FilesystemClientOptions) (*FilesystemClient, error) { + // TODO: set up container lease client + return nil, nil +} + +// LeaseID returns leaseID of the client. +func (c *FilesystemClient) LeaseID() *string { + return c.leaseID +} + +// AcquireLease acquires a lease on the filesystem for write and delete operations. +// The lease Duration must be between 15 and 60 seconds, or infinite (-1). +// For more information, see https://docs.microsoft.com/rest/api/storageservices/lease-blob. +func (c *FilesystemClient) AcquireLease(ctx context.Context, duration int32, o *FilesystemAcquireOptions) (FilesystemAcquireResponse, error) { + opts := o.format() + return c.containerClient.AcquireLease(ctx, duration, opts) +} + +// BreakLease breaks the filesystem's previously-acquired lease (if it exists). Pass the LeaseBreakDefault (-1) +// constant to break a fixed-Duration lease when it expires or an infinite lease immediately. +// For more information, see https://docs.microsoft.com/rest/api/storageservices/lease-blob. +func (c *FilesystemClient) BreakLease(ctx context.Context, o *FilesystemBreakOptions) (FilesystemBreakResponse, error) { + opts := o.format() + return c.containerClient.BreakLease(ctx, opts) +} + +// ChangeLease changes the filesystem's lease ID. +// For more information, see https://docs.microsoft.com/rest/api/storageservices/lease-blob. +func (c *FilesystemClient) ChangeLease(ctx context.Context, proposedLeaseID string, o *FilesystemChangeOptions) (FilesystemChangeResponse, error) { + opts := o.format() + return c.containerClient.ChangeLease(ctx, proposedLeaseID, opts) +} + +// RenewLease renews the filesystem's previously-acquired lease. +// For more information, see https://docs.microsoft.com/rest/api/storageservices/lease-blob. +func (c *FilesystemClient) RenewLease(ctx context.Context, o *FilesystemRenewOptions) (FilesystemRenewResponse, error) { + opts := o.format() + return c.containerClient.RenewLease(ctx, opts) +} + +// ReleaseLease releases the filesystem's previously-acquired lease. +func (c *FilesystemClient) ReleaseLease(ctx context.Context, o *FilesystemReleaseOptions) (FilesystemReleaseResponse, error) { + opts := o.format() + return c.containerClient.ReleaseLease(ctx, opts) +} diff --git a/sdk/storage/azdatalake/lease/models.go b/sdk/storage/azdatalake/lease/models.go new file mode 100644 index 000000000000..4d94dafc5ec0 --- /dev/null +++ b/sdk/storage/azdatalake/lease/models.go @@ -0,0 +1,173 @@ +//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 lease + +import ( + "github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/blob" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/lease" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake" +) + +// FilesystemAcquireOptions contains the optional parameters for the LeaseClient.AcquireLease method. +type FilesystemAcquireOptions struct { + ModifiedAccessConditions *azdatalake.ModifiedAccessConditions +} + +func (o *FilesystemAcquireOptions) format() *lease.ContainerAcquireOptions { + return &lease.ContainerAcquireOptions{ + ModifiedAccessConditions: &blob.ModifiedAccessConditions{ + IfModifiedSince: o.ModifiedAccessConditions.IfModifiedSince, + IfUnmodifiedSince: o.ModifiedAccessConditions.IfUnmodifiedSince, + IfMatch: o.ModifiedAccessConditions.IfMatch, + IfNoneMatch: o.ModifiedAccessConditions.IfNoneMatch, + }, + } +} + +// FilesystemBreakOptions contains the optional parameters for the LeaseClient.BreakLease method. +type FilesystemBreakOptions struct { + BreakPeriod *int32 + ModifiedAccessConditions *azdatalake.ModifiedAccessConditions +} + +func (o *FilesystemBreakOptions) format() *lease.ContainerBreakOptions { + return &lease.ContainerBreakOptions{ + BreakPeriod: o.BreakPeriod, + ModifiedAccessConditions: &blob.ModifiedAccessConditions{ + IfModifiedSince: o.ModifiedAccessConditions.IfModifiedSince, + IfUnmodifiedSince: o.ModifiedAccessConditions.IfUnmodifiedSince, + IfMatch: o.ModifiedAccessConditions.IfMatch, + IfNoneMatch: o.ModifiedAccessConditions.IfNoneMatch, + }, + } +} + +// FilesystemChangeOptions contains the optional parameters for the LeaseClient.ChangeLease method. +type FilesystemChangeOptions struct { + ModifiedAccessConditions *azdatalake.ModifiedAccessConditions +} + +func (o *FilesystemChangeOptions) format() *lease.ContainerChangeOptions { + return &lease.ContainerChangeOptions{ + ModifiedAccessConditions: &blob.ModifiedAccessConditions{ + IfModifiedSince: o.ModifiedAccessConditions.IfModifiedSince, + IfUnmodifiedSince: o.ModifiedAccessConditions.IfUnmodifiedSince, + IfMatch: o.ModifiedAccessConditions.IfMatch, + IfNoneMatch: o.ModifiedAccessConditions.IfNoneMatch, + }, + } +} + +type FilesystemReleaseOptions struct { + ModifiedAccessConditions *azdatalake.ModifiedAccessConditions +} + +func (o *FilesystemReleaseOptions) format() *lease.ContainerReleaseOptions { + return &lease.ContainerReleaseOptions{ + ModifiedAccessConditions: &blob.ModifiedAccessConditions{ + IfModifiedSince: o.ModifiedAccessConditions.IfModifiedSince, + IfUnmodifiedSince: o.ModifiedAccessConditions.IfUnmodifiedSince, + IfMatch: o.ModifiedAccessConditions.IfMatch, + IfNoneMatch: o.ModifiedAccessConditions.IfNoneMatch, + }, + } +} + +type FilesystemRenewOptions struct { + ModifiedAccessConditions *azdatalake.ModifiedAccessConditions +} + +func (o *FilesystemRenewOptions) format() *lease.ContainerRenewOptions { + return &lease.ContainerRenewOptions{ + ModifiedAccessConditions: &blob.ModifiedAccessConditions{ + IfModifiedSince: o.ModifiedAccessConditions.IfModifiedSince, + IfUnmodifiedSince: o.ModifiedAccessConditions.IfUnmodifiedSince, + IfMatch: o.ModifiedAccessConditions.IfMatch, + IfNoneMatch: o.ModifiedAccessConditions.IfNoneMatch, + }, + } +} + +// PathAcquireOptions contains the optional parameters for the LeaseClient.AcquireLease method. +type PathAcquireOptions struct { + ModifiedAccessConditions *azdatalake.ModifiedAccessConditions +} + +func (o *PathAcquireOptions) format() *lease.BlobAcquireOptions { + return &lease.BlobAcquireOptions{ + ModifiedAccessConditions: &blob.ModifiedAccessConditions{ + IfModifiedSince: o.ModifiedAccessConditions.IfModifiedSince, + IfUnmodifiedSince: o.ModifiedAccessConditions.IfUnmodifiedSince, + IfMatch: o.ModifiedAccessConditions.IfMatch, + IfNoneMatch: o.ModifiedAccessConditions.IfNoneMatch, + }, + } +} + +// PathBreakOptions contains the optional parameters for the LeaseClient.BreakLease method. +type PathBreakOptions struct { + BreakPeriod *int32 + ModifiedAccessConditions *azdatalake.ModifiedAccessConditions +} + +func (o *PathBreakOptions) format() *lease.BlobBreakOptions { + return &lease.BlobBreakOptions{ + BreakPeriod: o.BreakPeriod, + ModifiedAccessConditions: &blob.ModifiedAccessConditions{ + IfModifiedSince: o.ModifiedAccessConditions.IfModifiedSince, + IfUnmodifiedSince: o.ModifiedAccessConditions.IfUnmodifiedSince, + IfMatch: o.ModifiedAccessConditions.IfMatch, + IfNoneMatch: o.ModifiedAccessConditions.IfNoneMatch, + }, + } +} + +// PathChangeOptions contains the optional parameters for the LeaseClient.ChangeLease method. +type PathChangeOptions struct { + ModifiedAccessConditions *azdatalake.ModifiedAccessConditions +} + +func (o *PathChangeOptions) format() *lease.BlobChangeOptions { + return &lease.BlobChangeOptions{ + ModifiedAccessConditions: &blob.ModifiedAccessConditions{ + IfModifiedSince: o.ModifiedAccessConditions.IfModifiedSince, + IfUnmodifiedSince: o.ModifiedAccessConditions.IfUnmodifiedSince, + IfMatch: o.ModifiedAccessConditions.IfMatch, + IfNoneMatch: o.ModifiedAccessConditions.IfNoneMatch, + }, + } +} + +type PathReleaseOptions struct { + ModifiedAccessConditions *azdatalake.ModifiedAccessConditions +} + +func (o *PathReleaseOptions) format() *lease.BlobReleaseOptions { + return &lease.BlobReleaseOptions{ + ModifiedAccessConditions: &blob.ModifiedAccessConditions{ + IfModifiedSince: o.ModifiedAccessConditions.IfModifiedSince, + IfUnmodifiedSince: o.ModifiedAccessConditions.IfUnmodifiedSince, + IfMatch: o.ModifiedAccessConditions.IfMatch, + IfNoneMatch: o.ModifiedAccessConditions.IfNoneMatch, + }, + } +} + +type PathRenewOptions struct { + ModifiedAccessConditions *azdatalake.ModifiedAccessConditions +} + +func (o *PathRenewOptions) format() *lease.BlobRenewOptions { + return &lease.BlobRenewOptions{ + ModifiedAccessConditions: &blob.ModifiedAccessConditions{ + IfModifiedSince: o.ModifiedAccessConditions.IfModifiedSince, + IfUnmodifiedSince: o.ModifiedAccessConditions.IfUnmodifiedSince, + IfMatch: o.ModifiedAccessConditions.IfMatch, + IfNoneMatch: o.ModifiedAccessConditions.IfNoneMatch, + }, + } +} diff --git a/sdk/storage/azdatalake/lease/path_client.go b/sdk/storage/azdatalake/lease/path_client.go new file mode 100644 index 000000000000..57b06f5c20a2 --- /dev/null +++ b/sdk/storage/azdatalake/lease/path_client.go @@ -0,0 +1,82 @@ +//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 lease + +import ( + "context" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/lease" + "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/internal/base" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/internal/generated" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/path" +) + +// PathClient provides lease functionality for the underlying path client. +type PathClient struct { + blobClient *lease.BlobClient + pathClient *path.Client + leaseID *string +} + +// PathClientOptions contains the optional values when creating a PathClient. +type PathClientOptions struct { + // LeaseID contains a caller-provided lease ID. + LeaseID *string +} + +// NewPathClient creates a path lease client for the provided path client. +// - client - an instance of a path client +// - options - client options; pass nil to accept the default values +func NewPathClient[T directory.Client | file.Client](client *T, options *PathClientOptions) (*PathClient, error) { + // TODO: set up blob lease client + return nil, nil +} + +func (c *PathClient) generated() *generated.PathClient { + return base.InnerClient((*base.Client[generated.PathClient])(c.pathClient)) +} + +// LeaseID returns leaseID of the client. +func (c *PathClient) LeaseID() *string { + return c.leaseID +} + +// AcquireLease acquires a lease on the path for write and delete operations. +// The lease Duration must be between 15 and 60 seconds, or infinite (-1). +// For more information, see https://docs.microsoft.com/rest/api/storageservices/lease-blob. +func (c *PathClient) AcquireLease(ctx context.Context, duration int32, o *PathAcquireOptions) (PathAcquireResponse, error) { + opts := o.format() + return c.blobClient.AcquireLease(ctx, duration, opts) +} + +// BreakLease breaks the path's previously-acquired lease. +func (c *PathClient) BreakLease(ctx context.Context, o *PathBreakOptions) (PathBreakResponse, error) { + opts := o.format() + return c.blobClient.BreakLease(ctx, opts) +} + +// ChangeLease changes the path's lease ID. +// For more information, see https://docs.microsoft.com/rest/api/storageservices/lease-blob. +func (c *PathClient) ChangeLease(ctx context.Context, proposedID string, o *PathChangeOptions) (PathChangeResponse, error) { + opts := o.format() + return c.blobClient.ChangeLease(ctx, proposedID, opts) +} + +// RenewLease renews the path's previously-acquired lease. +// For more information, see https://docs.microsoft.com/rest/api/storageservices/lease-blob. +func (c *PathClient) RenewLease(ctx context.Context, o *PathRenewOptions) (PathRenewResponse, error) { + opts := o.format() + return c.blobClient.RenewLease(ctx, opts) +} + +// ReleaseLease releases the path's previously-acquired lease. +// For more information, see https://docs.microsoft.com/rest/api/storageservices/lease-blob. +func (c *PathClient) ReleaseLease(ctx context.Context, o *PathReleaseOptions) (PathReleaseResponse, error) { + opts := o.format() + return c.blobClient.ReleaseLease(ctx, opts) +} diff --git a/sdk/storage/azdatalake/lease/responses.go b/sdk/storage/azdatalake/lease/responses.go new file mode 100644 index 000000000000..1ff60df3b227 --- /dev/null +++ b/sdk/storage/azdatalake/lease/responses.go @@ -0,0 +1,39 @@ +//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 lease + +import "github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/lease" + +// FilesystemAcquireResponse contains the response from method FilesystemClient.AcquireLease. +type FilesystemAcquireResponse = lease.ContainerAcquireResponse + +// FilesystemBreakResponse contains the response from method FilesystemClient.BreakLease. +type FilesystemBreakResponse = lease.ContainerBreakResponse + +// FilesystemChangeResponse contains the response from method FilesystemClient.ChangeLease. +type FilesystemChangeResponse = lease.ContainerChangeResponse + +// FilesystemReleaseResponse contains the response from method FilesystemClient.ReleaseLease. +type FilesystemReleaseResponse = lease.ContainerReleaseResponse + +// FilesystemRenewResponse contains the response from method FilesystemClient.RenewLease. +type FilesystemRenewResponse = lease.ContainerRenewResponse + +// PathAcquireResponse contains the response from method PathClient.AcquireLease. +type PathAcquireResponse = lease.BlobAcquireResponse + +// PathBreakResponse contains the response from method PathClient.BreakLease. +type PathBreakResponse = lease.BlobBreakResponse + +// PathChangeResponse contains the response from method PathClient.ChangeLease. +type PathChangeResponse = lease.BlobChangeResponse + +// PathReleaseResponse contains the response from method PathClient.ReleaseLease. +type PathReleaseResponse = lease.BlobReleaseResponse + +// PathRenewResponse contains the response from method PathClient.RenewLease. +type PathRenewResponse = lease.BlobRenewResponse diff --git a/sdk/storage/azdatalake/service/client.go b/sdk/storage/azdatalake/service/client.go new file mode 100644 index 000000000000..5d887ffddd9d --- /dev/null +++ b/sdk/storage/azdatalake/service/client.go @@ -0,0 +1,113 @@ +//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 service + +import ( + "context" + "github.com/Azure/azure-sdk-for-go/sdk/azcore" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/filesystem" + "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" +) + +// Client represents a URL to the Azure Datalake Storage service. +type Client base.Client[generated.ServiceClient] + +// NewClient creates an instance of Client with the specified values. +// - serviceURL - the URL of the storage account e.g. https://.file.core.windows.net/ +// - cred - an Azure AD credential, typically obtained via the azidentity module +// - options - client options; pass nil to accept the default values +func NewClient(serviceURL string, cred azcore.TokenCredential, options *azdatalake.ClientOptions) (*Client, error) { + return nil, nil +} + +// NewClientWithNoCredential creates an instance of Client with the specified values. +// This is used to anonymously access a storage account or with a shared access signature (SAS) token. +// - serviceURL - the URL of the storage account e.g. https://.file.core.windows.net/? +// - options - client options; pass nil to accept the default values +func NewClientWithNoCredential(serviceURL string, options *azdatalake.ClientOptions) (*Client, error) { + return nil, nil +} + +// NewClientWithSharedKeyCredential creates an instance of Client with the specified values. +// - serviceURL - the URL of the storage account e.g. https://.file.core.windows.net/ +// - cred - a SharedKeyCredential created with the matching storage account and access key +// - options - client options; pass nil to accept the default values +func NewClientWithSharedKeyCredential(serviceURL string, cred *SharedKeyCredential, options *azdatalake.ClientOptions) (*Client, error) { + return nil, nil +} + +// NewClientFromConnectionString creates an instance of Client with the specified values. +// - connectionString - a connection string for the desired storage account +// - options - client options; pass nil to accept the default values +func NewClientFromConnectionString(connectionString string, options *azdatalake.ClientOptions) (*Client, error) { + return nil, nil +} + +// NewFilesystemClient creates a new share.Client object by concatenating shareName to the end of this Client's URL. +// The new share.Client uses the same request policy pipeline as the Client. +func (s *Client) NewFilesystemClient(filesystemName string) *filesystem.Client { + return nil +} + +// NewDirectoryClient creates a new share.Client object by concatenating shareName to the end of this Client's URL. +// The new share.Client uses the same request policy pipeline as the Client. +func (s *Client) NewDirectoryClient(directoryName string) *filesystem.Client { + return nil +} + +// NewFileClient creates a new share.Client object by concatenating shareName to the end of this Client's URL. +// The new share.Client uses the same request policy pipeline as the Client. +func (s *Client) NewFileClient(fileName string) *filesystem.Client { + return nil +} + +func (s *Client) generated() *generated.ServiceClient { + return base.InnerClient((*base.Client[generated.ServiceClient])(s)) +} + +func (s *Client) sharedKey() *exported.SharedKeyCredential { + return base.SharedKey((*base.Client[generated.ServiceClient])(s)) +} + +// URL returns the URL endpoint used by the Client object. +func (s *Client) URL() string { + return "s.generated().Endpoint()" +} + +// CreateFilesystem creates a new filesystem under the specified account. (blob3) +func (s *Client) CreateFilesystem(ctx context.Context, filesystem string, options *CreateFilesystemOptions) (CreateFilesystemResponse, error) { + filesystemClient := s.NewFilesystemClient(filesystem) + resp, err := filesystemClient.Create(ctx, options) + return resp, err +} + +// DeleteFilesystem deletes the specified filesystem. (blob3) +func (s *Client) DeleteFilesystem(ctx context.Context, filesystem string, options *DeleteFilesystemOptions) (DeleteFilesystemResponse, error) { + filesystemClient := s.NewFilesystemClient(filesystem) + resp, err := filesystemClient.Delete(ctx, options) + return resp, err +} + +// SetServiceProperties sets properties for a storage account's File service endpoint. (blob3) +func (s *Client) SetServiceProperties(ctx context.Context, options *SetPropertiesOptions) (SetPropertiesResponse, error) { + return SetPropertiesResponse{}, nil +} + +// GetProperties gets properties for a storage account's File service endpoint. (blob3) +func (s *Client) GetProperties(ctx context.Context, options *GetPropertiesOptions) (GetPropertiesResponse, error) { + return GetPropertiesResponse{}, nil +} + +// NewListFilesystemsPager operation returns a pager of the shares under the specified account. (blob3) +// For more information, see https://learn.microsoft.com/en-us/rest/api/storageservices/list-shares +func (s *Client) NewListFilesystemsPager(options *ListFilesystemsOptions) *runtime.Pager[ListFilesystemsResponse] { + return nil +} diff --git a/sdk/storage/azdatalake/service/models.go b/sdk/storage/azdatalake/service/models.go new file mode 100644 index 000000000000..bca2a179f73a --- /dev/null +++ b/sdk/storage/azdatalake/service/models.go @@ -0,0 +1,98 @@ +//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 service + +import ( + "github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/service" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/filesystem" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/internal/exported" +) + +type CreateFilesystemOptions = filesystem.CreateOptions + +type DeleteFilesystemOptions = filesystem.DeleteOptions + +// CORSRule - CORS is an HTTP feature that enables a web application running under one domain to access resources in another +// domain. Web browsers implement a security restriction known as same-origin policy that +// prevents a web page from calling APIs in a different domain; CORS provides a secure way to allow one domain (the origin +// domain) to call APIs in another domain. +type CORSRule = service.CORSRule + +// RetentionPolicy - the retention policy which determines how long the associated data should persist. +type RetentionPolicy = service.RetentionPolicy + +// Metrics - a summary of request statistics grouped by API in hour or minute aggregates +type Metrics = service.Metrics + +// Logging - Azure Analytics Logging settings. +type Logging = service.Logging + +// StaticWebsite - The properties that enable an account to host a static website. +type StaticWebsite = service.StaticWebsite + +// GetPropertiesOptions contains the optional parameters for the Client.GetProperties method. +type GetPropertiesOptions struct { + // placeholder for future options +} + +func (o *GetPropertiesOptions) format() *service.GetPropertiesOptions { + return nil +} + +// SetPropertiesOptions provides set of options for Client.SetProperties +type SetPropertiesOptions struct { + // The set of CORS rules. + CORS []*CORSRule + + // The default version to use for requests to the Datalake service if an incoming request's version is not specified. Possible + // values include version 2008-10-27 and all more recent versions. + DefaultServiceVersion *string + + // the retention policy which determines how long the associated data should persist. + DeleteRetentionPolicy *RetentionPolicy + + // a summary of request statistics grouped by API in hour or minute aggregates + // If version is not set - we default to "1.0" + HourMetrics *Metrics + + // Azure Analytics Logging settings. + // If version is not set - we default to "1.0" + Logging *Logging + + // a summary of request statistics grouped by API in hour or minute aggregates + // If version is not set - we default to "1.0" + MinuteMetrics *Metrics + + // The properties that enable an account to host a static website. + StaticWebsite *StaticWebsite +} + +func (o *SetPropertiesOptions) format() *service.SetPropertiesOptions { + return nil +} + +// ListFilesystemsInclude indicates what additional information the service should return with each filesystem. +type ListFilesystemsInclude struct { + // Tells the service whether to return metadata for each filesystem. + Metadata bool + + // Tells the service whether to return soft-deleted filesystems. + Deleted bool +} + +// ListFilesystemsOptions contains the optional parameters for the Client.List method. +type ListFilesystemsOptions struct { + Include ListFilesystemsInclude + Marker *string + MaxResults *int32 + Prefix *string +} + +// TODO: Design formatter to convert to blob + +// SharedKeyCredential contains an account's name and its primary or secondary key. +type SharedKeyCredential = exported.SharedKeyCredential diff --git a/sdk/storage/azdatalake/service/responses.go b/sdk/storage/azdatalake/service/responses.go new file mode 100644 index 000000000000..e9393cbdbee3 --- /dev/null +++ b/sdk/storage/azdatalake/service/responses.go @@ -0,0 +1,30 @@ +//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. +// Code generated by Microsoft (R) AutoRest Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. +// DO NOT EDIT. + +package service + +import ( + "github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/service" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/filesystem" +) + +// CreateFilesystemResponse contains the response fields for the CreateFilesystem operation. +type CreateFilesystemResponse = filesystem.CreateResponse + +// DeleteFilesystemResponse contains the response fields for the DeleteFilesystem operation. +type DeleteFilesystemResponse = filesystem.DeleteResponse + +// SetPropertiesResponse contains the response fields for the SetProperties operation. +type SetPropertiesResponse = service.SetPropertiesResponse + +// GetPropertiesResponse contains the response fields for the GetProperties operation. +type GetPropertiesResponse = service.GetPropertiesResponse + +// ListFilesystemsResponse contains the response fields for the ListFilesystems operation. +type ListFilesystemsResponse = service.ListContainersResponse From c09de0b242729cc09415e897e33b5992dc6c8b21 Mon Sep 17 00:00:00 2001 From: Tamer Sherif <69483382+tasherif-msft@users.noreply.github.com> Date: Sun, 18 Jun 2023 21:03:34 -0700 Subject: [PATCH 04/16] [Datalake] SAS Support (#21019) * Enable gocritic during linting (#20715) Enabled gocritic's evalOrder to catch dependencies on undefined behavior on return statements. Updated to latest version of golangci-lint. Fixed issue in azblob flagged by latest linter. * Cosmos DB: Enable merge support (#20716) * Adding header and value * Wiring and tests * format * Fixing value * change log * [azservicebus, azeventhubs] Stress test and logging improvement (#20710) Logging improvements: * Updating the logging to print more tracing information (per-link) in prep for the bigger release coming up. * Trimming out some of the verbose logging, seeing if I can get it a bit more reasonable. Stress tests: * Add a timestamp to the log name we generate and also default to append, not overwrite. * Use 0.5 cores, 0.5GB as our baseline. Some pods use more and I'll tune them more later. * update proxy version (#20712) Co-authored-by: Scott Beddall * Return an error when you try to send a message that's too large. (#20721) This now works just like the message batch - you'll get an ErrMessageTooLarge if you attempt to send a message that's too large for the link's configured size. NOTE: there's a patch to `internal/go-amqp/Sender.go` to match what's in go-amqp's main so it returns a programmatically useful error when the message is too large. Fixes #20647 * Changes in test that is failing in pipeline (#20693) * [azservicebus, azeventhubs] Treat 'entity full' as a fatal error (#20722) When the remote entity is full we get a resource-limit-exceeded condition. This isn't something we should keep retrying on and it's best to just abort and let the user know immediately, rather than hoping it might eventually clear out. This affected both Event Hubs and Service Bus. Fixes #20647 * [azservicebus/azeventhubs] Redirect stderr and stdout to tee (#20726) * Update changelog with latest features (#20730) * Update changelog with latest features Prepare for upcoming release. * bump minor version * pass along the artifact name so we can override it later (#20732) Co-authored-by: scbedd <45376673+scbedd@users.noreply.github.com> * [azeventhubs] Fixing checkpoint store race condition (#20727) The checkpoint store wasn't guarding against multiple owners claiming for the first time - fixing this by using IfNoneMatch Fixes #20717 * Fix azidentity troubleshooting guide link (#20736) * [Release] sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/0.1.0 (#20437) * [Release] sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/0.1.0 generation from spec commit: 85fb4ac6f8bfefd179e6c2632976a154b5c9ff04 * client factory * fix * fix * update * add sdk/resourcemanager/postgresql/armpostgresql live test (#20685) * add sdk/resourcemanager/postgresql/armpostgresql live test * update assets.json * set subscriptionId default value * format * add sdk/resourcemanager/eventhub/armeventhub live test (#20686) * add sdk/resourcemanager/eventhub/armeventhub live test * update assets * add sdk/resourcemanager/compute/armcompute live test (#20048) * add sdk/resourcemanager/compute/armcompute live test * skus filter * fix subscriptionId default value * fix * gofmt * update recording * sdk/resourcemanager/network/armnetwork live test (#20331) * sdk/resourcemanager/network/armnetwork live test * update subscriptionId default value * update recording * add sdk/resourcemanager/cosmos/armcosmos live test (#20705) * add sdk/resourcemanager/cosmos/armcosmos live test * update assets.json * update assets.json * update assets.json * update assets.json * Increment package version after release of azcore (#20740) * [azeventhubs] Improperly resetting etag in the checkpoint store (#20737) We shouldn't be resetting the etag to nil - it's what we use to enforce a "single winner" when doing ownership claims. The bug here was two-fold: I had bad logic in my previous claim ownership, which I fixed in a previous PR, but we need to reflect that same constraint properly in our in-memory checkpoint store for these tests. * Eng workflows sync and branch cleanup additions (#20743) Co-authored-by: James Suplizio * [azeventhubs] Latest start position can also be inclusive (ie, get the latest message) (#20744) * Update GitHubEventProcessor version and remove pull_request_review procesing (#20751) Co-authored-by: James Suplizio * Rename DisableAuthorityValidationAndInstanceDiscovery (#20746) * fix (#20707) * AzFile (#20739) * azfile: Fixing connection string parsing logic (#20798) * Fixing connection string parse logic * Update README * [azadmin] fix flaky test (#20758) * fix flaky test * charles suggestion * Prepare azidentity v1.3.0 for release (#20756) * Fix broken podman link (#20801) Co-authored-by: Wes Haggard * [azquery] update doc comments (#20755) * update doc comments * update statistics and visualization generation * prep-for-release * Fixed contribution section (#20752) Co-authored-by: Bob Tabor * [azeventhubs,azservicebus] Some API cleanup, renames (#20754) * Adding options to UpdateCheckpoint(), just for future potential expansion * Make Offset an int64, not a *int64 (it's not optional, it'll always come back with ReceivedEvents) * Adding more logging into the checkpoint store. * Point all imports at the production go-amqp * Add supporting features to enable distributed tracing (#20301) (#20708) * Add supporting features to enable distributed tracing This includes new internal pipeline policies and other supporting types. See the changelog for a full description. Added some missing doc comments. * fix linter issue * add net.peer.name trace attribute sequence custom HTTP header policy before logging policy. sequence logging policy after HTTP trace policy. keep body download policy at the end. * add span for iterating over pages * Restore ARM CAE support for azcore beta (#20657) This reverts commit 902097226ff3fe2fc6c3e7fc50d3478350253614. * Upgrade to stable azcore (#20808) * Increment package version after release of data/azcosmos (#20807) * Updating changelog (#20810) * Add fake package to azcore (#20711) * Add fake package to azcore This is the supporting infrastructure for the generated SDK fakes. * fix doc comment * Updating CHANGELOG.md (#20809) * changelog (#20811) * Increment package version after release of storage/azfile (#20813) * Update changelog (azblob) (#20815) * Updating CHANGELOG.md * Update the changelog with correct version * [azquery] migration guide (#20742) * migration guide * Charles feedback * Richard feedback --------- Co-authored-by: Charles Lowell <10964656+chlowell@users.noreply.github.com> * Increment package version after release of monitor/azquery (#20820) * [keyvault] prep for release (#20819) * prep for release * perf tests * update date * added sas support * small fix * query params fix * fix * added some tests * added more tests * resolved some comments * added encoding --------- Co-authored-by: Joel Hendrix Co-authored-by: Matias Quaranta Co-authored-by: Richard Park <51494936+richardpark-msft@users.noreply.github.com> Co-authored-by: Azure SDK Bot <53356347+azure-sdk@users.noreply.github.com> Co-authored-by: Scott Beddall Co-authored-by: siminsavani-msft <77068571+siminsavani-msft@users.noreply.github.com> Co-authored-by: scbedd <45376673+scbedd@users.noreply.github.com> Co-authored-by: Charles Lowell <10964656+chlowell@users.noreply.github.com> Co-authored-by: Peng Jiahui <46921893+Alancere@users.noreply.github.com> Co-authored-by: James Suplizio Co-authored-by: Sourav Gupta <98318303+souravgupta-msft@users.noreply.github.com> Co-authored-by: gracewilcox <43627800+gracewilcox@users.noreply.github.com> Co-authored-by: Wes Haggard Co-authored-by: Bob Tabor Co-authored-by: Bob Tabor --- sdk/storage/azdatalake/common.go | 2 - .../azdatalake/internal/exported/exported.go | 2 + .../exported/user_delegation_credential.go | 64 +++ sdk/storage/azdatalake/sas/account.go | 226 ++++++++ sdk/storage/azdatalake/sas/account_test.go | 169 ++++++ sdk/storage/azdatalake/sas/query_params.go | 506 ++++++++++++++++++ .../azdatalake/sas/query_params_test.go | 231 ++++++++ sdk/storage/azdatalake/sas/service.go | 413 ++++++++++++++ sdk/storage/azdatalake/sas/service_test.go | 219 ++++++++ sdk/storage/azdatalake/sas/url_parts.go | 109 ++++ sdk/storage/azdatalake/sas/url_parts_test.go | 73 +++ 11 files changed, 2012 insertions(+), 2 deletions(-) create mode 100644 sdk/storage/azdatalake/internal/exported/user_delegation_credential.go create mode 100644 sdk/storage/azdatalake/sas/account.go create mode 100644 sdk/storage/azdatalake/sas/account_test.go create mode 100644 sdk/storage/azdatalake/sas/query_params.go create mode 100644 sdk/storage/azdatalake/sas/query_params_test.go create mode 100644 sdk/storage/azdatalake/sas/service.go create mode 100644 sdk/storage/azdatalake/sas/service_test.go create mode 100644 sdk/storage/azdatalake/sas/url_parts.go create mode 100644 sdk/storage/azdatalake/sas/url_parts_test.go diff --git a/sdk/storage/azdatalake/common.go b/sdk/storage/azdatalake/common.go index 32a7862e8256..03fe643423db 100644 --- a/sdk/storage/azdatalake/common.go +++ b/sdk/storage/azdatalake/common.go @@ -16,8 +16,6 @@ type ClientOptions struct { azcore.ClientOptions } -const SnapshotTimeFormat = "2006-01-02T15:04:05.0000000Z07:00" - // AccessConditions identifies container-specific access conditions which you optionally set. type AccessConditions struct { ModifiedAccessConditions *ModifiedAccessConditions diff --git a/sdk/storage/azdatalake/internal/exported/exported.go b/sdk/storage/azdatalake/internal/exported/exported.go index 9bc1ca47df84..6a91ea05453a 100644 --- a/sdk/storage/azdatalake/internal/exported/exported.go +++ b/sdk/storage/azdatalake/internal/exported/exported.go @@ -11,6 +11,8 @@ import ( "strconv" ) +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. diff --git a/sdk/storage/azdatalake/internal/exported/user_delegation_credential.go b/sdk/storage/azdatalake/internal/exported/user_delegation_credential.go new file mode 100644 index 000000000000..91b933bf5737 --- /dev/null +++ b/sdk/storage/azdatalake/internal/exported/user_delegation_credential.go @@ -0,0 +1,64 @@ +//go:build go1.18 +// +build go1.18 + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package exported + +import ( + "crypto/hmac" + "crypto/sha256" + "encoding/base64" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/service" +) + +// NewUserDelegationCredential creates a new UserDelegationCredential using a Storage account's Name and a user delegation Key from it +func NewUserDelegationCredential(accountName string, udk UserDelegationKey) *UserDelegationCredential { + return &UserDelegationCredential{ + accountName: accountName, + userDelegationKey: udk, + } +} + +// UserDelegationKey contains UserDelegationKey. +type UserDelegationKey = service.UserDelegationKey + +// UserDelegationCredential contains an account's name and its user delegation key. +type UserDelegationCredential struct { + accountName string + userDelegationKey UserDelegationKey +} + +// getAccountName returns the Storage account's Name +func (f *UserDelegationCredential) getAccountName() string { + return f.accountName +} + +// GetAccountName is a helper method for accessing the user delegation key parameters outside this package. +func GetAccountName(udc *UserDelegationCredential) string { + return udc.getAccountName() +} + +// computeHMACSHA256 generates a hash signature for an HTTP request or for a SAS. +func (f *UserDelegationCredential) computeHMACSHA256(message string) (string, error) { + bytes, _ := base64.StdEncoding.DecodeString(*f.userDelegationKey.Value) + h := hmac.New(sha256.New, bytes) + _, err := h.Write([]byte(message)) + return base64.StdEncoding.EncodeToString(h.Sum(nil)), err +} + +// ComputeUDCHMACSHA256 is a helper method for computing the signed string outside this package. +func ComputeUDCHMACSHA256(udc *UserDelegationCredential, message string) (string, error) { + return udc.computeHMACSHA256(message) +} + +// getUDKParams returns UserDelegationKey +func (f *UserDelegationCredential) getUDKParams() *UserDelegationKey { + return &f.userDelegationKey +} + +// GetUDKParams is a helper method for accessing the user delegation key parameters outside this package. +func GetUDKParams(udc *UserDelegationCredential) *UserDelegationKey { + return udc.getUDKParams() +} diff --git a/sdk/storage/azdatalake/sas/account.go b/sdk/storage/azdatalake/sas/account.go new file mode 100644 index 000000000000..e5681c4ebdba --- /dev/null +++ b/sdk/storage/azdatalake/sas/account.go @@ -0,0 +1,226 @@ +//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 sas + +import ( + "bytes" + "errors" + "fmt" + "strings" + "time" + + "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/internal/exported" +) + +// SharedKeyCredential contains an account's name and its primary or secondary key. +type SharedKeyCredential = exported.SharedKeyCredential + +// UserDelegationCredential contains an account's name and its user delegation key. +type UserDelegationCredential = exported.UserDelegationCredential + +// AccountSignatureValues is used to generate a Shared Access Signature (SAS) for an Azure Storage account. +// For more information, see https://docs.microsoft.com/rest/api/storageservices/constructing-an-account-sas +type AccountSignatureValues struct { + Version string `param:"sv"` // If not specified, this format to SASVersion + Protocol Protocol `param:"spr"` // See the SASProtocol* constants + StartTime time.Time `param:"st"` // Not specified if IsZero + ExpiryTime time.Time `param:"se"` // Not specified if IsZero + Permissions string `param:"sp"` // Create by initializing AccountPermissions and then call String() + IPRange IPRange `param:"sip"` + ResourceTypes string `param:"srt"` // Create by initializing AccountResourceTypes and then call String() +} + +// SignWithSharedKey uses an account's shared key credential to sign this signature values to produce +// the proper SAS query parameters. +func (v AccountSignatureValues) SignWithSharedKey(sharedKeyCredential *SharedKeyCredential) (QueryParameters, error) { + // https://docs.microsoft.com/en-us/rest/api/storageservices/Constructing-an-Account-SAS + if v.ExpiryTime.IsZero() || v.Permissions == "" || v.ResourceTypes == "" { + return QueryParameters{}, errors.New("account SAS is missing at least one of these: ExpiryTime, Permissions, Service, or ResourceType") + } + if v.Version == "" { + v.Version = Version + } + perms, err := parseAccountPermissions(v.Permissions) + if err != nil { + return QueryParameters{}, err + } + v.Permissions = perms.String() + + resources, err := parseAccountResourceTypes(v.ResourceTypes) + if err != nil { + return QueryParameters{}, err + } + v.ResourceTypes = resources.String() + + startTime, expiryTime := formatTimesForSigning(v.StartTime, v.ExpiryTime) + + stringToSign := strings.Join([]string{ + sharedKeyCredential.AccountName(), + v.Permissions, + "b", // blob service + v.ResourceTypes, + startTime, + expiryTime, + v.IPRange.String(), + string(v.Protocol), + v.Version, + ""}, // That is right, the account SAS requires a terminating extra newline + "\n") + + signature, err := exported.ComputeHMACSHA256(sharedKeyCredential, stringToSign) + if err != nil { + return QueryParameters{}, err + } + p := QueryParameters{ + // Common SAS parameters + version: v.Version, + protocol: v.Protocol, + startTime: v.StartTime, + expiryTime: v.ExpiryTime, + permissions: v.Permissions, + ipRange: v.IPRange, + + // Account-specific SAS parameters + services: "b", // will always be "b" + resourceTypes: v.ResourceTypes, + + // Calculated SAS signature + signature: signature, + } + + return p, nil +} + +// AccountPermissions type simplifies creating the permissions string for an Azure Storage Account SAS. +// Initialize an instance of this type and then call its String method to set AccountSignatureValues' Permissions field. +type AccountPermissions struct { + Read, Write, Delete, DeletePreviousVersion, PermanentDelete, List, Add, Create, Update, Process, FilterByTags, Tag, SetImmutabilityPolicy bool +} + +// String produces the SAS permissions string for an Azure Storage account. +// Call this method to set AccountSignatureValues' Permissions field. +func (p *AccountPermissions) String() string { + var buffer bytes.Buffer + if p.Read { + buffer.WriteRune('r') + } + if p.Write { + buffer.WriteRune('w') + } + if p.Delete { + buffer.WriteRune('d') + } + if p.DeletePreviousVersion { + buffer.WriteRune('x') + } + if p.PermanentDelete { + buffer.WriteRune('y') + } + if p.List { + buffer.WriteRune('l') + } + if p.Add { + buffer.WriteRune('a') + } + if p.Create { + buffer.WriteRune('c') + } + if p.Update { + buffer.WriteRune('u') + } + if p.Process { + buffer.WriteRune('p') + } + if p.FilterByTags { + buffer.WriteRune('f') + } + if p.Tag { + buffer.WriteRune('t') + } + if p.SetImmutabilityPolicy { + buffer.WriteRune('i') + } + return buffer.String() +} + +// Parse initializes the AccountPermissions' fields from a string. +func parseAccountPermissions(s string) (AccountPermissions, error) { + p := AccountPermissions{} // Clear out the flags + for _, r := range s { + switch r { + case 'r': + p.Read = true + case 'w': + p.Write = true + case 'd': + p.Delete = true + case 'x': + p.DeletePreviousVersion = true + case 'y': + p.PermanentDelete = true + case 'l': + p.List = true + case 'a': + p.Add = true + case 'c': + p.Create = true + case 'u': + p.Update = true + case 'p': + p.Process = true + case 't': + p.Tag = true + case 'f': + p.FilterByTags = true + case 'i': + p.SetImmutabilityPolicy = true + default: + return AccountPermissions{}, fmt.Errorf("invalid permission character: '%v'", r) + } + } + return p, nil +} + +// AccountResourceTypes type simplifies creating the resource types string for an Azure Storage Account SAS. +// Initialize an instance of this type and then call its String method to set AccountSignatureValues' ResourceTypes field. +type AccountResourceTypes struct { + Service, Container, Object bool +} + +// String produces the SAS resource types string for an Azure Storage account. +// Call this method to set AccountSignatureValues' ResourceTypes field. +func (rt *AccountResourceTypes) String() string { + var buffer bytes.Buffer + if rt.Service { + buffer.WriteRune('s') + } + if rt.Container { + buffer.WriteRune('c') + } + if rt.Object { + buffer.WriteRune('o') + } + return buffer.String() +} + +// parseAccountResourceTypes initializes the AccountResourceTypes' fields from a string. +func parseAccountResourceTypes(s string) (AccountResourceTypes, error) { + rt := AccountResourceTypes{} + for _, r := range s { + switch r { + case 's': + rt.Service = true + case 'c': + rt.Container = true + case 'o': + rt.Object = true + default: + return AccountResourceTypes{}, fmt.Errorf("invalid resource type character: '%v'", r) + } + } + return rt, nil +} diff --git a/sdk/storage/azdatalake/sas/account_test.go b/sdk/storage/azdatalake/sas/account_test.go new file mode 100644 index 000000000000..c995fe393b23 --- /dev/null +++ b/sdk/storage/azdatalake/sas/account_test.go @@ -0,0 +1,169 @@ +//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 sas + +import ( + "github.com/stretchr/testify/require" + "testing" +) + +func TestAccountPermissions_String(t *testing.T) { + testdata := []struct { + input AccountPermissions + expected string + }{ + {input: AccountPermissions{Read: true}, expected: "r"}, + {input: AccountPermissions{Write: true}, expected: "w"}, + {input: AccountPermissions{Delete: true}, expected: "d"}, + {input: AccountPermissions{DeletePreviousVersion: true}, expected: "x"}, + {input: AccountPermissions{PermanentDelete: true}, expected: "y"}, + {input: AccountPermissions{List: true}, expected: "l"}, + {input: AccountPermissions{Add: true}, expected: "a"}, + {input: AccountPermissions{Create: true}, expected: "c"}, + {input: AccountPermissions{Update: true}, expected: "u"}, + {input: AccountPermissions{Process: true}, expected: "p"}, + {input: AccountPermissions{Tag: true}, expected: "t"}, + {input: AccountPermissions{FilterByTags: true}, expected: "f"}, + {input: AccountPermissions{SetImmutabilityPolicy: true}, expected: "i"}, + {input: AccountPermissions{ + Read: true, + Write: true, + Delete: true, + DeletePreviousVersion: true, + PermanentDelete: true, + List: true, + Add: true, + Create: true, + Update: true, + Process: true, + Tag: true, + FilterByTags: true, + SetImmutabilityPolicy: true, + }, expected: "rwdxylacupfti"}, + } + for _, c := range testdata { + require.Equal(t, c.expected, c.input.String()) + } +} + +func TestAccountPermissions_Parse(t *testing.T) { + testdata := []struct { + input string + expected AccountPermissions + }{ + {expected: AccountPermissions{Read: true}, input: "r"}, + {expected: AccountPermissions{Write: true}, input: "w"}, + {expected: AccountPermissions{Delete: true}, input: "d"}, + {expected: AccountPermissions{DeletePreviousVersion: true}, input: "x"}, + {expected: AccountPermissions{PermanentDelete: true}, input: "y"}, + {expected: AccountPermissions{List: true}, input: "l"}, + {expected: AccountPermissions{Add: true}, input: "a"}, + {expected: AccountPermissions{Create: true}, input: "c"}, + {expected: AccountPermissions{Update: true}, input: "u"}, + {expected: AccountPermissions{Process: true}, input: "p"}, + {expected: AccountPermissions{Tag: true}, input: "t"}, + {expected: AccountPermissions{FilterByTags: true}, input: "f"}, + {expected: AccountPermissions{SetImmutabilityPolicy: true}, input: "i"}, + {expected: AccountPermissions{ + Read: true, + Write: true, + Delete: true, + DeletePreviousVersion: true, + PermanentDelete: true, + List: true, + Add: true, + Create: true, + Update: true, + Process: true, + Tag: true, + FilterByTags: true, + SetImmutabilityPolicy: true, + }, input: "rwdxylacupfti"}, + {expected: AccountPermissions{ + Read: true, + Write: true, + Delete: true, + DeletePreviousVersion: true, + PermanentDelete: true, + List: true, + Add: true, + Create: true, + Update: true, + Process: true, + Tag: true, + FilterByTags: true, + SetImmutabilityPolicy: true, + }, input: "trwlapdixfycu"}, + } + for _, c := range testdata { + permissions, err := parseAccountPermissions(c.input) + require.Nil(t, err) + require.Equal(t, c.expected, permissions) + } +} + +func TestAccountPermissions_ParseNegative(t *testing.T) { + _, err := parseAccountPermissions("trwlapdixfycuz") // Here 'z' is invalid + require.NotNil(t, err) + require.Contains(t, err.Error(), "122") +} + +func TestAccountResourceTypes_String(t *testing.T) { + testdata := []struct { + input AccountResourceTypes + expected string + }{ + {input: AccountResourceTypes{Service: true}, expected: "s"}, + {input: AccountResourceTypes{Container: true}, expected: "c"}, + {input: AccountResourceTypes{Object: true}, expected: "o"}, + {input: AccountResourceTypes{ + Service: true, + Container: true, + Object: true, + }, expected: "sco"}, + } + for _, c := range testdata { + require.Equal(t, c.expected, c.input.String()) + } +} + +func TestAccountResourceTypes_Parse(t *testing.T) { + testdata := []struct { + input string + expected AccountResourceTypes + }{ + {expected: AccountResourceTypes{Service: true}, input: "s"}, + {expected: AccountResourceTypes{Container: true}, input: "c"}, + {expected: AccountResourceTypes{Object: true}, input: "o"}, + {expected: AccountResourceTypes{ + Service: true, + Container: true, + Object: true, + }, input: "sco"}, + {expected: AccountResourceTypes{ + Service: true, + Container: true, + Object: true, + }, input: "osc"}, + } + for _, c := range testdata { + permissions, err := parseAccountResourceTypes(c.input) + require.Nil(t, err) + require.Equal(t, c.expected, permissions) + } +} + +func TestAccountResourceTypes_ParseNegative(t *testing.T) { + _, err := parseAccountResourceTypes("scoz") // Here 'z' is invalid + require.NotNil(t, err) + require.Contains(t, err.Error(), "122") +} + +// TODO: Sign With Shared Key +// Negative Case +// Version not provided +// SignWithSharedKey tests diff --git a/sdk/storage/azdatalake/sas/query_params.go b/sdk/storage/azdatalake/sas/query_params.go new file mode 100644 index 000000000000..ed3cd252d93f --- /dev/null +++ b/sdk/storage/azdatalake/sas/query_params.go @@ -0,0 +1,506 @@ +//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 sas + +import ( + "errors" + "net" + "net/url" + "strings" + "time" +) + +// timeFormat represents the format of a SAS start or expiry time. Use it when formatting/parsing a time.Time. +const ( + timeFormat = "2006-01-02T15:04:05Z" // "2017-07-27T00:00:00Z" // ISO 8601 +) + +var ( + // Version is the default version encoded in the SAS token. + Version = "2020-02-10" +) + +// TimeFormats ISO 8601 format. +// Please refer to https://docs.microsoft.com/en-us/rest/api/storageservices/constructing-a-service-sas for more details. +var timeFormats = []string{"2006-01-02T15:04:05.0000000Z", timeFormat, "2006-01-02T15:04Z", "2006-01-02"} + +// Protocol indicates the http/https. +type Protocol string + +const ( + // ProtocolHTTPS can be specified for a SAS protocol. + ProtocolHTTPS Protocol = "https" + + // ProtocolHTTPSandHTTP can be specified for a SAS protocol. + ProtocolHTTPSandHTTP Protocol = "https,http" +) + +// FormatTimesForSigning converts a time.Time to a snapshotTimeFormat string suitable for a +// Field's StartTime or ExpiryTime fields. Returns "" if value.IsZero(). +func formatTimesForSigning(startTime, expiryTime time.Time) (string, string) { + ss := "" + if !startTime.IsZero() { + ss = formatTimeWithDefaultFormat(&startTime) + } + se := "" + if !expiryTime.IsZero() { + se = formatTimeWithDefaultFormat(&expiryTime) + } + return ss, se +} + +// formatTimeWithDefaultFormat format time with ISO 8601 in "yyyy-MM-ddTHH:mm:ssZ". +func formatTimeWithDefaultFormat(t *time.Time) string { + return formatTime(t, timeFormat) // By default, "yyyy-MM-ddTHH:mm:ssZ" is used +} + +// formatTime format time with given format, use ISO 8601 in "yyyy-MM-ddTHH:mm:ssZ" by default. +func formatTime(t *time.Time, format string) string { + if format != "" { + return t.Format(format) + } + return t.Format(timeFormat) // By default, "yyyy-MM-ddTHH:mm:ssZ" is used +} + +// ParseTime try to parse a SAS time string. +func parseTime(val string) (t time.Time, timeFormat string, err error) { + for _, sasTimeFormat := range timeFormats { + t, err = time.Parse(sasTimeFormat, val) + if err == nil { + timeFormat = sasTimeFormat + break + } + } + + if err != nil { + err = errors.New("fail to parse time with IOS 8601 formats, please refer to https://docs.microsoft.com/en-us/rest/api/storageservices/constructing-a-service-sas for more details") + } + + return +} + +// IPRange represents a SAS IP range's start IP and (optionally) end IP. +type IPRange struct { + Start net.IP // Not specified if length = 0 + End net.IP // Not specified if length = 0 +} + +// String returns a string representation of an IPRange. +func (ipr *IPRange) String() string { + if len(ipr.Start) == 0 { + return "" + } + start := ipr.Start.String() + if len(ipr.End) == 0 { + return start + } + return start + "-" + ipr.End.String() +} + +// https://docs.microsoft.com/en-us/rest/api/storageservices/constructing-a-service-sas + +// QueryParameters object represents the components that make up an Azure Storage SAS' query parameters. +// You parse a map of query parameters into its fields by calling NewQueryParameters(). You add the components +// to a query parameter map by calling AddToValues(). +// NOTE: Changing any field requires computing a new SAS signature using a XxxSASSignatureValues type. +// This type defines the components used by all Azure Storage resources (Containers, Blobs, Files, & Queues). +type QueryParameters struct { + // All members are immutable or values so copies of this struct are goroutine-safe. + version string `param:"sv"` + services string `param:"ss"` + resourceTypes string `param:"srt"` + protocol Protocol `param:"spr"` + startTime time.Time `param:"st"` + expiryTime time.Time `param:"se"` + snapshotTime time.Time `param:"snapshot"` + ipRange IPRange `param:"sip"` + identifier string `param:"si"` + resource string `param:"sr"` + permissions string `param:"sp"` + signature string `param:"sig"` + cacheControl string `param:"rscc"` + contentDisposition string `param:"rscd"` + contentEncoding string `param:"rsce"` + contentLanguage string `param:"rscl"` + contentType string `param:"rsct"` + signedOID string `param:"skoid"` + signedTID string `param:"sktid"` + signedStart time.Time `param:"skt"` + signedService string `param:"sks"` + signedExpiry time.Time `param:"ske"` + signedVersion string `param:"skv"` + signedDirectoryDepth string `param:"sdd"` + authorizedObjectID string `param:"saoid"` + unauthorizedObjectID string `param:"suoid"` + correlationID string `param:"scid"` + // private member used for startTime and expiryTime formatting. + stTimeFormat string + seTimeFormat string +} + +// AuthorizedObjectID returns authorizedObjectID. +func (p *QueryParameters) AuthorizedObjectID() string { + return p.authorizedObjectID +} + +// UnauthorizedObjectID returns unauthorizedObjectID. +func (p *QueryParameters) UnauthorizedObjectID() string { + return p.unauthorizedObjectID +} + +// SignedCorrelationID returns signedCorrelationID. +func (p *QueryParameters) SignedCorrelationID() string { + return p.correlationID +} + +// SignedOID returns signedOID. +func (p *QueryParameters) SignedOID() string { + return p.signedOID +} + +// SignedTID returns signedTID. +func (p *QueryParameters) SignedTID() string { + return p.signedTID +} + +// SignedStart returns signedStart. +func (p *QueryParameters) SignedStart() time.Time { + return p.signedStart +} + +// SignedExpiry returns signedExpiry. +func (p *QueryParameters) SignedExpiry() time.Time { + return p.signedExpiry +} + +// SignedService returns signedService. +func (p *QueryParameters) SignedService() string { + return p.signedService +} + +// SignedVersion returns signedVersion. +func (p *QueryParameters) SignedVersion() string { + return p.signedVersion +} + +// SnapshotTime returns snapshotTime. +func (p *QueryParameters) SnapshotTime() time.Time { + return p.snapshotTime +} + +// Version returns version. +func (p *QueryParameters) Version() string { + return p.version +} + +// Services returns services. +func (p *QueryParameters) Services() string { + return p.services +} + +// ResourceTypes returns resourceTypes. +func (p *QueryParameters) ResourceTypes() string { + return p.resourceTypes +} + +// Protocol returns protocol. +func (p *QueryParameters) Protocol() Protocol { + return p.protocol +} + +// StartTime returns startTime. +func (p *QueryParameters) StartTime() time.Time { + return p.startTime +} + +// ExpiryTime returns expiryTime. +func (p *QueryParameters) ExpiryTime() time.Time { + return p.expiryTime +} + +// IPRange returns ipRange. +func (p *QueryParameters) IPRange() IPRange { + return p.ipRange +} + +// Identifier returns identifier. +func (p *QueryParameters) Identifier() string { + return p.identifier +} + +// Resource returns resource. +func (p *QueryParameters) Resource() string { + return p.resource +} + +// Permissions returns permissions. +func (p *QueryParameters) Permissions() string { + return p.permissions +} + +// Signature returns signature. +func (p *QueryParameters) Signature() string { + return p.signature +} + +// CacheControl returns cacheControl. +func (p *QueryParameters) CacheControl() string { + return p.cacheControl +} + +// ContentDisposition returns contentDisposition. +func (p *QueryParameters) ContentDisposition() string { + return p.contentDisposition +} + +// ContentEncoding returns contentEncoding. +func (p *QueryParameters) ContentEncoding() string { + return p.contentEncoding +} + +// ContentLanguage returns contentLanguage. +func (p *QueryParameters) ContentLanguage() string { + return p.contentLanguage +} + +// ContentType returns contentType. +func (p *QueryParameters) ContentType() string { + return p.contentType +} + +// SignedDirectoryDepth returns signedDirectoryDepth. +func (p *QueryParameters) SignedDirectoryDepth() string { + return p.signedDirectoryDepth +} + +// Encode encodes the SAS query parameters into URL encoded form sorted by key. +func (p *QueryParameters) Encode() string { + v := url.Values{} + + if p.version != "" { + v.Add("sv", p.version) + } + if p.services != "" { + v.Add("ss", p.services) + } + if p.resourceTypes != "" { + v.Add("srt", p.resourceTypes) + } + if p.protocol != "" { + v.Add("spr", string(p.protocol)) + } + if !p.startTime.IsZero() { + v.Add("st", formatTime(&(p.startTime), p.stTimeFormat)) + } + if !p.expiryTime.IsZero() { + v.Add("se", formatTime(&(p.expiryTime), p.seTimeFormat)) + } + if len(p.ipRange.Start) > 0 { + v.Add("sip", p.ipRange.String()) + } + if p.identifier != "" { + v.Add("si", p.identifier) + } + if p.resource != "" { + v.Add("sr", p.resource) + } + if p.permissions != "" { + v.Add("sp", p.permissions) + } + if p.signedOID != "" { + v.Add("skoid", p.signedOID) + v.Add("sktid", p.signedTID) + v.Add("skt", p.signedStart.Format(timeFormat)) + v.Add("ske", p.signedExpiry.Format(timeFormat)) + v.Add("sks", p.signedService) + v.Add("skv", p.signedVersion) + } + if p.signature != "" { + v.Add("sig", p.signature) + } + if p.cacheControl != "" { + v.Add("rscc", p.cacheControl) + } + if p.contentDisposition != "" { + v.Add("rscd", p.contentDisposition) + } + if p.contentEncoding != "" { + v.Add("rsce", p.contentEncoding) + } + if p.contentLanguage != "" { + v.Add("rscl", p.contentLanguage) + } + if p.contentType != "" { + v.Add("rsct", p.contentType) + } + if p.signedDirectoryDepth != "" { + v.Add("sdd", p.signedDirectoryDepth) + } + if p.authorizedObjectID != "" { + v.Add("saoid", p.authorizedObjectID) + } + if p.unauthorizedObjectID != "" { + v.Add("suoid", p.unauthorizedObjectID) + } + if p.correlationID != "" { + v.Add("scid", p.correlationID) + } + + return v.Encode() +} + +// NewQueryParameters creates and initializes a QueryParameters object based on the +// query parameter map's passed-in values. If a key is unrecognized, it is ignored +func NewQueryParameters(values url.Values) QueryParameters { + p := QueryParameters{} + for k, v := range values { + val := v[0] + switch strings.ToLower(k) { + case "sv": + p.version = val + case "ss": + p.services = val + case "srt": + p.resourceTypes = val + case "spr": + p.protocol = Protocol(val) + case "st": + p.startTime, p.stTimeFormat, _ = parseTime(val) + case "se": + p.expiryTime, p.seTimeFormat, _ = parseTime(val) + case "sip": + dashIndex := strings.Index(val, "-") + if dashIndex == -1 { + p.ipRange.Start = net.ParseIP(val) + } else { + p.ipRange.Start = net.ParseIP(val[:dashIndex]) + p.ipRange.End = net.ParseIP(val[dashIndex+1:]) + } + case "si": + p.identifier = val + case "sr": + p.resource = val + case "sp": + p.permissions = val + case "sig": + p.signature = val + case "rscc": + p.cacheControl = val + case "rscd": + p.contentDisposition = val + case "rsce": + p.contentEncoding = val + case "rscl": + p.contentLanguage = val + case "rsct": + p.contentType = val + case "skoid": + p.signedOID = val + case "sktid": + p.signedTID = val + case "skt": + p.signedStart, _ = time.Parse(timeFormat, val) + case "ske": + p.signedExpiry, _ = time.Parse(timeFormat, val) + case "sks": + p.signedService = val + case "skv": + p.signedVersion = val + case "sdd": + p.signedDirectoryDepth = val + case "saoid": + p.authorizedObjectID = val + case "suoid": + p.unauthorizedObjectID = val + case "scid": + p.correlationID = val + default: + continue // query param didn't get recognized + } + } + return p +} + +// newQueryParameters creates and initializes a QueryParameters object based on the +// query parameter map's passed-in values. If deleteSASParametersFromValues is true, +// all SAS-related query parameters are removed from the passed-in map. If +// deleteSASParametersFromValues is false, the map passed-in map is unaltered. +func newQueryParameters(values url.Values, deleteSASParametersFromValues bool) QueryParameters { + p := QueryParameters{} + for k, v := range values { + val := v[0] + isSASKey := true + switch strings.ToLower(k) { + case "sv": + p.version = val + case "ss": + p.services = val + case "srt": + p.resourceTypes = val + case "spr": + p.protocol = Protocol(val) + case "st": + p.startTime, p.stTimeFormat, _ = parseTime(val) + case "se": + p.expiryTime, p.seTimeFormat, _ = parseTime(val) + case "sip": + dashIndex := strings.Index(val, "-") + if dashIndex == -1 { + p.ipRange.Start = net.ParseIP(val) + } else { + p.ipRange.Start = net.ParseIP(val[:dashIndex]) + p.ipRange.End = net.ParseIP(val[dashIndex+1:]) + } + case "si": + p.identifier = val + case "sr": + p.resource = val + case "sp": + p.permissions = val + //case "snapshot": + // p.snapshotTime, _ = time.Parse(exported.SnapshotTimeFormat, val) + case "sig": + p.signature = val + case "rscc": + p.cacheControl = val + case "rscd": + p.contentDisposition = val + case "rsce": + p.contentEncoding = val + case "rscl": + p.contentLanguage = val + case "rsct": + p.contentType = val + case "skoid": + p.signedOID = val + case "sktid": + p.signedTID = val + case "skt": + p.signedStart, _ = time.Parse(timeFormat, val) + case "ske": + p.signedExpiry, _ = time.Parse(timeFormat, val) + case "sks": + p.signedService = val + case "skv": + p.signedVersion = val + case "sdd": + p.signedDirectoryDepth = val + case "saoid": + p.authorizedObjectID = val + case "suoid": + p.unauthorizedObjectID = val + case "scid": + p.correlationID = val + default: + isSASKey = false // We didn't recognize the query parameter + } + if isSASKey && deleteSASParametersFromValues { + delete(values, k) + } + } + return p +} diff --git a/sdk/storage/azdatalake/sas/query_params_test.go b/sdk/storage/azdatalake/sas/query_params_test.go new file mode 100644 index 000000000000..1e50647a2ca3 --- /dev/null +++ b/sdk/storage/azdatalake/sas/query_params_test.go @@ -0,0 +1,231 @@ +//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 sas + +import ( + "fmt" + "net" + "net/url" + "strings" + "testing" + "time" + + "github.com/stretchr/testify/require" +) + +func TestFormatTimesForSigning(t *testing.T) { + testdata := []struct { + inputStart time.Time + inputEnd time.Time + inputSnapshot time.Time + expectedStart string + expectedEnd string + expectedSnapshot string + }{ + {expectedStart: "", expectedEnd: "", expectedSnapshot: ""}, + {inputStart: time.Date(1955, 6, 25, 22, 15, 56, 345456, time.UTC), expectedStart: "1955-06-25T22:15:56Z", expectedEnd: "", expectedSnapshot: ""}, + {inputEnd: time.Date(2023, 4, 5, 8, 50, 27, 4500, time.UTC), expectedStart: "", expectedEnd: "2023-04-05T08:50:27Z", expectedSnapshot: ""}, + {inputSnapshot: time.Date(2021, 1, 5, 22, 15, 33, 1234879, time.UTC), expectedStart: "", expectedEnd: "", expectedSnapshot: "2021-01-05T22:15:33.0012348Z"}, + { + inputStart: time.Date(1955, 6, 25, 22, 15, 56, 345456, time.UTC), + inputEnd: time.Date(2023, 4, 5, 8, 50, 27, 4500, time.UTC), + inputSnapshot: time.Date(2021, 1, 5, 22, 15, 33, 1234879, time.UTC), + expectedStart: "1955-06-25T22:15:56Z", + expectedEnd: "2023-04-05T08:50:27Z", + expectedSnapshot: "2021-01-05T22:15:33.0012348Z", + }, + } + for _, c := range testdata { + start, end := formatTimesForSigning(c.inputStart, c.inputEnd) + require.Equal(t, c.expectedStart, start) + require.Equal(t, c.expectedEnd, end) + } +} + +func TestFormatTimeWithDefaultFormat(t *testing.T) { + testdata := []struct { + input time.Time + expectedTime string + }{ + {input: time.Date(1955, 4, 5, 8, 50, 27, 4500, time.UTC), expectedTime: "1955-04-05T08:50:27Z"}, + {input: time.Date(1917, 3, 9, 16, 22, 56, 0, time.UTC), expectedTime: "1917-03-09T16:22:56Z"}, + {input: time.Date(2021, 1, 5, 22, 15, 0, 0, time.UTC), expectedTime: "2021-01-05T22:15:00Z"}, + {input: time.Date(2023, 6, 25, 0, 0, 0, 0, time.UTC), expectedTime: "2023-06-25T00:00:00Z"}, + } + for _, c := range testdata { + formattedTime := formatTimeWithDefaultFormat(&c.input) + require.Equal(t, c.expectedTime, formattedTime) + } +} + +func TestFormatTime(t *testing.T) { + testdata := []struct { + input time.Time + format string + expectedTime string + }{ + {input: time.Date(1955, 4, 5, 8, 50, 27, 4500, time.UTC), format: "2006-01-02T15:04:05.0000000Z", expectedTime: "1955-04-05T08:50:27.0000045Z"}, + {input: time.Date(1955, 4, 5, 8, 50, 27, 4500, time.UTC), format: "", expectedTime: "1955-04-05T08:50:27Z"}, + {input: time.Date(1917, 3, 9, 16, 22, 56, 0, time.UTC), format: "2006-01-02T15:04:05Z", expectedTime: "1917-03-09T16:22:56Z"}, + {input: time.Date(1917, 3, 9, 16, 22, 56, 0, time.UTC), format: "", expectedTime: "1917-03-09T16:22:56Z"}, + {input: time.Date(2021, 1, 5, 22, 15, 0, 0, time.UTC), format: "2006-01-02T15:04Z", expectedTime: "2021-01-05T22:15Z"}, + {input: time.Date(2021, 1, 5, 22, 15, 0, 0, time.UTC), format: "", expectedTime: "2021-01-05T22:15:00Z"}, + {input: time.Date(2023, 6, 25, 0, 0, 0, 0, time.UTC), format: "2006-01-02", expectedTime: "2023-06-25"}, + {input: time.Date(2023, 6, 25, 0, 0, 0, 0, time.UTC), format: "", expectedTime: "2023-06-25T00:00:00Z"}, + } + for _, c := range testdata { + formattedTime := formatTime(&c.input, c.format) + require.Equal(t, c.expectedTime, formattedTime) + } +} + +func TestParseTime(t *testing.T) { + testdata := []struct { + input string + expectedTime time.Time + expectedFormat string + }{ + {input: "1955-04-05T08:50:27.0000045Z", expectedTime: time.Date(1955, 4, 5, 8, 50, 27, 4500, time.UTC), expectedFormat: "2006-01-02T15:04:05.0000000Z"}, + {input: "1917-03-09T16:22:56Z", expectedTime: time.Date(1917, 3, 9, 16, 22, 56, 0, time.UTC), expectedFormat: "2006-01-02T15:04:05Z"}, + {input: "2021-01-05T22:15Z", expectedTime: time.Date(2021, 1, 5, 22, 15, 0, 0, time.UTC), expectedFormat: "2006-01-02T15:04Z"}, + {input: "2023-06-25", expectedTime: time.Date(2023, 6, 25, 0, 0, 0, 0, time.UTC), expectedFormat: "2006-01-02"}, + } + for _, c := range testdata { + parsedTime, format, err := parseTime(c.input) + require.Nil(t, err) + require.Equal(t, c.expectedTime, parsedTime) + require.Equal(t, c.expectedFormat, format) + } +} + +func TestParseTimeNegative(t *testing.T) { + _, _, err := parseTime("notatime") + require.Error(t, err, "fail to parse time with IOS 8601 formats, please refer to https://docs.microsoft.com/en-us/rest/api/storageservices/constructing-a-service-sas for more details") +} + +func TestIPRange_String(t *testing.T) { + testdata := []struct { + inputStart net.IP + inputEnd net.IP + expected string + }{ + {expected: ""}, + {inputStart: net.IPv4(10, 255, 0, 0), expected: "10.255.0.0"}, + {inputStart: net.IPv4(10, 255, 0, 0), inputEnd: net.IPv4(10, 255, 0, 50), expected: "10.255.0.0-10.255.0.50"}, + } + for _, c := range testdata { + var ipRange IPRange + if c.inputStart != nil { + ipRange.Start = c.inputStart + } + if c.inputEnd != nil { + ipRange.End = c.inputEnd + } + require.Equal(t, c.expected, ipRange.String()) + } +} + +func TestSAS(t *testing.T) { + // Note: This is a totally invalid fake SAS, this is just testing our ability to parse different query parameters on a SAS + const sas = "sv=2019-12-12&sr=b&st=2111-01-09T01:42:34.936Z&se=2222-03-09T01:42:34.936Z&sp=rw&sip=168.1.5.60-168.1.5.70&spr=https,http&si=myIdentifier&ss=bf&srt=s&rscc=cc&rscd=cd&rsce=ce&rscl=cl&rsct=ct&skoid=oid&sktid=tid&skt=2111-01-09T01:42:34.936Z&ske=2222-03-09T01:42:34.936Z&sks=s&skv=v&sdd=3&saoid=oid&suoid=oid&scid=cid&sig=clNxbtnkKSHw7f3KMEVVc4agaszoRFdbZr%2FWBmPNsrw%3D" + _url := fmt.Sprintf("https://teststorageaccount.blob.core.windows.net/testcontainer/testpath?%s", sas) + _uri, err := url.Parse(_url) + require.NoError(t, err) + sasQueryParams := newQueryParameters(_uri.Query(), true) + validateSAS(t, sas, sasQueryParams) +} + +func validateSAS(t *testing.T, sas string, parameters QueryParameters) { + sasCompMap := make(map[string]string) + for _, sasComp := range strings.Split(sas, "&") { + comp := strings.Split(sasComp, "=") + sasCompMap[comp[0]] = comp[1] + } + + require.Equal(t, parameters.Version(), sasCompMap["sv"]) + require.Equal(t, parameters.Services(), sasCompMap["ss"]) + require.Equal(t, parameters.ResourceTypes(), sasCompMap["srt"]) + require.Equal(t, string(parameters.Protocol()), sasCompMap["spr"]) + if _, ok := sasCompMap["st"]; ok { + startTime, _, err := parseTime(sasCompMap["st"]) + require.NoError(t, err) + require.Equal(t, parameters.StartTime(), startTime) + } + if _, ok := sasCompMap["se"]; ok { + endTime, _, err := parseTime(sasCompMap["se"]) + require.NoError(t, err) + require.Equal(t, parameters.ExpiryTime(), endTime) + } + + if _, ok := sasCompMap["snapshot"]; ok { + snapshotTime, _, err := parseTime(sasCompMap["snapshot"]) + require.NoError(t, err) + require.Equal(t, parameters.SnapshotTime(), snapshotTime) + } + ipRange := parameters.IPRange() + require.Equal(t, ipRange.String(), sasCompMap["sip"]) + require.Equal(t, parameters.Identifier(), sasCompMap["si"]) + require.Equal(t, parameters.Resource(), sasCompMap["sr"]) + require.Equal(t, parameters.Permissions(), sasCompMap["sp"]) + + sign, err := url.QueryUnescape(sasCompMap["sig"]) + require.NoError(t, err) + + require.Equal(t, parameters.Signature(), sign) + require.Equal(t, parameters.CacheControl(), sasCompMap["rscc"]) + require.Equal(t, parameters.ContentDisposition(), sasCompMap["rscd"]) + require.Equal(t, parameters.ContentEncoding(), sasCompMap["rsce"]) + require.Equal(t, parameters.ContentLanguage(), sasCompMap["rscl"]) + require.Equal(t, parameters.ContentType(), sasCompMap["rsct"]) + require.Equal(t, parameters.SignedOID(), sasCompMap["skoid"]) + require.Equal(t, parameters.SignedTID(), sasCompMap["sktid"]) + + if _, ok := sasCompMap["skt"]; ok { + signedStart, _, err := parseTime(sasCompMap["skt"]) + require.NoError(t, err) + require.Equal(t, parameters.SignedStart(), signedStart) + } + require.Equal(t, parameters.SignedService(), sasCompMap["sks"]) + + if _, ok := sasCompMap["ske"]; ok { + signedExpiry, _, err := parseTime(sasCompMap["ske"]) + require.NoError(t, err) + require.Equal(t, parameters.SignedExpiry(), signedExpiry) + } + + require.Equal(t, parameters.SignedVersion(), sasCompMap["skv"]) + require.Equal(t, parameters.SignedDirectoryDepth(), sasCompMap["sdd"]) + require.Equal(t, parameters.AuthorizedObjectID(), sasCompMap["saoid"]) + require.Equal(t, parameters.UnauthorizedObjectID(), sasCompMap["suoid"]) + require.Equal(t, parameters.SignedCorrelationID(), sasCompMap["scid"]) +} + +func TestSASInvalidQueryParameter(t *testing.T) { + // Signature is invalid below + const sas = "sv=2019-12-12&signature=clNxbtnkKSHw7f3KMEVVc4agaszoRFdbZr%2FWBmPNsrw%3D&sr=b" + _url := fmt.Sprintf("https://teststorageaccount.blob.core.windows.net/testcontainer/testpath?%s", sas) + _uri, err := url.Parse(_url) + require.NoError(t, err) + newQueryParameters(_uri.Query(), true) + // NewQueryParameters should not delete signature + require.Contains(t, _uri.Query(), "signature") +} + +func TestEncode(t *testing.T) { + // Note: This is a totally invalid fake SAS, this is just testing our ability to parse different query parameters on a SAS + expected := "rscc=cc&rscd=cd&rsce=ce&rscl=cl&rsct=ct&saoid=oid&scid=cid&sdd=3&se=2222-03-09T01%3A42%3A34Z&si=myIdentifier&sig=clNxbtnkKSHw7f3KMEVVc4agaszoRFdbZr%2FWBmPNsrw%3D&sip=168.1.5.60-168.1.5.70&ske=2222-03-09T01%3A42%3A34Z&skoid=oid&sks=s&skt=2111-01-09T01%3A42%3A34Z&sktid=tid&skv=v&sp=rw&spr=https%2Chttp&sr=b&srt=sco&ss=bf&st=2111-01-09T01%3A42%3A34Z&suoid=oid&sv=2019-12-12" + randomOrder := "sdd=3&scid=cid&se=2222-03-09T01:42:34.936Z&rsce=ce&ss=bf&skoid=oid&si=myIdentifier&ske=2222-03-09T01:42:34.936Z&saoid=oid&sip=168.1.5.60-168.1.5.70&rscc=cc&srt=sco&sig=clNxbtnkKSHw7f3KMEVVc4agaszoRFdbZr%2FWBmPNsrw%3D&rsct=ct&skt=2111-01-09T01:42:34.936Z&rscl=cl&suoid=oid&sv=2019-12-12&sr=b&st=2111-01-09T01:42:34.936Z&rscd=cd&sp=rw&sktid=tid&spr=https,http&sks=s&skv=v" + testdata := []string{expected, randomOrder} + + for _, sas := range testdata { + _url := fmt.Sprintf("https://teststorageaccount.blob.core.windows.net/testcontainer/testpath?%s", sas) + _uri, err := url.Parse(_url) + require.NoError(t, err) + queryParams := newQueryParameters(_uri.Query(), true) + require.Equal(t, expected, queryParams.Encode()) + } +} diff --git a/sdk/storage/azdatalake/sas/service.go b/sdk/storage/azdatalake/sas/service.go new file mode 100644 index 000000000000..23518b25676d --- /dev/null +++ b/sdk/storage/azdatalake/sas/service.go @@ -0,0 +1,413 @@ +//go:build go1.18 +// +build go1.18 + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package sas + +import ( + "bytes" + "errors" + "fmt" + "strings" + "time" + + "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/internal/exported" +) + +// DatalakeSignatureValues is used to generate a Shared Access Signature (SAS) for an Azure Storage filesystem or path. +// For more information on creating service sas, see https://docs.microsoft.com/rest/api/storageservices/constructing-a-service-sas +// For more information on creating user delegation sas, see https://docs.microsoft.com/rest/api/storageservices/create-user-delegation-sas +type DatalakeSignatureValues struct { + Version string `param:"sv"` // If not specified, this defaults to Version + Protocol Protocol `param:"spr"` // See the Protocol* constants + StartTime time.Time `param:"st"` // Not specified if IsZero + ExpiryTime time.Time `param:"se"` // Not specified if IsZero + Permissions string `param:"sp"` // Create by initializing FilesystemPermissions, FilePermissions or DirectoryPermissions and then call String() + IPRange IPRange `param:"sip"` + Identifier string `param:"si"` + FilesystemName string + // Use "" to create a Filesystem SAS + // DirectoryPath will set this to "" if it is passed + FilePath string + // Not nil for a directory SAS (ie sr=d) + // Use "" to create a Filesystem SAS + DirectoryPath string + CacheControl string // rscc + ContentDisposition string // rscd + ContentEncoding string // rsce + ContentLanguage string // rscl + ContentType string // rsct + AuthorizedObjectID string // saoid + UnauthorizedObjectID string // suoid + CorrelationID string // scid +} + +//TODO: add snapshot and versioning support in the future + +func getDirectoryDepth(path string) string { + if path == "" { + return "" + } + return fmt.Sprint(strings.Count(path, "/") + 1) +} + +// SignWithSharedKey uses an account's SharedKeyCredential to sign this signature values to produce the proper SAS query parameters. +func (v DatalakeSignatureValues) SignWithSharedKey(sharedKeyCredential *SharedKeyCredential) (QueryParameters, error) { + if v.ExpiryTime.IsZero() || v.Permissions == "" { + return QueryParameters{}, errors.New("service SAS is missing at least one of these: ExpiryTime or Permissions") + } + + //Make sure the permission characters are in the correct order + perms, err := parsePathPermissions(v.Permissions) + if err != nil { + return QueryParameters{}, err + } + v.Permissions = perms.String() + + resource := "c" + if v.DirectoryPath != "" { + resource = "d" + v.FilePath = "" + } else if v.FilePath == "" { + // do nothing + } else { + resource = "b" + } + + if v.Version == "" { + v.Version = Version + } + startTime, expiryTime := formatTimesForSigning(v.StartTime, v.ExpiryTime) + + signedIdentifier := v.Identifier + + // String to sign: http://msdn.microsoft.com/en-us/library/azure/dn140255.aspx + stringToSign := strings.Join([]string{ + v.Permissions, + startTime, + expiryTime, + getCanonicalName(sharedKeyCredential.AccountName(), v.FilesystemName, v.FilePath, v.DirectoryPath), + signedIdentifier, + v.IPRange.String(), + string(v.Protocol), + v.Version, + resource, + "", //snapshot not supported + v.CacheControl, // rscc + v.ContentDisposition, // rscd + v.ContentEncoding, // rsce + v.ContentLanguage, // rscl + v.ContentType}, // rsct + "\n") + + signature, err := exported.ComputeHMACSHA256(sharedKeyCredential, stringToSign) + if err != nil { + return QueryParameters{}, err + } + + p := QueryParameters{ + // Common SAS parameters + version: v.Version, + protocol: v.Protocol, + startTime: v.StartTime, + expiryTime: v.ExpiryTime, + permissions: v.Permissions, + ipRange: v.IPRange, + + // Container/Blob-specific SAS parameters + resource: resource, + identifier: v.Identifier, + cacheControl: v.CacheControl, + contentDisposition: v.ContentDisposition, + contentEncoding: v.ContentEncoding, + contentLanguage: v.ContentLanguage, + contentType: v.ContentType, + signedDirectoryDepth: getDirectoryDepth(v.DirectoryPath), + authorizedObjectID: v.AuthorizedObjectID, + unauthorizedObjectID: v.UnauthorizedObjectID, + correlationID: v.CorrelationID, + // Calculated SAS signature + signature: signature, + } + + return p, nil +} + +// SignWithUserDelegation uses an account's UserDelegationCredential to sign this signature values to produce the proper SAS query parameters. +func (v DatalakeSignatureValues) SignWithUserDelegation(userDelegationCredential *UserDelegationCredential) (QueryParameters, error) { + if userDelegationCredential == nil { + return QueryParameters{}, fmt.Errorf("cannot sign SAS query without User Delegation Key") + } + + if v.ExpiryTime.IsZero() || v.Permissions == "" { + return QueryParameters{}, errors.New("user delegation SAS is missing at least one of these: ExpiryTime or Permissions") + } + + // Parse the resource + resource := "c" + if v.DirectoryPath != "" { + resource = "d" + v.FilePath = "" + } else if v.FilePath == "" { + // do nothing + } else { + resource = "b" + } + // make sure the permission characters are in the correct order + if resource == "c" { + perms, err := parseFilesystemPermissions(v.Permissions) + if err != nil { + return QueryParameters{}, err + } + v.Permissions = perms.String() + } else { + perms, err := parsePathPermissions(v.Permissions) + if err != nil { + return QueryParameters{}, err + } + v.Permissions = perms.String() + } + + if v.Version == "" { + v.Version = Version + } + startTime, expiryTime := formatTimesForSigning(v.StartTime, v.ExpiryTime) + + udk := exported.GetUDKParams(userDelegationCredential) + + udkStart, udkExpiry := formatTimesForSigning(*udk.SignedStart, *udk.SignedExpiry) + + stringToSign := strings.Join([]string{ + v.Permissions, + startTime, + expiryTime, + getCanonicalName(exported.GetAccountName(userDelegationCredential), v.FilesystemName, v.FilePath, v.DirectoryPath), + *udk.SignedOID, + *udk.SignedTID, + udkStart, + udkExpiry, + *udk.SignedService, + *udk.SignedVersion, + v.AuthorizedObjectID, + v.UnauthorizedObjectID, + v.CorrelationID, + v.IPRange.String(), + string(v.Protocol), + v.Version, + resource, + "", //snapshot not supported + v.CacheControl, // rscc + v.ContentDisposition, // rscd + v.ContentEncoding, // rsce + v.ContentLanguage, // rscl + v.ContentType}, // rsct + "\n") + + signature, err := exported.ComputeUDCHMACSHA256(userDelegationCredential, stringToSign) + if err != nil { + return QueryParameters{}, err + } + + p := QueryParameters{ + // Common SAS parameters + version: v.Version, + protocol: v.Protocol, + startTime: v.StartTime, + expiryTime: v.ExpiryTime, + permissions: v.Permissions, + ipRange: v.IPRange, + + // Container/Blob-specific SAS parameters + resource: resource, + identifier: v.Identifier, + cacheControl: v.CacheControl, + contentDisposition: v.ContentDisposition, + contentEncoding: v.ContentEncoding, + contentLanguage: v.ContentLanguage, + contentType: v.ContentType, + signedDirectoryDepth: getDirectoryDepth(v.DirectoryPath), + authorizedObjectID: v.AuthorizedObjectID, + unauthorizedObjectID: v.UnauthorizedObjectID, + correlationID: v.CorrelationID, + // Calculated SAS signature + signature: signature, + } + + //User delegation SAS specific parameters + p.signedOID = *udk.SignedOID + p.signedTID = *udk.SignedTID + p.signedStart = *udk.SignedStart + p.signedExpiry = *udk.SignedExpiry + p.signedService = *udk.SignedService + p.signedVersion = *udk.SignedVersion + + return p, nil +} + +// getCanonicalName computes the canonical name for a container or blob resource for SAS signing. +func getCanonicalName(account string, filesystemName string, fileName string, directoryName string) string { + // Container: "/blob/account/containername" + // Blob: "/blob/account/containername/blobname" + elements := []string{"/blob/", account, "/", filesystemName} + if fileName != "" { + elements = append(elements, "/", strings.Replace(fileName, "\\", "/", -1)) + } else if directoryName != "" { + elements = append(elements, "/", directoryName) + } + return strings.Join(elements, "") +} + +// FilesystemPermissions type simplifies creating the permissions string for an Azure Storage container SAS. +// Initialize an instance of this type and then call its String method to set BlobSignatureValues' Permissions field. +// All permissions descriptions can be found here: https://docs.microsoft.com/en-us/rest/api/storageservices/create-service-sas#permissions-for-a-directory-container-or-blob +type FilesystemPermissions struct { + Read, Add, Create, Write, Delete, List, Move bool + Execute, ModifyOwnership, ModifyPermissions bool // Meant for hierarchical namespace accounts +} + +// String produces the SAS permissions string for an Azure Storage container. +// Call this method to set BlobSignatureValues' Permissions field. +func (p *FilesystemPermissions) String() string { + var b bytes.Buffer + if p.Read { + b.WriteRune('r') + } + if p.Add { + b.WriteRune('a') + } + if p.Create { + b.WriteRune('c') + } + if p.Write { + b.WriteRune('w') + } + if p.Delete { + b.WriteRune('d') + } + if p.List { + b.WriteRune('l') + } + if p.Move { + b.WriteRune('m') + } + if p.Execute { + b.WriteRune('e') + } + if p.ModifyOwnership { + b.WriteRune('o') + } + if p.ModifyPermissions { + b.WriteRune('p') + } + return b.String() +} + +// Parse initializes ContainerPermissions' fields from a string. +func parseFilesystemPermissions(s string) (FilesystemPermissions, error) { + p := FilesystemPermissions{} // Clear the flags + for _, r := range s { + switch r { + case 'r': + p.Read = true + case 'a': + p.Add = true + case 'c': + p.Create = true + case 'w': + p.Write = true + case 'd': + p.Delete = true + case 'l': + p.List = true + case 'm': + p.Move = true + case 'e': + p.Execute = true + case 'o': + p.ModifyOwnership = true + case 'p': + p.ModifyPermissions = true + default: + return FilesystemPermissions{}, fmt.Errorf("invalid permission: '%v'", r) + } + } + return p, nil +} + +// PathPermissions type simplifies creating the permissions string for an Azure Storage blob SAS. +// Initialize an instance of this type and then call its String method to set BlobSignatureValues' Permissions field. +type PathPermissions struct { + Read, Add, Create, Write, Delete, List, Move bool + Execute, Ownership, Permissions bool +} + +// String produces the SAS permissions string for an Azure Storage blob. +// Call this method to set BlobSignatureValues' Permissions field. +func (p *PathPermissions) String() string { + var b bytes.Buffer + if p.Read { + b.WriteRune('r') + } + if p.Add { + b.WriteRune('a') + } + if p.Create { + b.WriteRune('c') + } + if p.Write { + b.WriteRune('w') + } + if p.Delete { + b.WriteRune('d') + } + if p.List { + b.WriteRune('l') + } + if p.Move { + b.WriteRune('m') + } + if p.Execute { + b.WriteRune('e') + } + if p.Ownership { + b.WriteRune('o') + } + if p.Permissions { + b.WriteRune('p') + } + return b.String() +} + +// Parse initializes BlobPermissions' fields from a string. +func parsePathPermissions(s string) (PathPermissions, error) { + p := PathPermissions{} // Clear the flags + for _, r := range s { + switch r { + case 'r': + p.Read = true + case 'a': + p.Add = true + case 'c': + p.Create = true + case 'w': + p.Write = true + case 'd': + p.Delete = true + case 'l': + p.List = true + case 'm': + p.Move = true + case 'e': + p.Execute = true + case 'o': + p.Ownership = true + case 'p': + p.Permissions = true + default: + return PathPermissions{}, fmt.Errorf("invalid permission: '%v'", r) + } + } + return p, nil +} diff --git a/sdk/storage/azdatalake/sas/service_test.go b/sdk/storage/azdatalake/sas/service_test.go new file mode 100644 index 000000000000..218a6c116eac --- /dev/null +++ b/sdk/storage/azdatalake/sas/service_test.go @@ -0,0 +1,219 @@ +//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 sas + +import ( + "github.com/stretchr/testify/require" + "testing" +) + +func TestFilesystemPermissions_String(t *testing.T) { + testdata := []struct { + input FilesystemPermissions + expected string + }{ + {input: FilesystemPermissions{Read: true}, expected: "r"}, + {input: FilesystemPermissions{Add: true}, expected: "a"}, + {input: FilesystemPermissions{Create: true}, expected: "c"}, + {input: FilesystemPermissions{Write: true}, expected: "w"}, + {input: FilesystemPermissions{Delete: true}, expected: "d"}, + {input: FilesystemPermissions{List: true}, expected: "l"}, + {input: FilesystemPermissions{Move: true}, expected: "m"}, + {input: FilesystemPermissions{Execute: true}, expected: "e"}, + {input: FilesystemPermissions{ModifyOwnership: true}, expected: "o"}, + {input: FilesystemPermissions{ModifyPermissions: true}, expected: "p"}, + {input: FilesystemPermissions{ + Read: true, + Add: true, + Create: true, + Write: true, + Delete: true, + List: true, + Move: true, + Execute: true, + ModifyOwnership: true, + ModifyPermissions: true, + }, expected: "racwdlmeop"}, + } + for _, c := range testdata { + require.Equal(t, c.expected, c.input.String()) + } +} + +func TestFilesystemPermissions_Parse(t *testing.T) { + testdata := []struct { + input string + expected FilesystemPermissions + }{ + {expected: FilesystemPermissions{Read: true}, input: "r"}, + {expected: FilesystemPermissions{Add: true}, input: "a"}, + {expected: FilesystemPermissions{Create: true}, input: "c"}, + {expected: FilesystemPermissions{Write: true}, input: "w"}, + {expected: FilesystemPermissions{Delete: true}, input: "d"}, + {expected: FilesystemPermissions{List: true}, input: "l"}, + {expected: FilesystemPermissions{Move: true}, input: "m"}, + {expected: FilesystemPermissions{Execute: true}, input: "e"}, + {expected: FilesystemPermissions{ModifyOwnership: true}, input: "o"}, + {expected: FilesystemPermissions{ModifyPermissions: true}, input: "p"}, + {expected: FilesystemPermissions{ + Read: true, + Add: true, + Create: true, + Write: true, + Delete: true, + List: true, + Move: true, + Execute: true, + ModifyOwnership: true, + ModifyPermissions: true, + }, input: "racwdlmeop"}, + {expected: FilesystemPermissions{ + Read: true, + Add: true, + Create: true, + Write: true, + Delete: true, + List: true, + Move: true, + Execute: true, + ModifyOwnership: true, + ModifyPermissions: true, + }, input: "cpwmreodal"}, // Wrong order parses correctly + } + for _, c := range testdata { + permissions, err := parseFilesystemPermissions(c.input) + require.Nil(t, err) + require.Equal(t, c.expected, permissions) + } +} + +func TestFilesystemPermissions_ParseNegative(t *testing.T) { + _, err := parseFilesystemPermissions("cpwmreodalz") // Here 'z' is invalid + require.NotNil(t, err) + require.Contains(t, err.Error(), "122") +} + +func TestPathPermissions_String(t *testing.T) { + testdata := []struct { + input PathPermissions + expected string + }{ + {input: PathPermissions{Read: true}, expected: "r"}, + {input: PathPermissions{Add: true}, expected: "a"}, + {input: PathPermissions{Create: true}, expected: "c"}, + {input: PathPermissions{Write: true}, expected: "w"}, + {input: PathPermissions{Delete: true}, expected: "d"}, + {input: PathPermissions{List: true}, expected: "l"}, + {input: PathPermissions{Move: true}, expected: "m"}, + {input: PathPermissions{Execute: true}, expected: "e"}, + {input: PathPermissions{Ownership: true}, expected: "o"}, + {input: PathPermissions{Permissions: true}, expected: "p"}, + {input: PathPermissions{ + Read: true, + Add: true, + Create: true, + Write: true, + Delete: true, + List: true, + Move: true, + Execute: true, + Ownership: true, + Permissions: true, + }, expected: "racwdlmeop"}, + } + for _, c := range testdata { + require.Equal(t, c.expected, c.input.String()) + } +} + +func TestPathPermissions_Parse(t *testing.T) { + testdata := []struct { + expected PathPermissions + input string + }{ + {expected: PathPermissions{Read: true}, input: "r"}, + {expected: PathPermissions{Add: true}, input: "a"}, + {expected: PathPermissions{Create: true}, input: "c"}, + {expected: PathPermissions{Write: true}, input: "w"}, + {expected: PathPermissions{Delete: true}, input: "d"}, + {expected: PathPermissions{List: true}, input: "l"}, + {expected: PathPermissions{Move: true}, input: "m"}, + {expected: PathPermissions{Execute: true}, input: "e"}, + {expected: PathPermissions{Ownership: true}, input: "o"}, + {expected: PathPermissions{Permissions: true}, input: "p"}, + {expected: PathPermissions{ + Read: true, + Add: true, + Create: true, + Write: true, + Delete: true, + List: true, + Move: true, + Execute: true, + Ownership: true, + Permissions: true, + }, input: "racwdlmeop"}, + {expected: PathPermissions{ + Read: true, + Add: true, + Create: true, + Write: true, + Delete: true, + List: true, + Move: true, + Execute: true, + Ownership: true, + Permissions: true, + }, input: "apwecrdlmo"}, // Wrong order parses correctly + } + for _, c := range testdata { + permissions, err := parsePathPermissions(c.input) + require.Nil(t, err) + require.Equal(t, c.expected, permissions) + } +} + +func TestParsePermissionsNegative(t *testing.T) { + _, err := parsePathPermissions("awecrdlfmo") // Here 'f' is invalid + require.NotNil(t, err) + require.Contains(t, err.Error(), "102") +} + +func TestGetCanonicalName(t *testing.T) { + testdata := []struct { + inputAccount string + inputContainer string + inputBlob string + inputDirectory string + expected string + }{ + {inputAccount: "fakestorageaccount", inputContainer: "fakestoragecontainer", expected: "/blob/fakestorageaccount/fakestoragecontainer"}, + {inputAccount: "fakestorageaccount", inputContainer: "fakestoragecontainer", inputBlob: "fakestorageblob", expected: "/blob/fakestorageaccount/fakestoragecontainer/fakestorageblob"}, + {inputAccount: "fakestorageaccount", inputContainer: "fakestoragecontainer", inputBlob: "fakestoragevirtualdir/fakestorageblob", expected: "/blob/fakestorageaccount/fakestoragecontainer/fakestoragevirtualdir/fakestorageblob"}, + {inputAccount: "fakestorageaccount", inputContainer: "fakestoragecontainer", inputBlob: "fakestoragevirtualdir\\fakestorageblob", expected: "/blob/fakestorageaccount/fakestoragecontainer/fakestoragevirtualdir/fakestorageblob"}, + {inputAccount: "fakestorageaccount", inputContainer: "fakestoragecontainer", inputBlob: "fakestoragedirectory", expected: "/blob/fakestorageaccount/fakestoragecontainer/fakestoragedirectory"}, + } + for _, c := range testdata { + require.Equal(t, c.expected, getCanonicalName(c.inputAccount, c.inputContainer, c.inputBlob, c.inputDirectory)) + } +} + +func TestGetDirectoryDepth(t *testing.T) { + testdata := []struct { + input string + expected string + }{ + {input: "", expected: ""}, + {input: "myfile", expected: "1"}, + {input: "mydirectory", expected: "1"}, + {input: "mydirectory/myfile", expected: "2"}, + {input: "mydirectory/mysubdirectory", expected: "2"}, + } + for _, c := range testdata { + require.Equal(t, c.expected, getDirectoryDepth(c.input)) + } +} diff --git a/sdk/storage/azdatalake/sas/url_parts.go b/sdk/storage/azdatalake/sas/url_parts.go new file mode 100644 index 000000000000..8af46a1329ad --- /dev/null +++ b/sdk/storage/azdatalake/sas/url_parts.go @@ -0,0 +1,109 @@ +//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 sas + +import ( + "net/url" + "strings" + + "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/internal/shared" +) + +// IPEndpointStyleInfo is used for IP endpoint style URL when working with Azure storage emulator. +// Ex: "https://10.132.141.33/accountname/containername" +type IPEndpointStyleInfo struct { + AccountName string // "" if not using IP endpoint style +} + +// URLParts object represents the components that make up an Azure Storage Container/Blob URL. +// NOTE: Changing any SAS-related field requires computing a new SAS signature. +type URLParts struct { + Scheme string // Ex: "https://" + Host string // Ex: "account.blob.core.windows.net", "10.132.141.33", "10.132.141.33:80" + IPEndpointStyleInfo IPEndpointStyleInfo + FilesystemName string // "" if no container + PathName string // "" if no blob + SAS QueryParameters + UnparsedParams string +} + +// ParseURL parses a URL initializing URLParts' fields including any SAS-related & snapshot query parameters. +// Any other query parameters remain in the UnparsedParams field. +func ParseURL(u string) (URLParts, error) { + uri, err := url.Parse(u) + if err != nil { + return URLParts{}, err + } + + up := URLParts{ + Scheme: uri.Scheme, + Host: uri.Host, + } + + // Find the container & blob names (if any) + if uri.Path != "" { + path := uri.Path + if path[0] == '/' { + path = path[1:] // If path starts with a slash, remove it + } + if shared.IsIPEndpointStyle(up.Host) { + if accountEndIndex := strings.Index(path, "/"); accountEndIndex == -1 { // Slash not found; path has account name & no container name or blob + up.IPEndpointStyleInfo.AccountName = path + path = "" // No ContainerName present in the URL so path should be empty + } else { + up.IPEndpointStyleInfo.AccountName = path[:accountEndIndex] // The account name is the part between the slashes + path = path[accountEndIndex+1:] // path refers to portion after the account name now (container & blob names) + } + } + + filesystemEndIndex := strings.Index(path, "/") // Find the next slash (if it exists) + if filesystemEndIndex == -1 { // Slash not found; path has container name & no blob name + up.FilesystemName = path + } else { + up.FilesystemName = path[:filesystemEndIndex] // The container name is the part between the slashes + up.PathName = path[filesystemEndIndex+1:] // The blob name is after the container slash + } + } + + // Convert the query parameters to a case-sensitive map & trim whitespace + paramsMap := uri.Query() + up.SAS = newQueryParameters(paramsMap, true) + up.UnparsedParams = paramsMap.Encode() + return up, nil +} + +// String returns a URL object whose fields are initialized from the URLParts fields. The URL's RawQuery +// field contains the SAS, snapshot, and unparsed query parameters. +func (up URLParts) String() string { + path := "" + if shared.IsIPEndpointStyle(up.Host) && up.IPEndpointStyleInfo.AccountName != "" { + path += "/" + up.IPEndpointStyleInfo.AccountName + } + // Concatenate container & blob names (if they exist) + if up.FilesystemName != "" { + path += "/" + up.FilesystemName + if up.PathName != "" { + path += "/" + up.PathName + } + } + + rawQuery := up.UnparsedParams + sas := up.SAS.Encode() + if sas != "" { + if len(rawQuery) > 0 { + rawQuery += "&" + } + rawQuery += sas + } + u := url.URL{ + Scheme: up.Scheme, + Host: up.Host, + Path: path, + RawQuery: rawQuery, + } + return u.String() +} diff --git a/sdk/storage/azdatalake/sas/url_parts_test.go b/sdk/storage/azdatalake/sas/url_parts_test.go new file mode 100644 index 000000000000..88b8d94f7a10 --- /dev/null +++ b/sdk/storage/azdatalake/sas/url_parts_test.go @@ -0,0 +1,73 @@ +//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 sas + +import ( + "fmt" + "testing" + + "github.com/stretchr/testify/require" +) + +func TestParseURLIPStyle(t *testing.T) { + urlWithIP := "https://127.0.0.1:5000/fakestorageaccount" + blobURLParts, err := ParseURL(urlWithIP) + require.NoError(t, err) + require.Equal(t, blobURLParts.Scheme, "https") + require.Equal(t, blobURLParts.Host, "127.0.0.1:5000") + require.Equal(t, blobURLParts.IPEndpointStyleInfo.AccountName, "fakestorageaccount") + + urlWithIP = "https://127.0.0.1:5000/fakestorageaccount/fakecontainer" + blobURLParts, err = ParseURL(urlWithIP) + require.NoError(t, err) + require.Equal(t, blobURLParts.Scheme, "https") + require.Equal(t, blobURLParts.Host, "127.0.0.1:5000") + require.Equal(t, blobURLParts.IPEndpointStyleInfo.AccountName, "fakestorageaccount") + require.Equal(t, blobURLParts.FilesystemName, "fakecontainer") + + urlWithIP = "https://127.0.0.1:5000/fakestorageaccount/fakecontainer/fakeblob" + blobURLParts, err = ParseURL(urlWithIP) + require.NoError(t, err) + require.Equal(t, blobURLParts.Scheme, "https") + require.Equal(t, blobURLParts.Host, "127.0.0.1:5000") + require.Equal(t, blobURLParts.IPEndpointStyleInfo.AccountName, "fakestorageaccount") + require.Equal(t, blobURLParts.FilesystemName, "fakecontainer") + require.Equal(t, blobURLParts.PathName, "fakeblob") +} + +func TestParseURL(t *testing.T) { + testStorageAccount := "fakestorageaccount" + host := fmt.Sprintf("%s.blob.core.windows.net", testStorageAccount) + testContainer := "fakecontainer" + fileNames := []string{"/._.TESTT.txt", "/.gitignore/dummyfile1"} + + const sasStr = "sv=2019-12-12&sr=b&st=2111-01-09T01:42:34.936Z&se=2222-03-09T01:42:34.936Z&sp=rw&sip=168.1.5.60-168.1.5.70&spr=https,http&si=myIdentifier&ss=bf&srt=s&sig=clNxbtnkKSHw7f3KMEVVc4agaszoRFdbZr%2FWBmPNsrw%3D" + + for _, fileName := range fileNames { + urlWithVersion := fmt.Sprintf("https://%s.blob.core.windows.net/%s%s", testStorageAccount, testContainer, fileName) + blobURLParts, err := ParseURL(urlWithVersion) + require.NoError(t, err) + + require.Equal(t, blobURLParts.Scheme, "https") + require.Equal(t, blobURLParts.Host, host) + require.Equal(t, blobURLParts.FilesystemName, testContainer) + + validateSAS(t, sasStr, blobURLParts.SAS) + } + + for _, fileName := range fileNames { + urlWithVersion := fmt.Sprintf("https://%s.blob.core.windows.net/%s%s", testStorageAccount, testContainer, fileName) + blobURLParts, err := ParseURL(urlWithVersion) + require.NoError(t, err) + + require.Equal(t, blobURLParts.Scheme, "https") + require.Equal(t, blobURLParts.Host, host) + require.Equal(t, blobURLParts.FilesystemName, testContainer) + + validateSAS(t, sasStr, blobURLParts.SAS) + } +} From 47082af2e6bfcc12465aac8cc2666ffff7ee8a8d Mon Sep 17 00:00:00 2001 From: Tamer Sherif <69483382+tasherif-msft@users.noreply.github.com> Date: Mon, 26 Jun 2023 14:23:56 -0700 Subject: [PATCH 05/16] [Datalake] Client Constructors (#21034) * Enable gocritic during linting (#20715) Enabled gocritic's evalOrder to catch dependencies on undefined behavior on return statements. Updated to latest version of golangci-lint. Fixed issue in azblob flagged by latest linter. * Cosmos DB: Enable merge support (#20716) * Adding header and value * Wiring and tests * format * Fixing value * change log * [azservicebus, azeventhubs] Stress test and logging improvement (#20710) Logging improvements: * Updating the logging to print more tracing information (per-link) in prep for the bigger release coming up. * Trimming out some of the verbose logging, seeing if I can get it a bit more reasonable. Stress tests: * Add a timestamp to the log name we generate and also default to append, not overwrite. * Use 0.5 cores, 0.5GB as our baseline. Some pods use more and I'll tune them more later. * update proxy version (#20712) Co-authored-by: Scott Beddall * Return an error when you try to send a message that's too large. (#20721) This now works just like the message batch - you'll get an ErrMessageTooLarge if you attempt to send a message that's too large for the link's configured size. NOTE: there's a patch to `internal/go-amqp/Sender.go` to match what's in go-amqp's main so it returns a programmatically useful error when the message is too large. Fixes #20647 * Changes in test that is failing in pipeline (#20693) * [azservicebus, azeventhubs] Treat 'entity full' as a fatal error (#20722) When the remote entity is full we get a resource-limit-exceeded condition. This isn't something we should keep retrying on and it's best to just abort and let the user know immediately, rather than hoping it might eventually clear out. This affected both Event Hubs and Service Bus. Fixes #20647 * [azservicebus/azeventhubs] Redirect stderr and stdout to tee (#20726) * Update changelog with latest features (#20730) * Update changelog with latest features Prepare for upcoming release. * bump minor version * pass along the artifact name so we can override it later (#20732) Co-authored-by: scbedd <45376673+scbedd@users.noreply.github.com> * [azeventhubs] Fixing checkpoint store race condition (#20727) The checkpoint store wasn't guarding against multiple owners claiming for the first time - fixing this by using IfNoneMatch Fixes #20717 * Fix azidentity troubleshooting guide link (#20736) * [Release] sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/0.1.0 (#20437) * [Release] sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/0.1.0 generation from spec commit: 85fb4ac6f8bfefd179e6c2632976a154b5c9ff04 * client factory * fix * fix * update * add sdk/resourcemanager/postgresql/armpostgresql live test (#20685) * add sdk/resourcemanager/postgresql/armpostgresql live test * update assets.json * set subscriptionId default value * format * add sdk/resourcemanager/eventhub/armeventhub live test (#20686) * add sdk/resourcemanager/eventhub/armeventhub live test * update assets * add sdk/resourcemanager/compute/armcompute live test (#20048) * add sdk/resourcemanager/compute/armcompute live test * skus filter * fix subscriptionId default value * fix * gofmt * update recording * sdk/resourcemanager/network/armnetwork live test (#20331) * sdk/resourcemanager/network/armnetwork live test * update subscriptionId default value * update recording * add sdk/resourcemanager/cosmos/armcosmos live test (#20705) * add sdk/resourcemanager/cosmos/armcosmos live test * update assets.json * update assets.json * update assets.json * update assets.json * Increment package version after release of azcore (#20740) * [azeventhubs] Improperly resetting etag in the checkpoint store (#20737) We shouldn't be resetting the etag to nil - it's what we use to enforce a "single winner" when doing ownership claims. The bug here was two-fold: I had bad logic in my previous claim ownership, which I fixed in a previous PR, but we need to reflect that same constraint properly in our in-memory checkpoint store for these tests. * Eng workflows sync and branch cleanup additions (#20743) Co-authored-by: James Suplizio * [azeventhubs] Latest start position can also be inclusive (ie, get the latest message) (#20744) * Update GitHubEventProcessor version and remove pull_request_review procesing (#20751) Co-authored-by: James Suplizio * Rename DisableAuthorityValidationAndInstanceDiscovery (#20746) * fix (#20707) * AzFile (#20739) * azfile: Fixing connection string parsing logic (#20798) * Fixing connection string parse logic * Update README * [azadmin] fix flaky test (#20758) * fix flaky test * charles suggestion * Prepare azidentity v1.3.0 for release (#20756) * Fix broken podman link (#20801) Co-authored-by: Wes Haggard * [azquery] update doc comments (#20755) * update doc comments * update statistics and visualization generation * prep-for-release * Fixed contribution section (#20752) Co-authored-by: Bob Tabor * [azeventhubs,azservicebus] Some API cleanup, renames (#20754) * Adding options to UpdateCheckpoint(), just for future potential expansion * Make Offset an int64, not a *int64 (it's not optional, it'll always come back with ReceivedEvents) * Adding more logging into the checkpoint store. * Point all imports at the production go-amqp * Add supporting features to enable distributed tracing (#20301) (#20708) * Add supporting features to enable distributed tracing This includes new internal pipeline policies and other supporting types. See the changelog for a full description. Added some missing doc comments. * fix linter issue * add net.peer.name trace attribute sequence custom HTTP header policy before logging policy. sequence logging policy after HTTP trace policy. keep body download policy at the end. * add span for iterating over pages * Restore ARM CAE support for azcore beta (#20657) This reverts commit 902097226ff3fe2fc6c3e7fc50d3478350253614. * Upgrade to stable azcore (#20808) * Increment package version after release of data/azcosmos (#20807) * Updating changelog (#20810) * Add fake package to azcore (#20711) * Add fake package to azcore This is the supporting infrastructure for the generated SDK fakes. * fix doc comment * Updating CHANGELOG.md (#20809) * changelog (#20811) * Increment package version after release of storage/azfile (#20813) * Update changelog (azblob) (#20815) * Updating CHANGELOG.md * Update the changelog with correct version * [azquery] migration guide (#20742) * migration guide * Charles feedback * Richard feedback --------- Co-authored-by: Charles Lowell <10964656+chlowell@users.noreply.github.com> * Increment package version after release of monitor/azquery (#20820) * [keyvault] prep for release (#20819) * prep for release * perf tests * update date * added sas support * small fix * query params fix * fix * added some tests * added more tests * resolved some comments * added encoding * added constructors * cleanup * cleanup * gmt * added all necessary builders * merge branch * removed path client --------- Co-authored-by: Joel Hendrix Co-authored-by: Matias Quaranta Co-authored-by: Richard Park <51494936+richardpark-msft@users.noreply.github.com> Co-authored-by: Azure SDK Bot <53356347+azure-sdk@users.noreply.github.com> Co-authored-by: Scott Beddall Co-authored-by: siminsavani-msft <77068571+siminsavani-msft@users.noreply.github.com> Co-authored-by: scbedd <45376673+scbedd@users.noreply.github.com> Co-authored-by: Charles Lowell <10964656+chlowell@users.noreply.github.com> Co-authored-by: Peng Jiahui <46921893+Alancere@users.noreply.github.com> Co-authored-by: James Suplizio Co-authored-by: Sourav Gupta <98318303+souravgupta-msft@users.noreply.github.com> Co-authored-by: gracewilcox <43627800+gracewilcox@users.noreply.github.com> Co-authored-by: Wes Haggard Co-authored-by: Bob Tabor Co-authored-by: Bob Tabor --- sdk/storage/azdatalake/common.go | 6 - sdk/storage/azdatalake/directory/client.go | 158 ++++++++++-- sdk/storage/azdatalake/directory/constants.go | 34 ++- sdk/storage/azdatalake/directory/models.go | 225 +++++++++++++++-- sdk/storage/azdatalake/directory/responses.go | 28 +-- sdk/storage/azdatalake/file/client.go | 162 +++++++++++-- sdk/storage/azdatalake/file/constants.go | 29 +-- sdk/storage/azdatalake/file/models.go | 228 ++++++++++++++++-- sdk/storage/azdatalake/file/responses.go | 26 +- sdk/storage/azdatalake/filesystem/client.go | 108 +++++++-- .../azdatalake/internal/base/clients.go | 74 ++++++ .../exported/shared_key_credential.go | 12 +- .../internal/generated/filesystem_client.go | 21 +- .../internal/generated/path_client.go | 19 +- .../internal/generated/service_client.go | 19 +- .../azdatalake/internal/path/client.go | 71 ------ .../azdatalake/internal/path/constants.go | 43 ---- .../azdatalake/internal/path/models.go | 227 ----------------- .../azdatalake/internal/path/responses.go | 42 ---- .../azdatalake/internal/shared/shared.go | 7 + sdk/storage/azdatalake/service/client.go | 108 +++++++-- 21 files changed, 1058 insertions(+), 589 deletions(-) delete mode 100644 sdk/storage/azdatalake/internal/path/client.go delete mode 100644 sdk/storage/azdatalake/internal/path/constants.go delete mode 100644 sdk/storage/azdatalake/internal/path/models.go delete mode 100644 sdk/storage/azdatalake/internal/path/responses.go diff --git a/sdk/storage/azdatalake/common.go b/sdk/storage/azdatalake/common.go index 03fe643423db..fb79dcc0dc7a 100644 --- a/sdk/storage/azdatalake/common.go +++ b/sdk/storage/azdatalake/common.go @@ -7,15 +7,9 @@ package azdatalake import ( - "github.com/Azure/azure-sdk-for-go/sdk/azcore" "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/internal/generated" ) -// ClientOptions contains the optional parameters when creating a Client. -type ClientOptions struct { - azcore.ClientOptions -} - // AccessConditions identifies container-specific access conditions which you optionally set. type AccessConditions struct { ModifiedAccessConditions *ModifiedAccessConditions diff --git a/sdk/storage/azdatalake/directory/client.go b/sdk/storage/azdatalake/directory/client.go index f376ad4ec7b8..6aaf8bf63138 100644 --- a/sdk/storage/azdatalake/directory/client.go +++ b/sdk/storage/azdatalake/directory/client.go @@ -9,44 +9,123 @@ package directory import ( "context" "github.com/Azure/azure-sdk-for-go/sdk/azcore" - "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake" - "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/internal/path" + "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/blob" + "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/shared" + "strings" ) -// Client represents a URL to the Azure Datalake Storage service allowing you to manipulate datalake directories. -type Client struct { - path.Client -} +// ClientOptions contains the optional parameters when creating a Client. +type ClientOptions base.ClientOptions -// NewClient creates an instance of Client with the specified values. -// - serviceURL - the URL of the storage account e.g. https://.dfs.core.windows.net/ -// - cred - an Azure AD credential, typically obtained via the azidentity module -// - options - client options; pass nil to accept the default values -func NewClient(serviceURL string, cred azcore.TokenCredential, options *azdatalake.ClientOptions) (*Client, error) { - return nil, nil -} +// Client represents a URL to the Azure Datalake Storage service. +type Client base.CompositeClient[generated.PathClient, generated.PathClient, blob.Client] + +//TODO: NewClient() // NewClientWithNoCredential creates an instance of Client with the specified values. // This is used to anonymously access a storage account or with a shared access signature (SAS) token. // - serviceURL - the URL of the storage account e.g. https://.dfs.core.windows.net/? // - options - client options; pass nil to accept the default values -func NewClientWithNoCredential(serviceURL string, options *azdatalake.ClientOptions) (*Client, error) { - return nil, nil +func NewClientWithNoCredential(directoryURL string, options *ClientOptions) (*Client, error) { + blobURL := strings.Replace(directoryURL, ".dfs.", ".blob.", 1) + directoryURL = strings.Replace(directoryURL, ".blob.", ".dfs.", 1) + + conOptions := shared.GetClientOptions(options) + plOpts := runtime.PipelineOptions{} + base.SetPipelineOptions((*base.ClientOptions)(conOptions), &plOpts) + + azClient, err := azcore.NewClient(shared.DirectoryClient, exported.ModuleVersion, plOpts, &conOptions.ClientOptions) + if err != nil { + return nil, err + } + + blobClientOpts := blob.ClientOptions{ + ClientOptions: options.ClientOptions, + } + blobClient, _ := blob.NewClientWithNoCredential(blobURL, &blobClientOpts) + dirClient := base.NewPathClient(directoryURL, blobURL, blobClient, azClient, nil, (*base.ClientOptions)(conOptions)) + + return (*Client)(dirClient), nil } // NewClientWithSharedKeyCredential creates an instance of Client with the specified values. // - serviceURL - the URL of the storage account e.g. https://.dfs.core.windows.net/ // - cred - a SharedKeyCredential created with the matching storage account and access key // - options - client options; pass nil to accept the default values -func NewClientWithSharedKeyCredential(serviceURL string, cred *SharedKeyCredential, options *azdatalake.ClientOptions) (*Client, error) { - return nil, nil +func NewClientWithSharedKeyCredential(directoryURL string, cred *SharedKeyCredential, options *ClientOptions) (*Client, error) { + blobURL := strings.Replace(directoryURL, ".dfs.", ".blob.", 1) + directoryURL = strings.Replace(directoryURL, ".blob.", ".dfs.", 1) + + authPolicy := exported.NewSharedKeyCredPolicy(cred) + conOptions := shared.GetClientOptions(options) + plOpts := runtime.PipelineOptions{ + PerRetry: []policy.Policy{authPolicy}, + } + base.SetPipelineOptions((*base.ClientOptions)(conOptions), &plOpts) + + azClient, err := azcore.NewClient(shared.DirectoryClient, exported.ModuleVersion, plOpts, &conOptions.ClientOptions) + if err != nil { + return nil, err + } + + blobClientOpts := blob.ClientOptions{ + ClientOptions: options.ClientOptions, + } + blobSharedKeyCredential, _ := blob.NewSharedKeyCredential(cred.AccountName(), cred.AccountKey()) + blobClient, _ := blob.NewClientWithSharedKeyCredential(blobURL, blobSharedKeyCredential, &blobClientOpts) + dirClient := base.NewPathClient(directoryURL, blobURL, blobClient, azClient, nil, (*base.ClientOptions)(conOptions)) + + return (*Client)(dirClient), nil } // NewClientFromConnectionString creates an instance of Client with the specified values. // - connectionString - a connection string for the desired storage account // - options - client options; pass nil to accept the default values -func NewClientFromConnectionString(connectionString string, options *azdatalake.ClientOptions) (*Client, error) { - return nil, nil +func NewClientFromConnectionString(connectionString string, options *ClientOptions) (*Client, error) { + parsed, err := shared.ParseConnectionString(connectionString) + if err != nil { + return nil, err + } + + if parsed.AccountKey != "" && parsed.AccountName != "" { + credential, err := exported.NewSharedKeyCredential(parsed.AccountName, parsed.AccountKey) + if err != nil { + return nil, err + } + return NewClientWithSharedKeyCredential(parsed.ServiceURL, credential, options) + } + + return NewClientWithNoCredential(parsed.ServiceURL, options) +} + +func (d *Client) generatedFSClientWithDFS() *generated.PathClient { + //base.SharedKeyComposite((*base.CompositeClient[generated.BlobClient, generated.BlockBlobClient])(bb)) + dirClientWithDFS, _, _ := base.InnerClients((*base.CompositeClient[generated.PathClient, generated.PathClient, blob.Client])(d)) + return dirClientWithDFS +} + +func (d *Client) generatedFSClientWithBlob() *generated.PathClient { + _, dirClientWithBlob, _ := base.InnerClients((*base.CompositeClient[generated.PathClient, generated.PathClient, blob.Client])(d)) + return dirClientWithBlob +} + +func (d *Client) blobClient() *blob.Client { + _, _, blobClient := base.InnerClients((*base.CompositeClient[generated.PathClient, generated.PathClient, blob.Client])(d)) + return blobClient +} + +func (d *Client) sharedKey() *exported.SharedKeyCredential { + return base.SharedKeyComposite((*base.CompositeClient[generated.PathClient, generated.PathClient, blob.Client])(d)) +} + +// URL returns the URL endpoint used by the Client object. +func (d *Client) URL() string { + return "s.generated().Endpoint()" } // Create creates a new directory (dfs1). @@ -70,3 +149,44 @@ func (d *Client) GetProperties(ctx context.Context, options *GetPropertiesOption func (d *Client) Rename(ctx context.Context, newName string, options *RenameOptions) (RenameResponse, error) { return RenameResponse{}, nil } + +// SetAccessControl sets the owner, owning group, and permissions for a file or directory (dfs1). +func (d *Client) SetAccessControl(ctx context.Context, options *SetAccessControlOptions) (SetAccessControlResponse, error) { + return SetAccessControlResponse{}, nil +} + +// 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 +} + +// 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 +} + +// 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 +} + +// 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 +} + +// SetMetadata sets the metadata for a file or directory (blob3). +func (d *Client) SetMetadata(ctx context.Context, options *SetMetadataOptions) (SetMetadataResponse, error) { + // TODO: call directly into blob + return SetMetadataResponse{}, nil +} + +// SetHTTPHeaders sets the HTTP headers for a file or 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 +} diff --git a/sdk/storage/azdatalake/directory/constants.go b/sdk/storage/azdatalake/directory/constants.go index 70e675e9f10a..ca7d9525c6ac 100644 --- a/sdk/storage/azdatalake/directory/constants.go +++ b/sdk/storage/azdatalake/directory/constants.go @@ -7,29 +7,37 @@ package directory import ( - "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/internal/path" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/blob" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/internal/generated" ) -// RenameMode defines the rename mode for RenameDirectory -type RenameMode = path.RenameMode +type ResourceType = generated.PathResourceType +// TODO: consider the possibility of not exposing this and just pass it under the hood const ( - RenameModeLegacy RenameMode = path.RenameModeLegacy - RenameModePosix RenameMode = path.RenameModePosix + ResourceTypeFile ResourceType = generated.PathResourceTypeFile + ResourceTypeDirectory ResourceType = generated.PathResourceTypeDirectory ) -// SetAccessControlRecursiveMode defines the set access control recursive mode for SetAccessControlRecursive -type SetAccessControlRecursiveMode = path.SetAccessControlRecursiveMode +type RenameMode = generated.PathRenameMode +// TODO: consider the possibility of not exposing this and just pass it under the hood const ( - SetAccessControlRecursiveModeSet SetAccessControlRecursiveMode = path.SetAccessControlRecursiveModeSet - SetAccessControlRecursiveModeModify SetAccessControlRecursiveMode = path.SetAccessControlRecursiveModeModify - SetAccessControlRecursiveModeRemove SetAccessControlRecursiveMode = path.SetAccessControlRecursiveModeRemove + RenameModeLegacy RenameMode = generated.PathRenameModeLegacy + RenameModePosix RenameMode = generated.PathRenameModePosix ) -type EncryptionAlgorithmType = path.EncryptionAlgorithmType +type SetAccessControlRecursiveMode = generated.PathSetAccessControlRecursiveMode const ( - EncryptionAlgorithmTypeNone EncryptionAlgorithmType = path.EncryptionAlgorithmTypeNone - EncryptionAlgorithmTypeAES256 EncryptionAlgorithmType = path.EncryptionAlgorithmTypeAES256 + SetAccessControlRecursiveModeSet SetAccessControlRecursiveMode = generated.PathSetAccessControlRecursiveModeSet + SetAccessControlRecursiveModeModify SetAccessControlRecursiveMode = generated.PathSetAccessControlRecursiveModeModify + SetAccessControlRecursiveModeRemove SetAccessControlRecursiveMode = generated.PathSetAccessControlRecursiveModeRemove +) + +type EncryptionAlgorithmType = blob.EncryptionAlgorithmType + +const ( + EncryptionAlgorithmTypeNone EncryptionAlgorithmType = blob.EncryptionAlgorithmTypeNone + EncryptionAlgorithmTypeAES256 EncryptionAlgorithmType = blob.EncryptionAlgorithmTypeAES256 ) diff --git a/sdk/storage/azdatalake/directory/models.go b/sdk/storage/azdatalake/directory/models.go index 4be9c742e337..e349e0478da8 100644 --- a/sdk/storage/azdatalake/directory/models.go +++ b/sdk/storage/azdatalake/directory/models.go @@ -11,7 +11,6 @@ import ( "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake" "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" "time" ) @@ -99,38 +98,218 @@ func (o *GetPropertiesOptions) format() *blob.GetPropertiesOptions { // ===================================== PATH IMPORTS =========================================== -// CPKInfo contains a group of parameters for client provided encryption key. -type CPKInfo = path.CPKInfo +// SetAccessControlOptions contains the optional parameters when calling the SetAccessControl operation. dfs endpoint +type SetAccessControlOptions struct { + // Owner is the owner of the path. + Owner *string + // Group is the owning group of the path. + Group *string + // ACL is the access control list for the path. + ACL *string + // Permissions is the octal representation of the permissions for user, group and mask. + Permissions *string + // AccessConditions contains parameters for accessing the path. + AccessConditions *azdatalake.AccessConditions +} -// CPKScopeInfo contains a group of parameters for client provided encryption scope. -type CPKScopeInfo = path.CPKScopeInfo +func (o *SetAccessControlOptions) format() (*generated.PathClientSetAccessControlOptions, *generated.LeaseAccessConditions, *generated.ModifiedAccessConditions, error) { + if o == nil { + return nil, nil, nil, nil + } + // call path formatter since we're hitting dfs in this operation + leaseAccessConditions, modifiedAccessConditions := shared.FormatPathAccessConditions(o.AccessConditions) + return &generated.PathClientSetAccessControlOptions{ + Owner: o.Owner, + Group: o.Group, + ACL: o.ACL, + Permissions: o.Permissions, + }, leaseAccessConditions, modifiedAccessConditions, nil +} -// HTTPHeaders contains the HTTP headers for path operations. -type HTTPHeaders = path.HTTPHeaders +// GetAccessControlOptions contains the optional parameters when calling the GetAccessControl operation. +type GetAccessControlOptions struct { + // UPN is the user principal name. + UPN *bool + // AccessConditions contains parameters for accessing the path. + AccessConditions *azdatalake.AccessConditions +} -// SourceModifiedAccessConditions identifies the source path access conditions. -type SourceModifiedAccessConditions = path.SourceModifiedAccessConditions +func (o *GetAccessControlOptions) format() (*generated.PathClientGetPropertiesOptions, *generated.LeaseAccessConditions, *generated.ModifiedAccessConditions, error) { + action := generated.PathGetPropertiesActionGetAccessControl + if o == nil { + return &generated.PathClientGetPropertiesOptions{ + Action: &action, + }, nil, nil, nil + } + // call path formatter since we're hitting dfs in this operation + leaseAccessConditions, modifiedAccessConditions := shared.FormatPathAccessConditions(o.AccessConditions) + return &generated.PathClientGetPropertiesOptions{ + Upn: o.UPN, + Action: &action, + }, leaseAccessConditions, modifiedAccessConditions, nil +} -// SetAccessControlOptions contains the optional parameters when calling the SetAccessControl operation. -type SetAccessControlOptions = path.SetAccessControlOptions +// 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 + // 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 +} -// GetAccessControlOptions contains the optional parameters when calling the GetAccessControl operation. -type GetAccessControlOptions = path.GetAccessControlOptions +func (o *SetAccessControlRecursiveOptions) format() (*generated.PathClientSetAccessControlRecursiveOptions, error) { + // TODO: design formatter + return nil, nil +} -// SetAccessControlRecursiveOptions contains the optional parameters when calling the SetAccessControlRecursive operation. -type SetAccessControlRecursiveOptions = path.SetAccessControlRecursiveOptions +// 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 +} -// SetMetadataOptions contains the optional parameters when calling the SetMetadata operation. -type SetMetadataOptions = path.SetMetadataOptions +func (o *UpdateAccessControlRecursiveOptions) format() (*generated.PathClientSetAccessControlRecursiveOptions, error) { + // TODO: design formatter - similar to SetAccessControlRecursiveOptions + return nil, nil +} -// SetHTTPHeadersOptions contains the optional parameters when calling the SetHTTPHeaders operation. -type SetHTTPHeadersOptions = path.SetHTTPHeadersOptions +// 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 +} -// RemoveAccessControlRecursiveOptions contains the optional parameters when calling the RemoveAccessControlRecursive operation. -type RemoveAccessControlRecursiveOptions = path.RemoveAccessControlRecursiveOptions +func (o *RemoveAccessControlRecursiveOptions) format() (*generated.PathClientSetAccessControlRecursiveOptions, error) { + // TODO: design formatter - similar to SetAccessControlRecursiveOptions + return nil, nil +} -// UpdateAccessControlRecursiveOptions contains the optional parameters when calling the UpdateAccessControlRecursive operation. -type UpdateAccessControlRecursiveOptions = path.UpdateAccessControlRecursiveOptions +// SetHTTPHeadersOptions contains the optional parameters for the Client.SetHTTPHeaders method. +type SetHTTPHeadersOptions struct { + AccessConditions *azdatalake.AccessConditions +} + +func (o *SetHTTPHeadersOptions) format() *blob.SetHTTPHeadersOptions { + if o == nil { + return nil + } + accessConditions := shared.FormatBlobAccessConditions(o.AccessConditions) + return &blob.SetHTTPHeadersOptions{ + AccessConditions: accessConditions, + } +} + +// HTTPHeaders contains the HTTP headers for path operations. +type HTTPHeaders struct { + // Optional. Sets the path's cache control. If specified, this property is stored with the path and returned with a read request. + CacheControl *string + // Optional. Sets the path's Content-Disposition header. + ContentDisposition *string + // Optional. Sets the path's content encoding. If specified, this property is stored with the blobpath and returned with a read + // request. + ContentEncoding *string + // Optional. Set the path's content language. If specified, this property is stored with the path and returned with a read + // request. + ContentLanguage *string + // Specify the transactional md5 for the body, to be validated by the service. + ContentMD5 []byte + // Optional. Sets the path's content type. If specified, this property is stored with the path and returned with a read request. + ContentType *string +} + +func (o *HTTPHeaders) formatBlobHTTPHeaders() (*blob.HTTPHeaders, error) { + if o == nil { + return nil, nil + } + opts := blob.HTTPHeaders{ + BlobCacheControl: o.CacheControl, + BlobContentDisposition: o.ContentDisposition, + BlobContentEncoding: o.ContentEncoding, + BlobContentLanguage: o.ContentLanguage, + BlobContentMD5: o.ContentMD5, + BlobContentType: o.ContentType, + } + return &opts, nil +} + +func (o *HTTPHeaders) formatPathHTTPHeaders() (*generated.PathHTTPHeaders, error) { + // TODO: will be used for file related ops, like append + if o == nil { + return nil, nil + } + opts := generated.PathHTTPHeaders{ + CacheControl: o.CacheControl, + ContentDisposition: o.ContentDisposition, + ContentEncoding: o.ContentEncoding, + ContentLanguage: o.ContentLanguage, + ContentMD5: o.ContentMD5, + ContentType: o.ContentType, + TransactionalContentHash: o.ContentMD5, + } + return &opts, nil +} + +// SetMetadataOptions provides set of configurations for Set Metadata on path operation +type SetMetadataOptions struct { + AccessConditions *azdatalake.AccessConditions + CPKInfo *CPKInfo + CPKScopeInfo *CPKScopeInfo +} + +func (o *SetMetadataOptions) format() *blob.SetMetadataOptions { + if o == nil { + return nil + } + accessConditions := shared.FormatBlobAccessConditions(o.AccessConditions) + return &blob.SetMetadataOptions{ + AccessConditions: accessConditions, + CPKInfo: &blob.CPKInfo{ + EncryptionKey: o.CPKInfo.EncryptionKey, + EncryptionAlgorithm: o.CPKInfo.EncryptionAlgorithm, + EncryptionKeySHA256: o.CPKInfo.EncryptionKeySHA256, + }, + CPKScopeInfo: &blob.CPKScopeInfo{ + EncryptionScope: o.CPKScopeInfo.EncryptionScope, + }, + } +} + +// CPKInfo contains a group of parameters for the PathClient.Download method. +type CPKInfo struct { + EncryptionAlgorithm *EncryptionAlgorithmType + EncryptionKey *string + EncryptionKeySHA256 *string +} + +// CPKScopeInfo contains a group of parameters for the PathClient.SetMetadata method. +type CPKScopeInfo struct { + EncryptionScope *string +} + +// SourceModifiedAccessConditions identifies the source path access conditions. +type SourceModifiedAccessConditions = generated.SourceModifiedAccessConditions // SharedKeyCredential contains an account's name and its primary or secondary key. type SharedKeyCredential = exported.SharedKeyCredential diff --git a/sdk/storage/azdatalake/directory/responses.go b/sdk/storage/azdatalake/directory/responses.go index 19a975c5a384..3327f41360ce 100644 --- a/sdk/storage/azdatalake/directory/responses.go +++ b/sdk/storage/azdatalake/directory/responses.go @@ -7,8 +7,8 @@ package directory import ( + "github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/blob" "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/internal/generated" - "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/internal/path" ) // CreateResponse contains the response fields for the Create operation. @@ -17,29 +17,29 @@ type CreateResponse = generated.PathClientCreateResponse // DeleteResponse contains the response fields for the Delete operation. type DeleteResponse = generated.PathClientDeleteResponse +// RenameResponse contains the response fields for the Create operation. +type RenameResponse = generated.PathClientCreateResponse + // SetAccessControlResponse contains the response fields for the SetAccessControl operation. -type SetAccessControlResponse = path.SetAccessControlResponse +type SetAccessControlResponse = generated.PathClientSetAccessControlResponse // SetAccessControlRecursiveResponse contains the response fields for the SetAccessControlRecursive operation. -type SetAccessControlRecursiveResponse = path.SetAccessControlRecursiveResponse +type SetAccessControlRecursiveResponse = generated.PathClientSetAccessControlRecursiveResponse // UpdateAccessControlRecursiveResponse contains the response fields for the UpdateAccessControlRecursive operation. -type UpdateAccessControlRecursiveResponse = path.SetAccessControlRecursiveResponse +type UpdateAccessControlRecursiveResponse = generated.PathClientSetAccessControlRecursiveResponse // RemoveAccessControlRecursiveResponse contains the response fields for the RemoveAccessControlRecursive operation. -type RemoveAccessControlRecursiveResponse = path.SetAccessControlRecursiveResponse +type RemoveAccessControlRecursiveResponse = generated.PathClientSetAccessControlRecursiveResponse + +// GetAccessControlResponse contains the response fields for the GetAccessControl operation. +type GetAccessControlResponse = generated.PathClientGetPropertiesResponse // GetPropertiesResponse contains the response fields for the GetProperties operation. -type GetPropertiesResponse = path.GetPropertiesResponse +type GetPropertiesResponse = generated.PathClientGetPropertiesResponse // SetMetadataResponse contains the response fields for the SetMetadata operation. -type SetMetadataResponse = path.SetMetadataResponse +type SetMetadataResponse = blob.SetMetadataResponse // SetHTTPHeadersResponse contains the response fields for the SetHTTPHeaders operation. -type SetHTTPHeadersResponse = path.SetHTTPHeadersResponse - -// RenameResponse contains the response fields for the Rename operation. -type RenameResponse = path.CreateResponse - -// GetAccessControlResponse contains the response fields for the GetAccessControl operation. -type GetAccessControlResponse = path.GetAccessControlResponse +type SetHTTPHeadersResponse = blob.SetHTTPHeadersResponse diff --git a/sdk/storage/azdatalake/file/client.go b/sdk/storage/azdatalake/file/client.go index 84e9b64ca4ae..f76101a3c5b3 100644 --- a/sdk/storage/azdatalake/file/client.go +++ b/sdk/storage/azdatalake/file/client.go @@ -9,44 +9,123 @@ package file import ( "context" "github.com/Azure/azure-sdk-for-go/sdk/azcore" - "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake" - "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/internal/path" + "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/blob" + "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/shared" + "strings" ) -// Client represents a URL to the Azure Datalake Storage service allowing you to manipulate files. -type Client struct { - path.Client -} +// ClientOptions contains the optional parameters when creating a Client. +type ClientOptions base.ClientOptions -// NewClient creates an instance of Client with the specified values. -// - serviceURL - the URL of the storage account e.g. https://.file.core.windows.net/ -// - cred - an Azure AD credential, typically obtained via the azidentity module -// - options - client options; pass nil to accept the default values -func NewClient(serviceURL string, cred azcore.TokenCredential, options *azdatalake.ClientOptions) (*Client, error) { - return nil, nil -} +// Client represents a URL to the Azure Datalake Storage service. +type Client base.CompositeClient[generated.PathClient, generated.PathClient, blob.Client] + +//TODO: NewClient() // NewClientWithNoCredential creates an instance of Client with the specified values. // This is used to anonymously access a storage account or with a shared access signature (SAS) token. -// - serviceURL - the URL of the storage account e.g. https://.file.core.windows.net/? +// - serviceURL - the URL of the storage account e.g. https://.dfs.core.windows.net/? // - options - client options; pass nil to accept the default values -func NewClientWithNoCredential(serviceURL string, options *azdatalake.ClientOptions) (*Client, error) { - return nil, nil +func NewClientWithNoCredential(fileURL string, options *ClientOptions) (*Client, error) { + blobURL := strings.Replace(fileURL, ".dfs.", ".blob.", 1) + fileURL = strings.Replace(fileURL, ".blob.", ".dfs.", 1) + + conOptions := shared.GetClientOptions(options) + plOpts := runtime.PipelineOptions{} + base.SetPipelineOptions((*base.ClientOptions)(conOptions), &plOpts) + + azClient, err := azcore.NewClient(shared.FileClient, exported.ModuleVersion, plOpts, &conOptions.ClientOptions) + if err != nil { + return nil, err + } + + blobClientOpts := blob.ClientOptions{ + ClientOptions: options.ClientOptions, + } + blobClient, _ := blob.NewClientWithNoCredential(blobURL, &blobClientOpts) + fileClient := base.NewPathClient(fileURL, blobURL, blobClient, azClient, nil, (*base.ClientOptions)(conOptions)) + + return (*Client)(fileClient), nil } // NewClientWithSharedKeyCredential creates an instance of Client with the specified values. -// - serviceURL - the URL of the storage account e.g. https://.file.core.windows.net/ +// - serviceURL - the URL of the storage account e.g. https://.dfs.core.windows.net/ // - cred - a SharedKeyCredential created with the matching storage account and access key // - options - client options; pass nil to accept the default values -func NewClientWithSharedKeyCredential(serviceURL string, cred *SharedKeyCredential, options *azdatalake.ClientOptions) (*Client, error) { - return nil, nil +func NewClientWithSharedKeyCredential(fileURL string, cred *SharedKeyCredential, options *ClientOptions) (*Client, error) { + blobURL := strings.Replace(fileURL, ".dfs.", ".blob.", 1) + fileURL = strings.Replace(fileURL, ".blob.", ".dfs.", 1) + + authPolicy := exported.NewSharedKeyCredPolicy(cred) + conOptions := shared.GetClientOptions(options) + plOpts := runtime.PipelineOptions{ + PerRetry: []policy.Policy{authPolicy}, + } + base.SetPipelineOptions((*base.ClientOptions)(conOptions), &plOpts) + + azClient, err := azcore.NewClient(shared.FileClient, exported.ModuleVersion, plOpts, &conOptions.ClientOptions) + if err != nil { + return nil, err + } + + blobClientOpts := blob.ClientOptions{ + ClientOptions: options.ClientOptions, + } + blobSharedKeyCredential, _ := blob.NewSharedKeyCredential(cred.AccountName(), cred.AccountKey()) + blobClient, _ := blob.NewClientWithSharedKeyCredential(blobURL, blobSharedKeyCredential, &blobClientOpts) + fileClient := base.NewPathClient(fileURL, blobURL, blobClient, azClient, nil, (*base.ClientOptions)(conOptions)) + + return (*Client)(fileClient), nil } // NewClientFromConnectionString creates an instance of Client with the specified values. // - connectionString - a connection string for the desired storage account // - options - client options; pass nil to accept the default values -func NewClientFromConnectionString(connectionString string, options *azdatalake.ClientOptions) (*Client, error) { - return nil, nil +func NewClientFromConnectionString(connectionString string, options *ClientOptions) (*Client, error) { + parsed, err := shared.ParseConnectionString(connectionString) + if err != nil { + return nil, err + } + + if parsed.AccountKey != "" && parsed.AccountName != "" { + credential, err := exported.NewSharedKeyCredential(parsed.AccountName, parsed.AccountKey) + if err != nil { + return nil, err + } + return NewClientWithSharedKeyCredential(parsed.ServiceURL, credential, options) + } + + return NewClientWithNoCredential(parsed.ServiceURL, options) +} + +func (f *Client) generatedFSClientWithDFS() *generated.PathClient { + //base.SharedKeyComposite((*base.CompositeClient[generated.BlobClient, generated.BlockBlobClient])(bb)) + dirClientWithDFS, _, _ := base.InnerClients((*base.CompositeClient[generated.PathClient, generated.PathClient, blob.Client])(f)) + return dirClientWithDFS +} + +func (f *Client) generatedFSClientWithBlob() *generated.PathClient { + _, dirClientWithBlob, _ := base.InnerClients((*base.CompositeClient[generated.PathClient, generated.PathClient, blob.Client])(f)) + return dirClientWithBlob +} + +func (f *Client) blobClient() *blob.Client { + _, _, blobClient := base.InnerClients((*base.CompositeClient[generated.PathClient, generated.PathClient, blob.Client])(f)) + return blobClient +} + +func (f *Client) sharedKey() *exported.SharedKeyCredential { + return base.SharedKeyComposite((*base.CompositeClient[generated.PathClient, generated.PathClient, blob.Client])(f)) +} + +// URL returns the URL endpoint used by the Client object. +func (f *Client) URL() string { + return "s.generated().Endpoint()" } // Create creates a new file (dfs1). @@ -98,3 +177,44 @@ func (f *Client) Flush(ctx context.Context) { func (f *Client) Download(ctx context.Context) { } + +// SetAccessControl sets the owner, owning group, and permissions for a file or directory (dfs1). +func (f *Client) SetAccessControl(ctx context.Context, options *SetAccessControlOptions) (SetAccessControlResponse, error) { + return SetAccessControlResponse{}, nil +} + +// SetAccessControlRecursive sets the owner, owning group, and permissions for a file or directory (dfs1). +func (f *Client) SetAccessControlRecursive(ctx context.Context, options *SetAccessControlRecursiveOptions) (SetAccessControlRecursiveResponse, error) { + // TODO explicitly pass SetAccessControlRecursiveMode + return SetAccessControlRecursiveResponse{}, nil +} + +// UpdateAccessControlRecursive updates the owner, owning group, and permissions for a file or directory (dfs1). +func (f *Client) UpdateAccessControlRecursive(ctx context.Context, options *UpdateAccessControlRecursiveOptions) (UpdateAccessControlRecursiveResponse, error) { + // TODO explicitly pass SetAccessControlRecursiveMode + return SetAccessControlRecursiveResponse{}, nil +} + +// GetAccessControl gets the owner, owning group, and permissions for a file or directory (dfs1). +func (f *Client) GetAccessControl(ctx context.Context, options *GetAccessControlOptions) (GetAccessControlResponse, error) { + return GetAccessControlResponse{}, nil +} + +// RemoveAccessControlRecursive removes the owner, owning group, and permissions for a file or directory (dfs1). +func (f *Client) RemoveAccessControlRecursive(ctx context.Context, options *RemoveAccessControlRecursiveOptions) (RemoveAccessControlRecursiveResponse, error) { + // TODO explicitly pass SetAccessControlRecursiveMode + return SetAccessControlRecursiveResponse{}, nil +} + +// SetMetadata sets the metadata for a file or directory (blob3). +func (f *Client) SetMetadata(ctx context.Context, options *SetMetadataOptions) (SetMetadataResponse, error) { + // TODO: call directly into blob + return SetMetadataResponse{}, nil +} + +// SetHTTPHeaders sets the HTTP headers for a file or directory (blob3). +func (f *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 +} diff --git a/sdk/storage/azdatalake/file/constants.go b/sdk/storage/azdatalake/file/constants.go index 5ce02ebff960..60eabcfcce37 100644 --- a/sdk/storage/azdatalake/file/constants.go +++ b/sdk/storage/azdatalake/file/constants.go @@ -7,36 +7,37 @@ package file import ( - "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/internal/path" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/blob" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/internal/generated" ) -type ResourceType = path.ResourceType +type ResourceType = generated.PathResourceType // TODO: consider the possibility of not exposing this and just pass it under the hood const ( - ResourceTypeFile ResourceType = path.ResourceTypeFile - ResourceTypeDirectory ResourceType = path.ResourceTypeDirectory + ResourceTypeFile ResourceType = generated.PathResourceTypeFile + ResourceTypeDirectory ResourceType = generated.PathResourceTypeDirectory ) -type RenameMode = path.RenameMode +type RenameMode = generated.PathRenameMode // TODO: consider the possibility of not exposing this and just pass it under the hood const ( - RenameModeLegacy RenameMode = path.RenameModeLegacy - RenameModePosix RenameMode = path.RenameModePosix + RenameModeLegacy RenameMode = generated.PathRenameModeLegacy + RenameModePosix RenameMode = generated.PathRenameModePosix ) -type SetAccessControlRecursiveMode = path.SetAccessControlRecursiveMode +type SetAccessControlRecursiveMode = generated.PathSetAccessControlRecursiveMode const ( - SetAccessControlRecursiveModeSet SetAccessControlRecursiveMode = path.SetAccessControlRecursiveModeSet - SetAccessControlRecursiveModeModify SetAccessControlRecursiveMode = path.SetAccessControlRecursiveModeModify - SetAccessControlRecursiveModeRemove SetAccessControlRecursiveMode = path.SetAccessControlRecursiveModeRemove + SetAccessControlRecursiveModeSet SetAccessControlRecursiveMode = generated.PathSetAccessControlRecursiveModeSet + SetAccessControlRecursiveModeModify SetAccessControlRecursiveMode = generated.PathSetAccessControlRecursiveModeModify + SetAccessControlRecursiveModeRemove SetAccessControlRecursiveMode = generated.PathSetAccessControlRecursiveModeRemove ) -type EncryptionAlgorithmType = path.EncryptionAlgorithmType +type EncryptionAlgorithmType = blob.EncryptionAlgorithmType const ( - EncryptionAlgorithmTypeNone EncryptionAlgorithmType = path.EncryptionAlgorithmTypeNone - EncryptionAlgorithmTypeAES256 EncryptionAlgorithmType = path.EncryptionAlgorithmTypeAES256 + EncryptionAlgorithmTypeNone EncryptionAlgorithmType = blob.EncryptionAlgorithmTypeNone + EncryptionAlgorithmTypeAES256 EncryptionAlgorithmType = blob.EncryptionAlgorithmTypeAES256 ) diff --git a/sdk/storage/azdatalake/file/models.go b/sdk/storage/azdatalake/file/models.go index f45f6041b50b..18551b86a14d 100644 --- a/sdk/storage/azdatalake/file/models.go +++ b/sdk/storage/azdatalake/file/models.go @@ -11,7 +11,6 @@ import ( "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake" "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" "time" ) @@ -101,39 +100,221 @@ func (o *GetPropertiesOptions) format() *blob.GetPropertiesOptions { } // ===================================== PATH IMPORTS =========================================== +// SetAccessControlOptions contains the optional parameters when calling the SetAccessControl operation. dfs endpoint +type SetAccessControlOptions struct { + // Owner is the owner of the path. + Owner *string + // Group is the owning group of the path. + Group *string + // ACL is the access control list for the path. + ACL *string + // Permissions is the octal representation of the permissions for user, group and mask. + Permissions *string + // AccessConditions contains parameters for accessing the path. + AccessConditions *azdatalake.AccessConditions +} + +func (o *SetAccessControlOptions) format() (*generated.PathClientSetAccessControlOptions, *generated.LeaseAccessConditions, *generated.ModifiedAccessConditions, error) { + if o == nil { + return nil, nil, nil, nil + } + // call path formatter since we're hitting dfs in this operation + leaseAccessConditions, modifiedAccessConditions := shared.FormatPathAccessConditions(o.AccessConditions) + return &generated.PathClientSetAccessControlOptions{ + Owner: o.Owner, + Group: o.Group, + ACL: o.ACL, + Permissions: o.Permissions, + }, leaseAccessConditions, modifiedAccessConditions, nil +} + +// GetAccessControlOptions contains the optional parameters when calling the GetAccessControl operation. +type GetAccessControlOptions struct { + // UPN is the user principal name. + UPN *bool + // AccessConditions contains parameters for accessing the path. + AccessConditions *azdatalake.AccessConditions +} + +func (o *GetAccessControlOptions) format() (*generated.PathClientGetPropertiesOptions, *generated.LeaseAccessConditions, *generated.ModifiedAccessConditions, error) { + action := generated.PathGetPropertiesActionGetAccessControl + if o == nil { + return &generated.PathClientGetPropertiesOptions{ + Action: &action, + }, nil, nil, nil + } + // call path formatter since we're hitting dfs in this operation + leaseAccessConditions, modifiedAccessConditions := shared.FormatPathAccessConditions(o.AccessConditions) + return &generated.PathClientGetPropertiesOptions{ + Upn: o.UPN, + Action: &action, + }, leaseAccessConditions, modifiedAccessConditions, nil +} + +// 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 + // 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 +} + +// 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 +} + +func (o *UpdateAccessControlRecursiveOptions) format() (*generated.PathClientSetAccessControlRecursiveOptions, error) { + // TODO: design formatter - similar to SetAccessControlRecursiveOptions + return nil, nil +} + +// 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 +} -// CPKInfo contains a group of parameters for client provided encryption key. -type CPKInfo = path.CPKInfo +// SetHTTPHeadersOptions contains the optional parameters for the Client.SetHTTPHeaders method. +type SetHTTPHeadersOptions struct { + AccessConditions *azdatalake.AccessConditions +} -// CPKScopeInfo contains a group of parameters for client provided encryption scope. -type CPKScopeInfo = path.CPKScopeInfo +func (o *SetHTTPHeadersOptions) format() *blob.SetHTTPHeadersOptions { + if o == nil { + return nil + } + accessConditions := shared.FormatBlobAccessConditions(o.AccessConditions) + return &blob.SetHTTPHeadersOptions{ + AccessConditions: accessConditions, + } +} // HTTPHeaders contains the HTTP headers for path operations. -type HTTPHeaders = path.HTTPHeaders +type HTTPHeaders struct { + // Optional. Sets the path's cache control. If specified, this property is stored with the path and returned with a read request. + CacheControl *string + // Optional. Sets the path's Content-Disposition header. + ContentDisposition *string + // Optional. Sets the path's content encoding. If specified, this property is stored with the blobpath and returned with a read + // request. + ContentEncoding *string + // Optional. Set the path's content language. If specified, this property is stored with the path and returned with a read + // request. + ContentLanguage *string + // Specify the transactional md5 for the body, to be validated by the service. + ContentMD5 []byte + // Optional. Sets the path's content type. If specified, this property is stored with the path and returned with a read request. + ContentType *string +} -// SourceModifiedAccessConditions identifies the source path access conditions. -type SourceModifiedAccessConditions = path.SourceModifiedAccessConditions +func (o *HTTPHeaders) formatBlobHTTPHeaders() (*blob.HTTPHeaders, error) { + if o == nil { + return nil, nil + } + opts := blob.HTTPHeaders{ + BlobCacheControl: o.CacheControl, + BlobContentDisposition: o.ContentDisposition, + BlobContentEncoding: o.ContentEncoding, + BlobContentLanguage: o.ContentLanguage, + BlobContentMD5: o.ContentMD5, + BlobContentType: o.ContentType, + } + return &opts, nil +} -// SetAccessControlOptions contains the optional parameters when calling the SetAccessControl operation. -type SetAccessControlOptions = path.SetAccessControlOptions +func (o *HTTPHeaders) formatPathHTTPHeaders() (*generated.PathHTTPHeaders, error) { + // TODO: will be used for file related ops, like append + if o == nil { + return nil, nil + } + opts := generated.PathHTTPHeaders{ + CacheControl: o.CacheControl, + ContentDisposition: o.ContentDisposition, + ContentEncoding: o.ContentEncoding, + ContentLanguage: o.ContentLanguage, + ContentMD5: o.ContentMD5, + ContentType: o.ContentType, + TransactionalContentHash: o.ContentMD5, + } + return &opts, nil +} -// GetAccessControlOptions contains the optional parameters when calling the GetAccessControl operation. -type GetAccessControlOptions = path.GetAccessControlOptions +// SetMetadataOptions provides set of configurations for Set Metadata on path operation +type SetMetadataOptions struct { + AccessConditions *azdatalake.AccessConditions + CPKInfo *CPKInfo + CPKScopeInfo *CPKScopeInfo +} -// SetAccessControlRecursiveOptions contains the optional parameters when calling the SetAccessControlRecursive operation. -type SetAccessControlRecursiveOptions = path.SetAccessControlRecursiveOptions +func (o *SetMetadataOptions) format() *blob.SetMetadataOptions { + if o == nil { + return nil + } + accessConditions := shared.FormatBlobAccessConditions(o.AccessConditions) + return &blob.SetMetadataOptions{ + AccessConditions: accessConditions, + CPKInfo: &blob.CPKInfo{ + EncryptionKey: o.CPKInfo.EncryptionKey, + EncryptionAlgorithm: o.CPKInfo.EncryptionAlgorithm, + EncryptionKeySHA256: o.CPKInfo.EncryptionKeySHA256, + }, + CPKScopeInfo: &blob.CPKScopeInfo{ + EncryptionScope: o.CPKScopeInfo.EncryptionScope, + }, + } +} -// SetMetadataOptions contains the optional parameters when calling the SetMetadata operation. -type SetMetadataOptions = path.SetMetadataOptions +// CPKInfo contains a group of parameters for the PathClient.Download method. +type CPKInfo struct { + EncryptionAlgorithm *EncryptionAlgorithmType + EncryptionKey *string + EncryptionKeySHA256 *string +} -// SetHTTPHeadersOptions contains the optional parameters when calling the SetHTTPHeaders operation. -type SetHTTPHeadersOptions = path.SetHTTPHeadersOptions +// CPKScopeInfo contains a group of parameters for the PathClient.SetMetadata method. +type CPKScopeInfo struct { + EncryptionScope *string +} -// RemoveAccessControlRecursiveOptions contains the optional parameters when calling the RemoveAccessControlRecursive operation. -type RemoveAccessControlRecursiveOptions = path.RemoveAccessControlRecursiveOptions +// SourceModifiedAccessConditions identifies the source path access conditions. +type SourceModifiedAccessConditions = generated.SourceModifiedAccessConditions -// UpdateAccessControlRecursiveOptions contains the optional parameters when calling the UpdateAccessControlRecursive operation. -type UpdateAccessControlRecursiveOptions = path.UpdateAccessControlRecursiveOptions +// SharedKeyCredential contains an account's name and its primary or secondary key. +type SharedKeyCredential = exported.SharedKeyCredential // ExpiryType defines values for ExpiryType. type ExpiryType = exported.ExpiryType @@ -152,6 +333,3 @@ type ExpiryTypeNever = exported.ExpiryTypeNever // SetExpiryOptions contains the optional parameters for the Client.SetExpiry method. type SetExpiryOptions = exported.SetExpiryOptions - -// SharedKeyCredential contains an account's name and its primary or secondary key. -type SharedKeyCredential = exported.SharedKeyCredential diff --git a/sdk/storage/azdatalake/file/responses.go b/sdk/storage/azdatalake/file/responses.go index 8543eaf3902a..e7ace65c52ee 100644 --- a/sdk/storage/azdatalake/file/responses.go +++ b/sdk/storage/azdatalake/file/responses.go @@ -7,8 +7,8 @@ package file import ( + "github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/blob" "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/internal/generated" - "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/internal/path" ) // SetExpiryResponse contains the response fields for the SetExpiry operation. @@ -21,28 +21,28 @@ type CreateResponse = generated.PathClientCreateResponse type DeleteResponse = generated.PathClientDeleteResponse // SetAccessControlResponse contains the response fields for the SetAccessControl operation. -type SetAccessControlResponse = path.SetAccessControlResponse +type SetAccessControlResponse = generated.PathClientSetAccessControlResponse // SetAccessControlRecursiveResponse contains the response fields for the SetAccessControlRecursive operation. -type SetAccessControlRecursiveResponse = path.SetAccessControlRecursiveResponse +type SetAccessControlRecursiveResponse = generated.PathClientSetAccessControlRecursiveResponse // UpdateAccessControlRecursiveResponse contains the response fields for the UpdateAccessControlRecursive operation. -type UpdateAccessControlRecursiveResponse = path.SetAccessControlRecursiveResponse +type UpdateAccessControlRecursiveResponse = generated.PathClientSetAccessControlRecursiveResponse // RemoveAccessControlRecursiveResponse contains the response fields for the RemoveAccessControlRecursive operation. -type RemoveAccessControlRecursiveResponse = path.SetAccessControlRecursiveResponse +type RemoveAccessControlRecursiveResponse = generated.PathClientSetAccessControlRecursiveResponse + +// GetAccessControlResponse contains the response fields for the GetAccessControl operation. +type GetAccessControlResponse = generated.PathClientGetPropertiesResponse // GetPropertiesResponse contains the response fields for the GetProperties operation. -type GetPropertiesResponse = path.GetPropertiesResponse +type GetPropertiesResponse = generated.PathClientGetPropertiesResponse // SetMetadataResponse contains the response fields for the SetMetadata operation. -type SetMetadataResponse = path.SetMetadataResponse +type SetMetadataResponse = blob.SetMetadataResponse // SetHTTPHeadersResponse contains the response fields for the SetHTTPHeaders operation. -type SetHTTPHeadersResponse = path.SetHTTPHeadersResponse +type SetHTTPHeadersResponse = blob.SetHTTPHeadersResponse -// RenameResponse contains the response fields for the Rename operation. -type RenameResponse = path.CreateResponse - -// GetAccessControlResponse contains the response fields for the GetAccessControl operation. -type GetAccessControlResponse = path.GetAccessControlResponse +// RenameResponse contains the response fields for the Create operation. +type RenameResponse = generated.PathClientCreateResponse diff --git a/sdk/storage/azdatalake/filesystem/client.go b/sdk/storage/azdatalake/filesystem/client.go index ae2cbdb536d2..06f76dd537c7 100644 --- a/sdk/storage/azdatalake/filesystem/client.go +++ b/sdk/storage/azdatalake/filesystem/client.go @@ -9,53 +9,119 @@ package filesystem import ( "context" "github.com/Azure/azure-sdk-for-go/sdk/azcore" + "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/azdatalake" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/blob" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/container" "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/shared" + "strings" ) -// Client represents a URL to the Azure Datalake Storage service allowing you to manipulate filesystems. -type Client base.Client[generated.FileSystemClient] +// ClientOptions contains the optional parameters when creating a Client. +type ClientOptions base.ClientOptions -// NewClient creates an instance of Client with the specified values. -// - serviceURL - the URL of the storage account e.g. https://.file.core.windows.net/ -// - cred - an Azure AD credential, typically obtained via the azidentity module -// - options - client options; pass nil to accept the default values -func NewClient(serviceURL string, cred azcore.TokenCredential, options *azdatalake.ClientOptions) (*Client, error) { - return nil, nil -} +// Client represents a URL to the Azure Datalake Storage service. +type Client base.CompositeClient[generated.FileSystemClient, generated.FileSystemClient, container.Client] + +//TODO: NewClient() // NewClientWithNoCredential creates an instance of Client with the specified values. // This is used to anonymously access a storage account or with a shared access signature (SAS) token. -// - serviceURL - the URL of the storage account e.g. https://.file.core.windows.net/? +// - serviceURL - the URL of the storage account e.g. https://.dfs.core.windows.net/? // - options - client options; pass nil to accept the default values -func NewClientWithNoCredential(serviceURL string, options *azdatalake.ClientOptions) (*Client, error) { - return nil, nil +func NewClientWithNoCredential(filesystemURL string, options *ClientOptions) (*Client, error) { + containerURL := strings.Replace(filesystemURL, ".dfs.", ".blob.", 1) + filesystemURL = strings.Replace(filesystemURL, ".blob.", ".dfs.", 1) + + conOptions := shared.GetClientOptions(options) + plOpts := runtime.PipelineOptions{} + base.SetPipelineOptions((*base.ClientOptions)(conOptions), &plOpts) + + azClient, err := azcore.NewClient(shared.FilesystemClient, exported.ModuleVersion, plOpts, &conOptions.ClientOptions) + if err != nil { + return nil, err + } + + containerClientOpts := container.ClientOptions{ + ClientOptions: options.ClientOptions, + } + blobContainerClient, _ := container.NewClientWithNoCredential(containerURL, &containerClientOpts) + fsClient := base.NewFilesystemClient(filesystemURL, containerURL, blobContainerClient, azClient, nil, (*base.ClientOptions)(conOptions)) + + return (*Client)(fsClient), nil } // NewClientWithSharedKeyCredential creates an instance of Client with the specified values. -// - serviceURL - the URL of the storage account e.g. https://.file.core.windows.net/ +// - serviceURL - the URL of the storage account e.g. https://.dfs.core.windows.net/ // - cred - a SharedKeyCredential created with the matching storage account and access key // - options - client options; pass nil to accept the default values -func NewClientWithSharedKeyCredential(serviceURL string, cred *SharedKeyCredential, options *azdatalake.ClientOptions) (*Client, error) { - return nil, nil +func NewClientWithSharedKeyCredential(filesystemURL string, cred *SharedKeyCredential, options *ClientOptions) (*Client, error) { + containerURL := strings.Replace(filesystemURL, ".dfs.", ".blob.", 1) + filesystemURL = strings.Replace(filesystemURL, ".blob.", ".dfs.", 1) + + authPolicy := exported.NewSharedKeyCredPolicy(cred) + conOptions := shared.GetClientOptions(options) + plOpts := runtime.PipelineOptions{ + PerRetry: []policy.Policy{authPolicy}, + } + base.SetPipelineOptions((*base.ClientOptions)(conOptions), &plOpts) + + azClient, err := azcore.NewClient(shared.FilesystemClient, exported.ModuleVersion, plOpts, &conOptions.ClientOptions) + if err != nil { + return nil, err + } + + containerClientOpts := container.ClientOptions{ + ClientOptions: options.ClientOptions, + } + blobSharedKeyCredential, _ := blob.NewSharedKeyCredential(cred.AccountName(), cred.AccountKey()) + blobContainerClient, _ := container.NewClientWithSharedKeyCredential(containerURL, blobSharedKeyCredential, &containerClientOpts) + fsClient := base.NewFilesystemClient(filesystemURL, containerURL, blobContainerClient, azClient, cred, (*base.ClientOptions)(conOptions)) + + return (*Client)(fsClient), nil } // NewClientFromConnectionString creates an instance of Client with the specified values. // - connectionString - a connection string for the desired storage account // - options - client options; pass nil to accept the default values -func NewClientFromConnectionString(connectionString string, options *azdatalake.ClientOptions) (*Client, error) { - return nil, nil +func NewClientFromConnectionString(connectionString string, options *ClientOptions) (*Client, error) { + parsed, err := shared.ParseConnectionString(connectionString) + if err != nil { + return nil, err + } + + if parsed.AccountKey != "" && parsed.AccountName != "" { + credential, err := exported.NewSharedKeyCredential(parsed.AccountName, parsed.AccountKey) + if err != nil { + return nil, err + } + return NewClientWithSharedKeyCredential(parsed.ServiceURL, credential, options) + } + + return NewClientWithNoCredential(parsed.ServiceURL, options) +} + +func (fs *Client) generatedFSClientWithDFS() *generated.FileSystemClient { + //base.SharedKeyComposite((*base.CompositeClient[generated.BlobClient, generated.BlockBlobClient])(bb)) + fsClientWithDFS, _, _ := base.InnerClients((*base.CompositeClient[generated.FileSystemClient, generated.FileSystemClient, container.Client])(fs)) + return fsClientWithDFS +} + +func (fs *Client) generatedFSClientWithBlob() *generated.FileSystemClient { + _, fsClientWithBlob, _ := base.InnerClients((*base.CompositeClient[generated.FileSystemClient, generated.FileSystemClient, container.Client])(fs)) + return fsClientWithBlob } -func (fs *Client) generated() *generated.FileSystemClient { - return base.InnerClient((*base.Client[generated.FileSystemClient])(fs)) +func (fs *Client) containerClient() *container.Client { + _, _, containerClient := base.InnerClients((*base.CompositeClient[generated.FileSystemClient, generated.FileSystemClient, container.Client])(fs)) + return containerClient } func (fs *Client) sharedKey() *exported.SharedKeyCredential { - return base.SharedKey((*base.Client[generated.FileSystemClient])(fs)) + return base.SharedKeyComposite((*base.CompositeClient[generated.FileSystemClient, generated.FileSystemClient, container.Client])(fs)) } // URL returns the URL endpoint used by the Client object. diff --git a/sdk/storage/azdatalake/internal/base/clients.go b/sdk/storage/azdatalake/internal/base/clients.go index 40c909a17596..e526f500a25e 100644 --- a/sdk/storage/azdatalake/internal/base/clients.go +++ b/sdk/storage/azdatalake/internal/base/clients.go @@ -7,12 +7,25 @@ package base import ( + "github.com/Azure/azure-sdk-for-go/sdk/azcore" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/blob" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/container" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/service" "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/internal/exported" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/internal/generated" ) +// ClientOptions contains the optional parameters when creating a Client. +type ClientOptions struct { + azcore.ClientOptions + pipelineOptions *runtime.PipelineOptions +} + type Client[T any] struct { inner *T sharedKey *exported.SharedKeyCredential + options *ClientOptions } func InnerClient[T any](client *Client[T]) *T { @@ -22,3 +35,64 @@ func InnerClient[T any](client *Client[T]) *T { func SharedKey[T any](client *Client[T]) *exported.SharedKeyCredential { return client.sharedKey } + +func GetClientOptions[T any](client *Client[T]) *ClientOptions { + return client.options +} + +func GetPipelineOptions(clOpts *ClientOptions) *runtime.PipelineOptions { + return clOpts.pipelineOptions +} + +func SetPipelineOptions(clOpts *ClientOptions, plOpts *runtime.PipelineOptions) { + clOpts.pipelineOptions = plOpts +} + +type CompositeClient[T, K, U any] struct { + // generated client with dfs + innerT *T + // generated client with blob + innerK *K + // blob client + innerU *U + sharedKey *exported.SharedKeyCredential + options *ClientOptions +} + +func InnerClients[T, K, U any](client *CompositeClient[T, K, U]) (*T, *K, *U) { + return client.innerT, client.innerK, client.innerU +} + +func SharedKeyComposite[T, K, U any](client *CompositeClient[T, K, U]) *exported.SharedKeyCredential { + return client.sharedKey +} + +func NewFilesystemClient(fsURL string, fsURLWithBlobEndpoint string, client *container.Client, azClient *azcore.Client, sharedKey *exported.SharedKeyCredential, options *ClientOptions) *CompositeClient[generated.FileSystemClient, generated.FileSystemClient, container.Client] { + return &CompositeClient[generated.FileSystemClient, generated.FileSystemClient, container.Client]{ + innerT: generated.NewFilesystemClient(fsURL, azClient), + innerK: generated.NewFilesystemClient(fsURLWithBlobEndpoint, azClient), + sharedKey: sharedKey, + innerU: client, + options: options, + } +} + +func NewServiceClient(serviceURL string, serviceURLWithBlobEndpoint string, client *service.Client, azClient *azcore.Client, sharedKey *exported.SharedKeyCredential, options *ClientOptions) *CompositeClient[generated.ServiceClient, generated.ServiceClient, service.Client] { + return &CompositeClient[generated.ServiceClient, generated.ServiceClient, service.Client]{ + innerT: generated.NewServiceClient(serviceURL, azClient), + innerK: generated.NewServiceClient(serviceURLWithBlobEndpoint, azClient), + sharedKey: sharedKey, + innerU: client, + options: options, + } +} + +func NewPathClient(dirURL string, dirURLWithBlobEndpoint string, client *blob.Client, azClient *azcore.Client, sharedKey *exported.SharedKeyCredential, options *ClientOptions) *CompositeClient[generated.PathClient, generated.PathClient, blob.Client] { + return &CompositeClient[generated.PathClient, generated.PathClient, blob.Client]{ + innerT: generated.NewPathClient(dirURL, azClient), + innerK: generated.NewPathClient(dirURLWithBlobEndpoint, azClient), + sharedKey: sharedKey, + innerU: client, + options: options, + } +} diff --git a/sdk/storage/azdatalake/internal/exported/shared_key_credential.go b/sdk/storage/azdatalake/internal/exported/shared_key_credential.go index 01934a0f14de..980b5a9a4f5a 100644 --- a/sdk/storage/azdatalake/internal/exported/shared_key_credential.go +++ b/sdk/storage/azdatalake/internal/exported/shared_key_credential.go @@ -28,7 +28,7 @@ import ( // NewSharedKeyCredential creates an immutable SharedKeyCredential containing the // storage account's name and either its primary or secondary key. func NewSharedKeyCredential(accountName string, accountKey string) (*SharedKeyCredential, error) { - c := SharedKeyCredential{accountName: accountName} + c := SharedKeyCredential{accountName: accountName, accountKeyString: accountKey} if err := c.SetAccountKey(accountKey); err != nil { return nil, err } @@ -38,8 +38,9 @@ func NewSharedKeyCredential(accountName string, accountKey string) (*SharedKeyCr // SharedKeyCredential contains an account's name and its primary or secondary key. type SharedKeyCredential struct { // Only the NewSharedKeyCredential method should set these; all other methods should treat them as read-only - accountName string - accountKey atomic.Value // []byte + accountName string + accountKey atomic.Value // []byte + accountKeyString string } // AccountName returns the Storage account's name. @@ -47,6 +48,11 @@ func (c *SharedKeyCredential) AccountName() string { return c.accountName } +// AccountKey returns the Storage account's name. +func (c *SharedKeyCredential) AccountKey() string { + return c.accountKeyString +} + // SetAccountKey replaces the existing account key with the specified account key. func (c *SharedKeyCredential) SetAccountKey(accountKey string) error { _bytes, err := base64.StdEncoding.DecodeString(accountKey) diff --git a/sdk/storage/azdatalake/internal/generated/filesystem_client.go b/sdk/storage/azdatalake/internal/generated/filesystem_client.go index 27c60f60cbcb..d35651c781b8 100644 --- a/sdk/storage/azdatalake/internal/generated/filesystem_client.go +++ b/sdk/storage/azdatalake/internal/generated/filesystem_client.go @@ -7,17 +7,28 @@ package generated import ( - "github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime" + "github.com/Azure/azure-sdk-for-go/sdk/azcore" "time" ) +// used to convert times from UTC to GMT before sending across the wire +var gmt = time.FixedZone("GMT", 0) + func (client *FileSystemClient) Endpoint() string { return client.endpoint } -func (client *FileSystemClient) Pipeline() runtime.Pipeline { - return client.internal.Pipeline() +func (client *FileSystemClient) InternalClient() *azcore.Client { + return client.internal } -// used to convert times from UTC to GMT before sending across the wire -var gmt = time.FixedZone("GMT", 0) +// NewFilesystemClient creates a new instance of ServiceClient with the specified values. +// - endpoint - The URL of the service account, share, directory or file that is the target of the desired operation. +// - azClient - azcore.Client is a basic HTTP client. It consists of a pipeline and tracing provider. +func NewFilesystemClient(endpoint string, azClient *azcore.Client) *FileSystemClient { + client := &FileSystemClient{ + internal: azClient, + endpoint: endpoint, + } + return client +} diff --git a/sdk/storage/azdatalake/internal/generated/path_client.go b/sdk/storage/azdatalake/internal/generated/path_client.go index 3de3766c9850..e12c424816c9 100644 --- a/sdk/storage/azdatalake/internal/generated/path_client.go +++ b/sdk/storage/azdatalake/internal/generated/path_client.go @@ -6,12 +6,25 @@ package generated -import "github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime" +import ( + "github.com/Azure/azure-sdk-for-go/sdk/azcore" +) func (client *PathClient) Endpoint() string { return client.endpoint } -func (client *PathClient) Pipeline() runtime.Pipeline { - return client.internal.Pipeline() +func (client *PathClient) InternalClient() *azcore.Client { + return client.internal +} + +// NewPathClient creates a new instance of ServiceClient with the specified values. +// - endpoint - The URL of the service account, share, directory or file that is the target of the desired operation. +// - azClient - azcore.Client is a basic HTTP client. It consists of a pipeline and tracing provider. +func NewPathClient(endpoint string, azClient *azcore.Client) *PathClient { + client := &PathClient{ + internal: azClient, + endpoint: endpoint, + } + return client } diff --git a/sdk/storage/azdatalake/internal/generated/service_client.go b/sdk/storage/azdatalake/internal/generated/service_client.go index 22f11c20a9fd..8c99594b7dbd 100644 --- a/sdk/storage/azdatalake/internal/generated/service_client.go +++ b/sdk/storage/azdatalake/internal/generated/service_client.go @@ -6,12 +6,25 @@ package generated -import "github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime" +import ( + "github.com/Azure/azure-sdk-for-go/sdk/azcore" +) func (client *ServiceClient) Endpoint() string { return client.endpoint } -func (client *ServiceClient) Pipeline() runtime.Pipeline { - return client.internal.Pipeline() +func (client *ServiceClient) InternalClient() *azcore.Client { + return client.internal +} + +// NewServiceClient creates a new instance of ServiceClient with the specified values. +// - endpoint - The URL of the service account, share, directory or file that is the target of the desired operation. +// - azClient - azcore.Client is a basic HTTP client. It consists of a pipeline and tracing provider. +func NewServiceClient(endpoint string, azClient *azcore.Client) *ServiceClient { + client := &ServiceClient{ + internal: azClient, + endpoint: endpoint, + } + return client } diff --git a/sdk/storage/azdatalake/internal/path/client.go b/sdk/storage/azdatalake/internal/path/client.go deleted file mode 100644 index bfeab81bcbcc..000000000000 --- a/sdk/storage/azdatalake/internal/path/client.go +++ /dev/null @@ -1,71 +0,0 @@ -//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 path - -import ( - "context" - "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" -) - -// Client represents a URL to the Azure Datalake Storage service allowing you to manipulate paths. -type Client base.Client[generated.PathClient] - -func (p *Client) generated() *generated.PathClient { - return base.InnerClient((*base.Client[generated.PathClient])(p)) -} - -func (p *Client) sharedKey() *exported.SharedKeyCredential { - return base.SharedKey((*base.Client[generated.PathClient])(p)) -} - -// URL returns the URL endpoint used by the Client object. -func (p *Client) URL() string { - return "s.generated().Endpoint()" -} - -// SetAccessControl sets the owner, owning group, and permissions for a file or directory (dfs1). -func (p *Client) SetAccessControl(ctx context.Context, options *SetAccessControlOptions) (SetAccessControlResponse, error) { - return SetAccessControlResponse{}, nil -} - -// SetAccessControlRecursive sets the owner, owning group, and permissions for a file or directory (dfs1). -func (p *Client) SetAccessControlRecursive(ctx context.Context, options *SetAccessControlRecursiveOptions) (SetAccessControlRecursiveResponse, error) { - // TODO explicitly pass SetAccessControlRecursiveMode - return SetAccessControlRecursiveResponse{}, nil -} - -// UpdateAccessControlRecursive updates the owner, owning group, and permissions for a file or directory (dfs1). -func (p *Client) UpdateAccessControlRecursive(ctx context.Context, options *UpdateAccessControlRecursiveOptions) (UpdateAccessControlRecursiveResponse, error) { - // TODO explicitly pass SetAccessControlRecursiveMode - return SetAccessControlRecursiveResponse{}, nil -} - -// GetAccessControl gets the owner, owning group, and permissions for a file or directory (dfs1). -func (p *Client) GetAccessControl(ctx context.Context, options *GetAccessControlOptions) (GetAccessControlResponse, error) { - return GetAccessControlResponse{}, nil -} - -// RemoveAccessControlRecursive removes the owner, owning group, and permissions for a file or directory (dfs1). -func (p *Client) RemoveAccessControlRecursive(ctx context.Context, options *RemoveAccessControlRecursiveOptions) (RemoveAccessControlRecursiveResponse, error) { - // TODO explicitly pass SetAccessControlRecursiveMode - return SetAccessControlRecursiveResponse{}, nil -} - -// SetMetadata sets the metadata for a file or directory (blob3). -func (p *Client) SetMetadata(ctx context.Context, options *SetMetadataOptions) (SetMetadataResponse, error) { - // TODO: call directly into blob - return SetMetadataResponse{}, nil -} - -// SetHTTPHeaders sets the HTTP headers for a file or directory (blob3). -func (p *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 -} diff --git a/sdk/storage/azdatalake/internal/path/constants.go b/sdk/storage/azdatalake/internal/path/constants.go deleted file mode 100644 index d2d11defca1c..000000000000 --- a/sdk/storage/azdatalake/internal/path/constants.go +++ /dev/null @@ -1,43 +0,0 @@ -//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 path - -import ( - "github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/blob" - "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/internal/generated" -) - -type ResourceType = generated.PathResourceType - -// TODO: consider the possibility of not exposing this and just pass it under the hood -const ( - ResourceTypeFile ResourceType = generated.PathResourceTypeFile - ResourceTypeDirectory ResourceType = generated.PathResourceTypeDirectory -) - -type RenameMode = generated.PathRenameMode - -// TODO: consider the possibility of not exposing this and just pass it under the hood -const ( - RenameModeLegacy RenameMode = generated.PathRenameModeLegacy - RenameModePosix RenameMode = generated.PathRenameModePosix -) - -type SetAccessControlRecursiveMode = generated.PathSetAccessControlRecursiveMode - -const ( - SetAccessControlRecursiveModeSet SetAccessControlRecursiveMode = generated.PathSetAccessControlRecursiveModeSet - SetAccessControlRecursiveModeModify SetAccessControlRecursiveMode = generated.PathSetAccessControlRecursiveModeModify - SetAccessControlRecursiveModeRemove SetAccessControlRecursiveMode = generated.PathSetAccessControlRecursiveModeRemove -) - -type EncryptionAlgorithmType = blob.EncryptionAlgorithmType - -const ( - EncryptionAlgorithmTypeNone EncryptionAlgorithmType = blob.EncryptionAlgorithmTypeNone - EncryptionAlgorithmTypeAES256 EncryptionAlgorithmType = blob.EncryptionAlgorithmTypeAES256 -) diff --git a/sdk/storage/azdatalake/internal/path/models.go b/sdk/storage/azdatalake/internal/path/models.go deleted file mode 100644 index 75cca62c85c8..000000000000 --- a/sdk/storage/azdatalake/internal/path/models.go +++ /dev/null @@ -1,227 +0,0 @@ -//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 path - -import ( - "github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/blob" - "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake" - "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/internal/generated" - "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/internal/shared" -) - -// SetAccessControlOptions contains the optional parameters when calling the SetAccessControl operation. dfs endpoint -type SetAccessControlOptions struct { - // Owner is the owner of the path. - Owner *string - // Group is the owning group of the path. - Group *string - // ACL is the access control list for the path. - ACL *string - // Permissions is the octal representation of the permissions for user, group and mask. - Permissions *string - // AccessConditions contains parameters for accessing the path. - AccessConditions *azdatalake.AccessConditions -} - -func (o *SetAccessControlOptions) format() (*generated.PathClientSetAccessControlOptions, *generated.LeaseAccessConditions, *generated.ModifiedAccessConditions, error) { - if o == nil { - return nil, nil, nil, nil - } - // call path formatter since we're hitting dfs in this operation - leaseAccessConditions, modifiedAccessConditions := shared.FormatPathAccessConditions(o.AccessConditions) - return &generated.PathClientSetAccessControlOptions{ - Owner: o.Owner, - Group: o.Group, - ACL: o.ACL, - Permissions: o.Permissions, - }, leaseAccessConditions, modifiedAccessConditions, nil -} - -// GetAccessControlOptions contains the optional parameters when calling the GetAccessControl operation. -type GetAccessControlOptions struct { - // UPN is the user principal name. - UPN *bool - // AccessConditions contains parameters for accessing the path. - AccessConditions *azdatalake.AccessConditions -} - -func (o *GetAccessControlOptions) format() (*generated.PathClientGetPropertiesOptions, *generated.LeaseAccessConditions, *generated.ModifiedAccessConditions, error) { - action := generated.PathGetPropertiesActionGetAccessControl - if o == nil { - return &generated.PathClientGetPropertiesOptions{ - Action: &action, - }, nil, nil, nil - } - // call path formatter since we're hitting dfs in this operation - leaseAccessConditions, modifiedAccessConditions := shared.FormatPathAccessConditions(o.AccessConditions) - return &generated.PathClientGetPropertiesOptions{ - Upn: o.UPN, - Action: &action, - }, leaseAccessConditions, modifiedAccessConditions, nil -} - -// 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 - // 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 -} - -// 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 -} - -func (o *UpdateAccessControlRecursiveOptions) format() (*generated.PathClientSetAccessControlRecursiveOptions, error) { - // TODO: design formatter - similar to SetAccessControlRecursiveOptions - return nil, nil -} - -// 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 -} - -// SetHTTPHeadersOptions contains the optional parameters for the Client.SetHTTPHeaders method. -type SetHTTPHeadersOptions struct { - AccessConditions *azdatalake.AccessConditions -} - -func (o *SetHTTPHeadersOptions) format() *blob.SetHTTPHeadersOptions { - if o == nil { - return nil - } - accessConditions := shared.FormatBlobAccessConditions(o.AccessConditions) - return &blob.SetHTTPHeadersOptions{ - AccessConditions: accessConditions, - } -} - -// HTTPHeaders contains the HTTP headers for path operations. -type HTTPHeaders struct { - // Optional. Sets the path's cache control. If specified, this property is stored with the path and returned with a read request. - CacheControl *string - // Optional. Sets the path's Content-Disposition header. - ContentDisposition *string - // Optional. Sets the path's content encoding. If specified, this property is stored with the blobpath and returned with a read - // request. - ContentEncoding *string - // Optional. Set the path's content language. If specified, this property is stored with the path and returned with a read - // request. - ContentLanguage *string - // Specify the transactional md5 for the body, to be validated by the service. - ContentMD5 []byte - // Optional. Sets the path's content type. If specified, this property is stored with the path and returned with a read request. - ContentType *string -} - -func (o *HTTPHeaders) formatBlobHTTPHeaders() (*blob.HTTPHeaders, error) { - if o == nil { - return nil, nil - } - opts := blob.HTTPHeaders{ - BlobCacheControl: o.CacheControl, - BlobContentDisposition: o.ContentDisposition, - BlobContentEncoding: o.ContentEncoding, - BlobContentLanguage: o.ContentLanguage, - BlobContentMD5: o.ContentMD5, - BlobContentType: o.ContentType, - } - return &opts, nil -} - -func (o *HTTPHeaders) formatPathHTTPHeaders() (*generated.PathHTTPHeaders, error) { - // TODO: will be used for file related ops, like append - if o == nil { - return nil, nil - } - opts := generated.PathHTTPHeaders{ - CacheControl: o.CacheControl, - ContentDisposition: o.ContentDisposition, - ContentEncoding: o.ContentEncoding, - ContentLanguage: o.ContentLanguage, - ContentMD5: o.ContentMD5, - ContentType: o.ContentType, - TransactionalContentHash: o.ContentMD5, - } - return &opts, nil -} - -// SetMetadataOptions provides set of configurations for Set Metadata on path operation -type SetMetadataOptions struct { - AccessConditions *azdatalake.AccessConditions - CPKInfo *CPKInfo - CPKScopeInfo *CPKScopeInfo -} - -func (o *SetMetadataOptions) format() *blob.SetMetadataOptions { - if o == nil { - return nil - } - accessConditions := shared.FormatBlobAccessConditions(o.AccessConditions) - return &blob.SetMetadataOptions{ - AccessConditions: accessConditions, - CPKInfo: &blob.CPKInfo{ - EncryptionKey: o.CPKInfo.EncryptionKey, - EncryptionAlgorithm: o.CPKInfo.EncryptionAlgorithm, - EncryptionKeySHA256: o.CPKInfo.EncryptionKeySHA256, - }, - CPKScopeInfo: &blob.CPKScopeInfo{ - EncryptionScope: o.CPKScopeInfo.EncryptionScope, - }, - } -} - -// CPKInfo contains a group of parameters for the PathClient.Download method. -type CPKInfo struct { - EncryptionAlgorithm *EncryptionAlgorithmType - EncryptionKey *string - EncryptionKeySHA256 *string -} - -// CPKScopeInfo contains a group of parameters for the PathClient.SetMetadata method. -type CPKScopeInfo struct { - EncryptionScope *string -} - -// SourceModifiedAccessConditions identifies the source path access conditions. -type SourceModifiedAccessConditions = generated.SourceModifiedAccessConditions diff --git a/sdk/storage/azdatalake/internal/path/responses.go b/sdk/storage/azdatalake/internal/path/responses.go deleted file mode 100644 index e61078ead210..000000000000 --- a/sdk/storage/azdatalake/internal/path/responses.go +++ /dev/null @@ -1,42 +0,0 @@ -//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 path - -import ( - "github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/blob" - "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/internal/generated" -) - -// CreateResponse contains the response fields for the Create operation. -type CreateResponse = generated.PathClientCreateResponse - -// DeleteResponse contains the response fields for the Delete operation. -type DeleteResponse = generated.PathClientDeleteResponse - -// SetAccessControlResponse contains the response fields for the SetAccessControl operation. -type SetAccessControlResponse = generated.PathClientSetAccessControlResponse - -// SetAccessControlRecursiveResponse contains the response fields for the SetAccessControlRecursive operation. -type SetAccessControlRecursiveResponse = generated.PathClientSetAccessControlRecursiveResponse - -// UpdateAccessControlRecursiveResponse contains the response fields for the UpdateAccessControlRecursive operation. -type UpdateAccessControlRecursiveResponse = generated.PathClientSetAccessControlRecursiveResponse - -// RemoveAccessControlRecursiveResponse contains the response fields for the RemoveAccessControlRecursive operation. -type RemoveAccessControlRecursiveResponse = generated.PathClientSetAccessControlRecursiveResponse - -// GetAccessControlResponse contains the response fields for the GetAccessControl operation. -type GetAccessControlResponse = generated.PathClientGetPropertiesResponse - -// GetPropertiesResponse contains the response fields for the GetProperties operation. -type GetPropertiesResponse = generated.PathClientGetPropertiesResponse - -// SetMetadataResponse contains the response fields for the SetMetadata operation. -type SetMetadataResponse = blob.SetMetadataResponse - -// SetHTTPHeadersResponse contains the response fields for the SetHTTPHeaders operation. -type SetHTTPHeadersResponse = blob.SetHTTPHeadersResponse diff --git a/sdk/storage/azdatalake/internal/shared/shared.go b/sdk/storage/azdatalake/internal/shared/shared.go index d94f84deb8a6..7fd977d8b059 100644 --- a/sdk/storage/azdatalake/internal/shared/shared.go +++ b/sdk/storage/azdatalake/internal/shared/shared.go @@ -24,6 +24,13 @@ const ( TokenScope = "https://storage.azure.com/.default" ) +const ( + ServiceClient = "azdatalake/service.Client" + FilesystemClient = "azdatalake/share.Client" + DirectoryClient = "azdatalake/directory.Client" + FileClient = "azdatalake/file.Client" +) + const ( HeaderAuthorization = "Authorization" HeaderXmsDate = "x-ms-date" diff --git a/sdk/storage/azdatalake/service/client.go b/sdk/storage/azdatalake/service/client.go index 5d887ffddd9d..eeac42200d11 100644 --- a/sdk/storage/azdatalake/service/client.go +++ b/sdk/storage/azdatalake/service/client.go @@ -9,46 +9,97 @@ package service import ( "context" "github.com/Azure/azure-sdk-for-go/sdk/azcore" + "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/azdatalake" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/blob" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/service" "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/filesystem" "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/shared" + "strings" ) -// Client represents a URL to the Azure Datalake Storage service. -type Client base.Client[generated.ServiceClient] +// ClientOptions contains the optional parameters when creating a Client. +type ClientOptions base.ClientOptions -// NewClient creates an instance of Client with the specified values. -// - serviceURL - the URL of the storage account e.g. https://.file.core.windows.net/ -// - cred - an Azure AD credential, typically obtained via the azidentity module -// - options - client options; pass nil to accept the default values -func NewClient(serviceURL string, cred azcore.TokenCredential, options *azdatalake.ClientOptions) (*Client, error) { - return nil, nil -} +// Client represents a URL to the Azure Datalake Storage service. +type Client base.CompositeClient[generated.ServiceClient, generated.ServiceClient, service.Client] // NewClientWithNoCredential creates an instance of Client with the specified values. -// This is used to anonymously access a storage account or with a shared access signature (SAS) token. -// - serviceURL - the URL of the storage account e.g. https://.file.core.windows.net/? -// - options - client options; pass nil to accept the default values -func NewClientWithNoCredential(serviceURL string, options *azdatalake.ClientOptions) (*Client, error) { - return nil, nil +// - serviceURL - the URL of the storage account e.g. https://.dfs.core.windows.net/ +// - options - client options; pass nil to accept the default values. +func NewClientWithNoCredential(serviceURL string, options *ClientOptions) (*Client, error) { + blobServiceURL := strings.Replace(serviceURL, ".dfs.", ".blob.", 1) + datalakeServiceURL := strings.Replace(serviceURL, ".blob.", ".dfs.", 1) + + conOptions := shared.GetClientOptions(options) + plOpts := runtime.PipelineOptions{} + base.SetPipelineOptions((*base.ClientOptions)(conOptions), &plOpts) + + azClient, err := azcore.NewClient(shared.ServiceClient, exported.ModuleVersion, plOpts, &conOptions.ClientOptions) + if err != nil { + return nil, err + } + + blobServiceClientOpts := service.ClientOptions{ + ClientOptions: options.ClientOptions, + } + blobSvcClient, _ := service.NewClientWithNoCredential(blobServiceURL, &blobServiceClientOpts) + svcClient := base.NewServiceClient(datalakeServiceURL, blobServiceURL, blobSvcClient, azClient, nil, (*base.ClientOptions)(conOptions)) + + return (*Client)(svcClient), nil } // NewClientWithSharedKeyCredential creates an instance of Client with the specified values. -// - serviceURL - the URL of the storage account e.g. https://.file.core.windows.net/ +// - serviceURL - the URL of the storage account e.g. https://.dfs.core.windows.net/ // - cred - a SharedKeyCredential created with the matching storage account and access key // - options - client options; pass nil to accept the default values -func NewClientWithSharedKeyCredential(serviceURL string, cred *SharedKeyCredential, options *azdatalake.ClientOptions) (*Client, error) { - return nil, nil +func NewClientWithSharedKeyCredential(serviceURL string, cred *SharedKeyCredential, options *ClientOptions) (*Client, error) { + blobServiceURL := strings.Replace(serviceURL, ".dfs.", ".blob.", 1) + datalakeServiceURL := strings.Replace(serviceURL, ".blob.", ".dfs.", 1) + + authPolicy := exported.NewSharedKeyCredPolicy(cred) + conOptions := shared.GetClientOptions(options) + plOpts := runtime.PipelineOptions{ + PerRetry: []policy.Policy{authPolicy}, + } + base.SetPipelineOptions((*base.ClientOptions)(conOptions), &plOpts) + + azClient, err := azcore.NewClient(shared.ServiceClient, exported.ModuleVersion, plOpts, &conOptions.ClientOptions) + if err != nil { + return nil, err + } + + blobServiceClientOpts := service.ClientOptions{ + ClientOptions: options.ClientOptions, + } + blobSharedKeyCredential, _ := blob.NewSharedKeyCredential(cred.AccountName(), cred.AccountKey()) + blobSvcClient, _ := service.NewClientWithSharedKeyCredential(blobServiceURL, blobSharedKeyCredential, &blobServiceClientOpts) + svcClient := base.NewServiceClient(datalakeServiceURL, blobServiceURL, blobSvcClient, azClient, cred, (*base.ClientOptions)(conOptions)) + + return (*Client)(svcClient), nil } // NewClientFromConnectionString creates an instance of Client with the specified values. // - connectionString - a connection string for the desired storage account // - options - client options; pass nil to accept the default values -func NewClientFromConnectionString(connectionString string, options *azdatalake.ClientOptions) (*Client, error) { - return nil, nil +func NewClientFromConnectionString(connectionString string, options *ClientOptions) (*Client, error) { + parsed, err := shared.ParseConnectionString(connectionString) + if err != nil { + return nil, err + } + + if parsed.AccountKey != "" && parsed.AccountName != "" { + credential, err := exported.NewSharedKeyCredential(parsed.AccountName, parsed.AccountKey) + if err != nil { + return nil, err + } + return NewClientWithSharedKeyCredential(parsed.ServiceURL, credential, options) + } + + return NewClientWithNoCredential(parsed.ServiceURL, options) } // NewFilesystemClient creates a new share.Client object by concatenating shareName to the end of this Client's URL. @@ -69,12 +120,23 @@ func (s *Client) NewFileClient(fileName string) *filesystem.Client { return nil } -func (s *Client) generated() *generated.ServiceClient { - return base.InnerClient((*base.Client[generated.ServiceClient])(s)) +func (s *Client) generatedFSClientWithDFS() *generated.ServiceClient { + svcClientWithDFS, _, _ := base.InnerClients((*base.CompositeClient[generated.ServiceClient, generated.ServiceClient, service.Client])(s)) + return svcClientWithDFS +} + +func (s *Client) generatedFSClientWithBlob() *generated.ServiceClient { + _, svcClientWithBlob, _ := base.InnerClients((*base.CompositeClient[generated.ServiceClient, generated.ServiceClient, service.Client])(s)) + return svcClientWithBlob +} + +func (s *Client) containerClient() *service.Client { + _, _, serviceClient := base.InnerClients((*base.CompositeClient[generated.ServiceClient, generated.ServiceClient, service.Client])(s)) + return serviceClient } func (s *Client) sharedKey() *exported.SharedKeyCredential { - return base.SharedKey((*base.Client[generated.ServiceClient])(s)) + return base.SharedKeyComposite((*base.CompositeClient[generated.ServiceClient, generated.ServiceClient, service.Client])(s)) } // URL returns the URL endpoint used by the Client object. From 6fe421ea3bdb09ec16aec0666360759f885cb893 Mon Sep 17 00:00:00 2001 From: Tamer Sherif <69483382+tasherif-msft@users.noreply.github.com> Date: Tue, 4 Jul 2023 10:20:49 -0700 Subject: [PATCH 06/16] [AzDatalake] Filesystem Client Implementation + Test Framework (#21067) * Enable gocritic during linting (#20715) Enabled gocritic's evalOrder to catch dependencies on undefined behavior on return statements. Updated to latest version of golangci-lint. Fixed issue in azblob flagged by latest linter. * Cosmos DB: Enable merge support (#20716) * Adding header and value * Wiring and tests * format * Fixing value * change log * [azservicebus, azeventhubs] Stress test and logging improvement (#20710) Logging improvements: * Updating the logging to print more tracing information (per-link) in prep for the bigger release coming up. * Trimming out some of the verbose logging, seeing if I can get it a bit more reasonable. Stress tests: * Add a timestamp to the log name we generate and also default to append, not overwrite. * Use 0.5 cores, 0.5GB as our baseline. Some pods use more and I'll tune them more later. * update proxy version (#20712) Co-authored-by: Scott Beddall * Return an error when you try to send a message that's too large. (#20721) This now works just like the message batch - you'll get an ErrMessageTooLarge if you attempt to send a message that's too large for the link's configured size. NOTE: there's a patch to `internal/go-amqp/Sender.go` to match what's in go-amqp's main so it returns a programmatically useful error when the message is too large. Fixes #20647 * Changes in test that is failing in pipeline (#20693) * [azservicebus, azeventhubs] Treat 'entity full' as a fatal error (#20722) When the remote entity is full we get a resource-limit-exceeded condition. This isn't something we should keep retrying on and it's best to just abort and let the user know immediately, rather than hoping it might eventually clear out. This affected both Event Hubs and Service Bus. Fixes #20647 * [azservicebus/azeventhubs] Redirect stderr and stdout to tee (#20726) * Update changelog with latest features (#20730) * Update changelog with latest features Prepare for upcoming release. * bump minor version * pass along the artifact name so we can override it later (#20732) Co-authored-by: scbedd <45376673+scbedd@users.noreply.github.com> * [azeventhubs] Fixing checkpoint store race condition (#20727) The checkpoint store wasn't guarding against multiple owners claiming for the first time - fixing this by using IfNoneMatch Fixes #20717 * Fix azidentity troubleshooting guide link (#20736) * [Release] sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/0.1.0 (#20437) * [Release] sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/0.1.0 generation from spec commit: 85fb4ac6f8bfefd179e6c2632976a154b5c9ff04 * client factory * fix * fix * update * add sdk/resourcemanager/postgresql/armpostgresql live test (#20685) * add sdk/resourcemanager/postgresql/armpostgresql live test * update assets.json * set subscriptionId default value * format * add sdk/resourcemanager/eventhub/armeventhub live test (#20686) * add sdk/resourcemanager/eventhub/armeventhub live test * update assets * add sdk/resourcemanager/compute/armcompute live test (#20048) * add sdk/resourcemanager/compute/armcompute live test * skus filter * fix subscriptionId default value * fix * gofmt * update recording * sdk/resourcemanager/network/armnetwork live test (#20331) * sdk/resourcemanager/network/armnetwork live test * update subscriptionId default value * update recording * add sdk/resourcemanager/cosmos/armcosmos live test (#20705) * add sdk/resourcemanager/cosmos/armcosmos live test * update assets.json * update assets.json * update assets.json * update assets.json * Increment package version after release of azcore (#20740) * [azeventhubs] Improperly resetting etag in the checkpoint store (#20737) We shouldn't be resetting the etag to nil - it's what we use to enforce a "single winner" when doing ownership claims. The bug here was two-fold: I had bad logic in my previous claim ownership, which I fixed in a previous PR, but we need to reflect that same constraint properly in our in-memory checkpoint store for these tests. * Eng workflows sync and branch cleanup additions (#20743) Co-authored-by: James Suplizio * [azeventhubs] Latest start position can also be inclusive (ie, get the latest message) (#20744) * Update GitHubEventProcessor version and remove pull_request_review procesing (#20751) Co-authored-by: James Suplizio * Rename DisableAuthorityValidationAndInstanceDiscovery (#20746) * fix (#20707) * AzFile (#20739) * azfile: Fixing connection string parsing logic (#20798) * Fixing connection string parse logic * Update README * [azadmin] fix flaky test (#20758) * fix flaky test * charles suggestion * Prepare azidentity v1.3.0 for release (#20756) * Fix broken podman link (#20801) Co-authored-by: Wes Haggard * [azquery] update doc comments (#20755) * update doc comments * update statistics and visualization generation * prep-for-release * Fixed contribution section (#20752) Co-authored-by: Bob Tabor * [azeventhubs,azservicebus] Some API cleanup, renames (#20754) * Adding options to UpdateCheckpoint(), just for future potential expansion * Make Offset an int64, not a *int64 (it's not optional, it'll always come back with ReceivedEvents) * Adding more logging into the checkpoint store. * Point all imports at the production go-amqp * Add supporting features to enable distributed tracing (#20301) (#20708) * Add supporting features to enable distributed tracing This includes new internal pipeline policies and other supporting types. See the changelog for a full description. Added some missing doc comments. * fix linter issue * add net.peer.name trace attribute sequence custom HTTP header policy before logging policy. sequence logging policy after HTTP trace policy. keep body download policy at the end. * add span for iterating over pages * Restore ARM CAE support for azcore beta (#20657) This reverts commit 902097226ff3fe2fc6c3e7fc50d3478350253614. * Upgrade to stable azcore (#20808) * Increment package version after release of data/azcosmos (#20807) * Updating changelog (#20810) * Add fake package to azcore (#20711) * Add fake package to azcore This is the supporting infrastructure for the generated SDK fakes. * fix doc comment * Updating CHANGELOG.md (#20809) * changelog (#20811) * Increment package version after release of storage/azfile (#20813) * Update changelog (azblob) (#20815) * Updating CHANGELOG.md * Update the changelog with correct version * [azquery] migration guide (#20742) * migration guide * Charles feedback * Richard feedback --------- Co-authored-by: Charles Lowell <10964656+chlowell@users.noreply.github.com> * Increment package version after release of monitor/azquery (#20820) * [keyvault] prep for release (#20819) * prep for release * perf tests * update date * added new client methods * moved access conditions and wrote first test * added more tests * added path listing * list deleted paths * fixed formatter and added more tests * added more tests * marker fix * log * fixed constructor validation * comment * assets update: --------- Co-authored-by: Joel Hendrix Co-authored-by: Matias Quaranta Co-authored-by: Richard Park <51494936+richardpark-msft@users.noreply.github.com> Co-authored-by: Azure SDK Bot <53356347+azure-sdk@users.noreply.github.com> Co-authored-by: Scott Beddall Co-authored-by: siminsavani-msft <77068571+siminsavani-msft@users.noreply.github.com> Co-authored-by: scbedd <45376673+scbedd@users.noreply.github.com> Co-authored-by: Charles Lowell <10964656+chlowell@users.noreply.github.com> Co-authored-by: Peng Jiahui <46921893+Alancere@users.noreply.github.com> Co-authored-by: James Suplizio Co-authored-by: Sourav Gupta <98318303+souravgupta-msft@users.noreply.github.com> Co-authored-by: gracewilcox <43627800+gracewilcox@users.noreply.github.com> Co-authored-by: Wes Haggard Co-authored-by: Bob Tabor Co-authored-by: Bob Tabor --- sdk/storage/azdatalake/assets.json | 6 + sdk/storage/azdatalake/common.go | 31 +- .../azdatalake/datalakeerror/error_codes.go | 181 +++ sdk/storage/azdatalake/directory/client.go | 62 +- sdk/storage/azdatalake/directory/models.go | 53 +- sdk/storage/azdatalake/directory/responses.go | 3 + sdk/storage/azdatalake/file/client.go | 62 +- sdk/storage/azdatalake/file/models.go | 53 +- sdk/storage/azdatalake/file/responses.go | 3 + sdk/storage/azdatalake/filesystem/client.go | 175 ++- .../azdatalake/filesystem/client_test.go | 1205 +++++++++++++++++ .../azdatalake/filesystem/constants.go | 43 + sdk/storage/azdatalake/filesystem/models.go | 116 +- .../azdatalake/filesystem/responses.go | 113 +- sdk/storage/azdatalake/go.mod | 10 +- sdk/storage/azdatalake/go.sum | 15 +- .../{shared => exported}/access_conditions.go | 51 +- .../azdatalake/internal/exported/path.go | 1 + .../internal/testcommon/clients_auth.go | 110 ++ .../azdatalake/internal/testcommon/common.go | 78 ++ .../azdatalake/lease/filesystem_client.go | 11 +- sdk/storage/azdatalake/lease/models.go | 31 +- sdk/storage/azdatalake/lease/path_client.go | 8 - sdk/storage/azdatalake/service/client.go | 55 +- 24 files changed, 2308 insertions(+), 168 deletions(-) create mode 100644 sdk/storage/azdatalake/assets.json create mode 100644 sdk/storage/azdatalake/datalakeerror/error_codes.go create mode 100644 sdk/storage/azdatalake/filesystem/client_test.go rename sdk/storage/azdatalake/internal/{shared => exported}/access_conditions.go (51%) create mode 100644 sdk/storage/azdatalake/internal/exported/path.go create mode 100644 sdk/storage/azdatalake/internal/testcommon/clients_auth.go create mode 100644 sdk/storage/azdatalake/internal/testcommon/common.go diff --git a/sdk/storage/azdatalake/assets.json b/sdk/storage/azdatalake/assets.json new file mode 100644 index 000000000000..cc6130dbb776 --- /dev/null +++ b/sdk/storage/azdatalake/assets.json @@ -0,0 +1,6 @@ +{ + "AssetsRepo": "Azure/azure-sdk-assets", + "AssetsRepoPrefixPath": "go", + "TagPrefix": "go/storage/azdatalake", + "Tag": "go/storage/azdatalake_e05ec93d89" +} \ No newline at end of file diff --git a/sdk/storage/azdatalake/common.go b/sdk/storage/azdatalake/common.go index fb79dcc0dc7a..fc67050f51ee 100644 --- a/sdk/storage/azdatalake/common.go +++ b/sdk/storage/azdatalake/common.go @@ -7,17 +7,30 @@ package azdatalake import ( - "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/internal/generated" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/internal/exported" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/sas" ) -// AccessConditions identifies container-specific access conditions which you optionally set. -type AccessConditions struct { - ModifiedAccessConditions *ModifiedAccessConditions - LeaseAccessConditions *LeaseAccessConditions +// SharedKeyCredential contains an account's name and its primary or secondary key. +type SharedKeyCredential = exported.SharedKeyCredential + +// NewSharedKeyCredential creates an immutable SharedKeyCredential containing the +// storage account's name and either its primary or secondary key. +func NewSharedKeyCredential(accountName, accountKey string) (*SharedKeyCredential, error) { + return exported.NewSharedKeyCredential(accountName, accountKey) } -// LeaseAccessConditions contains optional parameters to access leased entity. -type LeaseAccessConditions = generated.LeaseAccessConditions +// URLParts object represents the components that make up an Azure Storage Container/Blob URL. +// NOTE: Changing any SAS-related field requires computing a new SAS signature. +type URLParts = sas.URLParts + +// ParseURL parses a URL initializing URLParts' fields including any SAS-related & snapshot query parameters. Any other +// query parameters remain in the UnparsedParams field. This method overwrites all fields in the URLParts object. +func ParseURL(u string) (URLParts, error) { + return sas.ParseURL(u) +} -// ModifiedAccessConditions contains a group of parameters for specifying access conditions. -type ModifiedAccessConditions = generated.ModifiedAccessConditions +// 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 = exported.HTTPRange diff --git a/sdk/storage/azdatalake/datalakeerror/error_codes.go b/sdk/storage/azdatalake/datalakeerror/error_codes.go new file mode 100644 index 000000000000..2acc2e79fdc6 --- /dev/null +++ b/sdk/storage/azdatalake/datalakeerror/error_codes.go @@ -0,0 +1,181 @@ +//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 datalakeerror + +import ( + "errors" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/bloberror" + + "github.com/Azure/azure-sdk-for-go/sdk/azcore" +) + +// HasCode returns true if the provided error is an *azcore.ResponseError +// with its ErrorCode field equal to one of the specified Codes. +func HasCode(err error, codes ...Code) bool { + var respErr *azcore.ResponseError + if !errors.As(err, &respErr) { + return false + } + + for _, code := range codes { + if respErr.ErrorCode == string(code) { + return true + } + } + + return false +} + +type StorageErrorCode string + +// Code - Error codes returned by the service +type Code = bloberror.Code + +const ( + ContentLengthMustBeZero StorageErrorCode = "ContentLengthMustBeZero" + PathAlreadyExists StorageErrorCode = "PathAlreadyExists" + InvalidFlushPosition StorageErrorCode = "InvalidFlushPosition" + InvalidPropertyName StorageErrorCode = "InvalidPropertyName" + InvalidSourceURI StorageErrorCode = "InvalidSourceUri" + UnsupportedRestVersion StorageErrorCode = "UnsupportedRestVersion" + FileSystemNotFound StorageErrorCode = "FilesystemNotFound" + PathNotFound StorageErrorCode = "PathNotFound" + RenameDestinationParentPathNotFound StorageErrorCode = "RenameDestinationParentPathNotFound" + SourcePathNotFound StorageErrorCode = "SourcePathNotFound" + DestinationPathIsBeingDeleted StorageErrorCode = "DestinationPathIsBeingDeleted" + FileSystemAlreadyExists StorageErrorCode = "FilesystemAlreadyExists" + FileSystemBeingDeleted StorageErrorCode = "FilesystemBeingDeleted" + InvalidDestinationPath StorageErrorCode = "InvalidDestinationPath" + InvalidRenameSourcePath StorageErrorCode = "InvalidRenameSourcePath" + InvalidSourceOrDestinationResourceType StorageErrorCode = "InvalidSourceOrDestinationResourceType" + LeaseIsAlreadyBroken StorageErrorCode = "LeaseIsAlreadyBroken" + LeaseNameMismatch StorageErrorCode = "LeaseNameMismatch" + PathConflict StorageErrorCode = "PathConflict" + SourcePathIsBeingDeleted StorageErrorCode = "SourcePathIsBeingDeleted" +) + +const ( + AccountAlreadyExists Code = "AccountAlreadyExists" + AccountBeingCreated Code = "AccountBeingCreated" + AccountIsDisabled Code = "AccountIsDisabled" + AppendPositionConditionNotMet Code = "AppendPositionConditionNotMet" + AuthenticationFailed Code = "AuthenticationFailed" + AuthorizationFailure Code = "AuthorizationFailure" + AuthorizationPermissionMismatch Code = "AuthorizationPermissionMismatch" + AuthorizationProtocolMismatch Code = "AuthorizationProtocolMismatch" + AuthorizationResourceTypeMismatch Code = "AuthorizationResourceTypeMismatch" + AuthorizationServiceMismatch Code = "AuthorizationServiceMismatch" + AuthorizationSourceIPMismatch Code = "AuthorizationSourceIPMismatch" + BlobAlreadyExists Code = "BlobAlreadyExists" + PathArchived Code = "BlobArchived" + PathBeingRehydrated Code = "BlobBeingRehydrated" + PathImmutableDueToPolicy Code = "BlobImmutableDueToPolicy" + PathNotArchived Code = "BlobNotArchived" + BlobNotFound Code = "BlobNotFound" + PathOverwritten Code = "BlobOverwritten" + PathTierInadequateForContentLength Code = "BlobTierInadequateForContentLength" + PathUsesCustomerSpecifiedEncryption Code = "BlobUsesCustomerSpecifiedEncryption" + BlockCountExceedsLimit Code = "BlockCountExceedsLimit" + BlockListTooLong Code = "BlockListTooLong" + CannotChangeToLowerTier Code = "CannotChangeToLowerTier" + CannotVerifyCopySource Code = "CannotVerifyCopySource" + ConditionHeadersNotSupported Code = "ConditionHeadersNotSupported" + ConditionNotMet Code = "ConditionNotMet" + FilesystemAlreadyExists Code = "ContainerAlreadyExists" + ContainerBeingDeleted Code = "ContainerBeingDeleted" + ContainerDisabled Code = "ContainerDisabled" + ContainerNotFound Code = "ContainerNotFound" + ContentLengthLargerThanTierLimit Code = "ContentLengthLargerThanTierLimit" + CopyAcrossAccountsNotSupported Code = "CopyAcrossAccountsNotSupported" + CopyIDMismatch Code = "CopyIdMismatch" + EmptyMetadataKey Code = "EmptyMetadataKey" + FeatureVersionMismatch Code = "FeatureVersionMismatch" + IncrementalCopyPathMismatch Code = "IncrementalCopyBlobMismatch" + IncrementalCopyOfEralierVersionSnapshotNotAllowed Code = "IncrementalCopyOfEralierVersionSnapshotNotAllowed" + IncrementalCopySourceMustBeSnapshot Code = "IncrementalCopySourceMustBeSnapshot" + InfiniteLeaseDurationRequired Code = "InfiniteLeaseDurationRequired" + InsufficientAccountPermissions Code = "InsufficientAccountPermissions" + InternalError Code = "InternalError" + InvalidAuthenticationInfo Code = "InvalidAuthenticationInfo" + InvalidBlobOrBlock Code = "InvalidBlobOrBlock" + InvalidPathTier Code = "InvalidBlobTier" + InvalidPathType Code = "InvalidBlobType" + InvalidBlockID Code = "InvalidBlockId" + InvalidBlockList Code = "InvalidBlockList" + InvalidHTTPVerb Code = "InvalidHttpVerb" + InvalidHeaderValue Code = "InvalidHeaderValue" + InvalidInput Code = "InvalidInput" + InvalidMD5 Code = "InvalidMd5" + InvalidMetadata Code = "InvalidMetadata" + InvalidOperation Code = "InvalidOperation" + InvalidPageRange Code = "InvalidPageRange" + InvalidQueryParameterValue Code = "InvalidQueryParameterValue" + InvalidRange Code = "InvalidRange" + InvalidResourceName Code = "InvalidResourceName" + InvalidSourcePathType Code = "InvalidSourceBlobType" + InvalidSourcePathURL Code = "InvalidSourceBlobUrl" + InvalidURI Code = "InvalidUri" + InvalidVersionForPageBlobOperation Code = "InvalidVersionForPageBlobOperation" + InvalidXMLDocument Code = "InvalidXmlDocument" + InvalidXMLNodeValue Code = "InvalidXmlNodeValue" + LeaseAlreadyBroken Code = "LeaseAlreadyBroken" + LeaseAlreadyPresent Code = "LeaseAlreadyPresent" + LeaseIDMismatchWithBlobOperation Code = "LeaseIdMismatchWithBlobOperation" + LeaseIDMismatchWithContainerOperation Code = "LeaseIdMismatchWithContainerOperation" + LeaseIDMismatchWithLeaseOperation Code = "LeaseIdMismatchWithLeaseOperation" + LeaseIDMissing Code = "LeaseIdMissing" + LeaseIsBreakingAndCannotBeAcquired Code = "LeaseIsBreakingAndCannotBeAcquired" + LeaseIsBreakingAndCannotBeChanged Code = "LeaseIsBreakingAndCannotBeChanged" + LeaseIsBrokenAndCannotBeRenewed Code = "LeaseIsBrokenAndCannotBeRenewed" + LeaseLost Code = "LeaseLost" + LeaseNotPresentWithBlobOperation Code = "LeaseNotPresentWithBlobOperation" + LeaseNotPresentWithContainerOperation Code = "LeaseNotPresentWithContainerOperation" + LeaseNotPresentWithLeaseOperation Code = "LeaseNotPresentWithLeaseOperation" + MD5Mismatch Code = "Md5Mismatch" + CRC64Mismatch Code = "Crc64Mismatch" + MaxBlobSizeConditionNotMet Code = "MaxBlobSizeConditionNotMet" + MetadataTooLarge Code = "MetadataTooLarge" + MissingContentLengthHeader Code = "MissingContentLengthHeader" + MissingRequiredHeader Code = "MissingRequiredHeader" + MissingRequiredQueryParameter Code = "MissingRequiredQueryParameter" + MissingRequiredXMLNode Code = "MissingRequiredXmlNode" + MultipleConditionHeadersNotSupported Code = "MultipleConditionHeadersNotSupported" + NoAuthenticationInformation Code = "NoAuthenticationInformation" + NoPendingCopyOperation Code = "NoPendingCopyOperation" + OperationNotAllowedOnIncrementalCopyBlob Code = "OperationNotAllowedOnIncrementalCopyBlob" + OperationTimedOut Code = "OperationTimedOut" + OutOfRangeInput Code = "OutOfRangeInput" + OutOfRangeQueryParameterValue Code = "OutOfRangeQueryParameterValue" + PendingCopyOperation Code = "PendingCopyOperation" + PreviousSnapshotCannotBeNewer Code = "PreviousSnapshotCannotBeNewer" + PreviousSnapshotNotFound Code = "PreviousSnapshotNotFound" + PreviousSnapshotOperationNotSupported Code = "PreviousSnapshotOperationNotSupported" + RequestBodyTooLarge Code = "RequestBodyTooLarge" + RequestURLFailedToParse Code = "RequestUrlFailedToParse" + ResourceAlreadyExists Code = "ResourceAlreadyExists" + ResourceNotFound Code = "ResourceNotFound" + ResourceTypeMismatch Code = "ResourceTypeMismatch" + SequenceNumberConditionNotMet Code = "SequenceNumberConditionNotMet" + SequenceNumberIncrementTooLarge Code = "SequenceNumberIncrementTooLarge" + ServerBusy Code = "ServerBusy" + SnapshotCountExceeded Code = "SnapshotCountExceeded" + SnapshotOperationRateExceeded Code = "SnapshotOperationRateExceeded" + SnapshotsPresent Code = "SnapshotsPresent" + SourceConditionNotMet Code = "SourceConditionNotMet" + SystemInUse Code = "SystemInUse" + TargetConditionNotMet Code = "TargetConditionNotMet" + UnauthorizedBlobOverwrite Code = "UnauthorizedBlobOverwrite" + UnsupportedHTTPVerb Code = "UnsupportedHttpVerb" + UnsupportedHeader Code = "UnsupportedHeader" + UnsupportedQueryParameter Code = "UnsupportedQueryParameter" + UnsupportedXMLNode Code = "UnsupportedXmlNode" +) + +var ( + // MissingSharedKeyCredential - Error is returned when SAS URL is being created without SharedKeyCredential. + MissingSharedKeyCredential = bloberror.MissingSharedKeyCredential +) diff --git a/sdk/storage/azdatalake/directory/client.go b/sdk/storage/azdatalake/directory/client.go index 6aaf8bf63138..1cdb330d3d0e 100644 --- a/sdk/storage/azdatalake/directory/client.go +++ b/sdk/storage/azdatalake/directory/client.go @@ -25,11 +25,41 @@ type ClientOptions base.ClientOptions // Client represents a URL to the Azure Datalake Storage service. type Client base.CompositeClient[generated.PathClient, generated.PathClient, blob.Client] -//TODO: NewClient() +// NewClient creates an instance of Client with the specified values. +// - directoryURL - the URL of the directory e.g. https://.dfs.core.windows.net/fs/dir +// - cred - an Azure AD credential, typically obtained via the azidentity module +// - options - client options; pass nil to accept the default values +func NewClient(directoryURL string, cred azcore.TokenCredential, options *ClientOptions) (*Client, error) { + blobURL := strings.Replace(directoryURL, ".dfs.", ".blob.", 1) + directoryURL = strings.Replace(directoryURL, ".blob.", ".dfs.", 1) + + authPolicy := shared.NewStorageChallengePolicy(cred) + conOptions := shared.GetClientOptions(options) + plOpts := runtime.PipelineOptions{ + PerRetry: []policy.Policy{authPolicy}, + } + base.SetPipelineOptions((*base.ClientOptions)(conOptions), &plOpts) + + azClient, err := azcore.NewClient(shared.FileClient, exported.ModuleVersion, plOpts, &conOptions.ClientOptions) + if err != nil { + return nil, err + } + + if options == nil { + options = &ClientOptions{} + } + blobClientOpts := blob.ClientOptions{ + ClientOptions: options.ClientOptions, + } + blobClient, _ := blob.NewClient(blobURL, cred, &blobClientOpts) + dirClient := base.NewPathClient(directoryURL, blobURL, blobClient, azClient, nil, (*base.ClientOptions)(conOptions)) + + return (*Client)(dirClient), nil +} // NewClientWithNoCredential creates an instance of Client with the specified values. // This is used to anonymously access a storage account or with a shared access signature (SAS) token. -// - serviceURL - the URL of the storage account e.g. https://.dfs.core.windows.net/? +// - directoryURL - the URL of the storage account e.g. https://.dfs.core.windows.net/fs/dir? // - options - client options; pass nil to accept the default values func NewClientWithNoCredential(directoryURL string, options *ClientOptions) (*Client, error) { blobURL := strings.Replace(directoryURL, ".dfs.", ".blob.", 1) @@ -44,6 +74,9 @@ func NewClientWithNoCredential(directoryURL string, options *ClientOptions) (*Cl return nil, err } + if options == nil { + options = &ClientOptions{} + } blobClientOpts := blob.ClientOptions{ ClientOptions: options.ClientOptions, } @@ -54,7 +87,7 @@ func NewClientWithNoCredential(directoryURL string, options *ClientOptions) (*Cl } // NewClientWithSharedKeyCredential creates an instance of Client with the specified values. -// - serviceURL - the URL of the storage account e.g. https://.dfs.core.windows.net/ +// - directoryURL - the URL of the storage account e.g. https://.dfs.core.windows.net/fs/dir // - cred - a SharedKeyCredential created with the matching storage account and access key // - options - client options; pass nil to accept the default values func NewClientWithSharedKeyCredential(directoryURL string, cred *SharedKeyCredential, options *ClientOptions) (*Client, error) { @@ -73,6 +106,9 @@ func NewClientWithSharedKeyCredential(directoryURL string, cred *SharedKeyCreden return nil, err } + if options == nil { + options = &ClientOptions{} + } blobClientOpts := blob.ClientOptions{ ClientOptions: options.ClientOptions, } @@ -103,13 +139,13 @@ func NewClientFromConnectionString(connectionString string, options *ClientOptio return NewClientWithNoCredential(parsed.ServiceURL, options) } -func (d *Client) generatedFSClientWithDFS() *generated.PathClient { +func (d *Client) generatedDirClientWithDFS() *generated.PathClient { //base.SharedKeyComposite((*base.CompositeClient[generated.BlobClient, generated.BlockBlobClient])(bb)) dirClientWithDFS, _, _ := base.InnerClients((*base.CompositeClient[generated.PathClient, generated.PathClient, blob.Client])(d)) return dirClientWithDFS } -func (d *Client) generatedFSClientWithBlob() *generated.PathClient { +func (d *Client) generatedDirClientWithBlob() *generated.PathClient { _, dirClientWithBlob, _ := base.InnerClients((*base.CompositeClient[generated.PathClient, generated.PathClient, blob.Client])(d)) return dirClientWithBlob } @@ -123,9 +159,14 @@ func (d *Client) sharedKey() *exported.SharedKeyCredential { return base.SharedKeyComposite((*base.CompositeClient[generated.PathClient, generated.PathClient, blob.Client])(d)) } -// URL returns the URL endpoint used by the Client object. -func (d *Client) URL() string { - return "s.generated().Endpoint()" +// DFSURL returns the URL endpoint used by the Client object. +func (d *Client) DFSURL() string { + return d.generatedDirClientWithDFS().Endpoint() +} + +// BlobURL returns the URL endpoint used by the Client object. +func (d *Client) BlobURL() string { + return d.generatedDirClientWithBlob().Endpoint() } // Create creates a new directory (dfs1). @@ -190,3 +231,8 @@ func (d *Client) SetHTTPHeaders(ctx context.Context, httpHeaders HTTPHeaders, op // TODO: call into blob return SetHTTPHeadersResponse{}, nil } + +// UndeletePath restores the specified path that was previously deleted. (dfs op/blob2). +func (d *Client) UndeletePath(ctx context.Context, path string, options *UndeletePathOptions) (UndeletePathResponse, error) { + return UndeletePathResponse{}, nil +} diff --git a/sdk/storage/azdatalake/directory/models.go b/sdk/storage/azdatalake/directory/models.go index e349e0478da8..d8ad23d234f9 100644 --- a/sdk/storage/azdatalake/directory/models.go +++ b/sdk/storage/azdatalake/directory/models.go @@ -8,17 +8,15 @@ package directory import ( "github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/blob" - "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake" "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/shared" "time" ) // CreateOptions contains the optional parameters when calling the Create operation. dfs endpoint type CreateOptions struct { // AccessConditions contains parameters for accessing the file. - AccessConditions *azdatalake.AccessConditions + AccessConditions *AccessConditions // Metadata is a map of name-value pairs to associate with the file storage object. Metadata map[string]*string // CPKInfo contains a group of parameters for client provided encryption key. @@ -44,7 +42,7 @@ type CreateOptions struct { 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 - leaseAccessConditions, modifiedAccessConditions := shared.FormatPathAccessConditions(o.AccessConditions) + leaseAccessConditions, modifiedAccessConditions := exported.FormatPathAccessConditions(o.AccessConditions) httpHeaders := &generated.PathHTTPHeaders{ CacheControl: o.HTTPHeaders.CacheControl, ContentDisposition: o.HTTPHeaders.ContentDisposition, @@ -60,11 +58,11 @@ func (o *CreateOptions) format() (*generated.LeaseAccessConditions, *generated.M // DeleteOptions contains the optional parameters when calling the Delete operation. dfs endpoint type DeleteOptions struct { // AccessConditions specifies parameters for accessing the directory - AccessConditions *azdatalake.AccessConditions + AccessConditions *AccessConditions } func (o *DeleteOptions) format() (*generated.LeaseAccessConditions, *generated.ModifiedAccessConditions, error) { - leaseAccessConditions, modifiedAccessConditions := shared.FormatPathAccessConditions(o.AccessConditions) + leaseAccessConditions, modifiedAccessConditions := exported.FormatPathAccessConditions(o.AccessConditions) return leaseAccessConditions, modifiedAccessConditions, nil } @@ -72,12 +70,12 @@ type RenameOptions struct { // SourceModifiedAccessConditions specifies parameters for accessing the source directory SourceModifiedAccessConditions *SourceModifiedAccessConditions // AccessConditions specifies parameters for accessing the destination directory - AccessConditions *azdatalake.AccessConditions + AccessConditions *AccessConditions } // GetPropertiesOptions contains the optional parameters for the Client.GetProperties method type GetPropertiesOptions struct { - AccessConditions *azdatalake.AccessConditions + AccessConditions *AccessConditions CPKInfo *CPKInfo } @@ -85,7 +83,7 @@ func (o *GetPropertiesOptions) format() *blob.GetPropertiesOptions { if o == nil { return nil } - accessConditions := shared.FormatBlobAccessConditions(o.AccessConditions) + accessConditions := exported.FormatBlobAccessConditions(o.AccessConditions) return &blob.GetPropertiesOptions{ AccessConditions: accessConditions, CPKInfo: &blob.CPKInfo{ @@ -109,7 +107,7 @@ type SetAccessControlOptions struct { // Permissions is the octal representation of the permissions for user, group and mask. Permissions *string // AccessConditions contains parameters for accessing the path. - AccessConditions *azdatalake.AccessConditions + AccessConditions *AccessConditions } func (o *SetAccessControlOptions) format() (*generated.PathClientSetAccessControlOptions, *generated.LeaseAccessConditions, *generated.ModifiedAccessConditions, error) { @@ -117,7 +115,7 @@ func (o *SetAccessControlOptions) format() (*generated.PathClientSetAccessContro return nil, nil, nil, nil } // call path formatter since we're hitting dfs in this operation - leaseAccessConditions, modifiedAccessConditions := shared.FormatPathAccessConditions(o.AccessConditions) + leaseAccessConditions, modifiedAccessConditions := exported.FormatPathAccessConditions(o.AccessConditions) return &generated.PathClientSetAccessControlOptions{ Owner: o.Owner, Group: o.Group, @@ -131,7 +129,7 @@ type GetAccessControlOptions struct { // UPN is the user principal name. UPN *bool // AccessConditions contains parameters for accessing the path. - AccessConditions *azdatalake.AccessConditions + AccessConditions *AccessConditions } func (o *GetAccessControlOptions) format() (*generated.PathClientGetPropertiesOptions, *generated.LeaseAccessConditions, *generated.ModifiedAccessConditions, error) { @@ -142,7 +140,7 @@ func (o *GetAccessControlOptions) format() (*generated.PathClientGetPropertiesOp }, nil, nil, nil } // call path formatter since we're hitting dfs in this operation - leaseAccessConditions, modifiedAccessConditions := shared.FormatPathAccessConditions(o.AccessConditions) + leaseAccessConditions, modifiedAccessConditions := exported.FormatPathAccessConditions(o.AccessConditions) return &generated.PathClientGetPropertiesOptions{ Upn: o.UPN, Action: &action, @@ -208,14 +206,14 @@ func (o *RemoveAccessControlRecursiveOptions) format() (*generated.PathClientSet // SetHTTPHeadersOptions contains the optional parameters for the Client.SetHTTPHeaders method. type SetHTTPHeadersOptions struct { - AccessConditions *azdatalake.AccessConditions + AccessConditions *AccessConditions } func (o *SetHTTPHeadersOptions) format() *blob.SetHTTPHeadersOptions { if o == nil { return nil } - accessConditions := shared.FormatBlobAccessConditions(o.AccessConditions) + accessConditions := exported.FormatBlobAccessConditions(o.AccessConditions) return &blob.SetHTTPHeadersOptions{ AccessConditions: accessConditions, } @@ -273,7 +271,7 @@ func (o *HTTPHeaders) formatPathHTTPHeaders() (*generated.PathHTTPHeaders, error // SetMetadataOptions provides set of configurations for Set Metadata on path operation type SetMetadataOptions struct { - AccessConditions *azdatalake.AccessConditions + AccessConditions *AccessConditions CPKInfo *CPKInfo CPKScopeInfo *CPKScopeInfo } @@ -282,7 +280,7 @@ func (o *SetMetadataOptions) format() *blob.SetMetadataOptions { if o == nil { return nil } - accessConditions := shared.FormatBlobAccessConditions(o.AccessConditions) + accessConditions := exported.FormatBlobAccessConditions(o.AccessConditions) return &blob.SetMetadataOptions{ AccessConditions: accessConditions, CPKInfo: &blob.CPKInfo{ @@ -308,8 +306,29 @@ type CPKScopeInfo struct { EncryptionScope *string } +// UndeletePathOptions contains the optional parameters for the Filesystem.UndeletePath operation. +type UndeletePathOptions struct { + // placeholder +} + +func (o *UndeletePathOptions) format() *UndeletePathOptions { + if o == nil { + return nil + } + return &UndeletePathOptions{} +} + // SourceModifiedAccessConditions identifies the source path access conditions. type SourceModifiedAccessConditions = generated.SourceModifiedAccessConditions // SharedKeyCredential contains an account's name and its primary or secondary key. type SharedKeyCredential = exported.SharedKeyCredential + +// AccessConditions identifies blob-specific access conditions which you optionally set. +type AccessConditions = exported.AccessConditions + +// LeaseAccessConditions contains optional parameters to access leased entity. +type LeaseAccessConditions = exported.LeaseAccessConditions + +// ModifiedAccessConditions contains a group of parameters for specifying access conditions. +type ModifiedAccessConditions = exported.ModifiedAccessConditions diff --git a/sdk/storage/azdatalake/directory/responses.go b/sdk/storage/azdatalake/directory/responses.go index 3327f41360ce..6a4f34714df9 100644 --- a/sdk/storage/azdatalake/directory/responses.go +++ b/sdk/storage/azdatalake/directory/responses.go @@ -43,3 +43,6 @@ type SetMetadataResponse = blob.SetMetadataResponse // SetHTTPHeadersResponse contains the response fields for the SetHTTPHeaders operation. type SetHTTPHeadersResponse = blob.SetHTTPHeadersResponse + +// UndeletePathResponse contains the response from method FilesystemClient.UndeletePath. +type UndeletePathResponse = generated.PathClientUndeleteResponse diff --git a/sdk/storage/azdatalake/file/client.go b/sdk/storage/azdatalake/file/client.go index f76101a3c5b3..f6fd6f09e6b3 100644 --- a/sdk/storage/azdatalake/file/client.go +++ b/sdk/storage/azdatalake/file/client.go @@ -25,11 +25,41 @@ type ClientOptions base.ClientOptions // Client represents a URL to the Azure Datalake Storage service. type Client base.CompositeClient[generated.PathClient, generated.PathClient, blob.Client] -//TODO: NewClient() +// NewClient creates an instance of Client with the specified values. +// - fileURL - the URL of the blob e.g. https://.dfs.core.windows.net/fs/file.txt +// - cred - an Azure AD credential, typically obtained via the azidentity module +// - options - client options; pass nil to accept the default values +func NewClient(fileURL string, cred azcore.TokenCredential, options *ClientOptions) (*Client, error) { + blobURL := strings.Replace(fileURL, ".dfs.", ".blob.", 1) + fileURL = strings.Replace(fileURL, ".blob.", ".dfs.", 1) + + authPolicy := shared.NewStorageChallengePolicy(cred) + conOptions := shared.GetClientOptions(options) + plOpts := runtime.PipelineOptions{ + PerRetry: []policy.Policy{authPolicy}, + } + base.SetPipelineOptions((*base.ClientOptions)(conOptions), &plOpts) + + azClient, err := azcore.NewClient(shared.FileClient, exported.ModuleVersion, plOpts, &conOptions.ClientOptions) + if err != nil { + return nil, err + } + + if options == nil { + options = &ClientOptions{} + } + blobClientOpts := blob.ClientOptions{ + ClientOptions: options.ClientOptions, + } + blobClient, _ := blob.NewClient(blobURL, cred, &blobClientOpts) + fileClient := base.NewPathClient(fileURL, blobURL, blobClient, azClient, nil, (*base.ClientOptions)(conOptions)) + + return (*Client)(fileClient), nil +} // NewClientWithNoCredential creates an instance of Client with the specified values. // This is used to anonymously access a storage account or with a shared access signature (SAS) token. -// - serviceURL - the URL of the storage account e.g. https://.dfs.core.windows.net/? +// - fileURL - the URL of the storage account e.g. https://.dfs.core.windows.net/fs/file.txt? // - options - client options; pass nil to accept the default values func NewClientWithNoCredential(fileURL string, options *ClientOptions) (*Client, error) { blobURL := strings.Replace(fileURL, ".dfs.", ".blob.", 1) @@ -44,6 +74,9 @@ func NewClientWithNoCredential(fileURL string, options *ClientOptions) (*Client, return nil, err } + if options == nil { + options = &ClientOptions{} + } blobClientOpts := blob.ClientOptions{ ClientOptions: options.ClientOptions, } @@ -54,7 +87,7 @@ func NewClientWithNoCredential(fileURL string, options *ClientOptions) (*Client, } // NewClientWithSharedKeyCredential creates an instance of Client with the specified values. -// - serviceURL - the URL of the storage account e.g. https://.dfs.core.windows.net/ +// - fileURL - the URL of the storage account e.g. https://.dfs.core.windows.net/fs/file.txt // - cred - a SharedKeyCredential created with the matching storage account and access key // - options - client options; pass nil to accept the default values func NewClientWithSharedKeyCredential(fileURL string, cred *SharedKeyCredential, options *ClientOptions) (*Client, error) { @@ -73,6 +106,9 @@ func NewClientWithSharedKeyCredential(fileURL string, cred *SharedKeyCredential, return nil, err } + if options == nil { + options = &ClientOptions{} + } blobClientOpts := blob.ClientOptions{ ClientOptions: options.ClientOptions, } @@ -103,13 +139,13 @@ func NewClientFromConnectionString(connectionString string, options *ClientOptio return NewClientWithNoCredential(parsed.ServiceURL, options) } -func (f *Client) generatedFSClientWithDFS() *generated.PathClient { +func (f *Client) generatedFileClientWithDFS() *generated.PathClient { //base.SharedKeyComposite((*base.CompositeClient[generated.BlobClient, generated.BlockBlobClient])(bb)) dirClientWithDFS, _, _ := base.InnerClients((*base.CompositeClient[generated.PathClient, generated.PathClient, blob.Client])(f)) return dirClientWithDFS } -func (f *Client) generatedFSClientWithBlob() *generated.PathClient { +func (f *Client) generatedFileClientWithBlob() *generated.PathClient { _, dirClientWithBlob, _ := base.InnerClients((*base.CompositeClient[generated.PathClient, generated.PathClient, blob.Client])(f)) return dirClientWithBlob } @@ -123,9 +159,14 @@ func (f *Client) sharedKey() *exported.SharedKeyCredential { return base.SharedKeyComposite((*base.CompositeClient[generated.PathClient, generated.PathClient, blob.Client])(f)) } -// URL returns the URL endpoint used by the Client object. -func (f *Client) URL() string { - return "s.generated().Endpoint()" +// DFSURL returns the URL endpoint used by the Client object. +func (f *Client) DFSURL() string { + return f.generatedFileClientWithDFS().Endpoint() +} + +// BlobURL returns the URL endpoint used by the Client object. +func (f *Client) BlobURL() string { + return f.generatedFileClientWithBlob().Endpoint() } // Create creates a new file (dfs1). @@ -218,3 +259,8 @@ func (f *Client) SetHTTPHeaders(ctx context.Context, httpHeaders HTTPHeaders, op // TODO: call into blob return SetHTTPHeadersResponse{}, nil } + +// UndeletePath restores the specified path that was previously deleted. (dfs op/blob2). +func (f *Client) UndeletePath(ctx context.Context, path string, options *UndeletePathOptions) (UndeletePathResponse, error) { + return UndeletePathResponse{}, nil +} diff --git a/sdk/storage/azdatalake/file/models.go b/sdk/storage/azdatalake/file/models.go index 18551b86a14d..d05d0953d430 100644 --- a/sdk/storage/azdatalake/file/models.go +++ b/sdk/storage/azdatalake/file/models.go @@ -8,17 +8,15 @@ package file import ( "github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/blob" - "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake" "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/shared" "time" ) // CreateOptions contains the optional parameters when calling the Create operation. dfs endpoint. TODO: Design formatter type CreateOptions struct { // AccessConditions contains parameters for accessing the file. - AccessConditions *azdatalake.AccessConditions + AccessConditions *AccessConditions // Metadata is a map of name-value pairs to associate with the file storage object. Metadata map[string]*string // CPKInfo contains a group of parameters for client provided encryption key. @@ -46,7 +44,7 @@ type CreateOptions struct { 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 - leaseAccessConditions, modifiedAccessConditions := shared.FormatPathAccessConditions(o.AccessConditions) + leaseAccessConditions, modifiedAccessConditions := exported.FormatPathAccessConditions(o.AccessConditions) httpHeaders := &generated.PathHTTPHeaders{ CacheControl: o.HTTPHeaders.CacheControl, ContentDisposition: o.HTTPHeaders.ContentDisposition, @@ -62,11 +60,11 @@ func (o *CreateOptions) format() (*generated.LeaseAccessConditions, *generated.M // DeleteOptions contains the optional parameters when calling the Delete operation. dfs endpoint type DeleteOptions struct { // AccessConditions contains parameters for accessing the file. - AccessConditions *azdatalake.AccessConditions + AccessConditions *AccessConditions } func (o *DeleteOptions) format() (*generated.LeaseAccessConditions, *generated.ModifiedAccessConditions, error) { - leaseAccessConditions, modifiedAccessConditions := shared.FormatPathAccessConditions(o.AccessConditions) + leaseAccessConditions, modifiedAccessConditions := exported.FormatPathAccessConditions(o.AccessConditions) return leaseAccessConditions, modifiedAccessConditions, nil } @@ -75,12 +73,12 @@ type RenameOptions struct { // SourceModifiedAccessConditions identifies the source path access conditions. SourceModifiedAccessConditions *SourceModifiedAccessConditions // AccessConditions contains parameters for accessing the file. - AccessConditions *azdatalake.AccessConditions + AccessConditions *AccessConditions } // GetPropertiesOptions contains the optional parameters for the Client.GetProperties method type GetPropertiesOptions struct { - AccessConditions *azdatalake.AccessConditions + AccessConditions *AccessConditions CPKInfo *CPKInfo } @@ -88,7 +86,7 @@ func (o *GetPropertiesOptions) format() *blob.GetPropertiesOptions { if o == nil { return nil } - accessConditions := shared.FormatBlobAccessConditions(o.AccessConditions) + accessConditions := exported.FormatBlobAccessConditions(o.AccessConditions) return &blob.GetPropertiesOptions{ AccessConditions: accessConditions, CPKInfo: &blob.CPKInfo{ @@ -111,7 +109,7 @@ type SetAccessControlOptions struct { // Permissions is the octal representation of the permissions for user, group and mask. Permissions *string // AccessConditions contains parameters for accessing the path. - AccessConditions *azdatalake.AccessConditions + AccessConditions *AccessConditions } func (o *SetAccessControlOptions) format() (*generated.PathClientSetAccessControlOptions, *generated.LeaseAccessConditions, *generated.ModifiedAccessConditions, error) { @@ -119,7 +117,7 @@ func (o *SetAccessControlOptions) format() (*generated.PathClientSetAccessContro return nil, nil, nil, nil } // call path formatter since we're hitting dfs in this operation - leaseAccessConditions, modifiedAccessConditions := shared.FormatPathAccessConditions(o.AccessConditions) + leaseAccessConditions, modifiedAccessConditions := exported.FormatPathAccessConditions(o.AccessConditions) return &generated.PathClientSetAccessControlOptions{ Owner: o.Owner, Group: o.Group, @@ -133,7 +131,7 @@ type GetAccessControlOptions struct { // UPN is the user principal name. UPN *bool // AccessConditions contains parameters for accessing the path. - AccessConditions *azdatalake.AccessConditions + AccessConditions *AccessConditions } func (o *GetAccessControlOptions) format() (*generated.PathClientGetPropertiesOptions, *generated.LeaseAccessConditions, *generated.ModifiedAccessConditions, error) { @@ -144,7 +142,7 @@ func (o *GetAccessControlOptions) format() (*generated.PathClientGetPropertiesOp }, nil, nil, nil } // call path formatter since we're hitting dfs in this operation - leaseAccessConditions, modifiedAccessConditions := shared.FormatPathAccessConditions(o.AccessConditions) + leaseAccessConditions, modifiedAccessConditions := exported.FormatPathAccessConditions(o.AccessConditions) return &generated.PathClientGetPropertiesOptions{ Upn: o.UPN, Action: &action, @@ -210,14 +208,14 @@ func (o *RemoveAccessControlRecursiveOptions) format() (*generated.PathClientSet // SetHTTPHeadersOptions contains the optional parameters for the Client.SetHTTPHeaders method. type SetHTTPHeadersOptions struct { - AccessConditions *azdatalake.AccessConditions + AccessConditions *AccessConditions } func (o *SetHTTPHeadersOptions) format() *blob.SetHTTPHeadersOptions { if o == nil { return nil } - accessConditions := shared.FormatBlobAccessConditions(o.AccessConditions) + accessConditions := exported.FormatBlobAccessConditions(o.AccessConditions) return &blob.SetHTTPHeadersOptions{ AccessConditions: accessConditions, } @@ -275,7 +273,7 @@ func (o *HTTPHeaders) formatPathHTTPHeaders() (*generated.PathHTTPHeaders, error // SetMetadataOptions provides set of configurations for Set Metadata on path operation type SetMetadataOptions struct { - AccessConditions *azdatalake.AccessConditions + AccessConditions *AccessConditions CPKInfo *CPKInfo CPKScopeInfo *CPKScopeInfo } @@ -284,7 +282,7 @@ func (o *SetMetadataOptions) format() *blob.SetMetadataOptions { if o == nil { return nil } - accessConditions := shared.FormatBlobAccessConditions(o.AccessConditions) + accessConditions := exported.FormatBlobAccessConditions(o.AccessConditions) return &blob.SetMetadataOptions{ AccessConditions: accessConditions, CPKInfo: &blob.CPKInfo{ @@ -310,6 +308,18 @@ type CPKScopeInfo struct { EncryptionScope *string } +// UndeletePathOptions contains the optional parameters for the Filesystem.UndeletePath operation. +type UndeletePathOptions struct { + // placeholder +} + +func (o *UndeletePathOptions) format() *UndeletePathOptions { + if o == nil { + return nil + } + return &UndeletePathOptions{} +} + // SourceModifiedAccessConditions identifies the source path access conditions. type SourceModifiedAccessConditions = generated.SourceModifiedAccessConditions @@ -333,3 +343,12 @@ type ExpiryTypeNever = exported.ExpiryTypeNever // SetExpiryOptions contains the optional parameters for the Client.SetExpiry method. type SetExpiryOptions = exported.SetExpiryOptions + +// AccessConditions identifies blob-specific access conditions which you optionally set. +type AccessConditions = exported.AccessConditions + +// LeaseAccessConditions contains optional parameters to access leased entity. +type LeaseAccessConditions = exported.LeaseAccessConditions + +// ModifiedAccessConditions contains a group of parameters for specifying access conditions. +type ModifiedAccessConditions = exported.ModifiedAccessConditions diff --git a/sdk/storage/azdatalake/file/responses.go b/sdk/storage/azdatalake/file/responses.go index e7ace65c52ee..9222c5c042c3 100644 --- a/sdk/storage/azdatalake/file/responses.go +++ b/sdk/storage/azdatalake/file/responses.go @@ -46,3 +46,6 @@ type SetHTTPHeadersResponse = blob.SetHTTPHeadersResponse // RenameResponse contains the response fields for the Create operation. type RenameResponse = generated.PathClientCreateResponse + +// UndeletePathResponse contains the response from method FilesystemClient.UndeletePath. +type UndeletePathResponse = generated.PathClientUndeleteResponse diff --git a/sdk/storage/azdatalake/filesystem/client.go b/sdk/storage/azdatalake/filesystem/client.go index 06f76dd537c7..151ca389efea 100644 --- a/sdk/storage/azdatalake/filesystem/client.go +++ b/sdk/storage/azdatalake/filesystem/client.go @@ -13,11 +13,16 @@ import ( "github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime" "github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/blob" "github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/container" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake" + "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/shared" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/sas" + "net/http" "strings" + "time" ) // ClientOptions contains the optional parameters when creating a Client. @@ -26,11 +31,41 @@ type ClientOptions base.ClientOptions // Client represents a URL to the Azure Datalake Storage service. type Client base.CompositeClient[generated.FileSystemClient, generated.FileSystemClient, container.Client] -//TODO: NewClient() +// NewClient creates an instance of Client with the specified values. +// - filesystemURL - the URL of the blob e.g. https://.dfs.core.windows.net/fs +// - cred - an Azure AD credential, typically obtained via the azidentity module +// - options - client options; pass nil to accept the default values +func NewClient(filesystemURL string, cred azcore.TokenCredential, options *ClientOptions) (*Client, error) { + containerURL := strings.Replace(filesystemURL, ".dfs.", ".blob.", 1) + filesystemURL = strings.Replace(filesystemURL, ".blob.", ".dfs.", 1) + + authPolicy := shared.NewStorageChallengePolicy(cred) + conOptions := shared.GetClientOptions(options) + plOpts := runtime.PipelineOptions{ + PerRetry: []policy.Policy{authPolicy}, + } + base.SetPipelineOptions((*base.ClientOptions)(conOptions), &plOpts) + + azClient, err := azcore.NewClient(shared.FilesystemClient, exported.ModuleVersion, plOpts, &conOptions.ClientOptions) + if err != nil { + return nil, err + } + + if options == nil { + options = &ClientOptions{} + } + containerClientOpts := container.ClientOptions{ + ClientOptions: options.ClientOptions, + } + blobContainerClient, _ := container.NewClient(containerURL, cred, &containerClientOpts) + fsClient := base.NewFilesystemClient(filesystemURL, containerURL, blobContainerClient, azClient, nil, (*base.ClientOptions)(conOptions)) + + return (*Client)(fsClient), nil +} // NewClientWithNoCredential creates an instance of Client with the specified values. // This is used to anonymously access a storage account or with a shared access signature (SAS) token. -// - serviceURL - the URL of the storage account e.g. https://.dfs.core.windows.net/? +// - filesystemURL - the URL of the storage account e.g. https://.dfs.core.windows.net/fs? // - options - client options; pass nil to accept the default values func NewClientWithNoCredential(filesystemURL string, options *ClientOptions) (*Client, error) { containerURL := strings.Replace(filesystemURL, ".dfs.", ".blob.", 1) @@ -45,6 +80,9 @@ func NewClientWithNoCredential(filesystemURL string, options *ClientOptions) (*C return nil, err } + if options == nil { + options = &ClientOptions{} + } containerClientOpts := container.ClientOptions{ ClientOptions: options.ClientOptions, } @@ -55,7 +93,7 @@ func NewClientWithNoCredential(filesystemURL string, options *ClientOptions) (*C } // NewClientWithSharedKeyCredential creates an instance of Client with the specified values. -// - serviceURL - the URL of the storage account e.g. https://.dfs.core.windows.net/ +// - filesystemURL - the URL of the storage account e.g. https://.dfs.core.windows.net/fs // - cred - a SharedKeyCredential created with the matching storage account and access key // - options - client options; pass nil to accept the default values func NewClientWithSharedKeyCredential(filesystemURL string, cred *SharedKeyCredential, options *ClientOptions) (*Client, error) { @@ -74,6 +112,9 @@ func NewClientWithSharedKeyCredential(filesystemURL string, cred *SharedKeyCrede return nil, err } + if options == nil { + options = &ClientOptions{} + } containerClientOpts := container.ClientOptions{ ClientOptions: options.ClientOptions, } @@ -124,58 +165,150 @@ func (fs *Client) sharedKey() *exported.SharedKeyCredential { return base.SharedKeyComposite((*base.CompositeClient[generated.FileSystemClient, generated.FileSystemClient, container.Client])(fs)) } -// URL returns the URL endpoint used by the Client object. -func (fs *Client) URL() string { - return "s.generated().Endpoint()" +// DFSURL returns the URL endpoint used by the Client object. +func (fs *Client) DFSURL() string { + return fs.generatedFSClientWithDFS().Endpoint() +} + +// BlobURL returns the URL endpoint used by the Client object. +func (fs *Client) BlobURL() string { + return fs.generatedFSClientWithBlob().Endpoint() } // Create creates a new filesystem under the specified account. (blob3). func (fs *Client) Create(ctx context.Context, options *CreateOptions) (CreateResponse, error) { - return CreateResponse{}, nil + opts := options.format() + return fs.containerClient().Create(ctx, opts) } // Delete deletes the specified filesystem and any files or directories it contains. (blob3). func (fs *Client) Delete(ctx context.Context, options *DeleteOptions) (DeleteResponse, error) { - return DeleteResponse{}, nil + opts := options.format() + return fs.containerClient().Delete(ctx, opts) } // GetProperties returns all user-defined metadata, standard HTTP properties, and system properties for the filesystem. (blob3). func (fs *Client) GetProperties(ctx context.Context, options *GetPropertiesOptions) (GetPropertiesResponse, error) { - // TODO: format blob response to fs response - return GetPropertiesResponse{}, nil + opts := options.format() + newResp := GetPropertiesResponse{} + resp, err := fs.containerClient().GetProperties(ctx, opts) + // TODO: find a cleaner way to not use lease from blob package + formatFilesystemProperties(&newResp, &resp) + return newResp, err } // SetMetadata sets one or more user-defined name-value pairs for the specified filesystem. (blob3). func (fs *Client) SetMetadata(ctx context.Context, options *SetMetadataOptions) (SetMetadataResponse, error) { - return SetMetadataResponse{}, nil + opts := options.format() + return fs.containerClient().SetMetadata(ctx, opts) } // SetAccessPolicy sets the permissions for the specified filesystem or the files and directories under it. (blob3). func (fs *Client) SetAccessPolicy(ctx context.Context, options *SetAccessPolicyOptions) (SetAccessPolicyResponse, error) { - return SetAccessPolicyResponse{}, nil + opts := options.format() + return fs.containerClient().SetAccessPolicy(ctx, opts) } // GetAccessPolicy returns the permissions for the specified filesystem or the files and directories under it. (blob3). func (fs *Client) GetAccessPolicy(ctx context.Context, options *GetAccessPolicyOptions) (GetAccessPolicyResponse, error) { - return GetAccessPolicyResponse{}, nil + opts := options.format() + newResp := GetAccessPolicyResponse{} + resp, err := fs.containerClient().GetAccessPolicy(ctx, opts) + formatGetAccessPolicyResponse(&newResp, &resp) + return newResp, err } -// UndeletePath restores the specified path that was previously deleted. (dfs op/blob2). -func (fs *Client) UndeletePath(ctx context.Context, path string, options *UndeletePathOptions) (UndeletePathResponse, error) { - return UndeletePathResponse{}, nil -} +// TODO: implement undelete path in fs client as well // NewListPathsPager operation returns a pager of the shares under the specified account. (dfs1) // For more information, see https://learn.microsoft.com/en-us/rest/api/storageservices/list-shares func (fs *Client) NewListPathsPager(recursive bool, options *ListPathsOptions) *runtime.Pager[ListPathsSegmentResponse] { //TODO: look into possibility of using blob endpoint like list deleted paths is - //TODO: will use ListPathsCreateRequest - return nil + listOptions := options.format() + return runtime.NewPager(runtime.PagingHandler[ListPathsSegmentResponse]{ + More: func(page ListPathsSegmentResponse) bool { + return page.Continuation != nil && len(*page.Continuation) > 0 + }, + Fetcher: func(ctx context.Context, page *ListPathsSegmentResponse) (ListPathsSegmentResponse, error) { + var req *policy.Request + var err error + if page == nil { + req, err = fs.generatedFSClientWithDFS().ListPathsCreateRequest(ctx, recursive, &listOptions) + } else { + listOptions.Continuation = page.Continuation + req, err = fs.generatedFSClientWithDFS().ListPathsCreateRequest(ctx, recursive, &listOptions) + } + if err != nil { + return ListPathsSegmentResponse{}, err + } + resp, err := fs.generatedFSClientWithDFS().InternalClient().Pipeline().Do(req) + if err != nil { + return ListPathsSegmentResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusOK) { + return ListPathsSegmentResponse{}, runtime.NewResponseError(resp) + } + return fs.generatedFSClientWithDFS().ListPathsHandleResponse(resp) + }, + }) } // NewListDeletedPathsPager operation returns a pager of the shares under the specified account. (dfs op/blob2). // For more information, see https://learn.microsoft.com/en-us/rest/api/storageservices/list-shares func (fs *Client) NewListDeletedPathsPager(options *ListDeletedPathsOptions) *runtime.Pager[ListDeletedPathsSegmentResponse] { - //TODO: will use ListBlobHierarchySegmentCreateRequest - return nil + listOptions := options.format() + return runtime.NewPager(runtime.PagingHandler[ListDeletedPathsSegmentResponse]{ + More: func(page ListDeletedPathsSegmentResponse) bool { + return page.NextMarker != nil && len(*page.NextMarker) > 0 + }, + Fetcher: func(ctx context.Context, page *ListDeletedPathsSegmentResponse) (ListDeletedPathsSegmentResponse, error) { + var req *policy.Request + var err error + if page == nil { + req, err = fs.generatedFSClientWithDFS().ListBlobHierarchySegmentCreateRequest(ctx, &listOptions) + } else { + listOptions.Marker = page.NextMarker + req, err = fs.generatedFSClientWithDFS().ListBlobHierarchySegmentCreateRequest(ctx, &listOptions) + } + if err != nil { + return ListDeletedPathsSegmentResponse{}, err + } + resp, err := fs.generatedFSClientWithDFS().InternalClient().Pipeline().Do(req) + if err != nil { + return ListDeletedPathsSegmentResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusOK) { + return ListDeletedPathsSegmentResponse{}, runtime.NewResponseError(resp) + } + return fs.generatedFSClientWithDFS().ListBlobHierarchySegmentHandleResponse(resp) + }, + }) +} + +// GetSASURL is a convenience method for generating a SAS token for the currently pointed at container. +// It can only be used if the credential supplied during creation was a SharedKeyCredential. +func (fs *Client) GetSASURL(permissions sas.FilesystemPermissions, expiry time.Time, o *GetSASURLOptions) (string, error) { + if fs.sharedKey() == nil { + return "", datalakeerror.MissingSharedKeyCredential + } + st := o.format() + urlParts, err := azdatalake.ParseURL(fs.BlobURL()) + if err != nil { + return "", err + } + qps, err := sas.DatalakeSignatureValues{ + Version: sas.Version, + Protocol: sas.ProtocolHTTPS, + FilesystemName: urlParts.FilesystemName, + Permissions: permissions.String(), + StartTime: st, + ExpiryTime: expiry.UTC(), + }.SignWithSharedKey(fs.sharedKey()) + if err != nil { + return "", err + } + + endpoint := fs.BlobURL() + "?" + qps.Encode() + + return endpoint, nil } diff --git a/sdk/storage/azdatalake/filesystem/client_test.go b/sdk/storage/azdatalake/filesystem/client_test.go new file mode 100644 index 000000000000..fa78bef404ad --- /dev/null +++ b/sdk/storage/azdatalake/filesystem/client_test.go @@ -0,0 +1,1205 @@ +//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 filesystem_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/filesystem" + "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" + "strconv" + "strings" + "testing" + "time" +) + +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 validateFilesystemDeleted(_require *require.Assertions, filesystemClient *filesystem.Client) { + _, err := filesystemClient.GetAccessPolicy(context.Background(), nil) + _require.NotNil(err) + + testcommon.ValidateBlobErrorCode(_require, err, datalakeerror.ContainerNotFound) +} + +func (s *RecordedTestSuite) TestCreateFilesystem() { + _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) +} + +func (s *RecordedTestSuite) TestCreateFilesystemWithOptions() { + _require := require.New(s.T()) + testName := s.T().Name() + + filesystemName := testcommon.GenerateFilesystemName(testName) + testStr := "hello" + metadata := map[string]*string{"foo": &testStr, "bar": &testStr} + access := filesystem.Filesystem + opts := filesystem.CreateOptions{ + Metadata: metadata, + Access: &access, + } + 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(), &opts) + _require.Nil(err) + + props, err := fsClient.GetProperties(context.Background(), nil) + _require.NotNil(props.Metadata) + _require.Equal(*props.PublicAccess, filesystem.Filesystem) +} + +func (s *RecordedTestSuite) TestCreateFilesystemWithFileAccess() { + _require := require.New(s.T()) + testName := s.T().Name() + + filesystemName := testcommon.GenerateFilesystemName(testName) + testStr := "hello" + metadata := map[string]*string{"foo": &testStr, "bar": &testStr} + access := filesystem.File + opts := filesystem.CreateOptions{ + Metadata: metadata, + Access: &access, + } + 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(), &opts) + _require.Nil(err) + props, err := fsClient.GetProperties(context.Background(), nil) + _require.NotNil(props.Metadata) + _require.Equal(*props.PublicAccess, filesystem.File) +} + +func (s *RecordedTestSuite) TestCreateFilesystemEmptyMetadata() { + _require := require.New(s.T()) + testName := s.T().Name() + + filesystemName := testcommon.GenerateFilesystemName(testName) + metadata := map[string]*string{"foo": nil, "bar": nil} + access := filesystem.Filesystem + opts := filesystem.CreateOptions{ + Metadata: metadata, + Access: &access, + } + 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(), &opts) + _require.Nil(err) + + props, err := fsClient.GetProperties(context.Background(), nil) + _require.Nil(props.Metadata) + _require.Equal(*props.PublicAccess, filesystem.Filesystem) + +} + +func (s *RecordedTestSuite) TestFilesystemCreateInvalidName() { + _require := require.New(s.T()) + + fsClient, err := testcommon.GetFilesystemClient("foo bar", s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + _, err = fsClient.Create(context.Background(), nil) + _require.NotNil(err) + testcommon.ValidateBlobErrorCode(_require, err, datalakeerror.InvalidResourceName) +} + +func (s *RecordedTestSuite) TestFilesystemCreateNameCollision() { + _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) + + _, err = fsClient.Create(context.Background(), nil) + _require.NotNil(err) + testcommon.ValidateBlobErrorCode(_require, err, datalakeerror.FilesystemAlreadyExists) +} + +func (s *RecordedTestSuite) TestFilesystemGetProperties() { + _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) + + resp, err := fsClient.GetProperties(context.Background(), nil) + _require.Nil(err) + _require.NotNil(resp.ETag) + _require.Nil(resp.Metadata) +} + +func (s *RecordedTestSuite) TestFilesystemDelete() { + _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) + + _, err = fsClient.Create(context.Background(), nil) + _require.Nil(err) + + _, err = fsClient.Delete(context.Background(), nil) + _require.Nil(err) + + validateFilesystemDeleted(_require, fsClient) +} + +func (s *RecordedTestSuite) TestFilesystemDeleteNonExistent() { + _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) + + _, err = fsClient.Delete(context.Background(), nil) + _require.NotNil(err) + + testcommon.ValidateBlobErrorCode(_require, err, datalakeerror.ContainerNotFound) +} + +func (s *RecordedTestSuite) TestFilesystemDeleteIfModifiedSinceTrue() { + _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) + + resp, err := fsClient.Create(context.Background(), nil) + _require.Nil(err) + + currentTime := testcommon.GetRelativeTimeFromAnchor(resp.Date, -10) + + deleteFilesystemOptions := filesystem.DeleteOptions{ + AccessConditions: &filesystem.AccessConditions{ + ModifiedAccessConditions: &filesystem.ModifiedAccessConditions{ + IfModifiedSince: ¤tTime, + }, + }, + } + _, err = fsClient.Delete(context.Background(), &deleteFilesystemOptions) + _require.Nil(err) + validateFilesystemDeleted(_require, fsClient) +} + +func (s *RecordedTestSuite) TestFilesystemDeleteIfModifiedSinceFalse() { + _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) + + resp, err := fsClient.Create(context.Background(), nil) + _require.Nil(err) + defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + + currentTime := testcommon.GetRelativeTimeFromAnchor(resp.Date, 10) + + deleteFilesystemOptions := filesystem.DeleteOptions{ + AccessConditions: &filesystem.AccessConditions{ + ModifiedAccessConditions: &filesystem.ModifiedAccessConditions{ + IfModifiedSince: ¤tTime, + }, + }, + } + _, err = fsClient.Delete(context.Background(), &deleteFilesystemOptions) + _require.NotNil(err) + testcommon.ValidateBlobErrorCode(_require, err, datalakeerror.ConditionNotMet) +} + +func (s *RecordedTestSuite) TestFilesystemDeleteIfUnModifiedSinceTrue() { + _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) + + resp, err := fsClient.Create(context.Background(), nil) + _require.Nil(err) + + currentTime := testcommon.GetRelativeTimeFromAnchor(resp.Date, 10) + + deleteFilesystemOptions := filesystem.DeleteOptions{ + AccessConditions: &filesystem.AccessConditions{ + ModifiedAccessConditions: &filesystem.ModifiedAccessConditions{ + IfUnmodifiedSince: ¤tTime, + }, + }, + } + _, err = fsClient.Delete(context.Background(), &deleteFilesystemOptions) + _require.Nil(err) + + validateFilesystemDeleted(_require, fsClient) +} + +func (s *RecordedTestSuite) TestFilesystemDeleteIfUnModifiedSinceFalse() { + _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) + + resp, err := fsClient.Create(context.Background(), nil) + _require.Nil(err) + defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + + currentTime := testcommon.GetRelativeTimeFromAnchor(resp.Date, -10) + + deleteFilesystemOptions := filesystem.DeleteOptions{ + AccessConditions: &filesystem.AccessConditions{ + ModifiedAccessConditions: &filesystem.ModifiedAccessConditions{ + IfUnmodifiedSince: ¤tTime, + }, + }, + } + _, err = fsClient.Delete(context.Background(), &deleteFilesystemOptions) + _require.NotNil(err) + + testcommon.ValidateBlobErrorCode(_require, err, datalakeerror.ConditionNotMet) +} + +func (s *RecordedTestSuite) TestFilesystemSetMetadataNonEmpty() { + _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) + + _, err = fsClient.Create(context.Background(), nil) + _require.Nil(err) + defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + + opts := filesystem.SetMetadataOptions{ + Metadata: testcommon.BasicMetadata, + } + _, err = fsClient.SetMetadata(context.Background(), &opts) + _require.Nil(err) + + resp1, err := fsClient.GetProperties(context.Background(), nil) + _require.Nil(err) + + for k, v := range testcommon.BasicMetadata { + _require.Equal(v, resp1.Metadata[k]) + } +} + +func (s *RecordedTestSuite) TestFilesystemSetMetadataEmpty() { + _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) + + _, err = fsClient.Create(context.Background(), nil) + _require.Nil(err) + defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + + opts := filesystem.SetMetadataOptions{ + Metadata: map[string]*string{}, + } + + _, err = fsClient.SetMetadata(context.Background(), &opts) + _require.Nil(err) + + resp1, err := fsClient.GetProperties(context.Background(), nil) + _require.Nil(err) + _require.Nil(resp1.Metadata) +} + +func (s *RecordedTestSuite) TestFilesystemSetMetadataNil() { + _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) + + _, err = fsClient.Create(context.Background(), nil) + _require.Nil(err) + defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + + _, err = fsClient.SetMetadata(context.Background(), nil) + _require.Nil(err) + + resp1, err := fsClient.GetProperties(context.Background(), nil) + _require.Nil(err) + _require.Nil(resp1.Metadata) +} + +func (s *RecordedTestSuite) TestFilesystemSetMetadataInvalidField() { + _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) + + _, err = fsClient.Create(context.Background(), nil) + _require.Nil(err) + defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + + opts := filesystem.SetMetadataOptions{ + Metadata: map[string]*string{"!nval!d Field!@#%": to.Ptr("value")}, + } + _, err = fsClient.SetMetadata(context.Background(), &opts) + _require.NotNil(err) + _require.Equal(strings.Contains(err.Error(), testcommon.InvalidHeaderErrorSubstring), true) +} + +func (s *RecordedTestSuite) TestFilesystemSetMetadataNonExistent() { + _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) + + _, err = fsClient.SetMetadata(context.Background(), nil) + _require.NotNil(err) + + testcommon.ValidateBlobErrorCode(_require, err, datalakeerror.ContainerNotFound) +} + +func (s *RecordedTestSuite) TestSetEmptyAccessPolicy() { + _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) + + _, err = fsClient.Create(context.Background(), nil) + _require.Nil(err) + defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + + _, err = fsClient.SetAccessPolicy(context.Background(), &filesystem.SetAccessPolicyOptions{}) + _require.Nil(err) +} + +func (s *RecordedTestSuite) TestSetNilAccessPolicy() { + _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) + + _, err = fsClient.Create(context.Background(), nil) + _require.Nil(err) + defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + + _, err = fsClient.SetAccessPolicy(context.Background(), nil) + _require.Nil(err) +} + +func (s *RecordedTestSuite) TestSetAccessPolicy() { + _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) + + _, err = fsClient.Create(context.Background(), nil) + _require.Nil(err) + defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + + start := time.Date(2020, 1, 1, 0, 0, 0, 0, time.UTC) + expiration := time.Date(2024, 1, 1, 0, 0, 0, 0, time.UTC) + permission := "r" + id := "1" + + signedIdentifiers := make([]*filesystem.SignedIdentifier, 0) + + signedIdentifiers = append(signedIdentifiers, &filesystem.SignedIdentifier{ + AccessPolicy: &filesystem.AccessPolicy{ + Expiry: &expiration, + Start: &start, + Permission: &permission, + }, + ID: &id, + }) + options := filesystem.SetAccessPolicyOptions{FilesystemACL: signedIdentifiers} + _, err = fsClient.SetAccessPolicy(context.Background(), &options) + _require.Nil(err) +} + +func (s *RecordedTestSuite) TestSetMultipleAccessPolicies() { + _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) + + _, err = fsClient.Create(context.Background(), nil) + _require.Nil(err) + defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + + id := "empty" + + signedIdentifiers := make([]*filesystem.SignedIdentifier, 0) + signedIdentifiers = append(signedIdentifiers, &filesystem.SignedIdentifier{ + ID: &id, + }) + + permission2 := "r" + id2 := "partial" + + signedIdentifiers = append(signedIdentifiers, &filesystem.SignedIdentifier{ + ID: &id2, + AccessPolicy: &filesystem.AccessPolicy{ + Permission: &permission2, + }, + }) + + id3 := "full" + permission3 := "r" + start := time.Date(2021, 6, 8, 2, 10, 9, 0, time.UTC) + expiry := time.Date(2021, 6, 8, 2, 10, 9, 0, time.UTC) + + signedIdentifiers = append(signedIdentifiers, &filesystem.SignedIdentifier{ + ID: &id3, + AccessPolicy: &filesystem.AccessPolicy{ + Start: &start, + Expiry: &expiry, + Permission: &permission3, + }, + }) + options := filesystem.SetAccessPolicyOptions{FilesystemACL: signedIdentifiers} + _, err = fsClient.SetAccessPolicy(context.Background(), &options) + _require.Nil(err) + + // Make a Get to assert two access policies + resp, err := fsClient.GetAccessPolicy(context.Background(), nil) + _require.Nil(err) + _require.Len(resp.SignedIdentifiers, 3) +} + +func (s *RecordedTestSuite) TestSetNullAccessPolicy() { + _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) + + _, err = fsClient.Create(context.Background(), nil) + _require.Nil(err) + defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + + id := "null" + + signedIdentifiers := make([]*filesystem.SignedIdentifier, 0) + signedIdentifiers = append(signedIdentifiers, &filesystem.SignedIdentifier{ + ID: &id, + }) + options := filesystem.SetAccessPolicyOptions{FilesystemACL: signedIdentifiers} + _, err = fsClient.SetAccessPolicy(context.Background(), &options) + _require.Nil(err) + + resp, err := fsClient.GetAccessPolicy(context.Background(), nil) + _require.Nil(err) + _require.Equal(len(resp.SignedIdentifiers), 1) +} + +func (s *RecordedTestSuite) TestFilesystemGetSetPermissionsMultiplePolicies() { + _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) + + _, err = fsClient.Create(context.Background(), nil) + _require.Nil(err) + defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + + // Define the policies + start, err := time.Parse(time.UnixDate, "Fri Jun 11 20:00:00 UTC 2021") + _require.Nil(err) + expiry := start.Add(5 * time.Minute) + expiry2 := start.Add(time.Minute) + readWrite := to.Ptr(filesystem.AccessPolicyPermission{Read: true, Write: true}).String() + readOnly := to.Ptr(filesystem.AccessPolicyPermission{Read: true}).String() + id1, id2 := "0000", "0001" + permissions := []*filesystem.SignedIdentifier{ + {ID: &id1, + AccessPolicy: &filesystem.AccessPolicy{ + Start: &start, + Expiry: &expiry, + Permission: &readWrite, + }, + }, + {ID: &id2, + AccessPolicy: &filesystem.AccessPolicy{ + Start: &start, + Expiry: &expiry2, + Permission: &readOnly, + }, + }, + } + options := filesystem.SetAccessPolicyOptions{FilesystemACL: permissions} + _, err = fsClient.SetAccessPolicy(context.Background(), &options) + + _require.Nil(err) + + resp, err := fsClient.GetAccessPolicy(context.Background(), nil) + _require.Nil(err) + _require.EqualValues(resp.SignedIdentifiers, permissions) +} + +func (s *RecordedTestSuite) TestFilesystemGetPermissionsPublicAccessNotNone() { + _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) + + access := filesystem.File + createContainerOptions := filesystem.CreateOptions{ + Access: &access, + } + _, err = fsClient.Create(context.Background(), &createContainerOptions) // We create the container explicitly so we can be sure the access policy is not empty + _require.Nil(err) + defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + + resp, err := fsClient.GetAccessPolicy(context.Background(), nil) + + _require.Nil(err) + _require.Equal(*resp.PublicAccess, filesystem.File) +} + +// TODO: TestFilesystemSetPermissionsPublicAccessNone() + +func (s *RecordedTestSuite) TestFilesystemSetPermissionsPublicAccessTypeFile() { + _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) + + _, err = fsClient.Create(context.Background(), nil) + _require.Nil(err) + defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + setAccessPolicyOptions := filesystem.SetAccessPolicyOptions{ + Access: to.Ptr(filesystem.File), + } + _, err = fsClient.SetAccessPolicy(context.Background(), &setAccessPolicyOptions) + _require.Nil(err) + + resp, err := fsClient.GetAccessPolicy(context.Background(), nil) + _require.Nil(err) + _require.Equal(*resp.PublicAccess, filesystem.File) +} + +func (s *RecordedTestSuite) TestFilesystemSetPermissionsPublicAccessFilesystem() { + _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) + + _, err = fsClient.Create(context.Background(), nil) + _require.Nil(err) + defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + + setAccessPolicyOptions := filesystem.SetAccessPolicyOptions{ + Access: to.Ptr(filesystem.Filesystem), + } + _, err = fsClient.SetAccessPolicy(context.Background(), &setAccessPolicyOptions) + _require.Nil(err) + + resp, err := fsClient.GetAccessPolicy(context.Background(), nil) + _require.Nil(err) + _require.Equal(*resp.PublicAccess, filesystem.Filesystem) +} + +func (s *RecordedTestSuite) TestFilesystemSetPermissionsACLMoreThanFive() { + _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) + + _, err = fsClient.Create(context.Background(), nil) + _require.Nil(err) + defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + + start, err := time.Parse(time.UnixDate, "Fri Jun 11 20:00:00 UTC 2021") + _require.Nil(err) + expiry, err := time.Parse(time.UnixDate, "Fri Jun 11 20:00:00 UTC 2049") + _require.Nil(err) + permissions := make([]*filesystem.SignedIdentifier, 6) + listOnly := to.Ptr(filesystem.AccessPolicyPermission{Read: true}).String() + for i := 0; i < 6; i++ { + id := "000" + strconv.Itoa(i) + permissions[i] = &filesystem.SignedIdentifier{ + ID: &id, + AccessPolicy: &filesystem.AccessPolicy{ + Start: &start, + Expiry: &expiry, + Permission: &listOnly, + }, + } + } + + access := filesystem.File + setAccessPolicyOptions := filesystem.SetAccessPolicyOptions{ + Access: &access, + } + setAccessPolicyOptions.FilesystemACL = permissions + _, err = fsClient.SetAccessPolicy(context.Background(), &setAccessPolicyOptions) + _require.NotNil(err) + + testcommon.ValidateBlobErrorCode(_require, err, datalakeerror.InvalidXMLDocument) +} + +func (s *RecordedTestSuite) TestFilesystemSetPermissionsDeleteAndModifyACL() { + _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) + + _, err = fsClient.Create(context.Background(), nil) + _require.Nil(err) + defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + + start, err := time.Parse(time.UnixDate, "Fri Jun 11 20:00:00 UTC 2021") + _require.Nil(err) + expiry, err := time.Parse(time.UnixDate, "Fri Jun 11 20:00:00 UTC 2049") + _require.Nil(err) + listOnly := to.Ptr(filesystem.AccessPolicyPermission{Read: true}).String() + permissions := make([]*filesystem.SignedIdentifier, 2) + for i := 0; i < 2; i++ { + id := "000" + strconv.Itoa(i) + permissions[i] = &filesystem.SignedIdentifier{ + ID: &id, + AccessPolicy: &filesystem.AccessPolicy{ + Start: &start, + Expiry: &expiry, + Permission: &listOnly, + }, + } + } + + access := filesystem.File + setAccessPolicyOptions := filesystem.SetAccessPolicyOptions{ + Access: &access, + } + setAccessPolicyOptions.FilesystemACL = permissions + _, err = fsClient.SetAccessPolicy(context.Background(), &setAccessPolicyOptions) + _require.Nil(err) + + resp, err := fsClient.GetAccessPolicy(context.Background(), nil) + _require.Nil(err) + _require.EqualValues(resp.SignedIdentifiers, permissions) + + permissions = resp.SignedIdentifiers[:1] // Delete the first policy by removing it from the slice + newId := "0004" + permissions[0].ID = &newId // Modify the remaining policy which is at index 0 in the new slice + setAccessPolicyOptions1 := filesystem.SetAccessPolicyOptions{ + Access: &access, + } + setAccessPolicyOptions1.FilesystemACL = permissions + _, err = fsClient.SetAccessPolicy(context.Background(), &setAccessPolicyOptions1) + _require.Nil(err) + + resp, err = fsClient.GetAccessPolicy(context.Background(), nil) + _require.Nil(err) + _require.Len(resp.SignedIdentifiers, 1) + _require.EqualValues(resp.SignedIdentifiers, permissions) +} + +func (s *RecordedTestSuite) TestFilesystemSetPermissionsDeleteAllPolicies() { + _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) + + _, err = fsClient.Create(context.Background(), nil) + _require.Nil(err) + defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + + start, err := time.Parse(time.UnixDate, "Fri Jun 11 20:00:00 UTC 2021") + _require.Nil(err) + expiry, err := time.Parse(time.UnixDate, "Fri Jun 11 20:00:00 UTC 2049") + _require.Nil(err) + permissions := make([]*filesystem.SignedIdentifier, 2) + listOnly := to.Ptr(filesystem.AccessPolicyPermission{Read: true}).String() + for i := 0; i < 2; i++ { + id := "000" + strconv.Itoa(i) + permissions[i] = &filesystem.SignedIdentifier{ + ID: &id, + AccessPolicy: &filesystem.AccessPolicy{ + Start: &start, + Expiry: &expiry, + Permission: &listOnly, + }, + } + } + + setAccessPolicyOptions := filesystem.SetAccessPolicyOptions{ + Access: to.Ptr(filesystem.File), + } + setAccessPolicyOptions.FilesystemACL = permissions + _, err = fsClient.SetAccessPolicy(context.Background(), &setAccessPolicyOptions) + _require.Nil(err) + + resp, err := fsClient.GetAccessPolicy(context.Background(), nil) + _require.Nil(err) + _require.Len(resp.SignedIdentifiers, len(permissions)) + _require.EqualValues(resp.SignedIdentifiers, permissions) + + setAccessPolicyOptions = filesystem.SetAccessPolicyOptions{ + Access: to.Ptr(filesystem.File), + } + setAccessPolicyOptions.FilesystemACL = []*filesystem.SignedIdentifier{} + _, err = fsClient.SetAccessPolicy(context.Background(), &setAccessPolicyOptions) + _require.Nil(err) + + resp, err = fsClient.GetAccessPolicy(context.Background(), nil) + _require.Nil(err) + _require.Nil(resp.SignedIdentifiers) +} + +func (s *RecordedTestSuite) TestFilesystemSetPermissionsInvalidPolicyTimes() { + _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) + + _, err = fsClient.Create(context.Background(), nil) + _require.Nil(err) + defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + + // Swap start and expiry + expiry, err := time.Parse(time.UnixDate, "Fri Jun 11 20:00:00 UTC 2021") + _require.Nil(err) + start, err := time.Parse(time.UnixDate, "Fri Jun 11 20:00:00 UTC 2049") + _require.Nil(err) + permissions := make([]*filesystem.SignedIdentifier, 2) + listOnly := to.Ptr(filesystem.AccessPolicyPermission{Read: true}).String() + for i := 0; i < 2; i++ { + id := "000" + strconv.Itoa(i) + permissions[i] = &filesystem.SignedIdentifier{ + ID: &id, + AccessPolicy: &filesystem.AccessPolicy{ + Start: &start, + Expiry: &expiry, + Permission: &listOnly, + }, + } + } + + setAccessPolicyOptions := filesystem.SetAccessPolicyOptions{ + Access: to.Ptr(filesystem.File), + } + setAccessPolicyOptions.FilesystemACL = permissions + _, err = fsClient.SetAccessPolicy(context.Background(), &setAccessPolicyOptions) + _require.Nil(err) +} + +func (s *RecordedTestSuite) TestFilesystemSetPermissionsNilPolicySlice() { + _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) + + _, err = fsClient.Create(context.Background(), nil) + _require.Nil(err) + defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + + _, err = fsClient.SetAccessPolicy(context.Background(), nil) + _require.Nil(err) +} + +func (s *RecordedTestSuite) TestFilesystemSetPermissionsSignedIdentifierTooLong() { + _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) + + _, err = fsClient.Create(context.Background(), nil) + _require.Nil(err) + defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + + id := "" + for i := 0; i < 65; i++ { + id += "a" + } + expiry, err := time.Parse(time.UnixDate, "Fri Jun 11 20:00:00 UTC 2021") + _require.Nil(err) + start := expiry.Add(5 * time.Minute).UTC() + permissions := make([]*filesystem.SignedIdentifier, 2) + listOnly := to.Ptr(filesystem.AccessPolicyPermission{Read: true}).String() + for i := 0; i < 2; i++ { + permissions[i] = &filesystem.SignedIdentifier{ + ID: &id, + AccessPolicy: &filesystem.AccessPolicy{ + Start: &start, + Expiry: &expiry, + Permission: &listOnly, + }, + } + } + + setAccessPolicyOptions := filesystem.SetAccessPolicyOptions{ + Access: to.Ptr(filesystem.File), + } + setAccessPolicyOptions.FilesystemACL = permissions + _, err = fsClient.SetAccessPolicy(context.Background(), &setAccessPolicyOptions) + _require.NotNil(err) + + testcommon.ValidateBlobErrorCode(_require, err, datalakeerror.InvalidXMLDocument) +} + +func (s *RecordedTestSuite) TestFilesystemSetPermissionsIfModifiedSinceTrue() { + _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) + + resp, err := fsClient.Create(context.Background(), nil) + _require.Nil(err) + defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + + currentTime := testcommon.GetRelativeTimeFromAnchor(resp.Date, -10) + + setAccessPolicyOptions := filesystem.SetAccessPolicyOptions{ + AccessConditions: &filesystem.AccessConditions{ + ModifiedAccessConditions: &filesystem.ModifiedAccessConditions{IfModifiedSince: ¤tTime}, + }, + } + _, err = fsClient.SetAccessPolicy(context.Background(), &setAccessPolicyOptions) + _require.Nil(err) + + resp1, err := fsClient.GetAccessPolicy(context.Background(), nil) + _require.Nil(err) + _require.Nil(resp1.PublicAccess) +} + +func (s *RecordedTestSuite) TestFilesystemSetPermissionsIfModifiedSinceFalse() { + _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) + + resp, err := fsClient.Create(context.Background(), nil) + _require.Nil(err) + defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + + currentTime := testcommon.GetRelativeTimeFromAnchor(resp.Date, 10) + + setAccessPolicyOptions := filesystem.SetAccessPolicyOptions{ + AccessConditions: &filesystem.AccessConditions{ + ModifiedAccessConditions: &filesystem.ModifiedAccessConditions{IfModifiedSince: ¤tTime}, + }, + } + _, err = fsClient.SetAccessPolicy(context.Background(), &setAccessPolicyOptions) + _require.NotNil(err) + + testcommon.ValidateBlobErrorCode(_require, err, datalakeerror.ConditionNotMet) +} + +func (s *RecordedTestSuite) TestFilesystemSetPermissionsIfUnModifiedSinceTrue() { + _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) + + resp, err := fsClient.Create(context.Background(), nil) + _require.Nil(err) + defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + + currentTime := testcommon.GetRelativeTimeFromAnchor(resp.Date, 10) + + setAccessPolicyOptions := filesystem.SetAccessPolicyOptions{ + AccessConditions: &filesystem.AccessConditions{ + ModifiedAccessConditions: &filesystem.ModifiedAccessConditions{IfUnmodifiedSince: ¤tTime}, + }, + } + _, err = fsClient.SetAccessPolicy(context.Background(), &setAccessPolicyOptions) + _require.Nil(err) + + resp1, err := fsClient.GetAccessPolicy(context.Background(), nil) + _require.Nil(err) + _require.Nil(resp1.PublicAccess) +} + +func (s *RecordedTestSuite) TestFilesystemSetPermissionsIfUnModifiedSinceFalse() { + _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) + + resp, err := fsClient.Create(context.Background(), nil) + _require.Nil(err) + defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + + currentTime := testcommon.GetRelativeTimeFromAnchor(resp.Date, -10) + + setAccessPolicyOptions := filesystem.SetAccessPolicyOptions{ + AccessConditions: &filesystem.AccessConditions{ + ModifiedAccessConditions: &filesystem.ModifiedAccessConditions{IfUnmodifiedSince: ¤tTime}, + }, + } + _, err = fsClient.SetAccessPolicy(context.Background(), &setAccessPolicyOptions) + _require.NotNil(err) + + testcommon.ValidateBlobErrorCode(_require, err, datalakeerror.ConditionNotMet) +} + +func (s *RecordedTestSuite) TestSetAccessPoliciesInDifferentTimeFormats() { + _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) + + _, err = fsClient.Create(context.Background(), nil) + _require.Nil(err) + defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + + id := "timeInEST" + permission := "rw" + loc, err := time.LoadLocation("EST") + _require.Nil(err) + start := time.Now().In(loc) + expiry := start.Add(10 * time.Hour) + + signedIdentifiers := make([]*filesystem.SignedIdentifier, 0) + signedIdentifiers = append(signedIdentifiers, &filesystem.SignedIdentifier{ + ID: &id, + AccessPolicy: &filesystem.AccessPolicy{ + Start: &start, + Expiry: &expiry, + Permission: &permission, + }, + }) + + id2 := "timeInIST" + permission2 := "r" + loc2, err := time.LoadLocation("Asia/Kolkata") + _require.Nil(err) + start2 := time.Now().In(loc2) + expiry2 := start2.Add(5 * time.Hour) + + signedIdentifiers = append(signedIdentifiers, &filesystem.SignedIdentifier{ + ID: &id2, + AccessPolicy: &filesystem.AccessPolicy{ + Start: &start2, + Expiry: &expiry2, + Permission: &permission2, + }, + }) + + id3 := "nilTime" + permission3 := "r" + + signedIdentifiers = append(signedIdentifiers, &filesystem.SignedIdentifier{ + ID: &id3, + AccessPolicy: &filesystem.AccessPolicy{ + Permission: &permission3, + }, + }) + options := filesystem.SetAccessPolicyOptions{FilesystemACL: signedIdentifiers} + _, err = fsClient.SetAccessPolicy(context.Background(), &options) + _require.Nil(err) + + // make a Get to assert three access policies + resp1, err := fsClient.GetAccessPolicy(context.Background(), nil) + _require.Nil(err) + _require.Len(resp1.SignedIdentifiers, 3) + _require.EqualValues(resp1.SignedIdentifiers, signedIdentifiers) +} + +func (s *RecordedTestSuite) TestSetAccessPolicyWithNullId() { + _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) + + _, err = fsClient.Create(context.Background(), nil) + _require.Nil(err) + defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + + signedIdentifiers := make([]*filesystem.SignedIdentifier, 0) + signedIdentifiers = append(signedIdentifiers, &filesystem.SignedIdentifier{ + AccessPolicy: &filesystem.AccessPolicy{ + Permission: to.Ptr("rw"), + }, + }) + + options := filesystem.SetAccessPolicyOptions{FilesystemACL: signedIdentifiers} + _, err = fsClient.SetAccessPolicy(context.Background(), &options) + _require.NotNil(err) + testcommon.ValidateBlobErrorCode(_require, err, datalakeerror.InvalidXMLDocument) + + resp1, err := fsClient.GetAccessPolicy(context.Background(), nil) + _require.Nil(err) + _require.Len(resp1.SignedIdentifiers, 0) +} + +func (s *UnrecordedTestSuite) TestSASFilesystemClient() { + _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) + + _, err = fsClient.Create(context.Background(), nil) + _require.Nil(err) + defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + + // Adding SAS and options + permissions := sas.FilesystemPermissions{ + Read: true, + Add: true, + Write: true, + Create: true, + Delete: true, + } + expiry := time.Now().Add(time.Hour) + + // filesystemSASURL is created with GetSASURL + sasUrl, err := fsClient.GetSASURL(permissions, expiry, nil) + _require.Nil(err) + + // Create filesystem client with sasUrl + _, err = filesystem.NewClientWithNoCredential(sasUrl, nil) + _require.Nil(err) +} + +// TODO: test sas on files + +//func (s *RecordedTestSuite) TestFilesystemListPaths() { +// _require := require.New(s.T()) +// //testName := s.T().Name() +// +// //filesystemName := testcommon.GenerateFilesystemName(testName) +// fsClient, err := testcommon.GetFilesystemClient("cont1", s.T(), testcommon.TestAccountDatalake, nil) +// _require.NoError(err) +// //defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) +// +// //_, err = fsClient.Create(context.Background(), nil) +// //_require.Nil(err) +// +// resp, err := fsClient.GetProperties(context.Background(), nil) +// _require.Nil(err) +// _require.NotNil(resp.ETag) +// _require.Nil(resp.Metadata) +// +// pager := fsClient.NewListPathsPager(true, nil) +// +// for pager.More() { +// _, err := pager.NextPage(context.Background()) +// _require.NotNil(err) +// if err != nil { +// break +// } +// } +//} + +// TODO: Lease tests diff --git a/sdk/storage/azdatalake/filesystem/constants.go b/sdk/storage/azdatalake/filesystem/constants.go index 3e0c373b87a1..3f862296578a 100644 --- a/sdk/storage/azdatalake/filesystem/constants.go +++ b/sdk/storage/azdatalake/filesystem/constants.go @@ -7,6 +7,7 @@ package filesystem import "github.com/Azure/azure-sdk-for-go/sdk/storage/azblob" +import "github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/lease" // PublicAccessType defines values for AccessType - private (default) or file or filesystem. type PublicAccessType = azblob.PublicAccessType @@ -15,3 +16,45 @@ const ( File PublicAccessType = azblob.PublicAccessTypeBlob Filesystem PublicAccessType = azblob.PublicAccessTypeContainer ) + +// StatusType defines values for StatusType +type StatusType = lease.StatusType + +const ( + StatusTypeLocked StatusType = lease.StatusTypeLocked + StatusTypeUnlocked StatusType = lease.StatusTypeUnlocked +) + +// PossibleStatusTypeValues returns the possible values for the StatusType const type. +func PossibleStatusTypeValues() []StatusType { + return lease.PossibleStatusTypeValues() +} + +// DurationType defines values for DurationType +type DurationType = lease.DurationType + +const ( + DurationTypeInfinite DurationType = lease.DurationTypeInfinite + DurationTypeFixed DurationType = lease.DurationTypeFixed +) + +// PossibleDurationTypeValues returns the possible values for the DurationType const type. +func PossibleDurationTypeValues() []DurationType { + return lease.PossibleDurationTypeValues() +} + +// StateType defines values for StateType +type StateType = lease.StateType + +const ( + StateTypeAvailable StateType = lease.StateTypeAvailable + StateTypeLeased StateType = lease.StateTypeLeased + StateTypeExpired StateType = lease.StateTypeExpired + StateTypeBreaking StateType = lease.StateTypeBreaking + StateTypeBroken StateType = lease.StateTypeBroken +) + +// PossibleStateTypeValues returns the possible values for the StateType const type. +func PossibleStateTypeValues() []StateType { + return lease.PossibleStateTypeValues() +} diff --git a/sdk/storage/azdatalake/filesystem/models.go b/sdk/storage/azdatalake/filesystem/models.go index ebb1946ec388..4da5f91d387e 100644 --- a/sdk/storage/azdatalake/filesystem/models.go +++ b/sdk/storage/azdatalake/filesystem/models.go @@ -8,9 +8,9 @@ package filesystem import ( "github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/container" - "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake" "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/internal/exported" - "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/internal/shared" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/internal/generated" + "time" ) // SetAccessPolicyOptions provides set of configurations for Filesystem.SetAccessPolicy operation. @@ -18,14 +18,17 @@ type SetAccessPolicyOptions struct { // Specifies whether data in the filesystem may be accessed publicly and the level of access. // If this header is not included in the request, filesystem data is private to the account owner. Access *PublicAccessType - AccessConditions *azdatalake.AccessConditions + AccessConditions *AccessConditions FilesystemACL []*SignedIdentifier } func (o *SetAccessPolicyOptions) format() *container.SetAccessPolicyOptions { + if o == nil { + return nil + } return &container.SetAccessPolicyOptions{ Access: o.Access, - AccessConditions: shared.FormatContainerAccessConditions(o.AccessConditions), + AccessConditions: exported.FormatContainerAccessConditions(o.AccessConditions), ContainerACL: o.FilesystemACL, } } @@ -43,6 +46,9 @@ type CreateOptions struct { } func (o *CreateOptions) format() *container.CreateOptions { + if o == nil { + return nil + } return &container.CreateOptions{ Access: o.Access, Metadata: o.Metadata, @@ -52,21 +58,30 @@ func (o *CreateOptions) format() *container.CreateOptions { // DeleteOptions contains the optional parameters for the Client.Delete method. type DeleteOptions struct { - AccessConditions *azdatalake.AccessConditions + AccessConditions *AccessConditions } func (o *DeleteOptions) format() *container.DeleteOptions { + if o == nil { + return nil + } return &container.DeleteOptions{ - AccessConditions: shared.FormatContainerAccessConditions(o.AccessConditions), + AccessConditions: exported.FormatContainerAccessConditions(o.AccessConditions), } } // GetPropertiesOptions contains the optional parameters for the FilesystemClient.GetProperties method. type GetPropertiesOptions struct { - LeaseAccessConditions *azdatalake.LeaseAccessConditions + LeaseAccessConditions *LeaseAccessConditions } func (o *GetPropertiesOptions) format() *container.GetPropertiesOptions { + if o == nil { + return nil + } + if o.LeaseAccessConditions == nil { + o.LeaseAccessConditions = &LeaseAccessConditions{} + } return &container.GetPropertiesOptions{ LeaseAccessConditions: &container.LeaseAccessConditions{ LeaseID: o.LeaseAccessConditions.LeaseID, @@ -77,30 +92,33 @@ func (o *GetPropertiesOptions) format() *container.GetPropertiesOptions { // SetMetadataOptions contains the optional parameters for the Client.SetMetadata method. type SetMetadataOptions struct { Metadata map[string]*string - AccessConditions *azdatalake.AccessConditions + AccessConditions *AccessConditions } func (o *SetMetadataOptions) format() *container.SetMetadataOptions { + if o == nil { + return nil + } + accConditions := exported.FormatContainerAccessConditions(o.AccessConditions) return &container.SetMetadataOptions{ - Metadata: o.Metadata, - LeaseAccessConditions: &container.LeaseAccessConditions{ - LeaseID: o.AccessConditions.LeaseAccessConditions.LeaseID, - }, - ModifiedAccessConditions: &container.ModifiedAccessConditions{ - IfMatch: o.AccessConditions.ModifiedAccessConditions.IfMatch, - IfNoneMatch: o.AccessConditions.ModifiedAccessConditions.IfNoneMatch, - IfModifiedSince: o.AccessConditions.ModifiedAccessConditions.IfModifiedSince, - IfUnmodifiedSince: o.AccessConditions.ModifiedAccessConditions.IfUnmodifiedSince, - }, + Metadata: o.Metadata, + LeaseAccessConditions: accConditions.LeaseAccessConditions, + ModifiedAccessConditions: accConditions.ModifiedAccessConditions, } } // GetAccessPolicyOptions contains the optional parameters for the Client.GetAccessPolicy method. type GetAccessPolicyOptions struct { - LeaseAccessConditions *azdatalake.LeaseAccessConditions + LeaseAccessConditions *LeaseAccessConditions } func (o *GetAccessPolicyOptions) format() *container.GetAccessPolicyOptions { + if o == nil { + return nil + } + if o.LeaseAccessConditions == nil { + o.LeaseAccessConditions = &LeaseAccessConditions{} + } return &container.GetAccessPolicyOptions{ LeaseAccessConditions: &container.LeaseAccessConditions{ LeaseID: o.LeaseAccessConditions.LeaseID, @@ -114,6 +132,10 @@ type CPKScopeInfo = container.CPKScopeInfo // AccessPolicy - An Access policy. type AccessPolicy = container.AccessPolicy +// AccessPolicyPermission type simplifies creating the permissions string for a container's access policy. +// Initialize an instance of this type and then call its String method to set AccessPolicy's Permission field. +type AccessPolicyPermission = exported.AccessPolicyPermission + // SignedIdentifier - signed identifier. type SignedIdentifier = container.SignedIdentifier @@ -125,18 +147,66 @@ type ListPathsOptions struct { Upn *bool } +func (o *ListPathsOptions) format() generated.FileSystemClientListPathsOptions { + if o == nil { + return generated.FileSystemClientListPathsOptions{} + } + + return generated.FileSystemClientListPathsOptions{ + Continuation: o.Marker, + MaxResults: o.MaxResults, + Path: o.Prefix, + Upn: o.Upn, + } +} + // ListDeletedPathsOptions contains the optional parameters for the Filesystem.ListDeletedPaths operation. PLACEHOLDER type ListDeletedPathsOptions struct { Marker *string MaxResults *int32 Prefix *string - Upn *bool } -// UndeletePathOptions contains the optional parameters for the Filesystem.UndeletePath operation. -type UndeletePathOptions struct { - // placeholder +func (o *ListDeletedPathsOptions) format() generated.FileSystemClientListBlobHierarchySegmentOptions { + showOnly := "deleted" + if o == nil { + return generated.FileSystemClientListBlobHierarchySegmentOptions{Showonly: &showOnly} + } + return generated.FileSystemClientListBlobHierarchySegmentOptions{ + Marker: o.Marker, + MaxResults: o.MaxResults, + Prefix: o.Prefix, + Showonly: &showOnly, + } +} + +// GetSASURLOptions contains the optional parameters for the Client.GetSASURL method. +type GetSASURLOptions struct { + StartTime *time.Time +} + +func (o *GetSASURLOptions) format() time.Time { + if o == nil { + return time.Time{} + } + + var st time.Time + if o.StartTime != nil { + st = o.StartTime.UTC() + } else { + st = time.Time{} + } + return st } // SharedKeyCredential contains an account's name and its primary or secondary key. type SharedKeyCredential = exported.SharedKeyCredential + +// AccessConditions identifies blob-specific access conditions which you optionally set. +type AccessConditions = exported.AccessConditions + +// LeaseAccessConditions contains optional parameters to access leased entity. +type LeaseAccessConditions = exported.LeaseAccessConditions + +// ModifiedAccessConditions contains a group of parameters for specifying access conditions. +type ModifiedAccessConditions = exported.ModifiedAccessConditions diff --git a/sdk/storage/azdatalake/filesystem/responses.go b/sdk/storage/azdatalake/filesystem/responses.go index 06b9d8b78a86..e0d4c79b9533 100644 --- a/sdk/storage/azdatalake/filesystem/responses.go +++ b/sdk/storage/azdatalake/filesystem/responses.go @@ -7,8 +7,10 @@ package filesystem import ( + "github.com/Azure/azure-sdk-for-go/sdk/azcore" "github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/container" "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/internal/generated" + "time" ) // CreateResponse contains the response from method FilesystemClient.Create. @@ -24,16 +26,117 @@ type SetMetadataResponse = container.SetMetadataResponse type SetAccessPolicyResponse = container.SetAccessPolicyResponse // GetAccessPolicyResponse contains the response from method FilesystemClient.GetAccessPolicy. -type GetAccessPolicyResponse = container.GetAccessPolicyResponse +type GetAccessPolicyResponse struct { + // PublicAccess contains the information returned from the x-ms-blob-public-access header response. + PublicAccess *PublicAccessType `xml:"BlobPublicAccess"` + + // ClientRequestID contains the information returned from the x-ms-client-request-id header response. + ClientRequestID *string `xml:"ClientRequestID"` + + // Date contains the information returned from the Date header response. + Date *time.Time `xml:"Date"` + + // ETag contains the information returned from the ETag header response. + ETag *azcore.ETag `xml:"ETag"` + + // LastModified contains the information returned from the Last-Modified header response. + LastModified *time.Time `xml:"LastModified"` + + // RequestID contains the information returned from the x-ms-request-id header response. + RequestID *string `xml:"RequestID"` + + // a collection of signed identifiers + SignedIdentifiers []*SignedIdentifier `xml:"SignedIdentifier"` + + // Version contains the information returned from the x-ms-version header response. + Version *string `xml:"Version"` +} + +// since we want to remove the blob prefix in access type +func formatGetAccessPolicyResponse(r *GetAccessPolicyResponse, contResp *container.GetAccessPolicyResponse) { + r.PublicAccess = contResp.BlobPublicAccess + r.ClientRequestID = contResp.ClientRequestID + r.Date = contResp.Date + r.ETag = contResp.ETag + r.LastModified = contResp.LastModified + r.RequestID = contResp.RequestID + r.SignedIdentifiers = contResp.SignedIdentifiers + r.Version = contResp.Version +} // GetPropertiesResponse contains the response from method FilesystemClient.GetProperties. -type GetPropertiesResponse = generated.FileSystemClientGetPropertiesResponse +type GetPropertiesResponse struct { + // BlobPublicAccess contains the information returned from the x-ms-blob-public-access header response. + PublicAccess *PublicAccessType + + // ClientRequestID contains the information returned from the x-ms-client-request-id header response. + ClientRequestID *string + + // Date contains the information returned from the Date header response. + Date *time.Time + + // DefaultEncryptionScope contains the information returned from the x-ms-default-encryption-scope header response. + DefaultEncryptionScope *string + + // DenyEncryptionScopeOverride contains the information returned from the x-ms-deny-encryption-scope-override header response. + DenyEncryptionScopeOverride *bool + + // ETag contains the information returned from the ETag header response. + ETag *azcore.ETag + + // HasImmutabilityPolicy contains the information returned from the x-ms-has-immutability-policy header response. + HasImmutabilityPolicy *bool + + // HasLegalHold contains the information returned from the x-ms-has-legal-hold header response. + HasLegalHold *bool + + // IsImmutableStorageWithVersioningEnabled contains the information returned from the x-ms-immutable-storage-with-versioning-enabled + // header response. + IsImmutableStorageWithVersioningEnabled *bool + + // LastModified contains the information returned from the Last-Modified header response. + LastModified *time.Time + + // LeaseDuration contains the information returned from the x-ms-lease-duration header response. + LeaseDuration *DurationType + + // LeaseState contains the information returned from the x-ms-lease-state header response. + LeaseState *StateType + + // LeaseStatus contains the information returned from the x-ms-lease-status header response. + LeaseStatus *StatusType + + // Metadata contains the information returned from the x-ms-meta header response. + Metadata map[string]*string + + // RequestID contains the information returned from the x-ms-request-id header response. + RequestID *string + + // Version contains the information returned from the x-ms-version header response. + Version *string +} + +func formatFilesystemProperties(r *GetPropertiesResponse, contResp *container.GetPropertiesResponse) { + r.PublicAccess = contResp.BlobPublicAccess + r.ClientRequestID = contResp.ClientRequestID + r.Date = contResp.Date + r.DefaultEncryptionScope = contResp.DefaultEncryptionScope + r.DenyEncryptionScopeOverride = contResp.DenyEncryptionScopeOverride + r.ETag = contResp.ETag + r.HasImmutabilityPolicy = contResp.HasImmutabilityPolicy + r.HasLegalHold = contResp.HasLegalHold + r.IsImmutableStorageWithVersioningEnabled = contResp.IsImmutableStorageWithVersioningEnabled + r.LastModified = contResp.LastModified + r.LeaseDuration = contResp.LeaseDuration + r.LeaseState = contResp.LeaseState + r.LeaseStatus = contResp.LeaseStatus + r.Metadata = contResp.Metadata + r.RequestID = contResp.RequestID + r.Version = contResp.Version +} // ListPathsSegmentResponse contains the response from method FilesystemClient.ListPathsSegment. type ListPathsSegmentResponse = generated.FileSystemClientListPathsResponse // ListDeletedPathsSegmentResponse contains the response from method FilesystemClient.ListPathsSegment. type ListDeletedPathsSegmentResponse = generated.FileSystemClientListBlobHierarchySegmentResponse - -// UndeletePathResponse contains the response from method FilesystemClient.UndeletePath. -type UndeletePathResponse = generated.PathClientUndeleteResponse diff --git a/sdk/storage/azdatalake/go.mod b/sdk/storage/azdatalake/go.mod index 6fc071bf6038..815ae6a72795 100644 --- a/sdk/storage/azdatalake/go.mod +++ b/sdk/storage/azdatalake/go.mod @@ -4,23 +4,17 @@ go 1.18 require ( github.com/Azure/azure-sdk-for-go/sdk/azcore v1.5.0 - github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.1.0 github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0 github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.0.0 github.com/stretchr/testify v1.7.1 ) require ( - github.com/AzureAD/microsoft-authentication-library-for-go v0.5.1 // indirect github.com/davecgh/go-spew v1.1.1 // indirect - github.com/golang-jwt/jwt v3.2.1+incompatible // indirect - github.com/google/uuid v1.1.1 // indirect - github.com/kylelemons/godebug v1.1.0 // indirect - github.com/pkg/browser v0.0.0-20210115035449-ce105d075bb4 // indirect + github.com/dnaeon/go-vcr v1.1.0 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - golang.org/x/crypto v0.0.0-20220511200225-c6db032c6c88 // indirect golang.org/x/net v0.8.0 // indirect - golang.org/x/sys v0.6.0 // indirect golang.org/x/text v0.8.0 // indirect + gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect ) diff --git a/sdk/storage/azdatalake/go.sum b/sdk/storage/azdatalake/go.sum index 44c525ae55ed..7999cbb85ae5 100644 --- a/sdk/storage/azdatalake/go.sum +++ b/sdk/storage/azdatalake/go.sum @@ -1,44 +1,37 @@ github.com/Azure/azure-sdk-for-go/sdk/azcore v1.5.0 h1:xGLAFFd9D3iLGxYiUGPdITSzsFmU1K8VtfuUHWAoN7M= github.com/Azure/azure-sdk-for-go/sdk/azcore v1.5.0/go.mod h1:bjGvMhVMb+EEm3VRNQawDMUyMMjo+S5ewNjflkep/0Q= github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.1.0 h1:QkAcEIAKbNL4KoFr4SathZPhDhF4mVwpBMFlYjyAqy8= -github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.1.0/go.mod h1:bhXu1AjYL+wutSL/kpSq6s7733q2Rb0yuot9Zgfqa/0= github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0 h1:sXr+ck84g/ZlZUOZiNELInmMgOsuGwdjjVkEIde0OtY= github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0/go.mod h1:okt5dMMTOFjX/aovMlrjvvXoPMBVSPzk9185BT0+eZM= github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.0.0 h1:u/LLAOFgsMv7HmNL4Qufg58y+qElGOt5qv0z1mURkRY= github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.0.0/go.mod h1:2e8rMJtl2+2j+HXbTBwnyGpm5Nou7KhvSfxOq8JpTag= github.com/AzureAD/microsoft-authentication-library-for-go v0.5.1 h1:BWe8a+f/t+7KY7zH2mqygeUD0t8hNFXe08p1Pb3/jKE= -github.com/AzureAD/microsoft-authentication-library-for-go v0.5.1/go.mod h1:Vt9sXTKwMyGcOxSmLDMnGPgqsUg7m8pe215qMLrDXw4= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/dnaeon/go-vcr v1.1.0 h1:ReYa/UBrRyQdant9B4fNHGoCNKw6qh6P0fsdGmZpR7c= +github.com/dnaeon/go-vcr v1.1.0/go.mod h1:M7tiix8f0r6mKKJ3Yq/kqU1OYf3MnfmBWVbPx/yU9ko= github.com/golang-jwt/jwt v3.2.1+incompatible h1:73Z+4BJcrTC+KczS6WvTPvRGOp1WmfEP4Q1lOd9Z/+c= -github.com/golang-jwt/jwt v3.2.1+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I= -github.com/golang-jwt/jwt/v4 v4.2.0 h1:besgBTC8w8HjP6NzQdxwKH9Z5oQMZ24ThTrHp3cZ8eU= github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY= -github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= -github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= -github.com/montanaflynn/stats v0.6.6/go.mod h1:etXPPgVO6n31NxCd9KQUMvCM+ve0ruNzt6R8Bnaayow= +github.com/modocache/gover v0.0.0-20171022184752-b58185e213c5/go.mod h1:caMODM3PzxT8aQXRPkAt8xlV/e7d7w8GM5g0fa5F0D8= github.com/pkg/browser v0.0.0-20210115035449-ce105d075bb4 h1:Qj1ukM4GlMWXNdMBuXcXfz/Kw9s1qm0CLY32QxuSImI= -github.com/pkg/browser v0.0.0-20210115035449-ce105d075bb4/go.mod h1:N6UoU20jOqggOuDwUaBQpluzLNDqif3kq9z2wpdYEfQ= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= golang.org/x/crypto v0.0.0-20220511200225-c6db032c6c88 h1:Tgea0cVUD0ivh5ADBX4WwuI12DUd2to3nCYe2eayMIw= -golang.org/x/crypto v0.0.0-20220511200225-c6db032c6c88/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/net v0.8.0 h1:Zrh2ngAOFYneWTAIAPethzeaQLuHwhuBkuV6ZiRnUaQ= golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= -golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.6.0 h1:MVltZSvRTcU2ljQOhs94SXPftV6DCNnZViHeQps87pQ= -golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/text v0.8.0 h1:57P1ETyNKtuIjB4SRd15iJxuhj8Gc416Y78H3qgMh68= golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/sdk/storage/azdatalake/internal/shared/access_conditions.go b/sdk/storage/azdatalake/internal/exported/access_conditions.go similarity index 51% rename from sdk/storage/azdatalake/internal/shared/access_conditions.go rename to sdk/storage/azdatalake/internal/exported/access_conditions.go index a51de4518f6b..974cb1ed628e 100644 --- a/sdk/storage/azdatalake/internal/shared/access_conditions.go +++ b/sdk/storage/azdatalake/internal/exported/access_conditions.go @@ -1,16 +1,36 @@ -package shared +package exported import ( "github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/blob" "github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/container" - "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake" "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/internal/generated" ) +// AccessConditions identifies container-specific access conditions which you optionally set. +type AccessConditions struct { + ModifiedAccessConditions *ModifiedAccessConditions + LeaseAccessConditions *LeaseAccessConditions +} + +// LeaseAccessConditions contains optional parameters to access leased entity. +type LeaseAccessConditions = generated.LeaseAccessConditions + +// ModifiedAccessConditions contains a group of parameters for specifying access conditions. +type ModifiedAccessConditions = generated.ModifiedAccessConditions + // FormatContainerAccessConditions formats FilesystemAccessConditions into container's LeaseAccessConditions and ModifiedAccessConditions. -func FormatContainerAccessConditions(b *azdatalake.AccessConditions) *container.AccessConditions { +func FormatContainerAccessConditions(b *AccessConditions) *container.AccessConditions { if b == nil { - return nil + return &container.AccessConditions{ + LeaseAccessConditions: &container.LeaseAccessConditions{}, + ModifiedAccessConditions: &container.ModifiedAccessConditions{}, + } + } + if b.LeaseAccessConditions == nil { + b.LeaseAccessConditions = &LeaseAccessConditions{} + } + if b.ModifiedAccessConditions == nil { + b.ModifiedAccessConditions = &ModifiedAccessConditions{} } return &container.AccessConditions{ LeaseAccessConditions: &container.LeaseAccessConditions{ @@ -26,9 +46,15 @@ func FormatContainerAccessConditions(b *azdatalake.AccessConditions) *container. } // FormatPathAccessConditions formats PathAccessConditions into path's LeaseAccessConditions and ModifiedAccessConditions. -func FormatPathAccessConditions(p *azdatalake.AccessConditions) (*generated.LeaseAccessConditions, *generated.ModifiedAccessConditions) { +func FormatPathAccessConditions(p *AccessConditions) (*generated.LeaseAccessConditions, *generated.ModifiedAccessConditions) { if p == nil { - return nil, nil + return &generated.LeaseAccessConditions{}, &generated.ModifiedAccessConditions{} + } + if p.LeaseAccessConditions == nil { + p.LeaseAccessConditions = &LeaseAccessConditions{} + } + if p.ModifiedAccessConditions == nil { + p.ModifiedAccessConditions = &ModifiedAccessConditions{} } return &generated.LeaseAccessConditions{ LeaseID: p.LeaseAccessConditions.LeaseID, @@ -41,9 +67,18 @@ func FormatPathAccessConditions(p *azdatalake.AccessConditions) (*generated.Leas } // FormatBlobAccessConditions formats PathAccessConditions into blob's LeaseAccessConditions and ModifiedAccessConditions. -func FormatBlobAccessConditions(p *azdatalake.AccessConditions) *blob.AccessConditions { +func FormatBlobAccessConditions(p *AccessConditions) *blob.AccessConditions { if p == nil { - return nil + return &blob.AccessConditions{ + LeaseAccessConditions: &blob.LeaseAccessConditions{}, + ModifiedAccessConditions: &blob.ModifiedAccessConditions{}, + } + } + if p.LeaseAccessConditions == nil { + p.LeaseAccessConditions = &LeaseAccessConditions{} + } + if p.ModifiedAccessConditions == nil { + p.ModifiedAccessConditions = &ModifiedAccessConditions{} } return &blob.AccessConditions{LeaseAccessConditions: &blob.LeaseAccessConditions{ LeaseID: p.LeaseAccessConditions.LeaseID, diff --git a/sdk/storage/azdatalake/internal/exported/path.go b/sdk/storage/azdatalake/internal/exported/path.go new file mode 100644 index 000000000000..eabd8aa3ddaa --- /dev/null +++ b/sdk/storage/azdatalake/internal/exported/path.go @@ -0,0 +1 @@ +package exported diff --git a/sdk/storage/azdatalake/internal/testcommon/clients_auth.go b/sdk/storage/azdatalake/internal/testcommon/clients_auth.go new file mode 100644 index 000000000000..e65e4914b2c6 --- /dev/null +++ b/sdk/storage/azdatalake/internal/testcommon/clients_auth.go @@ -0,0 +1,110 @@ +package testcommon + +import ( + "context" + "errors" + "github.com/Azure/azure-sdk-for-go/sdk/azcore" + "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/filesystem" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/service" + "github.com/stretchr/testify/require" + "testing" +) + +const ( + DefaultEndpointSuffix = "core.windows.net/" + DefaultBlobEndpointSuffix = "blob.core.windows.net/" + AccountNameEnvVar = "AZURE_STORAGE_ACCOUNT_NAME" + AccountKeyEnvVar = "AZURE_STORAGE_ACCOUNT_KEY" + DefaultEndpointSuffixEnvVar = "AZURE_STORAGE_ENDPOINT_SUFFIX" + SubscriptionID = "SUBSCRIPTION_ID" + ResourceGroupName = "RESOURCE_GROUP_NAME" +) + +const ( + FakeStorageAccount = "fakestorage" + FakeBlobStorageURL = "https://fakestorage.blob.core.windows.net" + FakeDFSStorageURL = "https://fakestorage.dfs.core.windows.net" + FakeToken = "faketoken" +) + +var BasicMetadata = map[string]*string{"Foo": to.Ptr("bar")} + +type TestAccountType string + +const ( + TestAccountDefault TestAccountType = "" + TestAccountSecondary TestAccountType = "SECONDARY_" + TestAccountPremium TestAccountType = "PREMIUM_" + TestAccountSoftDelete TestAccountType = "SOFT_DELETE_" + TestAccountDatalake TestAccountType = "DATALAKE_" + TestAccountImmutable TestAccountType = "IMMUTABLE_" +) + +func SetClientOptions(t *testing.T, opts *azcore.ClientOptions) { + opts.Logging.AllowedHeaders = append(opts.Logging.AllowedHeaders, "X-Request-Mismatch", "X-Request-Mismatch-Error") + + transport, err := recording.NewRecordingHTTPClient(t, nil) + require.NoError(t, err) + opts.Transport = transport +} + +func GetGenericAccountInfo(accountType TestAccountType) (string, string) { + if recording.GetRecordMode() == recording.PlaybackMode { + return FakeStorageAccount, "ZmFrZQ==" + } + accountNameEnvVar := string(accountType) + AccountNameEnvVar + accountKeyEnvVar := string(accountType) + AccountKeyEnvVar + accountName, _ := GetRequiredEnv(accountNameEnvVar) + accountKey, _ := GetRequiredEnv(accountKeyEnvVar) + return accountName, accountKey +} + +func GetGenericSharedKeyCredential(accountType TestAccountType) (*azdatalake.SharedKeyCredential, error) { + accountName, accountKey := GetGenericAccountInfo(accountType) + if accountName == "" || accountKey == "" { + return nil, errors.New(string(accountType) + AccountNameEnvVar + " and/or " + string(accountType) + AccountKeyEnvVar + " environment variables not specified.") + } + return azdatalake.NewSharedKeyCredential(accountName, accountKey) +} + +func GetServiceClient(t *testing.T, accountType TestAccountType, options *service.ClientOptions) (*service.Client, error) { + if options == nil { + options = &service.ClientOptions{} + } + + SetClientOptions(t, &options.ClientOptions) + + cred, err := GetGenericSharedKeyCredential(accountType) + if err != nil { + return nil, err + } + + serviceClient, err := service.NewClientWithSharedKeyCredential("https://"+cred.AccountName()+".dfs.core.windows.net/", cred, options) + + return serviceClient, err +} + +func GetFilesystemClient(fsName string, t *testing.T, accountType TestAccountType, options *filesystem.ClientOptions) (*filesystem.Client, error) { + if options == nil { + options = &filesystem.ClientOptions{} + } + + SetClientOptions(t, &options.ClientOptions) + + cred, err := GetGenericSharedKeyCredential(accountType) + if err != nil { + return nil, err + } + + filesystemClient, err := filesystem.NewClientWithSharedKeyCredential("https://"+cred.AccountName()+".dfs.core.windows.net/"+fsName, cred, options) + + return filesystemClient, err +} + +func DeleteFilesystem(ctx context.Context, _require *require.Assertions, filesystemClient *filesystem.Client) { + _, err := filesystemClient.Delete(ctx, nil) + _require.Nil(err) +} diff --git a/sdk/storage/azdatalake/internal/testcommon/common.go b/sdk/storage/azdatalake/internal/testcommon/common.go new file mode 100644 index 000000000000..71534c98af95 --- /dev/null +++ b/sdk/storage/azdatalake/internal/testcommon/common.go @@ -0,0 +1,78 @@ +package testcommon + +import ( + "errors" + "github.com/Azure/azure-sdk-for-go/sdk/azcore" + "github.com/Azure/azure-sdk-for-go/sdk/internal/recording" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/bloberror" + "github.com/stretchr/testify/require" + "os" + "strings" + "testing" + "time" +) + +const ( + FilesystemPrefix = "gofs" + FilePrefix = "gotestfile" + DefaultData = "Godatalakedata" + InvalidHeaderErrorSubstring = "invalid header field" // error thrown by the http client +) + +func GenerateFilesystemName(testName string) string { + return FilesystemPrefix + GenerateEntityName(testName) +} + +func GenerateEntityName(testName string) string { + return strings.ReplaceAll(strings.ReplaceAll(strings.ToLower(testName), "/", ""), "test", "") +} + +func BeforeTest(t *testing.T, suite string, test string) { + const blobURLRegex = `https://\S+\.blob\.core\.windows\.net` + const dfsURLRegex = `https://\S+\.dfs\.core\.windows\.net` + const tokenRegex = `(?:Bearer\s).*` + + require.NoError(t, recording.AddURISanitizer(FakeBlobStorageURL, blobURLRegex, nil)) + require.NoError(t, recording.AddURISanitizer(FakeDFSStorageURL, dfsURLRegex, nil)) + require.NoError(t, recording.AddHeaderRegexSanitizer("x-ms-copy-source", FakeBlobStorageURL, blobURLRegex, nil)) + require.NoError(t, recording.AddHeaderRegexSanitizer("x-ms-copy-source", FakeDFSStorageURL, dfsURLRegex, nil)) + require.NoError(t, recording.AddHeaderRegexSanitizer("x-ms-copy-source-authorization", FakeToken, tokenRegex, nil)) + // we freeze request IDs and timestamps to avoid creating noisy diffs + // NOTE: we can't freeze time stamps as that breaks some tests that use if-modified-since etc (maybe it can be fixed?) + //testframework.AddHeaderRegexSanitizer("X-Ms-Date", "Wed, 10 Aug 2022 23:34:14 GMT", "", nil) + require.NoError(t, recording.AddHeaderRegexSanitizer("x-ms-request-id", "00000000-0000-0000-0000-000000000000", "", nil)) + //testframework.AddHeaderRegexSanitizer("Date", "Wed, 10 Aug 2022 23:34:14 GMT", "", nil) + // TODO: more freezing + //testframework.AddBodyRegexSanitizer("RequestId:00000000-0000-0000-0000-000000000000", `RequestId:\w{8}-\w{4}-\w{4}-\w{4}-\w{12}`, nil) + //testframework.AddBodyRegexSanitizer("Time:2022-08-11T00:21:56.4562741Z", `Time:\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d*)?Z`, nil) + require.NoError(t, recording.Start(t, "sdk/storage/azdatalake/testdata", nil)) +} + +func AfterTest(t *testing.T, suite string, test string) { + require.NoError(t, recording.Stop(t, nil)) +} + +// GetRequiredEnv gets an environment variable by name and returns an error if it is not found +func GetRequiredEnv(name string) (string, error) { + env, ok := os.LookupEnv(name) + if ok { + return env, nil + } else { + return "", errors.New("Required environment variable not set: " + name) + } +} + +func ValidateBlobErrorCode(_require *require.Assertions, err error, code bloberror.Code) { + _require.NotNil(err) + var responseErr *azcore.ResponseError + errors.As(err, &responseErr) + if responseErr != nil { + _require.Equal(string(code), responseErr.ErrorCode) + } else { + _require.Contains(err.Error(), code) + } +} + +func GetRelativeTimeFromAnchor(anchorTime *time.Time, amount time.Duration) time.Time { + return anchorTime.Add(amount * time.Second) +} diff --git a/sdk/storage/azdatalake/lease/filesystem_client.go b/sdk/storage/azdatalake/lease/filesystem_client.go index e2c5100a859e..110171d15990 100644 --- a/sdk/storage/azdatalake/lease/filesystem_client.go +++ b/sdk/storage/azdatalake/lease/filesystem_client.go @@ -10,15 +10,12 @@ import ( "context" "github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/lease" "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/filesystem" - "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/internal/base" - "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/internal/generated" ) // FilesystemClient provides lease functionality for the underlying filesystem client. type FilesystemClient struct { - filesystemClient *filesystem.Client - leaseID *string - containerClient *lease.ContainerClient + leaseID *string + containerClient *lease.ContainerClient } // FilesystemClientOptions contains the optional values when creating a FilesystemClient. @@ -27,10 +24,6 @@ type FilesystemClientOptions struct { LeaseID *string } -func (c *FilesystemClient) generated() *generated.FileSystemClient { - return base.InnerClient((*base.Client[generated.FileSystemClient])(c.filesystemClient)) -} - // NewFilesystemClient creates a filesystem lease client for the provided filesystem client. // - client - an instance of a filesystem client // - options - client options; pass nil to accept the default values diff --git a/sdk/storage/azdatalake/lease/models.go b/sdk/storage/azdatalake/lease/models.go index 4d94dafc5ec0..c09d30a21b40 100644 --- a/sdk/storage/azdatalake/lease/models.go +++ b/sdk/storage/azdatalake/lease/models.go @@ -9,12 +9,12 @@ package lease import ( "github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/blob" "github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/lease" - "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/internal/exported" ) // FilesystemAcquireOptions contains the optional parameters for the LeaseClient.AcquireLease method. type FilesystemAcquireOptions struct { - ModifiedAccessConditions *azdatalake.ModifiedAccessConditions + ModifiedAccessConditions *ModifiedAccessConditions } func (o *FilesystemAcquireOptions) format() *lease.ContainerAcquireOptions { @@ -31,7 +31,7 @@ func (o *FilesystemAcquireOptions) format() *lease.ContainerAcquireOptions { // FilesystemBreakOptions contains the optional parameters for the LeaseClient.BreakLease method. type FilesystemBreakOptions struct { BreakPeriod *int32 - ModifiedAccessConditions *azdatalake.ModifiedAccessConditions + ModifiedAccessConditions *ModifiedAccessConditions } func (o *FilesystemBreakOptions) format() *lease.ContainerBreakOptions { @@ -48,7 +48,7 @@ func (o *FilesystemBreakOptions) format() *lease.ContainerBreakOptions { // FilesystemChangeOptions contains the optional parameters for the LeaseClient.ChangeLease method. type FilesystemChangeOptions struct { - ModifiedAccessConditions *azdatalake.ModifiedAccessConditions + ModifiedAccessConditions *ModifiedAccessConditions } func (o *FilesystemChangeOptions) format() *lease.ContainerChangeOptions { @@ -63,7 +63,7 @@ func (o *FilesystemChangeOptions) format() *lease.ContainerChangeOptions { } type FilesystemReleaseOptions struct { - ModifiedAccessConditions *azdatalake.ModifiedAccessConditions + ModifiedAccessConditions *ModifiedAccessConditions } func (o *FilesystemReleaseOptions) format() *lease.ContainerReleaseOptions { @@ -78,7 +78,7 @@ func (o *FilesystemReleaseOptions) format() *lease.ContainerReleaseOptions { } type FilesystemRenewOptions struct { - ModifiedAccessConditions *azdatalake.ModifiedAccessConditions + ModifiedAccessConditions *ModifiedAccessConditions } func (o *FilesystemRenewOptions) format() *lease.ContainerRenewOptions { @@ -94,7 +94,7 @@ func (o *FilesystemRenewOptions) format() *lease.ContainerRenewOptions { // PathAcquireOptions contains the optional parameters for the LeaseClient.AcquireLease method. type PathAcquireOptions struct { - ModifiedAccessConditions *azdatalake.ModifiedAccessConditions + ModifiedAccessConditions *ModifiedAccessConditions } func (o *PathAcquireOptions) format() *lease.BlobAcquireOptions { @@ -111,7 +111,7 @@ func (o *PathAcquireOptions) format() *lease.BlobAcquireOptions { // PathBreakOptions contains the optional parameters for the LeaseClient.BreakLease method. type PathBreakOptions struct { BreakPeriod *int32 - ModifiedAccessConditions *azdatalake.ModifiedAccessConditions + ModifiedAccessConditions *ModifiedAccessConditions } func (o *PathBreakOptions) format() *lease.BlobBreakOptions { @@ -128,7 +128,7 @@ func (o *PathBreakOptions) format() *lease.BlobBreakOptions { // PathChangeOptions contains the optional parameters for the LeaseClient.ChangeLease method. type PathChangeOptions struct { - ModifiedAccessConditions *azdatalake.ModifiedAccessConditions + ModifiedAccessConditions *ModifiedAccessConditions } func (o *PathChangeOptions) format() *lease.BlobChangeOptions { @@ -143,7 +143,7 @@ func (o *PathChangeOptions) format() *lease.BlobChangeOptions { } type PathReleaseOptions struct { - ModifiedAccessConditions *azdatalake.ModifiedAccessConditions + ModifiedAccessConditions *ModifiedAccessConditions } func (o *PathReleaseOptions) format() *lease.BlobReleaseOptions { @@ -158,7 +158,7 @@ func (o *PathReleaseOptions) format() *lease.BlobReleaseOptions { } type PathRenewOptions struct { - ModifiedAccessConditions *azdatalake.ModifiedAccessConditions + ModifiedAccessConditions *ModifiedAccessConditions } func (o *PathRenewOptions) format() *lease.BlobRenewOptions { @@ -171,3 +171,12 @@ func (o *PathRenewOptions) format() *lease.BlobRenewOptions { }, } } + +// AccessConditions identifies blob-specific access conditions which you optionally set. +type AccessConditions = exported.AccessConditions + +// LeaseAccessConditions contains optional parameters to access leased entity. +type LeaseAccessConditions = exported.LeaseAccessConditions + +// ModifiedAccessConditions contains a group of parameters for specifying access conditions. +type ModifiedAccessConditions = exported.ModifiedAccessConditions diff --git a/sdk/storage/azdatalake/lease/path_client.go b/sdk/storage/azdatalake/lease/path_client.go index 57b06f5c20a2..ec7aa846c47e 100644 --- a/sdk/storage/azdatalake/lease/path_client.go +++ b/sdk/storage/azdatalake/lease/path_client.go @@ -11,15 +11,11 @@ import ( "github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/lease" "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/internal/base" - "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/internal/generated" - "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/path" ) // PathClient provides lease functionality for the underlying path client. type PathClient struct { blobClient *lease.BlobClient - pathClient *path.Client leaseID *string } @@ -37,10 +33,6 @@ func NewPathClient[T directory.Client | file.Client](client *T, options *PathCli return nil, nil } -func (c *PathClient) generated() *generated.PathClient { - return base.InnerClient((*base.Client[generated.PathClient])(c.pathClient)) -} - // LeaseID returns leaseID of the client. func (c *PathClient) LeaseID() *string { return c.leaseID diff --git a/sdk/storage/azdatalake/service/client.go b/sdk/storage/azdatalake/service/client.go index eeac42200d11..129bb5533f9a 100644 --- a/sdk/storage/azdatalake/service/client.go +++ b/sdk/storage/azdatalake/service/client.go @@ -27,6 +27,38 @@ type ClientOptions base.ClientOptions // Client represents a URL to the Azure Datalake Storage service. type Client base.CompositeClient[generated.ServiceClient, generated.ServiceClient, service.Client] +// NewClient creates an instance of Client with the specified values. +// - serviceURL - the URL of the blob e.g. https://.dfs.core.windows.net/ +// - cred - an Azure AD credential, typically obtained via the azidentity module +// - options - client options; pass nil to accept the default values +func NewClient(serviceURL string, cred azcore.TokenCredential, options *ClientOptions) (*Client, error) { + blobServiceURL := strings.Replace(serviceURL, ".dfs.", ".blob.", 1) + datalakeServiceURL := strings.Replace(serviceURL, ".blob.", ".dfs.", 1) + + authPolicy := shared.NewStorageChallengePolicy(cred) + conOptions := shared.GetClientOptions(options) + plOpts := runtime.PipelineOptions{ + PerRetry: []policy.Policy{authPolicy}, + } + base.SetPipelineOptions((*base.ClientOptions)(conOptions), &plOpts) + + azClient, err := azcore.NewClient(shared.ServiceClient, exported.ModuleVersion, plOpts, &conOptions.ClientOptions) + if err != nil { + return nil, err + } + + if options == nil { + options = &ClientOptions{} + } + blobServiceClientOpts := service.ClientOptions{ + ClientOptions: options.ClientOptions, + } + blobSvcClient, _ := service.NewClient(blobServiceURL, cred, &blobServiceClientOpts) + svcClient := base.NewServiceClient(datalakeServiceURL, blobServiceURL, blobSvcClient, azClient, nil, (*base.ClientOptions)(conOptions)) + + return (*Client)(svcClient), nil +} + // NewClientWithNoCredential creates an instance of Client with the specified values. // - serviceURL - the URL of the storage account e.g. https://.dfs.core.windows.net/ // - options - client options; pass nil to accept the default values. @@ -43,6 +75,9 @@ func NewClientWithNoCredential(serviceURL string, options *ClientOptions) (*Clie return nil, err } + if options == nil { + options = &ClientOptions{} + } blobServiceClientOpts := service.ClientOptions{ ClientOptions: options.ClientOptions, } @@ -72,6 +107,9 @@ func NewClientWithSharedKeyCredential(serviceURL string, cred *SharedKeyCredenti return nil, err } + if options == nil { + options = &ClientOptions{} + } blobServiceClientOpts := service.ClientOptions{ ClientOptions: options.ClientOptions, } @@ -105,6 +143,8 @@ func NewClientFromConnectionString(connectionString string, options *ClientOptio // NewFilesystemClient creates a new share.Client object by concatenating shareName to the end of this Client's URL. // The new share.Client uses the same request policy pipeline as the Client. func (s *Client) NewFilesystemClient(filesystemName string) *filesystem.Client { + //fsURL := runtime.JoinPaths(s.generatedServiceClientWithDFS().Endpoint(), filesystemName) + //return (*filesystem.Client)(base.NewFilesystemClient(fsURL, s.generated().Pipeline(), s.credential())) return nil } @@ -120,12 +160,12 @@ func (s *Client) NewFileClient(fileName string) *filesystem.Client { return nil } -func (s *Client) generatedFSClientWithDFS() *generated.ServiceClient { +func (s *Client) generatedServiceClientWithDFS() *generated.ServiceClient { svcClientWithDFS, _, _ := base.InnerClients((*base.CompositeClient[generated.ServiceClient, generated.ServiceClient, service.Client])(s)) return svcClientWithDFS } -func (s *Client) generatedFSClientWithBlob() *generated.ServiceClient { +func (s *Client) generatedServiceClientWithBlob() *generated.ServiceClient { _, svcClientWithBlob, _ := base.InnerClients((*base.CompositeClient[generated.ServiceClient, generated.ServiceClient, service.Client])(s)) return svcClientWithBlob } @@ -139,9 +179,14 @@ func (s *Client) sharedKey() *exported.SharedKeyCredential { return base.SharedKeyComposite((*base.CompositeClient[generated.ServiceClient, generated.ServiceClient, service.Client])(s)) } -// URL returns the URL endpoint used by the Client object. -func (s *Client) URL() string { - return "s.generated().Endpoint()" +// DFSURL returns the URL endpoint used by the Client object. +func (s *Client) DFSURL() string { + return s.generatedServiceClientWithDFS().Endpoint() +} + +// BlobURL returns the URL endpoint used by the Client object. +func (s *Client) BlobURL() string { + return s.generatedServiceClientWithBlob().Endpoint() } // CreateFilesystem creates a new filesystem under the specified account. (blob3) From 79f06e1755ca829a58ac78e70791ab5595a1ee0c Mon Sep 17 00:00:00 2001 From: Tamer Sherif <69483382+tasherif-msft@users.noreply.github.com> Date: Fri, 7 Jul 2023 10:27:29 -0700 Subject: [PATCH 07/16] Feedback + Service Client (#21096) * Enable gocritic during linting (#20715) Enabled gocritic's evalOrder to catch dependencies on undefined behavior on return statements. Updated to latest version of golangci-lint. Fixed issue in azblob flagged by latest linter. * Cosmos DB: Enable merge support (#20716) * Adding header and value * Wiring and tests * format * Fixing value * change log * [azservicebus, azeventhubs] Stress test and logging improvement (#20710) Logging improvements: * Updating the logging to print more tracing information (per-link) in prep for the bigger release coming up. * Trimming out some of the verbose logging, seeing if I can get it a bit more reasonable. Stress tests: * Add a timestamp to the log name we generate and also default to append, not overwrite. * Use 0.5 cores, 0.5GB as our baseline. Some pods use more and I'll tune them more later. * update proxy version (#20712) Co-authored-by: Scott Beddall * Return an error when you try to send a message that's too large. (#20721) This now works just like the message batch - you'll get an ErrMessageTooLarge if you attempt to send a message that's too large for the link's configured size. NOTE: there's a patch to `internal/go-amqp/Sender.go` to match what's in go-amqp's main so it returns a programmatically useful error when the message is too large. Fixes #20647 * Changes in test that is failing in pipeline (#20693) * [azservicebus, azeventhubs] Treat 'entity full' as a fatal error (#20722) When the remote entity is full we get a resource-limit-exceeded condition. This isn't something we should keep retrying on and it's best to just abort and let the user know immediately, rather than hoping it might eventually clear out. This affected both Event Hubs and Service Bus. Fixes #20647 * [azservicebus/azeventhubs] Redirect stderr and stdout to tee (#20726) * Update changelog with latest features (#20730) * Update changelog with latest features Prepare for upcoming release. * bump minor version * pass along the artifact name so we can override it later (#20732) Co-authored-by: scbedd <45376673+scbedd@users.noreply.github.com> * [azeventhubs] Fixing checkpoint store race condition (#20727) The checkpoint store wasn't guarding against multiple owners claiming for the first time - fixing this by using IfNoneMatch Fixes #20717 * Fix azidentity troubleshooting guide link (#20736) * [Release] sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/0.1.0 (#20437) * [Release] sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/0.1.0 generation from spec commit: 85fb4ac6f8bfefd179e6c2632976a154b5c9ff04 * client factory * fix * fix * update * add sdk/resourcemanager/postgresql/armpostgresql live test (#20685) * add sdk/resourcemanager/postgresql/armpostgresql live test * update assets.json * set subscriptionId default value * format * add sdk/resourcemanager/eventhub/armeventhub live test (#20686) * add sdk/resourcemanager/eventhub/armeventhub live test * update assets * add sdk/resourcemanager/compute/armcompute live test (#20048) * add sdk/resourcemanager/compute/armcompute live test * skus filter * fix subscriptionId default value * fix * gofmt * update recording * sdk/resourcemanager/network/armnetwork live test (#20331) * sdk/resourcemanager/network/armnetwork live test * update subscriptionId default value * update recording * add sdk/resourcemanager/cosmos/armcosmos live test (#20705) * add sdk/resourcemanager/cosmos/armcosmos live test * update assets.json * update assets.json * update assets.json * update assets.json * Increment package version after release of azcore (#20740) * [azeventhubs] Improperly resetting etag in the checkpoint store (#20737) We shouldn't be resetting the etag to nil - it's what we use to enforce a "single winner" when doing ownership claims. The bug here was two-fold: I had bad logic in my previous claim ownership, which I fixed in a previous PR, but we need to reflect that same constraint properly in our in-memory checkpoint store for these tests. * Eng workflows sync and branch cleanup additions (#20743) Co-authored-by: James Suplizio * [azeventhubs] Latest start position can also be inclusive (ie, get the latest message) (#20744) * Update GitHubEventProcessor version and remove pull_request_review procesing (#20751) Co-authored-by: James Suplizio * Rename DisableAuthorityValidationAndInstanceDiscovery (#20746) * fix (#20707) * AzFile (#20739) * azfile: Fixing connection string parsing logic (#20798) * Fixing connection string parse logic * Update README * [azadmin] fix flaky test (#20758) * fix flaky test * charles suggestion * Prepare azidentity v1.3.0 for release (#20756) * Fix broken podman link (#20801) Co-authored-by: Wes Haggard * [azquery] update doc comments (#20755) * update doc comments * update statistics and visualization generation * prep-for-release * Fixed contribution section (#20752) Co-authored-by: Bob Tabor * [azeventhubs,azservicebus] Some API cleanup, renames (#20754) * Adding options to UpdateCheckpoint(), just for future potential expansion * Make Offset an int64, not a *int64 (it's not optional, it'll always come back with ReceivedEvents) * Adding more logging into the checkpoint store. * Point all imports at the production go-amqp * Add supporting features to enable distributed tracing (#20301) (#20708) * Add supporting features to enable distributed tracing This includes new internal pipeline policies and other supporting types. See the changelog for a full description. Added some missing doc comments. * fix linter issue * add net.peer.name trace attribute sequence custom HTTP header policy before logging policy. sequence logging policy after HTTP trace policy. keep body download policy at the end. * add span for iterating over pages * Restore ARM CAE support for azcore beta (#20657) This reverts commit 902097226ff3fe2fc6c3e7fc50d3478350253614. * Upgrade to stable azcore (#20808) * Increment package version after release of data/azcosmos (#20807) * Updating changelog (#20810) * Add fake package to azcore (#20711) * Add fake package to azcore This is the supporting infrastructure for the generated SDK fakes. * fix doc comment * Updating CHANGELOG.md (#20809) * changelog (#20811) * Increment package version after release of storage/azfile (#20813) * Update changelog (azblob) (#20815) * Updating CHANGELOG.md * Update the changelog with correct version * [azquery] migration guide (#20742) * migration guide * Charles feedback * Richard feedback --------- Co-authored-by: Charles Lowell <10964656+chlowell@users.noreply.github.com> * Increment package version after release of monitor/azquery (#20820) * [keyvault] prep for release (#20819) * prep for release * perf tests * update date * added new client methods * moved access conditions and wrote first test * added more tests * added path listing * list deleted paths * fixed formatter and added more tests * added more tests * marker fix * log * fixed constructor validation * comment * assets update: * some cleanup * missing models and log * cleanup, resolved apiview feedback * test * cleanup * added service tests * implemented listing * cleanup * cleanup --------- Co-authored-by: Joel Hendrix Co-authored-by: Matias Quaranta Co-authored-by: Richard Park <51494936+richardpark-msft@users.noreply.github.com> Co-authored-by: Azure SDK Bot <53356347+azure-sdk@users.noreply.github.com> Co-authored-by: Scott Beddall Co-authored-by: siminsavani-msft <77068571+siminsavani-msft@users.noreply.github.com> Co-authored-by: scbedd <45376673+scbedd@users.noreply.github.com> Co-authored-by: Charles Lowell <10964656+chlowell@users.noreply.github.com> Co-authored-by: Peng Jiahui <46921893+Alancere@users.noreply.github.com> Co-authored-by: James Suplizio Co-authored-by: Sourav Gupta <98318303+souravgupta-msft@users.noreply.github.com> Co-authored-by: gracewilcox <43627800+gracewilcox@users.noreply.github.com> Co-authored-by: Wes Haggard Co-authored-by: Bob Tabor Co-authored-by: Bob Tabor --- sdk/storage/azdatalake/directory/client.go | 19 +- sdk/storage/azdatalake/file/client.go | 20 +- sdk/storage/azdatalake/filesystem/client.go | 23 +- .../azdatalake/filesystem/constants.go | 2 + sdk/storage/azdatalake/filesystem/models.go | 6 + .../azdatalake/filesystem/responses.go | 19 +- sdk/storage/azdatalake/go.mod | 2 +- sdk/storage/azdatalake/go.sum | 4 +- .../azdatalake/internal/base/clients.go | 22 +- .../internal/exported/log_events.go | 20 + .../exported/shared_key_credential.go | 10 +- .../internal/shared/challenge_policy.go | 113 --- .../azdatalake/internal/shared/shared.go | 6 + .../internal/testcommon/clients_auth.go | 53 ++ sdk/storage/azdatalake/log.go | 19 + sdk/storage/azdatalake/sas/service.go | 58 +- sdk/storage/azdatalake/service/client.go | 102 ++- sdk/storage/azdatalake/service/client_test.go | 751 ++++++++++++++++++ sdk/storage/azdatalake/service/models.go | 104 ++- sdk/storage/azdatalake/service/responses.go | 98 ++- 20 files changed, 1234 insertions(+), 217 deletions(-) create mode 100644 sdk/storage/azdatalake/internal/exported/log_events.go delete mode 100644 sdk/storage/azdatalake/internal/shared/challenge_policy.go create mode 100644 sdk/storage/azdatalake/log.go create mode 100644 sdk/storage/azdatalake/service/client_test.go diff --git a/sdk/storage/azdatalake/directory/client.go b/sdk/storage/azdatalake/directory/client.go index 1cdb330d3d0e..749dfbc86724 100644 --- a/sdk/storage/azdatalake/directory/client.go +++ b/sdk/storage/azdatalake/directory/client.go @@ -16,7 +16,6 @@ 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/shared" - "strings" ) // ClientOptions contains the optional parameters when creating a Client. @@ -30,10 +29,9 @@ type Client base.CompositeClient[generated.PathClient, generated.PathClient, blo // - cred - an Azure AD credential, typically obtained via the azidentity module // - options - client options; pass nil to accept the default values func NewClient(directoryURL string, cred azcore.TokenCredential, options *ClientOptions) (*Client, error) { - blobURL := strings.Replace(directoryURL, ".dfs.", ".blob.", 1) - directoryURL = strings.Replace(directoryURL, ".blob.", ".dfs.", 1) + blobURL, directoryURL := shared.GetURLs(directoryURL) - authPolicy := shared.NewStorageChallengePolicy(cred) + authPolicy := runtime.NewBearerTokenPolicy(cred, []string{shared.TokenScope}, nil) conOptions := shared.GetClientOptions(options) plOpts := runtime.PipelineOptions{ PerRetry: []policy.Policy{authPolicy}, @@ -62,8 +60,7 @@ func NewClient(directoryURL string, cred azcore.TokenCredential, options *Client // - directoryURL - the URL of the storage account e.g. https://.dfs.core.windows.net/fs/dir? // - options - client options; pass nil to accept the default values func NewClientWithNoCredential(directoryURL string, options *ClientOptions) (*Client, error) { - blobURL := strings.Replace(directoryURL, ".dfs.", ".blob.", 1) - directoryURL = strings.Replace(directoryURL, ".blob.", ".dfs.", 1) + blobURL, directoryURL := shared.GetURLs(directoryURL) conOptions := shared.GetClientOptions(options) plOpts := runtime.PipelineOptions{} @@ -91,8 +88,7 @@ func NewClientWithNoCredential(directoryURL string, options *ClientOptions) (*Cl // - cred - a SharedKeyCredential created with the matching storage account and access key // - options - client options; pass nil to accept the default values func NewClientWithSharedKeyCredential(directoryURL string, cred *SharedKeyCredential, options *ClientOptions) (*Client, error) { - blobURL := strings.Replace(directoryURL, ".dfs.", ".blob.", 1) - directoryURL = strings.Replace(directoryURL, ".blob.", ".dfs.", 1) + blobURL, directoryURL := shared.GetURLs(directoryURL) authPolicy := exported.NewSharedKeyCredPolicy(cred) conOptions := shared.GetClientOptions(options) @@ -112,8 +108,11 @@ func NewClientWithSharedKeyCredential(directoryURL string, cred *SharedKeyCreden blobClientOpts := blob.ClientOptions{ ClientOptions: options.ClientOptions, } - blobSharedKeyCredential, _ := blob.NewSharedKeyCredential(cred.AccountName(), cred.AccountKey()) - blobClient, _ := blob.NewClientWithSharedKeyCredential(blobURL, blobSharedKeyCredential, &blobClientOpts) + blobSharedKey, err := cred.ConvertToBlobSharedKey() + if err != nil { + return nil, err + } + blobClient, _ := blob.NewClientWithSharedKeyCredential(blobURL, blobSharedKey, &blobClientOpts) dirClient := base.NewPathClient(directoryURL, blobURL, blobClient, azClient, nil, (*base.ClientOptions)(conOptions)) return (*Client)(dirClient), nil diff --git a/sdk/storage/azdatalake/file/client.go b/sdk/storage/azdatalake/file/client.go index f6fd6f09e6b3..c7355f3e0916 100644 --- a/sdk/storage/azdatalake/file/client.go +++ b/sdk/storage/azdatalake/file/client.go @@ -16,7 +16,6 @@ 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/shared" - "strings" ) // ClientOptions contains the optional parameters when creating a Client. @@ -30,10 +29,8 @@ type Client base.CompositeClient[generated.PathClient, generated.PathClient, blo // - cred - an Azure AD credential, typically obtained via the azidentity module // - options - client options; pass nil to accept the default values func NewClient(fileURL string, cred azcore.TokenCredential, options *ClientOptions) (*Client, error) { - blobURL := strings.Replace(fileURL, ".dfs.", ".blob.", 1) - fileURL = strings.Replace(fileURL, ".blob.", ".dfs.", 1) - - authPolicy := shared.NewStorageChallengePolicy(cred) + blobURL, fileURL := shared.GetURLs(fileURL) + authPolicy := runtime.NewBearerTokenPolicy(cred, []string{shared.TokenScope}, nil) conOptions := shared.GetClientOptions(options) plOpts := runtime.PipelineOptions{ PerRetry: []policy.Policy{authPolicy}, @@ -62,8 +59,7 @@ func NewClient(fileURL string, cred azcore.TokenCredential, options *ClientOptio // - fileURL - the URL of the storage account e.g. https://.dfs.core.windows.net/fs/file.txt? // - options - client options; pass nil to accept the default values func NewClientWithNoCredential(fileURL string, options *ClientOptions) (*Client, error) { - blobURL := strings.Replace(fileURL, ".dfs.", ".blob.", 1) - fileURL = strings.Replace(fileURL, ".blob.", ".dfs.", 1) + blobURL, fileURL := shared.GetURLs(fileURL) conOptions := shared.GetClientOptions(options) plOpts := runtime.PipelineOptions{} @@ -91,8 +87,7 @@ func NewClientWithNoCredential(fileURL string, options *ClientOptions) (*Client, // - cred - a SharedKeyCredential created with the matching storage account and access key // - options - client options; pass nil to accept the default values func NewClientWithSharedKeyCredential(fileURL string, cred *SharedKeyCredential, options *ClientOptions) (*Client, error) { - blobURL := strings.Replace(fileURL, ".dfs.", ".blob.", 1) - fileURL = strings.Replace(fileURL, ".blob.", ".dfs.", 1) + blobURL, fileURL := shared.GetURLs(fileURL) authPolicy := exported.NewSharedKeyCredPolicy(cred) conOptions := shared.GetClientOptions(options) @@ -112,8 +107,11 @@ func NewClientWithSharedKeyCredential(fileURL string, cred *SharedKeyCredential, blobClientOpts := blob.ClientOptions{ ClientOptions: options.ClientOptions, } - blobSharedKeyCredential, _ := blob.NewSharedKeyCredential(cred.AccountName(), cred.AccountKey()) - blobClient, _ := blob.NewClientWithSharedKeyCredential(blobURL, blobSharedKeyCredential, &blobClientOpts) + blobSharedKey, err := cred.ConvertToBlobSharedKey() + if err != nil { + return nil, err + } + blobClient, _ := blob.NewClientWithSharedKeyCredential(blobURL, blobSharedKey, &blobClientOpts) fileClient := base.NewPathClient(fileURL, blobURL, blobClient, azClient, nil, (*base.ClientOptions)(conOptions)) return (*Client)(fileClient), nil diff --git a/sdk/storage/azdatalake/filesystem/client.go b/sdk/storage/azdatalake/filesystem/client.go index 151ca389efea..0f182909cb69 100644 --- a/sdk/storage/azdatalake/filesystem/client.go +++ b/sdk/storage/azdatalake/filesystem/client.go @@ -11,7 +11,6 @@ import ( "github.com/Azure/azure-sdk-for-go/sdk/azcore" "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/blob" "github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/container" "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake" "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/datalakeerror" @@ -21,7 +20,6 @@ import ( "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" - "strings" "time" ) @@ -36,10 +34,8 @@ type Client base.CompositeClient[generated.FileSystemClient, generated.FileSyste // - cred - an Azure AD credential, typically obtained via the azidentity module // - options - client options; pass nil to accept the default values func NewClient(filesystemURL string, cred azcore.TokenCredential, options *ClientOptions) (*Client, error) { - containerURL := strings.Replace(filesystemURL, ".dfs.", ".blob.", 1) - filesystemURL = strings.Replace(filesystemURL, ".blob.", ".dfs.", 1) - - authPolicy := shared.NewStorageChallengePolicy(cred) + containerURL, filesystemURL := shared.GetURLs(filesystemURL) + authPolicy := runtime.NewBearerTokenPolicy(cred, []string{shared.TokenScope}, nil) conOptions := shared.GetClientOptions(options) plOpts := runtime.PipelineOptions{ PerRetry: []policy.Policy{authPolicy}, @@ -68,9 +64,7 @@ func NewClient(filesystemURL string, cred azcore.TokenCredential, options *Clien // - filesystemURL - the URL of the storage account e.g. https://.dfs.core.windows.net/fs? // - options - client options; pass nil to accept the default values func NewClientWithNoCredential(filesystemURL string, options *ClientOptions) (*Client, error) { - containerURL := strings.Replace(filesystemURL, ".dfs.", ".blob.", 1) - filesystemURL = strings.Replace(filesystemURL, ".blob.", ".dfs.", 1) - + containerURL, filesystemURL := shared.GetURLs(filesystemURL) conOptions := shared.GetClientOptions(options) plOpts := runtime.PipelineOptions{} base.SetPipelineOptions((*base.ClientOptions)(conOptions), &plOpts) @@ -97,9 +91,7 @@ func NewClientWithNoCredential(filesystemURL string, options *ClientOptions) (*C // - cred - a SharedKeyCredential created with the matching storage account and access key // - options - client options; pass nil to accept the default values func NewClientWithSharedKeyCredential(filesystemURL string, cred *SharedKeyCredential, options *ClientOptions) (*Client, error) { - containerURL := strings.Replace(filesystemURL, ".dfs.", ".blob.", 1) - filesystemURL = strings.Replace(filesystemURL, ".blob.", ".dfs.", 1) - + containerURL, filesystemURL := shared.GetURLs(filesystemURL) authPolicy := exported.NewSharedKeyCredPolicy(cred) conOptions := shared.GetClientOptions(options) plOpts := runtime.PipelineOptions{ @@ -118,8 +110,11 @@ func NewClientWithSharedKeyCredential(filesystemURL string, cred *SharedKeyCrede containerClientOpts := container.ClientOptions{ ClientOptions: options.ClientOptions, } - blobSharedKeyCredential, _ := blob.NewSharedKeyCredential(cred.AccountName(), cred.AccountKey()) - blobContainerClient, _ := container.NewClientWithSharedKeyCredential(containerURL, blobSharedKeyCredential, &containerClientOpts) + blobSharedKey, err := cred.ConvertToBlobSharedKey() + if err != nil { + return nil, err + } + blobContainerClient, _ := container.NewClientWithSharedKeyCredential(containerURL, blobSharedKey, &containerClientOpts) fsClient := base.NewFilesystemClient(filesystemURL, containerURL, blobContainerClient, azClient, cred, (*base.ClientOptions)(conOptions)) return (*Client)(fsClient), nil diff --git a/sdk/storage/azdatalake/filesystem/constants.go b/sdk/storage/azdatalake/filesystem/constants.go index 3f862296578a..f7ff23ec01cd 100644 --- a/sdk/storage/azdatalake/filesystem/constants.go +++ b/sdk/storage/azdatalake/filesystem/constants.go @@ -17,6 +17,8 @@ const ( Filesystem PublicAccessType = azblob.PublicAccessTypeContainer ) +// TODO: figure out a way to import this from datalake rather than blob again + // StatusType defines values for StatusType type StatusType = lease.StatusType diff --git a/sdk/storage/azdatalake/filesystem/models.go b/sdk/storage/azdatalake/filesystem/models.go index 4da5f91d387e..c36a5acf1eb8 100644 --- a/sdk/storage/azdatalake/filesystem/models.go +++ b/sdk/storage/azdatalake/filesystem/models.go @@ -210,3 +210,9 @@ type LeaseAccessConditions = exported.LeaseAccessConditions // ModifiedAccessConditions contains a group of parameters for specifying access conditions. type ModifiedAccessConditions = exported.ModifiedAccessConditions + +// PathList contains the path list +type PathList = generated.PathList + +// Path contains the path properties +type Path = generated.Path diff --git a/sdk/storage/azdatalake/filesystem/responses.go b/sdk/storage/azdatalake/filesystem/responses.go index e0d4c79b9533..9a2112657bcc 100644 --- a/sdk/storage/azdatalake/filesystem/responses.go +++ b/sdk/storage/azdatalake/filesystem/responses.go @@ -28,28 +28,28 @@ type SetAccessPolicyResponse = container.SetAccessPolicyResponse // GetAccessPolicyResponse contains the response from method FilesystemClient.GetAccessPolicy. type GetAccessPolicyResponse struct { // PublicAccess contains the information returned from the x-ms-blob-public-access header response. - PublicAccess *PublicAccessType `xml:"BlobPublicAccess"` + PublicAccess *PublicAccessType // ClientRequestID contains the information returned from the x-ms-client-request-id header response. - ClientRequestID *string `xml:"ClientRequestID"` + ClientRequestID *string // Date contains the information returned from the Date header response. - Date *time.Time `xml:"Date"` + Date *time.Time // ETag contains the information returned from the ETag header response. - ETag *azcore.ETag `xml:"ETag"` + ETag *azcore.ETag // LastModified contains the information returned from the Last-Modified header response. - LastModified *time.Time `xml:"LastModified"` + LastModified *time.Time // RequestID contains the information returned from the x-ms-request-id header response. - RequestID *string `xml:"RequestID"` + RequestID *string // a collection of signed identifiers - SignedIdentifiers []*SignedIdentifier `xml:"SignedIdentifier"` + SignedIdentifiers []*SignedIdentifier // Version contains the information returned from the x-ms-version header response. - Version *string `xml:"Version"` + Version *string } // since we want to remove the blob prefix in access type @@ -140,3 +140,6 @@ type ListPathsSegmentResponse = generated.FileSystemClientListPathsResponse // ListDeletedPathsSegmentResponse contains the response from method FilesystemClient.ListPathsSegment. type ListDeletedPathsSegmentResponse = generated.FileSystemClientListBlobHierarchySegmentResponse + +// ListBlobsHierarchySegmentResponse contains the response from method FilesystemClient.ListBlobsHierarchySegment. +type ListBlobsHierarchySegmentResponse = generated.ListBlobsHierarchySegmentResponse diff --git a/sdk/storage/azdatalake/go.mod b/sdk/storage/azdatalake/go.mod index 815ae6a72795..b1b48ee155fd 100644 --- a/sdk/storage/azdatalake/go.mod +++ b/sdk/storage/azdatalake/go.mod @@ -3,7 +3,7 @@ module github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake go 1.18 require ( - github.com/Azure/azure-sdk-for-go/sdk/azcore v1.5.0 + github.com/Azure/azure-sdk-for-go/sdk/azcore v1.6.1 github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0 github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.0.0 github.com/stretchr/testify v1.7.1 diff --git a/sdk/storage/azdatalake/go.sum b/sdk/storage/azdatalake/go.sum index 7999cbb85ae5..911682659b2b 100644 --- a/sdk/storage/azdatalake/go.sum +++ b/sdk/storage/azdatalake/go.sum @@ -1,5 +1,5 @@ -github.com/Azure/azure-sdk-for-go/sdk/azcore v1.5.0 h1:xGLAFFd9D3iLGxYiUGPdITSzsFmU1K8VtfuUHWAoN7M= -github.com/Azure/azure-sdk-for-go/sdk/azcore v1.5.0/go.mod h1:bjGvMhVMb+EEm3VRNQawDMUyMMjo+S5ewNjflkep/0Q= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.6.1 h1:SEy2xmstIphdPwNBUi7uhvjyjhVKISfwjfOJmuy7kg4= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.6.1/go.mod h1:bjGvMhVMb+EEm3VRNQawDMUyMMjo+S5ewNjflkep/0Q= github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.1.0 h1:QkAcEIAKbNL4KoFr4SathZPhDhF4mVwpBMFlYjyAqy8= github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0 h1:sXr+ck84g/ZlZUOZiNELInmMgOsuGwdjjVkEIde0OtY= github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0/go.mod h1:okt5dMMTOFjX/aovMlrjvvXoPMBVSPzk9185BT0+eZM= diff --git a/sdk/storage/azdatalake/internal/base/clients.go b/sdk/storage/azdatalake/internal/base/clients.go index e526f500a25e..3ebb6fc7ee69 100644 --- a/sdk/storage/azdatalake/internal/base/clients.go +++ b/sdk/storage/azdatalake/internal/base/clients.go @@ -22,24 +22,6 @@ type ClientOptions struct { pipelineOptions *runtime.PipelineOptions } -type Client[T any] struct { - inner *T - sharedKey *exported.SharedKeyCredential - options *ClientOptions -} - -func InnerClient[T any](client *Client[T]) *T { - return client.inner -} - -func SharedKey[T any](client *Client[T]) *exported.SharedKeyCredential { - return client.sharedKey -} - -func GetClientOptions[T any](client *Client[T]) *ClientOptions { - return client.options -} - func GetPipelineOptions(clOpts *ClientOptions) *runtime.PipelineOptions { return clOpts.pipelineOptions } @@ -96,3 +78,7 @@ func NewPathClient(dirURL string, dirURLWithBlobEndpoint string, client *blob.Cl options: options, } } + +func GetCompositeClientOptions[T, K, U any](client *CompositeClient[T, K, U]) *ClientOptions { + return client.options +} diff --git a/sdk/storage/azdatalake/internal/exported/log_events.go b/sdk/storage/azdatalake/internal/exported/log_events.go new file mode 100644 index 000000000000..4a9c3cafd628 --- /dev/null +++ b/sdk/storage/azdatalake/internal/exported/log_events.go @@ -0,0 +1,20 @@ +//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 exported + +import ( + "github.com/Azure/azure-sdk-for-go/sdk/internal/log" +) + +// NOTE: these are publicly exported via type-aliasing in azdatalake/log.go +const ( + // EventUpload is used when we compute number of chunks to upload and size of each chunk. + EventUpload log.Event = "azdatalake.Upload" + + // EventError is used for logging errors. + EventError log.Event = "azdatalake.Error" +) diff --git a/sdk/storage/azdatalake/internal/exported/shared_key_credential.go b/sdk/storage/azdatalake/internal/exported/shared_key_credential.go index 980b5a9a4f5a..63539ea0b10a 100644 --- a/sdk/storage/azdatalake/internal/exported/shared_key_credential.go +++ b/sdk/storage/azdatalake/internal/exported/shared_key_credential.go @@ -12,6 +12,7 @@ import ( "crypto/sha256" "encoding/base64" "fmt" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azblob" "net/http" "net/url" "sort" @@ -48,9 +49,12 @@ func (c *SharedKeyCredential) AccountName() string { return c.accountName } -// AccountKey returns the Storage account's name. -func (c *SharedKeyCredential) AccountKey() string { - return c.accountKeyString +func (c *SharedKeyCredential) ConvertToBlobSharedKey() (*azblob.SharedKeyCredential, error) { + cred, err := azblob.NewSharedKeyCredential(c.accountName, c.accountKeyString) + if err != nil { + return nil, err + } + return cred, nil } // SetAccountKey replaces the existing account key with the specified account key. diff --git a/sdk/storage/azdatalake/internal/shared/challenge_policy.go b/sdk/storage/azdatalake/internal/shared/challenge_policy.go deleted file mode 100644 index e7c8e9213d80..000000000000 --- a/sdk/storage/azdatalake/internal/shared/challenge_policy.go +++ /dev/null @@ -1,113 +0,0 @@ -//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 shared - -import ( - "errors" - "github.com/Azure/azure-sdk-for-go/sdk/azcore" - "github.com/Azure/azure-sdk-for-go/sdk/azcore/policy" - "github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime" - "net/http" - "strings" -) - -type storageAuthorizer struct { - scopes []string - tenantID string -} - -func NewStorageChallengePolicy(cred azcore.TokenCredential) policy.Policy { - s := storageAuthorizer{scopes: []string{TokenScope}} - return runtime.NewBearerTokenPolicy(cred, []string{TokenScope}, &policy.BearerTokenOptions{ - AuthorizationHandler: policy.AuthorizationHandler{ - OnRequest: s.onRequest, - OnChallenge: s.onChallenge, - }, - }) -} - -func (s *storageAuthorizer) onRequest(req *policy.Request, authNZ func(policy.TokenRequestOptions) error) error { - return authNZ(policy.TokenRequestOptions{Scopes: s.scopes}) -} - -func (s *storageAuthorizer) onChallenge(req *policy.Request, resp *http.Response, authNZ func(policy.TokenRequestOptions) error) error { - // parse the challenge - err := s.parseChallenge(resp) - if err != nil { - return err - } - // TODO: Set tenantID when policy.TokenRequestOptions supports it. https://github.com/Azure/azure-sdk-for-go/issues/19841 - return authNZ(policy.TokenRequestOptions{Scopes: s.scopes}) -} - -type challengePolicyError struct { - err error -} - -func (c *challengePolicyError) Error() string { - return c.err.Error() -} - -func (*challengePolicyError) NonRetriable() { - // marker method -} - -func (c *challengePolicyError) Unwrap() error { - return c.err -} - -// parses Tenant ID from auth challenge -// https://login.microsoftonline.com/00000000-0000-0000-0000-000000000000/oauth2/authorize -func parseTenant(url string) string { - if url == "" { - return "" - } - parts := strings.Split(url, "/") - if len(parts) >= 3 { - tenant := parts[3] - tenant = strings.ReplaceAll(tenant, ",", "") - return tenant - } else { - return "" - } -} - -func (s *storageAuthorizer) parseChallenge(resp *http.Response) error { - authHeader := resp.Header.Get("WWW-Authenticate") - if authHeader == "" { - return &challengePolicyError{err: errors.New("response has no WWW-Authenticate header for challenge authentication")} - } - - // Strip down to auth and resource - // Format is "Bearer authorization_uri=\"\" resource_id=\"\"" - authHeader = strings.ReplaceAll(authHeader, "Bearer ", "") - - parts := strings.Split(authHeader, " ") - - vals := map[string]string{} - for _, part := range parts { - subParts := strings.Split(part, "=") - if len(subParts) == 2 { - stripped := strings.ReplaceAll(subParts[1], "\"", "") - stripped = strings.TrimSuffix(stripped, ",") - vals[subParts[0]] = stripped - } - } - - s.tenantID = parseTenant(vals["authorization_uri"]) - - scope := vals["resource_id"] - if scope == "" { - return &challengePolicyError{err: errors.New("could not find a valid resource in the WWW-Authenticate header")} - } - - if !strings.HasSuffix(scope, "/.default") { - scope += "/.default" - } - s.scopes = []string{scope} - return nil -} diff --git a/sdk/storage/azdatalake/internal/shared/shared.go b/sdk/storage/azdatalake/internal/shared/shared.go index 7fd977d8b059..0e54e94827df 100644 --- a/sdk/storage/azdatalake/internal/shared/shared.go +++ b/sdk/storage/azdatalake/internal/shared/shared.go @@ -72,6 +72,12 @@ type ParsedConnectionString struct { AccountKey string } +func GetURLs(url string) (string, string) { + blobURL := strings.Replace(url, ".dfs.", ".blob.", 1) + dfsURL := strings.Replace(url, ".blob.", ".dfs.", 1) + return blobURL, dfsURL +} + func ParseConnectionString(connectionString string) (ParsedConnectionString, error) { const ( defaultScheme = "https" diff --git a/sdk/storage/azdatalake/internal/testcommon/clients_auth.go b/sdk/storage/azdatalake/internal/testcommon/clients_auth.go index e65e4914b2c6..5988e217e87e 100644 --- a/sdk/storage/azdatalake/internal/testcommon/clients_auth.go +++ b/sdk/storage/azdatalake/internal/testcommon/clients_auth.go @@ -3,6 +3,7 @@ package testcommon import ( "context" "errors" + "fmt" "github.com/Azure/azure-sdk-for-go/sdk/azcore" "github.com/Azure/azure-sdk-for-go/sdk/azcore/to" "github.com/Azure/azure-sdk-for-go/sdk/internal/recording" @@ -104,7 +105,59 @@ func GetFilesystemClient(fsName string, t *testing.T, accountType TestAccountTyp return filesystemClient, err } +func ServiceGetFilesystemClient(filesystemName string, s *service.Client) *filesystem.Client { + return s.NewFilesystemClient(filesystemName) +} + func DeleteFilesystem(ctx context.Context, _require *require.Assertions, filesystemClient *filesystem.Client) { _, err := filesystemClient.Delete(ctx, nil) _require.Nil(err) } + +func GetGenericConnectionString(accountType TestAccountType) (*string, error) { + accountName, accountKey := GetGenericAccountInfo(accountType) + if accountName == "" || accountKey == "" { + return nil, errors.New(string(accountType) + AccountNameEnvVar + " and/or " + string(accountType) + AccountKeyEnvVar + " environment variables not specified.") + } + connectionString := fmt.Sprintf("DefaultEndpointsProtocol=https;AccountName=%s;AccountKey=%s;EndpointSuffix=core.windows.net/", + accountName, accountKey) + return &connectionString, nil +} + +func CreateNewFilesystem(ctx context.Context, _require *require.Assertions, filesystemName string, serviceClient *service.Client) *filesystem.Client { + fsClient := ServiceGetFilesystemClient(filesystemName, serviceClient) + + _, err := fsClient.Create(ctx, nil) + _require.Nil(err) + // _require.Equal(cResp.RawResponse.StatusCode, 201) + return fsClient +} +func GetServiceClientFromConnectionString(t *testing.T, accountType TestAccountType, options *service.ClientOptions) (*service.Client, error) { + if options == nil { + options = &service.ClientOptions{} + } + SetClientOptions(t, &options.ClientOptions) + + transport, err := recording.NewRecordingHTTPClient(t, nil) + require.NoError(t, err) + options.Transport = transport + + cred, err := GetGenericConnectionString(accountType) + if err != nil { + return nil, err + } + svcClient, err := service.NewClientFromConnectionString(*cred, options) + return svcClient, err +} + +func GetServiceClientNoCredential(t *testing.T, sasUrl string, options *service.ClientOptions) (*service.Client, error) { + if options == nil { + options = &service.ClientOptions{} + } + + SetClientOptions(t, &options.ClientOptions) + + serviceClient, err := service.NewClientWithNoCredential(sasUrl, options) + + return serviceClient, err +} diff --git a/sdk/storage/azdatalake/log.go b/sdk/storage/azdatalake/log.go new file mode 100644 index 000000000000..a168fb01f8ba --- /dev/null +++ b/sdk/storage/azdatalake/log.go @@ -0,0 +1,19 @@ +//go:build go1.18 +// +build go1.18 + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package azdatalake + +import ( + "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/internal/exported" +) + +const ( + // EventUpload is used for logging events related to upload operation. + EventUpload = exported.EventUpload + + // EventError is used for logging errors. + EventError = exported.EventError +) diff --git a/sdk/storage/azdatalake/sas/service.go b/sdk/storage/azdatalake/sas/service.go index 23518b25676d..86a292028276 100644 --- a/sdk/storage/azdatalake/sas/service.go +++ b/sdk/storage/azdatalake/sas/service.go @@ -336,16 +336,16 @@ func parseFilesystemPermissions(s string) (FilesystemPermissions, error) { return p, nil } -// PathPermissions type simplifies creating the permissions string for an Azure Storage blob SAS. +// FilePermissions type simplifies creating the permissions string for an Azure Storage blob SAS. // Initialize an instance of this type and then call its String method to set BlobSignatureValues' Permissions field. -type PathPermissions struct { +type FilePermissions struct { Read, Add, Create, Write, Delete, List, Move bool Execute, Ownership, Permissions bool } // String produces the SAS permissions string for an Azure Storage blob. // Call this method to set BlobSignatureValues' Permissions field. -func (p *PathPermissions) String() string { +func (p *FilePermissions) String() string { var b bytes.Buffer if p.Read { b.WriteRune('r') @@ -380,9 +380,53 @@ func (p *PathPermissions) String() string { return b.String() } -// Parse initializes BlobPermissions' fields from a string. -func parsePathPermissions(s string) (PathPermissions, error) { - p := PathPermissions{} // Clear the flags +// DirectoryPermissions type simplifies creating the permissions string for an Azure Storage blob SAS. +// Initialize an instance of this type and then call its String method to set BlobSignatureValues' Permissions field. +type DirectoryPermissions struct { + Read, Add, Create, Write, Delete, List, Move bool + Execute, Ownership, Permissions bool +} + +// String produces the SAS permissions string for an Azure Storage blob. +// Call this method to set BlobSignatureValues' Permissions field. +func (p *DirectoryPermissions) String() string { + var b bytes.Buffer + if p.Read { + b.WriteRune('r') + } + if p.Add { + b.WriteRune('a') + } + if p.Create { + b.WriteRune('c') + } + if p.Write { + b.WriteRune('w') + } + if p.Delete { + b.WriteRune('d') + } + if p.List { + b.WriteRune('l') + } + if p.Move { + b.WriteRune('m') + } + if p.Execute { + b.WriteRune('e') + } + if p.Ownership { + b.WriteRune('o') + } + if p.Permissions { + b.WriteRune('p') + } + return b.String() +} + +// Since this is internal we can just always convert to FilePermissions to avoid some duplication here +func parsePathPermissions(s string) (FilePermissions, error) { + p := FilePermissions{} // Clear the flags for _, r := range s { switch r { case 'r': @@ -406,7 +450,7 @@ func parsePathPermissions(s string) (PathPermissions, error) { case 'p': p.Permissions = true default: - return PathPermissions{}, fmt.Errorf("invalid permission: '%v'", r) + return FilePermissions{}, fmt.Errorf("invalid permission: '%v'", r) } } return p, nil diff --git a/sdk/storage/azdatalake/service/client.go b/sdk/storage/azdatalake/service/client.go index 129bb5533f9a..9b7e8721c8db 100644 --- a/sdk/storage/azdatalake/service/client.go +++ b/sdk/storage/azdatalake/service/client.go @@ -11,14 +11,15 @@ import ( "github.com/Azure/azure-sdk-for-go/sdk/azcore" "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/blob" + "github.com/Azure/azure-sdk-for-go/sdk/internal/log" "github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/service" "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/filesystem" "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/shared" - "strings" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/sas" + "time" ) // ClientOptions contains the optional parameters when creating a Client. @@ -32,10 +33,8 @@ type Client base.CompositeClient[generated.ServiceClient, generated.ServiceClien // - cred - an Azure AD credential, typically obtained via the azidentity module // - options - client options; pass nil to accept the default values func NewClient(serviceURL string, cred azcore.TokenCredential, options *ClientOptions) (*Client, error) { - blobServiceURL := strings.Replace(serviceURL, ".dfs.", ".blob.", 1) - datalakeServiceURL := strings.Replace(serviceURL, ".blob.", ".dfs.", 1) - - authPolicy := shared.NewStorageChallengePolicy(cred) + blobServiceURL, datalakeServiceURL := shared.GetURLs(serviceURL) + authPolicy := runtime.NewBearerTokenPolicy(cred, []string{shared.TokenScope}, nil) conOptions := shared.GetClientOptions(options) plOpts := runtime.PipelineOptions{ PerRetry: []policy.Policy{authPolicy}, @@ -63,9 +62,7 @@ func NewClient(serviceURL string, cred azcore.TokenCredential, options *ClientOp // - serviceURL - the URL of the storage account e.g. https://.dfs.core.windows.net/ // - options - client options; pass nil to accept the default values. func NewClientWithNoCredential(serviceURL string, options *ClientOptions) (*Client, error) { - blobServiceURL := strings.Replace(serviceURL, ".dfs.", ".blob.", 1) - datalakeServiceURL := strings.Replace(serviceURL, ".blob.", ".dfs.", 1) - + blobServiceURL, datalakeServiceURL := shared.GetURLs(serviceURL) conOptions := shared.GetClientOptions(options) plOpts := runtime.PipelineOptions{} base.SetPipelineOptions((*base.ClientOptions)(conOptions), &plOpts) @@ -92,9 +89,7 @@ func NewClientWithNoCredential(serviceURL string, options *ClientOptions) (*Clie // - cred - a SharedKeyCredential created with the matching storage account and access key // - options - client options; pass nil to accept the default values func NewClientWithSharedKeyCredential(serviceURL string, cred *SharedKeyCredential, options *ClientOptions) (*Client, error) { - blobServiceURL := strings.Replace(serviceURL, ".dfs.", ".blob.", 1) - datalakeServiceURL := strings.Replace(serviceURL, ".blob.", ".dfs.", 1) - + blobServiceURL, datalakeServiceURL := shared.GetURLs(serviceURL) authPolicy := exported.NewSharedKeyCredPolicy(cred) conOptions := shared.GetClientOptions(options) plOpts := runtime.PipelineOptions{ @@ -113,8 +108,11 @@ func NewClientWithSharedKeyCredential(serviceURL string, cred *SharedKeyCredenti blobServiceClientOpts := service.ClientOptions{ ClientOptions: options.ClientOptions, } - blobSharedKeyCredential, _ := blob.NewSharedKeyCredential(cred.AccountName(), cred.AccountKey()) - blobSvcClient, _ := service.NewClientWithSharedKeyCredential(blobServiceURL, blobSharedKeyCredential, &blobServiceClientOpts) + blobSharedKey, err := cred.ConvertToBlobSharedKey() + if err != nil { + return nil, err + } + blobSvcClient, _ := service.NewClientWithSharedKeyCredential(blobServiceURL, blobSharedKey, &blobServiceClientOpts) svcClient := base.NewServiceClient(datalakeServiceURL, blobServiceURL, blobSvcClient, azClient, cred, (*base.ClientOptions)(conOptions)) return (*Client)(svcClient), nil @@ -140,23 +138,38 @@ func NewClientFromConnectionString(connectionString string, options *ClientOptio return NewClientWithNoCredential(parsed.ServiceURL, options) } +func (s *Client) getClientOptions() *base.ClientOptions { + return base.GetCompositeClientOptions((*base.CompositeClient[generated.ServiceClient, generated.ServiceClient, service.Client])(s)) +} + // NewFilesystemClient creates a new share.Client object by concatenating shareName to the end of this Client's URL. // The new share.Client uses the same request policy pipeline as the Client. func (s *Client) NewFilesystemClient(filesystemName string) *filesystem.Client { - //fsURL := runtime.JoinPaths(s.generatedServiceClientWithDFS().Endpoint(), filesystemName) - //return (*filesystem.Client)(base.NewFilesystemClient(fsURL, s.generated().Pipeline(), s.credential())) - return nil + filesystemURL := runtime.JoinPaths(s.generatedServiceClientWithDFS().Endpoint(), filesystemName) + // TODO: remove new azcore.Client creation after the API for shallow copying with new client name is implemented + clOpts := s.getClientOptions() + azClient, err := azcore.NewClient(shared.FilesystemClient, exported.ModuleVersion, *(base.GetPipelineOptions(clOpts)), &(clOpts.ClientOptions)) + if err != nil { + if log.Should(exported.EventError) { + log.Writef(exported.EventError, err.Error()) + } + return nil + } + filesystemURL, containerURL := shared.GetURLs(filesystemURL) + return (*filesystem.Client)(base.NewFilesystemClient(filesystemURL, containerURL, s.serviceClient().NewContainerClient(filesystemName), azClient, s.sharedKey(), clOpts)) } // NewDirectoryClient creates a new share.Client object by concatenating shareName to the end of this Client's URL. // The new share.Client uses the same request policy pipeline as the Client. func (s *Client) NewDirectoryClient(directoryName string) *filesystem.Client { + // TODO: implement once dir client is implemented return nil } // NewFileClient creates a new share.Client object by concatenating shareName to the end of this Client's URL. // The new share.Client uses the same request policy pipeline as the Client. func (s *Client) NewFileClient(fileName string) *filesystem.Client { + // TODO: implement once file client is implemented return nil } @@ -170,7 +183,7 @@ func (s *Client) generatedServiceClientWithBlob() *generated.ServiceClient { return svcClientWithBlob } -func (s *Client) containerClient() *service.Client { +func (s *Client) serviceClient() *service.Client { _, _, serviceClient := base.InnerClients((*base.CompositeClient[generated.ServiceClient, generated.ServiceClient, service.Client])(s)) return serviceClient } @@ -203,18 +216,61 @@ func (s *Client) DeleteFilesystem(ctx context.Context, filesystem string, option return resp, err } -// SetServiceProperties sets properties for a storage account's File service endpoint. (blob3) -func (s *Client) SetServiceProperties(ctx context.Context, options *SetPropertiesOptions) (SetPropertiesResponse, error) { - return SetPropertiesResponse{}, nil +// SetProperties sets properties for a storage account's File service endpoint. (blob3) +func (s *Client) SetProperties(ctx context.Context, options *SetPropertiesOptions) (SetPropertiesResponse, error) { + opts := options.format() + return s.serviceClient().SetProperties(ctx, opts) } // GetProperties gets properties for a storage account's File service endpoint. (blob3) func (s *Client) GetProperties(ctx context.Context, options *GetPropertiesOptions) (GetPropertiesResponse, error) { - return GetPropertiesResponse{}, nil + opts := options.format() + return s.serviceClient().GetProperties(ctx, opts) + } // NewListFilesystemsPager operation returns a pager of the shares under the specified account. (blob3) // For more information, see https://learn.microsoft.com/en-us/rest/api/storageservices/list-shares func (s *Client) NewListFilesystemsPager(options *ListFilesystemsOptions) *runtime.Pager[ListFilesystemsResponse] { - return nil + return runtime.NewPager(runtime.PagingHandler[ListFilesystemsResponse]{ + More: func(page ListFilesystemsResponse) bool { + return page.NextMarker != nil && len(*page.NextMarker) > 0 + }, + Fetcher: func(ctx context.Context, page *ListFilesystemsResponse) (ListFilesystemsResponse, error) { + if page == nil { + page = &ListFilesystemsResponse{} + opts := options.format() + page.blobPager = s.serviceClient().NewListContainersPager(opts) + } + newPage := ListFilesystemsResponse{} + currPage, err := page.blobPager.NextPage(context.TODO()) + if err != nil { + return newPage, err + } + newPage.Prefix = currPage.Prefix + newPage.Marker = currPage.Marker + newPage.MaxResults = currPage.MaxResults + newPage.NextMarker = currPage.NextMarker + newPage.Filesystems = convertContainerItemsToFSItems(currPage.ContainerItems) + newPage.ServiceEndpoint = currPage.ServiceEndpoint + newPage.blobPager = page.blobPager + + return newPage, err + }, + }) +} + +// GetSASURL is a convenience method for generating a SAS token for the currently pointed at account. +// It can only be used if the credential supplied during creation was a SharedKeyCredential. +func (s *Client) GetSASURL(resources sas.AccountResourceTypes, permissions sas.AccountPermissions, expiry time.Time, o *GetSASURLOptions) (string, error) { + // format all options to blob service options + res, perms, opts := o.format(resources, permissions) + return s.serviceClient().GetSASURL(res, perms, expiry, opts) } + +// TODO: Figure out how we can convert from blob delegation key to one defined in datalake +//// GetUserDelegationCredential obtains a UserDelegationKey object using the base ServiceURL object. +//// OAuth is required for this call, as well as any role that can delegate access to the storage account. +//func (s *Client) GetUserDelegationCredential(ctx context.Context, info KeyInfo, o *GetUserDelegationCredentialOptions) (*UserDelegationCredential, error) { +// return s.serviceClient().GetUserDelegationCredential(ctx, info, o) +//} diff --git a/sdk/storage/azdatalake/service/client_test.go b/sdk/storage/azdatalake/service/client_test.go new file mode 100644 index 000000000000..c222bac865d8 --- /dev/null +++ b/sdk/storage/azdatalake/service/client_test.go @@ -0,0 +1,751 @@ +//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 service_test + +import ( + "context" + "fmt" + "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/datalakeerror" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/filesystem" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/internal/shared" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/internal/testcommon" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/lease" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/sas" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/service" + "github.com/stretchr/testify/require" + "github.com/stretchr/testify/suite" + "os" + "testing" + "time" +) + +func Test(t *testing.T) { + recordMode := recording.GetRecordMode() + t.Logf("Running service Tests in %s mode\n", recordMode) + if recordMode == recording.LiveMode { + suite.Run(t, &ServiceRecordedTestsSuite{}) + suite.Run(t, &ServiceUnrecordedTestsSuite{}) + } else if recordMode == recording.PlaybackMode { + suite.Run(t, &ServiceRecordedTestsSuite{}) + } else if recordMode == recording.RecordingMode { + suite.Run(t, &ServiceRecordedTestsSuite{}) + } +} + +func (s *ServiceRecordedTestsSuite) BeforeTest(suite string, test string) { + testcommon.BeforeTest(s.T(), suite, test) +} + +func (s *ServiceRecordedTestsSuite) AfterTest(suite string, test string) { + testcommon.AfterTest(s.T(), suite, test) +} + +func (s *ServiceUnrecordedTestsSuite) BeforeTest(suite string, test string) { + +} + +func (s *ServiceUnrecordedTestsSuite) AfterTest(suite string, test string) { + +} + +type ServiceRecordedTestsSuite struct { + suite.Suite +} + +type ServiceUnrecordedTestsSuite struct { + suite.Suite +} + +func (s *ServiceRecordedTestsSuite) TestServiceClientFromConnectionString() { + _require := require.New(s.T()) + testName := s.T().Name() + + accountName, _ := testcommon.GetGenericAccountInfo(testcommon.TestAccountDatalake) + connectionString, _ := testcommon.GetGenericConnectionString(testcommon.TestAccountDatalake) + + parsedConnStr, err := shared.ParseConnectionString(*connectionString) + _require.Nil(err) + _require.Equal(parsedConnStr.ServiceURL, "https://"+accountName+".blob.core.windows.net/") + + sharedKeyCred, err := azdatalake.NewSharedKeyCredential(parsedConnStr.AccountName, parsedConnStr.AccountKey) + _require.Nil(err) + + svcClient, err := service.NewClientWithSharedKeyCredential(parsedConnStr.ServiceURL, sharedKeyCred, nil) + _require.Nil(err) + fsClient := testcommon.CreateNewFilesystem(context.Background(), _require, testcommon.GenerateFilesystemName(testName), svcClient) + defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) +} + +func (s *ServiceRecordedTestsSuite) TestSetPropertiesLogging() { + _require := require.New(s.T()) + svcClient, err := testcommon.GetServiceClient(s.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + days := to.Ptr[int32](5) + enabled := to.Ptr(true) + + loggingOpts := service.Logging{ + Read: enabled, Write: enabled, Delete: enabled, + RetentionPolicy: &service.RetentionPolicy{Enabled: enabled, Days: days}} + opts := service.SetPropertiesOptions{Logging: &loggingOpts} + _, err = svcClient.SetProperties(context.Background(), &opts) + + _require.Nil(err) + resp1, err := svcClient.GetProperties(context.Background(), nil) + + _require.Nil(err) + _require.Equal(resp1.Logging.Write, enabled) + _require.Equal(resp1.Logging.Read, enabled) + _require.Equal(resp1.Logging.Delete, enabled) + _require.Equal(resp1.Logging.RetentionPolicy.Days, days) + _require.Equal(resp1.Logging.RetentionPolicy.Enabled, enabled) +} + +func (s *ServiceRecordedTestsSuite) TestSetPropertiesHourMetrics() { + _require := require.New(s.T()) + svcClient, err := testcommon.GetServiceClient(s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + days := to.Ptr[int32](5) + enabled := to.Ptr(true) + + metricsOpts := service.Metrics{ + Enabled: enabled, IncludeAPIs: enabled, RetentionPolicy: &service.RetentionPolicy{Enabled: enabled, Days: days}} + opts := service.SetPropertiesOptions{HourMetrics: &metricsOpts} + _, err = svcClient.SetProperties(context.Background(), &opts) + + _require.Nil(err) + resp1, err := svcClient.GetProperties(context.Background(), nil) + + _require.Nil(err) + _require.Equal(resp1.HourMetrics.Enabled, enabled) + _require.Equal(resp1.HourMetrics.IncludeAPIs, enabled) + _require.Equal(resp1.HourMetrics.RetentionPolicy.Days, days) + _require.Equal(resp1.HourMetrics.RetentionPolicy.Enabled, enabled) +} + +func (s *ServiceRecordedTestsSuite) TestSetPropertiesMinuteMetrics() { + _require := require.New(s.T()) + svcClient, err := testcommon.GetServiceClient(s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + days := to.Ptr[int32](5) + enabled := to.Ptr(true) + + metricsOpts := service.Metrics{ + Enabled: enabled, IncludeAPIs: enabled, RetentionPolicy: &service.RetentionPolicy{Enabled: enabled, Days: days}} + opts := service.SetPropertiesOptions{MinuteMetrics: &metricsOpts} + _, err = svcClient.SetProperties(context.Background(), &opts) + + _require.Nil(err) + resp1, err := svcClient.GetProperties(context.Background(), nil) + + _require.Nil(err) + _require.Equal(resp1.MinuteMetrics.Enabled, enabled) + _require.Equal(resp1.MinuteMetrics.IncludeAPIs, enabled) + _require.Equal(resp1.MinuteMetrics.RetentionPolicy.Days, days) + _require.Equal(resp1.MinuteMetrics.RetentionPolicy.Enabled, enabled) +} + +func (s *ServiceRecordedTestsSuite) TestSetPropertiesSetCORSMultiple() { + _require := require.New(s.T()) + svcClient, err := testcommon.GetServiceClient(s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + defaultAge := to.Ptr[int32](500) + defaultStr := to.Ptr[string]("") + + allowedOrigins1 := "www.xyz.com" + allowedMethods1 := "GET" + CORSOpts1 := &service.CORSRule{AllowedOrigins: &allowedOrigins1, AllowedMethods: &allowedMethods1} + + allowedOrigins2 := "www.xyz.com,www.ab.com,www.bc.com" + allowedMethods2 := "GET, PUT" + maxAge2 := to.Ptr[int32](500) + exposedHeaders2 := "x-ms-meta-data*,x-ms-meta-source*,x-ms-meta-abc,x-ms-meta-bcd" + allowedHeaders2 := "x-ms-meta-data*,x-ms-meta-target*,x-ms-meta-xyz,x-ms-meta-foo" + + CORSOpts2 := &service.CORSRule{ + AllowedOrigins: &allowedOrigins2, AllowedMethods: &allowedMethods2, + MaxAgeInSeconds: maxAge2, ExposedHeaders: &exposedHeaders2, AllowedHeaders: &allowedHeaders2} + + CORSRules := []*service.CORSRule{CORSOpts1, CORSOpts2} + + opts := service.SetPropertiesOptions{CORS: CORSRules} + _, err = svcClient.SetProperties(context.Background(), &opts) + + _require.Nil(err) + resp, err := svcClient.GetProperties(context.Background(), nil) + for i := 0; i < len(resp.CORS); i++ { + if resp.CORS[i].AllowedOrigins == &allowedOrigins1 { + _require.Equal(resp.CORS[i].AllowedMethods, &allowedMethods1) + _require.Equal(resp.CORS[i].MaxAgeInSeconds, defaultAge) + _require.Equal(resp.CORS[i].ExposedHeaders, defaultStr) + _require.Equal(resp.CORS[i].AllowedHeaders, defaultStr) + + } else if resp.CORS[i].AllowedOrigins == &allowedOrigins2 { + _require.Equal(resp.CORS[i].AllowedMethods, &allowedMethods2) + _require.Equal(resp.CORS[i].MaxAgeInSeconds, &maxAge2) + _require.Equal(resp.CORS[i].ExposedHeaders, &exposedHeaders2) + _require.Equal(resp.CORS[i].AllowedHeaders, &allowedHeaders2) + } + } + _require.Nil(err) +} + +func (s *ServiceRecordedTestsSuite) TestAccountDeleteRetentionPolicy() { + _require := require.New(s.T()) + svcClient, err := testcommon.GetServiceClient(s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + days := to.Ptr[int32](5) + enabled := to.Ptr(true) + _, err = svcClient.SetProperties(context.Background(), &service.SetPropertiesOptions{DeleteRetentionPolicy: &service.RetentionPolicy{Enabled: enabled, Days: days}}) + _require.Nil(err) + + // From FE, 30 seconds is guaranteed to be enough. + time.Sleep(time.Second * 30) + + resp, err := svcClient.GetProperties(context.Background(), nil) + _require.Nil(err) + _require.EqualValues(*resp.StorageServiceProperties.DeleteRetentionPolicy.Enabled, *enabled) + _require.EqualValues(*resp.StorageServiceProperties.DeleteRetentionPolicy.Days, *days) + + disabled := false + _, err = svcClient.SetProperties(context.Background(), &service.SetPropertiesOptions{DeleteRetentionPolicy: &service.RetentionPolicy{Enabled: &disabled}}) + _require.Nil(err) + + // From FE, 30 seconds is guaranteed to be enough. + time.Sleep(time.Second * 30) + + resp, err = svcClient.GetProperties(context.Background(), nil) + _require.Nil(err) + _require.EqualValues(*resp.StorageServiceProperties.DeleteRetentionPolicy.Enabled, false) + _require.Nil(resp.StorageServiceProperties.DeleteRetentionPolicy.Days) +} + +func (s *ServiceRecordedTestsSuite) TestAccountDeleteRetentionPolicyEmpty() { + _require := require.New(s.T()) + svcClient, err := testcommon.GetServiceClient(s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + days := to.Ptr[int32](5) + enabled := to.Ptr(true) + _, err = svcClient.SetProperties(context.Background(), &service.SetPropertiesOptions{DeleteRetentionPolicy: &service.RetentionPolicy{Enabled: enabled, Days: days}}) + _require.Nil(err) + + // From FE, 30 seconds is guaranteed to be enough. + time.Sleep(time.Second * 30) + + resp, err := svcClient.GetProperties(context.Background(), nil) + _require.Nil(err) + _require.EqualValues(*resp.StorageServiceProperties.DeleteRetentionPolicy.Enabled, *enabled) + _require.EqualValues(*resp.StorageServiceProperties.DeleteRetentionPolicy.Days, *days) + + // Empty retention policy causes an error, this is different from track 1.5 + _, err = svcClient.SetProperties(context.Background(), &service.SetPropertiesOptions{DeleteRetentionPolicy: &service.RetentionPolicy{}}) + _require.NotNil(err) +} + +func (s *ServiceRecordedTestsSuite) TestAccountDeleteRetentionPolicyNil() { + _require := require.New(s.T()) + svcClient, err := testcommon.GetServiceClient(s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + days := to.Ptr[int32](5) + enabled := to.Ptr(true) + _, err = svcClient.SetProperties(context.Background(), &service.SetPropertiesOptions{DeleteRetentionPolicy: &service.RetentionPolicy{Enabled: enabled, Days: days}}) + _require.Nil(err) + + // From FE, 30 seconds is guaranteed to be enough. + time.Sleep(time.Second * 30) + + resp, err := svcClient.GetProperties(context.Background(), nil) + _require.Nil(err) + _require.EqualValues(*resp.StorageServiceProperties.DeleteRetentionPolicy.Enabled, *enabled) + _require.EqualValues(*resp.StorageServiceProperties.DeleteRetentionPolicy.Days, *days) + + _, err = svcClient.SetProperties(context.Background(), &service.SetPropertiesOptions{}) + _require.Nil(err) + + // From FE, 30 seconds is guaranteed to be enough. + time.Sleep(time.Second * 30) + + // If an element of service properties is not passed, the service keeps the current settings. + resp, err = svcClient.GetProperties(context.Background(), nil) + _require.Nil(err) + _require.EqualValues(*resp.StorageServiceProperties.DeleteRetentionPolicy.Enabled, *enabled) + _require.EqualValues(*resp.StorageServiceProperties.DeleteRetentionPolicy.Days, *days) + + // Disable for other tests + enabled = to.Ptr(false) + _, err = svcClient.SetProperties(context.Background(), &service.SetPropertiesOptions{DeleteRetentionPolicy: &service.RetentionPolicy{Enabled: enabled}}) + _require.Nil(err) +} + +func (s *ServiceRecordedTestsSuite) TestAccountDeleteRetentionPolicyDaysTooLarge() { + _require := require.New(s.T()) + var svcClient *service.Client + var err error + for i := 1; i <= 2; i++ { + if i == 1 { + svcClient, err = testcommon.GetServiceClient(s.T(), testcommon.TestAccountDatalake, nil) + } else { + svcClient, err = testcommon.GetServiceClientFromConnectionString(s.T(), testcommon.TestAccountDatalake, nil) + } + _require.Nil(err) + + days := int32(366) // Max days is 365. Left to the service for validation. + enabled := true + _, err = svcClient.SetProperties(context.Background(), &service.SetPropertiesOptions{DeleteRetentionPolicy: &service.RetentionPolicy{Enabled: &enabled, Days: &days}}) + _require.NotNil(err) + + testcommon.ValidateBlobErrorCode(_require, err, datalakeerror.InvalidXMLDocument) + } +} + +func (s *ServiceRecordedTestsSuite) TestAccountDeleteRetentionPolicyDaysOmitted() { + _require := require.New(s.T()) + svcClient, err := testcommon.GetServiceClient(s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + // Days is required if enabled is true. + enabled := true + _, err = svcClient.SetProperties(context.Background(), &service.SetPropertiesOptions{DeleteRetentionPolicy: &service.RetentionPolicy{Enabled: &enabled}}) + _require.NotNil(err) + + testcommon.ValidateBlobErrorCode(_require, err, datalakeerror.InvalidXMLDocument) +} + +func (s *ServiceRecordedTestsSuite) TestSASServiceClient() { + _require := require.New(s.T()) + testName := s.T().Name() + cred, _ := testcommon.GetGenericSharedKeyCredential(testcommon.TestAccountDatalake) + + serviceClient, err := service.NewClientWithSharedKeyCredential(fmt.Sprintf("https://%s.dfs.core.windows.net/", cred.AccountName()), cred, nil) + _require.Nil(err) + + fsName := testcommon.GenerateFilesystemName(testName) + + // Note: Always set all permissions, services, types to true to ensure order of string formed is correct. + resources := sas.AccountResourceTypes{ + Object: true, + Service: true, + Container: true, + } + permissions := sas.AccountPermissions{ + Read: true, + Write: true, + Delete: true, + DeletePreviousVersion: true, + List: true, + Add: true, + Create: true, + Update: true, + Process: true, + Tag: true, + FilterByTags: true, + PermanentDelete: true, + } + expiry := time.Now().Add(time.Hour) + sasUrl, err := serviceClient.GetSASURL(resources, permissions, expiry, nil) + _require.Nil(err) + + svcClient, err := testcommon.GetServiceClientNoCredential(s.T(), sasUrl, nil) + _require.Nil(err) + + // create fs using SAS + _, err = svcClient.CreateFilesystem(context.Background(), fsName, nil) + _require.Nil(err) + + _, err = svcClient.DeleteFilesystem(context.Background(), fsName, nil) + _require.Nil(err) +} + +func (s *ServiceRecordedTestsSuite) TestSASServiceClientNoKey() { + _require := require.New(s.T()) + accountName := os.Getenv("AZURE_STORAGE_ACCOUNT_NAME") + + serviceClient, err := service.NewClientWithNoCredential(fmt.Sprintf("https://%s.blob.core.windows.net/", accountName), nil) + _require.Nil(err) + resources := sas.AccountResourceTypes{ + Object: true, + Service: true, + Container: true, + } + permissions := sas.AccountPermissions{ + Read: true, + Write: true, + Delete: true, + DeletePreviousVersion: true, + List: true, + Add: true, + Create: true, + Update: true, + Process: true, + Tag: true, + FilterByTags: true, + PermanentDelete: true, + } + + expiry := time.Now().Add(time.Hour) + _, err = serviceClient.GetSASURL(resources, permissions, expiry, nil) + _require.Equal(err.Error(), "SAS can only be signed with a SharedKeyCredential") +} + +func (s *ServiceUnrecordedTestsSuite) TestSASServiceClientSignNegative() { + _require := require.New(s.T()) + accountName := os.Getenv("AZURE_STORAGE_ACCOUNT_NAME") + accountKey := os.Getenv("AZURE_STORAGE_ACCOUNT_KEY") + cred, err := azdatalake.NewSharedKeyCredential(accountName, accountKey) + _require.Nil(err) + + serviceClient, err := service.NewClientWithSharedKeyCredential(fmt.Sprintf("https://%s.blob.core.windows.net/", accountName), cred, nil) + _require.Nil(err) + resources := sas.AccountResourceTypes{ + Object: true, + Service: true, + Container: true, + } + permissions := sas.AccountPermissions{ + Read: true, + Write: true, + Delete: true, + DeletePreviousVersion: true, + List: true, + Add: true, + Create: true, + Update: true, + Process: true, + Tag: true, + FilterByTags: true, + PermanentDelete: true, + } + expiry := time.Time{} + _, err = serviceClient.GetSASURL(resources, permissions, expiry, nil) + _require.Equal(err.Error(), "account SAS is missing at least one of these: ExpiryTime, Permissions, Service, or ResourceType") +} + +func (s *ServiceUnrecordedTestsSuite) TestNoSharedKeyCredError() { + _require := require.New(s.T()) + accountName := os.Getenv("AZURE_STORAGE_ACCOUNT_NAME") + + // Creating service client without credentials + serviceClient, err := service.NewClientWithNoCredential(fmt.Sprintf("https://%s.blob.core.windows.net/", accountName), nil) + _require.Nil(err) + + // Adding SAS and options + resources := sas.AccountResourceTypes{ + Object: true, + Service: true, + Container: true, + } + permissions := sas.AccountPermissions{ + Read: true, + Add: true, + Write: true, + Create: true, + Update: true, + Delete: true, + } + start := time.Now().Add(-time.Hour) + expiry := start.Add(time.Hour) + opts := service.GetSASURLOptions{StartTime: &start} + + // GetSASURL fails (with MissingSharedKeyCredential) because service client is created without credentials + _, err = serviceClient.GetSASURL(resources, permissions, expiry, &opts) + _require.Equal(err, datalakeerror.MissingSharedKeyCredential) + +} + +func (s *ServiceRecordedTestsSuite) TestSASFilesystemClient() { + _require := require.New(s.T()) + testName := s.T().Name() + accountName := os.Getenv("AZURE_STORAGE_ACCOUNT_NAME") + accountKey := os.Getenv("AZURE_STORAGE_ACCOUNT_KEY") + cred, err := azdatalake.NewSharedKeyCredential(accountName, accountKey) + _require.Nil(err) + + serviceClient, err := service.NewClientWithSharedKeyCredential(fmt.Sprintf("https://%s.blob.core.windows.net/", accountName), cred, nil) + _require.Nil(err) + + fsName := testcommon.GenerateFilesystemName(testName) + fsClient := serviceClient.NewFilesystemClient(fsName) + + permissions := sas.FilesystemPermissions{ + Read: true, + Add: true, + } + start := time.Now().Add(-5 * time.Minute).UTC() + expiry := time.Now().Add(time.Hour) + + opts := filesystem.GetSASURLOptions{StartTime: &start} + sasUrl, err := fsClient.GetSASURL(permissions, expiry, &opts) + _require.Nil(err) + + fsClient2, err := filesystem.NewClientWithNoCredential(sasUrl, nil) + _require.Nil(err) + + _, err = fsClient2.Create(context.Background(), &filesystem.CreateOptions{Metadata: testcommon.BasicMetadata}) + _require.NotNil(err) + testcommon.ValidateBlobErrorCode(_require, err, datalakeerror.AuthorizationFailure) +} + +func (s *ServiceRecordedTestsSuite) TestSASFilesystem2() { + _require := require.New(s.T()) + testName := s.T().Name() + accountName := os.Getenv("AZURE_STORAGE_ACCOUNT_NAME") + accountKey := os.Getenv("AZURE_STORAGE_ACCOUNT_KEY") + cred, err := azdatalake.NewSharedKeyCredential(accountName, accountKey) + _require.Nil(err) + + serviceClient, err := service.NewClientWithSharedKeyCredential(fmt.Sprintf("https://%s.blob.core.windows.net/", accountName), cred, nil) + _require.Nil(err) + + fsName := testcommon.GenerateFilesystemName(testName) + fsClient := serviceClient.NewFilesystemClient(fsName) + start := time.Now().Add(-5 * time.Minute).UTC() + opts := filesystem.GetSASURLOptions{StartTime: &start} + + sasUrlReadAdd, err := fsClient.GetSASURL(sas.FilesystemPermissions{Read: true, Add: true}, time.Now().Add(time.Hour), &opts) + _require.Nil(err) + _, err = fsClient.Create(context.Background(), &filesystem.CreateOptions{Metadata: testcommon.BasicMetadata}) + _require.Nil(err) + defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + + fsClient1, err := filesystem.NewClientWithNoCredential(sasUrlReadAdd, nil) + _require.Nil(err) + + // filesystem metadata and properties can't be read or written with SAS auth + _, err = fsClient1.GetProperties(context.Background(), nil) + _require.Error(err) + testcommon.ValidateBlobErrorCode(_require, err, datalakeerror.AuthorizationFailure) + + start = time.Now().Add(-5 * time.Minute).UTC() + opts = filesystem.GetSASURLOptions{StartTime: &start} + + sasUrlRCWL, err := fsClient.GetSASURL(sas.FilesystemPermissions{Add: true, Create: true, Delete: true, List: true}, time.Now().Add(time.Hour), &opts) + _require.Nil(err) + + fsClient2, err := filesystem.NewClientWithNoCredential(sasUrlRCWL, nil) + _require.Nil(err) + + // filesystems can't be created, deleted, or listed with SAS auth + _, err = fsClient2.Create(context.Background(), nil) + _require.Error(err) + testcommon.ValidateBlobErrorCode(_require, err, datalakeerror.AuthorizationFailure) +} + +func (s *ServiceRecordedTestsSuite) TestListFilesystemsBasic() { + _require := require.New(s.T()) + testName := s.T().Name() + svcClient, err := testcommon.GetServiceClient(s.T(), testcommon.TestAccountDatalake, nil) + _require.Nil(err) + md := map[string]*string{ + "foo": to.Ptr("foovalue"), + "bar": to.Ptr("barvalue"), + } + + fsName := testcommon.GenerateFilesystemName(testName) + fsClient := testcommon.ServiceGetFilesystemClient(fsName, svcClient) + _, err = fsClient.Create(context.Background(), &filesystem.CreateOptions{Metadata: md}) + defer func(fsClient *filesystem.Client, ctx context.Context, options *filesystem.DeleteOptions) { + _, err := fsClient.Delete(ctx, options) + if err != nil { + _require.Nil(err) + } + }(fsClient, context.Background(), nil) + _require.Nil(err) + prefix := testcommon.FilesystemPrefix + listOptions := service.ListFilesystemsOptions{Prefix: &prefix, Include: service.ListFilesystemsInclude{Metadata: true}} + pager := svcClient.NewListFilesystemsPager(&listOptions) + + count := 0 + for pager.More() { + resp, err := pager.NextPage(context.Background()) + _require.Nil(err) + for _, ctnr := range resp.Filesystems { + _require.NotNil(ctnr.Name) + + if *ctnr.Name == fsName { + _require.NotNil(ctnr.Properties) + _require.NotNil(ctnr.Properties.LastModified) + _require.NotNil(ctnr.Properties.ETag) + _require.Equal(*ctnr.Properties.LeaseStatus, lease.StatusTypeUnlocked) + _require.Equal(*ctnr.Properties.LeaseState, lease.StateTypeAvailable) + _require.Nil(ctnr.Properties.LeaseDuration) + _require.Nil(ctnr.Properties.PublicAccess) + _require.NotNil(ctnr.Metadata) + + unwrappedMeta := map[string]*string{} + for k, v := range ctnr.Metadata { + if v != nil { + unwrappedMeta[k] = v + } + } + + _require.EqualValues(unwrappedMeta, md) + } + } + if err != nil { + break + } + } + + _require.Nil(err) + _require.GreaterOrEqual(count, 0) +} + +func (s *ServiceRecordedTestsSuite) TestListFilesystemsBasicUsingConnectionString() { + _require := require.New(s.T()) + testName := s.T().Name() + svcClient, err := testcommon.GetServiceClientFromConnectionString(s.T(), testcommon.TestAccountDefault, nil) + _require.Nil(err) + md := map[string]*string{ + "foo": to.Ptr("foovalue"), + "bar": to.Ptr("barvalue"), + } + + fsName := testcommon.GenerateFilesystemName(testName) + fsClient := testcommon.ServiceGetFilesystemClient(fsName, svcClient) + _, err = fsClient.Create(context.Background(), &filesystem.CreateOptions{Metadata: md}) + defer func(fsClient *filesystem.Client, ctx context.Context, options *filesystem.DeleteOptions) { + _, err := fsClient.Delete(ctx, options) + if err != nil { + _require.Nil(err) + } + }(fsClient, context.Background(), nil) + _require.Nil(err) + prefix := testcommon.FilesystemPrefix + listOptions := service.ListFilesystemsOptions{Prefix: &prefix, Include: service.ListFilesystemsInclude{Metadata: true}} + pager := svcClient.NewListFilesystemsPager(&listOptions) + + count := 0 + for pager.More() { + resp, err := pager.NextPage(context.Background()) + _require.Nil(err) + + for _, ctnr := range resp.Filesystems { + _require.NotNil(ctnr.Name) + + if *ctnr.Name == fsName { + _require.NotNil(ctnr.Properties) + _require.NotNil(ctnr.Properties.LastModified) + _require.NotNil(ctnr.Properties.ETag) + _require.Equal(*ctnr.Properties.LeaseStatus, lease.StatusTypeUnlocked) + _require.Equal(*ctnr.Properties.LeaseState, lease.StateTypeAvailable) + _require.Nil(ctnr.Properties.LeaseDuration) + _require.Nil(ctnr.Properties.PublicAccess) + _require.NotNil(ctnr.Metadata) + + unwrappedMeta := map[string]*string{} + for k, v := range ctnr.Metadata { + if v != nil { + unwrappedMeta[k] = v + } + } + + _require.EqualValues(unwrappedMeta, md) + } + } + if err != nil { + break + } + } + + _require.Nil(err) + _require.GreaterOrEqual(count, 0) +} + +func (s *ServiceRecordedTestsSuite) TestListFilesystemsPaged() { + _require := require.New(s.T()) + testName := s.T().Name() + svcClient, err := testcommon.GetServiceClient(s.T(), testcommon.TestAccountDefault, nil) + _require.Nil(err) + const numFilesystems = 6 + maxResults := int32(2) + const pagedFilesystemsPrefix = "azfilesystempaged" + + filesystems := make([]*filesystem.Client, numFilesystems) + expectedResults := make(map[string]bool) + for i := 0; i < numFilesystems; i++ { + fsName := pagedFilesystemsPrefix + testcommon.GenerateFilesystemName(testName) + fmt.Sprintf("%d", i) + fsClient := testcommon.CreateNewFilesystem(context.Background(), _require, fsName, svcClient) + filesystems[i] = fsClient + expectedResults[fsName] = false + } + + defer func() { + for i := range filesystems { + testcommon.DeleteFilesystem(context.Background(), _require, filesystems[i]) + } + }() + + prefix := pagedFilesystemsPrefix + testcommon.FilesystemPrefix + listOptions := service.ListFilesystemsOptions{MaxResults: &maxResults, Prefix: &prefix, Include: service.ListFilesystemsInclude{Metadata: true}} + count := 0 + results := make([]service.FilesystemItem, 0) + pager := svcClient.NewListFilesystemsPager(&listOptions) + + for pager.More() { + resp, err := pager.NextPage(context.Background()) + _require.Nil(err) + for _, ctnr := range resp.Filesystems { + _require.NotNil(ctnr.Name) + results = append(results, *ctnr) + count += 1 + } + } + + _require.Equal(count, numFilesystems) + _require.Equal(len(results), numFilesystems) + + // make sure each fs we see is expected + for _, ctnr := range results { + _, ok := expectedResults[*ctnr.Name] + _require.Equal(ok, true) + expectedResults[*ctnr.Name] = true + } + + // make sure every expected fs was seen + for _, seen := range expectedResults { + _require.Equal(seen, true) + } + +} + +func (s *ServiceRecordedTestsSuite) TestAccountListFilesystemsEmptyPrefix() { + _require := require.New(s.T()) + testName := s.T().Name() + svcClient, err := testcommon.GetServiceClient(s.T(), testcommon.TestAccountDefault, nil) + _require.NoError(err) + + fsClient1 := testcommon.CreateNewFilesystem(context.Background(), _require, testcommon.GenerateFilesystemName(testName)+"1", svcClient) + defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient1) + fsClient2 := testcommon.CreateNewFilesystem(context.Background(), _require, testcommon.GenerateFilesystemName(testName)+"2", svcClient) + defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient2) + + count := 0 + pager := svcClient.NewListFilesystemsPager(nil) + + for pager.More() { + resp, err := pager.NextPage(context.Background()) + _require.Nil(err) + + for _, container := range resp.Filesystems { + count++ + _require.NotNil(container.Name) + } + if err != nil { + break + } + } + _require.GreaterOrEqual(count, 2) +} diff --git a/sdk/storage/azdatalake/service/models.go b/sdk/storage/azdatalake/service/models.go index bca2a179f73a..7f8fb9c9bb6b 100644 --- a/sdk/storage/azdatalake/service/models.go +++ b/sdk/storage/azdatalake/service/models.go @@ -7,10 +7,14 @@ package service import ( + "github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/lease" "github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/service" "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/filesystem" "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/internal/exported" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/sas" + "time" ) +import blobSAS "github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/sas" type CreateFilesystemOptions = filesystem.CreateOptions @@ -22,6 +26,9 @@ type DeleteFilesystemOptions = filesystem.DeleteOptions // domain) to call APIs in another domain. type CORSRule = service.CORSRule +// StorageServiceProperties - Storage Service Properties. +type StorageServiceProperties = service.StorageServiceProperties + // RetentionPolicy - the retention policy which determines how long the associated data should persist. type RetentionPolicy = service.RetentionPolicy @@ -34,13 +41,31 @@ type Logging = service.Logging // StaticWebsite - The properties that enable an account to host a static website. type StaticWebsite = service.StaticWebsite +// SharedKeyCredential contains an account's name and its primary or secondary key. +type SharedKeyCredential = exported.SharedKeyCredential + +// GetUserDelegationCredentialOptions contains the optional parameters for the Client.GetUserDelegationCredential method. +type GetUserDelegationCredentialOptions = service.GetUserDelegationCredentialOptions + +// KeyInfo contains KeyInfo struct. +type KeyInfo = service.KeyInfo + +// UserDelegationCredential contains an account's name and its user delegation key. +type UserDelegationCredential = exported.UserDelegationCredential + +// UserDelegationKey contains UserDelegationKey. +type UserDelegationKey = exported.UserDelegationKey + // GetPropertiesOptions contains the optional parameters for the Client.GetProperties method. type GetPropertiesOptions struct { // placeholder for future options } func (o *GetPropertiesOptions) format() *service.GetPropertiesOptions { - return nil + if o == nil { + return nil + } + return &service.GetPropertiesOptions{} } // SetPropertiesOptions provides set of options for Client.SetProperties @@ -72,7 +97,18 @@ type SetPropertiesOptions struct { } func (o *SetPropertiesOptions) format() *service.SetPropertiesOptions { - return nil + if o == nil { + return nil + } + return &service.SetPropertiesOptions{ + CORS: o.CORS, + DefaultServiceVersion: o.DefaultServiceVersion, + DeleteRetentionPolicy: o.DeleteRetentionPolicy, + HourMetrics: o.HourMetrics, + Logging: o.Logging, + MinuteMetrics: o.MinuteMetrics, + StaticWebsite: o.StaticWebsite, + } } // ListFilesystemsInclude indicates what additional information the service should return with each filesystem. @@ -84,6 +120,16 @@ type ListFilesystemsInclude struct { Deleted bool } +func (o *ListFilesystemsInclude) format() service.ListContainersInclude { + if o == nil { + return service.ListContainersInclude{} + } + return service.ListContainersInclude{ + Metadata: o.Metadata, + Deleted: o.Deleted, + } +} + // ListFilesystemsOptions contains the optional parameters for the Client.List method. type ListFilesystemsOptions struct { Include ListFilesystemsInclude @@ -92,7 +138,55 @@ type ListFilesystemsOptions struct { Prefix *string } -// TODO: Design formatter to convert to blob +func (o *ListFilesystemsOptions) format() *service.ListContainersOptions { + if o == nil { + return nil + } + return &service.ListContainersOptions{ + Include: o.Include.format(), + Marker: o.Marker, + MaxResults: o.MaxResults, + Prefix: o.Prefix, + } +} -// SharedKeyCredential contains an account's name and its primary or secondary key. -type SharedKeyCredential = exported.SharedKeyCredential +// GetSASURLOptions contains the optional parameters for the Client.GetSASURL method. +type GetSASURLOptions struct { + StartTime *time.Time +} + +func (o *GetSASURLOptions) format(resources sas.AccountResourceTypes, permissions sas.AccountPermissions) (blobSAS.AccountResourceTypes, blobSAS.AccountPermissions, *service.GetSASURLOptions) { + res := blobSAS.AccountResourceTypes{ + Service: resources.Service, + Container: resources.Container, + Object: resources.Object, + } + perms := blobSAS.AccountPermissions{ + Read: permissions.Read, + Write: permissions.Write, + Delete: permissions.Delete, + List: permissions.List, + Add: permissions.Add, + Create: permissions.Create, + Update: permissions.Update, + Process: permissions.Process, + } + if o == nil { + return res, perms, nil + } + + return res, perms, &service.GetSASURLOptions{ + StartTime: o.StartTime, + } +} + +// listing response models +// TODO: find another way to import these + +type LeaseDurationType = lease.DurationType + +type LeaseStateType = lease.StateType + +type LeaseStatusType = lease.StatusType + +type PublicAccessType = filesystem.PublicAccessType diff --git a/sdk/storage/azdatalake/service/responses.go b/sdk/storage/azdatalake/service/responses.go index e9393cbdbee3..377532f3488f 100644 --- a/sdk/storage/azdatalake/service/responses.go +++ b/sdk/storage/azdatalake/service/responses.go @@ -10,8 +10,11 @@ package service import ( + "github.com/Azure/azure-sdk-for-go/sdk/azcore" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime" "github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/service" "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/filesystem" + "time" ) // CreateFilesystemResponse contains the response fields for the CreateFilesystem operation. @@ -26,5 +29,96 @@ type SetPropertiesResponse = service.SetPropertiesResponse // GetPropertiesResponse contains the response fields for the GetProperties operation. type GetPropertiesResponse = service.GetPropertiesResponse -// ListFilesystemsResponse contains the response fields for the ListFilesystems operation. -type ListFilesystemsResponse = service.ListContainersResponse +// TODO: use below after implementing listing + +type ListFilesystemsResponse struct { + ListFilesystemsSegmentResponse + // ClientRequestID contains the information returned from the x-ms-client-request-id header response. + ClientRequestID *string + + // RequestID contains the information returned from the x-ms-request-id header response. + RequestID *string + + // Version contains the information returned from the x-ms-version header response. + Version *string + + blobPager *runtime.Pager[service.ListContainersResponse] +} + +// ListFilesystemsSegmentResponse - An enumeration of containers +type ListFilesystemsSegmentResponse struct { + // REQUIRED + Filesystems []*FilesystemItem + + // REQUIRED + ServiceEndpoint *string + Marker *string + MaxResults *int32 + NextMarker *string + Prefix *string +} + +// FilesystemItem - An Azure Storage filesystem +type FilesystemItem struct { + // REQUIRED + Name *string + + // REQUIRED; Properties of a container + Properties *FilesystemProperties + Deleted *bool + + // Dictionary of + Metadata map[string]*string + Version *string +} + +// FilesystemProperties - Properties of a filesystem +type FilesystemProperties struct { + // REQUIRED + ETag *azcore.ETag + + // REQUIRED + LastModified *time.Time + DefaultEncryptionScope *string + DeletedTime *time.Time + HasImmutabilityPolicy *bool + HasLegalHold *bool + + // Indicates if version level worm is enabled on this container. + IsImmutableStorageWithVersioningEnabled *bool + LeaseDuration *LeaseDurationType + LeaseState *LeaseStateType + LeaseStatus *LeaseStatusType + PreventEncryptionScopeOverride *bool + PublicAccess *PublicAccessType + RemainingRetentionDays *int32 +} + +// converter from container items to filesystem items +func convertContainerItemsToFSItems(items []*service.ContainerItem) []*FilesystemItem { + var filesystemItems []*FilesystemItem + for _, item := range items { + filesystemItems = append(filesystemItems, &FilesystemItem{ + Name: item.Name, + Properties: &FilesystemProperties{ + LastModified: item.Properties.LastModified, + ETag: item.Properties.ETag, + DefaultEncryptionScope: item.Properties.DefaultEncryptionScope, + LeaseStatus: item.Properties.LeaseStatus, + LeaseState: item.Properties.LeaseState, + LeaseDuration: item.Properties.LeaseDuration, + PublicAccess: item.Properties.PublicAccess, + HasImmutabilityPolicy: item.Properties.HasImmutabilityPolicy, + HasLegalHold: item.Properties.HasLegalHold, + IsImmutableStorageWithVersioningEnabled: item.Properties.IsImmutableStorageWithVersioningEnabled, + PreventEncryptionScopeOverride: item.Properties.PreventEncryptionScopeOverride, + RemainingRetentionDays: item.Properties.RemainingRetentionDays, + DeletedTime: item.Properties.DeletedTime, + }, + Deleted: item.Deleted, + Metadata: item.Metadata, + Version: item.Version, + }) + } + return filesystemItems +} From 9a351b9985395b1eb662883707871f9a0cb0adbd Mon Sep 17 00:00:00 2001 From: Tamer Sherif <69483382+tasherif-msft@users.noreply.github.com> Date: Wed, 19 Jul 2023 10:30:52 -0700 Subject: [PATCH 08/16] [AzDatalake] File Client Support (#21141) * Enable gocritic during linting (#20715) Enabled gocritic's evalOrder to catch dependencies on undefined behavior on return statements. Updated to latest version of golangci-lint. Fixed issue in azblob flagged by latest linter. * Cosmos DB: Enable merge support (#20716) * Adding header and value * Wiring and tests * format * Fixing value * change log * [azservicebus, azeventhubs] Stress test and logging improvement (#20710) Logging improvements: * Updating the logging to print more tracing information (per-link) in prep for the bigger release coming up. * Trimming out some of the verbose logging, seeing if I can get it a bit more reasonable. Stress tests: * Add a timestamp to the log name we generate and also default to append, not overwrite. * Use 0.5 cores, 0.5GB as our baseline. Some pods use more and I'll tune them more later. * update proxy version (#20712) Co-authored-by: Scott Beddall * Return an error when you try to send a message that's too large. (#20721) This now works just like the message batch - you'll get an ErrMessageTooLarge if you attempt to send a message that's too large for the link's configured size. NOTE: there's a patch to `internal/go-amqp/Sender.go` to match what's in go-amqp's main so it returns a programmatically useful error when the message is too large. Fixes #20647 * Changes in test that is failing in pipeline (#20693) * [azservicebus, azeventhubs] Treat 'entity full' as a fatal error (#20722) When the remote entity is full we get a resource-limit-exceeded condition. This isn't something we should keep retrying on and it's best to just abort and let the user know immediately, rather than hoping it might eventually clear out. This affected both Event Hubs and Service Bus. Fixes #20647 * [azservicebus/azeventhubs] Redirect stderr and stdout to tee (#20726) * Update changelog with latest features (#20730) * Update changelog with latest features Prepare for upcoming release. * bump minor version * pass along the artifact name so we can override it later (#20732) Co-authored-by: scbedd <45376673+scbedd@users.noreply.github.com> * [azeventhubs] Fixing checkpoint store race condition (#20727) The checkpoint store wasn't guarding against multiple owners claiming for the first time - fixing this by using IfNoneMatch Fixes #20717 * Fix azidentity troubleshooting guide link (#20736) * [Release] sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/0.1.0 (#20437) * [Release] sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/0.1.0 generation from spec commit: 85fb4ac6f8bfefd179e6c2632976a154b5c9ff04 * client factory * fix * fix * update * add sdk/resourcemanager/postgresql/armpostgresql live test (#20685) * add sdk/resourcemanager/postgresql/armpostgresql live test * update assets.json * set subscriptionId default value * format * add sdk/resourcemanager/eventhub/armeventhub live test (#20686) * add sdk/resourcemanager/eventhub/armeventhub live test * update assets * add sdk/resourcemanager/compute/armcompute live test (#20048) * add sdk/resourcemanager/compute/armcompute live test * skus filter * fix subscriptionId default value * fix * gofmt * update recording * sdk/resourcemanager/network/armnetwork live test (#20331) * sdk/resourcemanager/network/armnetwork live test * update subscriptionId default value * update recording * add sdk/resourcemanager/cosmos/armcosmos live test (#20705) * add sdk/resourcemanager/cosmos/armcosmos live test * update assets.json * update assets.json * update assets.json * update assets.json * Increment package version after release of azcore (#20740) * [azeventhubs] Improperly resetting etag in the checkpoint store (#20737) We shouldn't be resetting the etag to nil - it's what we use to enforce a "single winner" when doing ownership claims. The bug here was two-fold: I had bad logic in my previous claim ownership, which I fixed in a previous PR, but we need to reflect that same constraint properly in our in-memory checkpoint store for these tests. * Eng workflows sync and branch cleanup additions (#20743) Co-authored-by: James Suplizio * [azeventhubs] Latest start position can also be inclusive (ie, get the latest message) (#20744) * Update GitHubEventProcessor version and remove pull_request_review procesing (#20751) Co-authored-by: James Suplizio * Rename DisableAuthorityValidationAndInstanceDiscovery (#20746) * fix (#20707) * AzFile (#20739) * azfile: Fixing connection string parsing logic (#20798) * Fixing connection string parse logic * Update README * [azadmin] fix flaky test (#20758) * fix flaky test * charles suggestion * Prepare azidentity v1.3.0 for release (#20756) * Fix broken podman link (#20801) Co-authored-by: Wes Haggard * [azquery] update doc comments (#20755) * update doc comments * update statistics and visualization generation * prep-for-release * Fixed contribution section (#20752) Co-authored-by: Bob Tabor * [azeventhubs,azservicebus] Some API cleanup, renames (#20754) * Adding options to UpdateCheckpoint(), just for future potential expansion * Make Offset an int64, not a *int64 (it's not optional, it'll always come back with ReceivedEvents) * Adding more logging into the checkpoint store. * Point all imports at the production go-amqp * Add supporting features to enable distributed tracing (#20301) (#20708) * Add supporting features to enable distributed tracing This includes new internal pipeline policies and other supporting types. See the changelog for a full description. Added some missing doc comments. * fix linter issue * add net.peer.name trace attribute sequence custom HTTP header policy before logging policy. sequence logging policy after HTTP trace policy. keep body download policy at the end. * add span for iterating over pages * Restore ARM CAE support for azcore beta (#20657) This reverts commit 902097226ff3fe2fc6c3e7fc50d3478350253614. * Upgrade to stable azcore (#20808) * Increment package version after release of data/azcosmos (#20807) * Updating changelog (#20810) * Add fake package to azcore (#20711) * Add fake package to azcore This is the supporting infrastructure for the generated SDK fakes. * fix doc comment * Updating CHANGELOG.md (#20809) * changelog (#20811) * Increment package version after release of storage/azfile (#20813) * Update changelog (azblob) (#20815) * Updating CHANGELOG.md * Update the changelog with correct version * [azquery] migration guide (#20742) * migration guide * Charles feedback * Richard feedback --------- Co-authored-by: Charles Lowell <10964656+chlowell@users.noreply.github.com> * Increment package version after release of monitor/azquery (#20820) * [keyvault] prep for release (#20819) * prep for release * perf tests * update date * added apis and models * cleanup * cleanup + block blob client * added tests * added tests * added tests * added more tests * added more tests * dir block client * sas test * sas test --------- Co-authored-by: Joel Hendrix Co-authored-by: Matias Quaranta Co-authored-by: Richard Park <51494936+richardpark-msft@users.noreply.github.com> Co-authored-by: Azure SDK Bot <53356347+azure-sdk@users.noreply.github.com> Co-authored-by: Scott Beddall Co-authored-by: siminsavani-msft <77068571+siminsavani-msft@users.noreply.github.com> Co-authored-by: scbedd <45376673+scbedd@users.noreply.github.com> Co-authored-by: Charles Lowell <10964656+chlowell@users.noreply.github.com> Co-authored-by: Peng Jiahui <46921893+Alancere@users.noreply.github.com> Co-authored-by: James Suplizio Co-authored-by: Sourav Gupta <98318303+souravgupta-msft@users.noreply.github.com> Co-authored-by: gracewilcox <43627800+gracewilcox@users.noreply.github.com> Co-authored-by: Wes Haggard Co-authored-by: Bob Tabor Co-authored-by: Bob Tabor --- sdk/storage/azdatalake/assets.json | 2 +- .../azdatalake/datalakeerror/error_codes.go | 3 + sdk/storage/azdatalake/directory/client.go | 28 +- sdk/storage/azdatalake/file/client.go | 200 +- sdk/storage/azdatalake/file/client_test.go | 2312 +++++++++++++++++ sdk/storage/azdatalake/file/constants.go | 51 +- sdk/storage/azdatalake/file/models.go | 355 ++- sdk/storage/azdatalake/file/responses.go | 54 +- .../azdatalake/filesystem/client_test.go | 24 +- sdk/storage/azdatalake/filesystem/models.go | 15 + .../azdatalake/internal/base/clients.go | 10 +- .../internal/exported/access_conditions.go | 9 + .../internal/exported/set_expiry.go | 38 +- .../internal/testcommon/clients_auth.go | 40 + .../azdatalake/internal/testcommon/common.go | 6 +- sdk/storage/azdatalake/service/client_test.go | 10 +- 16 files changed, 2869 insertions(+), 288 deletions(-) create mode 100644 sdk/storage/azdatalake/file/client_test.go diff --git a/sdk/storage/azdatalake/assets.json b/sdk/storage/azdatalake/assets.json index cc6130dbb776..e712ffb1d71d 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_e05ec93d89" + "Tag": "go/storage/azdatalake_820b86faa9" } \ No newline at end of file diff --git a/sdk/storage/azdatalake/datalakeerror/error_codes.go b/sdk/storage/azdatalake/datalakeerror/error_codes.go index 2acc2e79fdc6..a40e54cebe37 100644 --- a/sdk/storage/azdatalake/datalakeerror/error_codes.go +++ b/sdk/storage/azdatalake/datalakeerror/error_codes.go @@ -178,4 +178,7 @@ const ( var ( // MissingSharedKeyCredential - Error is returned when SAS URL is being created without SharedKeyCredential. MissingSharedKeyCredential = bloberror.MissingSharedKeyCredential + + // MissingParameters - Error is returned when at least one parameter should be set for any API. + MissingParameters = errors.New("at least one parameter should be set for SetAccessControl API") ) diff --git a/sdk/storage/azdatalake/directory/client.go b/sdk/storage/azdatalake/directory/client.go index 749dfbc86724..b48045888290 100644 --- a/sdk/storage/azdatalake/directory/client.go +++ b/sdk/storage/azdatalake/directory/client.go @@ -11,7 +11,7 @@ import ( "github.com/Azure/azure-sdk-for-go/sdk/azcore" "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/blob" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/blockblob" "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" @@ -22,7 +22,7 @@ import ( type ClientOptions base.ClientOptions // Client represents a URL to the Azure Datalake Storage service. -type Client base.CompositeClient[generated.PathClient, generated.PathClient, blob.Client] +type Client base.CompositeClient[generated.PathClient, generated.PathClient, blockblob.Client] // NewClient creates an instance of Client with the specified values. // - directoryURL - the URL of the directory e.g. https://.dfs.core.windows.net/fs/dir @@ -46,10 +46,10 @@ func NewClient(directoryURL string, cred azcore.TokenCredential, options *Client if options == nil { options = &ClientOptions{} } - blobClientOpts := blob.ClientOptions{ + blobClientOpts := blockblob.ClientOptions{ ClientOptions: options.ClientOptions, } - blobClient, _ := blob.NewClient(blobURL, cred, &blobClientOpts) + blobClient, _ := blockblob.NewClient(blobURL, cred, &blobClientOpts) dirClient := base.NewPathClient(directoryURL, blobURL, blobClient, azClient, nil, (*base.ClientOptions)(conOptions)) return (*Client)(dirClient), nil @@ -74,10 +74,10 @@ func NewClientWithNoCredential(directoryURL string, options *ClientOptions) (*Cl if options == nil { options = &ClientOptions{} } - blobClientOpts := blob.ClientOptions{ + blobClientOpts := blockblob.ClientOptions{ ClientOptions: options.ClientOptions, } - blobClient, _ := blob.NewClientWithNoCredential(blobURL, &blobClientOpts) + blobClient, _ := blockblob.NewClientWithNoCredential(blobURL, &blobClientOpts) dirClient := base.NewPathClient(directoryURL, blobURL, blobClient, azClient, nil, (*base.ClientOptions)(conOptions)) return (*Client)(dirClient), nil @@ -105,15 +105,15 @@ func NewClientWithSharedKeyCredential(directoryURL string, cred *SharedKeyCreden if options == nil { options = &ClientOptions{} } - blobClientOpts := blob.ClientOptions{ + blobClientOpts := blockblob.ClientOptions{ ClientOptions: options.ClientOptions, } blobSharedKey, err := cred.ConvertToBlobSharedKey() if err != nil { return nil, err } - blobClient, _ := blob.NewClientWithSharedKeyCredential(blobURL, blobSharedKey, &blobClientOpts) - dirClient := base.NewPathClient(directoryURL, blobURL, blobClient, azClient, nil, (*base.ClientOptions)(conOptions)) + blobClient, _ := blockblob.NewClientWithSharedKeyCredential(blobURL, blobSharedKey, &blobClientOpts) + dirClient := base.NewPathClient(directoryURL, blobURL, blobClient, azClient, cred, (*base.ClientOptions)(conOptions)) return (*Client)(dirClient), nil } @@ -140,22 +140,22 @@ func NewClientFromConnectionString(connectionString string, options *ClientOptio func (d *Client) generatedDirClientWithDFS() *generated.PathClient { //base.SharedKeyComposite((*base.CompositeClient[generated.BlobClient, generated.BlockBlobClient])(bb)) - dirClientWithDFS, _, _ := base.InnerClients((*base.CompositeClient[generated.PathClient, generated.PathClient, blob.Client])(d)) + dirClientWithDFS, _, _ := base.InnerClients((*base.CompositeClient[generated.PathClient, generated.PathClient, blockblob.Client])(d)) return dirClientWithDFS } func (d *Client) generatedDirClientWithBlob() *generated.PathClient { - _, dirClientWithBlob, _ := base.InnerClients((*base.CompositeClient[generated.PathClient, generated.PathClient, blob.Client])(d)) + _, dirClientWithBlob, _ := base.InnerClients((*base.CompositeClient[generated.PathClient, generated.PathClient, blockblob.Client])(d)) return dirClientWithBlob } -func (d *Client) blobClient() *blob.Client { - _, _, blobClient := base.InnerClients((*base.CompositeClient[generated.PathClient, generated.PathClient, blob.Client])(d)) +func (d *Client) blobClient() *blockblob.Client { + _, _, blobClient := base.InnerClients((*base.CompositeClient[generated.PathClient, generated.PathClient, blockblob.Client])(d)) return blobClient } func (d *Client) sharedKey() *exported.SharedKeyCredential { - return base.SharedKeyComposite((*base.CompositeClient[generated.PathClient, generated.PathClient, blob.Client])(d)) + return base.SharedKeyComposite((*base.CompositeClient[generated.PathClient, generated.PathClient, blockblob.Client])(d)) } // DFSURL returns the URL endpoint used by the Client object. diff --git a/sdk/storage/azdatalake/file/client.go b/sdk/storage/azdatalake/file/client.go index c7355f3e0916..9d3e9da012ff 100644 --- a/sdk/storage/azdatalake/file/client.go +++ b/sdk/storage/azdatalake/file/client.go @@ -11,18 +11,21 @@ import ( "github.com/Azure/azure-sdk-for-go/sdk/azcore" "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/blob" + "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/shared" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/sas" + "time" ) // ClientOptions contains the optional parameters when creating a Client. type ClientOptions base.ClientOptions // Client represents a URL to the Azure Datalake Storage service. -type Client base.CompositeClient[generated.PathClient, generated.PathClient, blob.Client] +type Client base.CompositeClient[generated.PathClient, generated.PathClient, blockblob.Client] // NewClient creates an instance of Client with the specified values. // - fileURL - the URL of the blob e.g. https://.dfs.core.windows.net/fs/file.txt @@ -45,10 +48,10 @@ func NewClient(fileURL string, cred azcore.TokenCredential, options *ClientOptio if options == nil { options = &ClientOptions{} } - blobClientOpts := blob.ClientOptions{ + blobClientOpts := blockblob.ClientOptions{ ClientOptions: options.ClientOptions, } - blobClient, _ := blob.NewClient(blobURL, cred, &blobClientOpts) + blobClient, _ := blockblob.NewClient(blobURL, cred, &blobClientOpts) fileClient := base.NewPathClient(fileURL, blobURL, blobClient, azClient, nil, (*base.ClientOptions)(conOptions)) return (*Client)(fileClient), nil @@ -73,10 +76,10 @@ func NewClientWithNoCredential(fileURL string, options *ClientOptions) (*Client, if options == nil { options = &ClientOptions{} } - blobClientOpts := blob.ClientOptions{ + blobClientOpts := blockblob.ClientOptions{ ClientOptions: options.ClientOptions, } - blobClient, _ := blob.NewClientWithNoCredential(blobURL, &blobClientOpts) + blobClient, _ := blockblob.NewClientWithNoCredential(blobURL, &blobClientOpts) fileClient := base.NewPathClient(fileURL, blobURL, blobClient, azClient, nil, (*base.ClientOptions)(conOptions)) return (*Client)(fileClient), nil @@ -104,15 +107,15 @@ func NewClientWithSharedKeyCredential(fileURL string, cred *SharedKeyCredential, if options == nil { options = &ClientOptions{} } - blobClientOpts := blob.ClientOptions{ + blobClientOpts := blockblob.ClientOptions{ ClientOptions: options.ClientOptions, } blobSharedKey, err := cred.ConvertToBlobSharedKey() if err != nil { return nil, err } - blobClient, _ := blob.NewClientWithSharedKeyCredential(blobURL, blobSharedKey, &blobClientOpts) - fileClient := base.NewPathClient(fileURL, blobURL, blobClient, azClient, nil, (*base.ClientOptions)(conOptions)) + blobClient, _ := blockblob.NewClientWithSharedKeyCredential(blobURL, blobSharedKey, &blobClientOpts) + fileClient := base.NewPathClient(fileURL, blobURL, blobClient, azClient, cred, (*base.ClientOptions)(conOptions)) return (*Client)(fileClient), nil } @@ -139,22 +142,26 @@ func NewClientFromConnectionString(connectionString string, options *ClientOptio func (f *Client) generatedFileClientWithDFS() *generated.PathClient { //base.SharedKeyComposite((*base.CompositeClient[generated.BlobClient, generated.BlockBlobClient])(bb)) - dirClientWithDFS, _, _ := base.InnerClients((*base.CompositeClient[generated.PathClient, generated.PathClient, blob.Client])(f)) + dirClientWithDFS, _, _ := base.InnerClients((*base.CompositeClient[generated.PathClient, generated.PathClient, blockblob.Client])(f)) return dirClientWithDFS } func (f *Client) generatedFileClientWithBlob() *generated.PathClient { - _, dirClientWithBlob, _ := base.InnerClients((*base.CompositeClient[generated.PathClient, generated.PathClient, blob.Client])(f)) + _, dirClientWithBlob, _ := base.InnerClients((*base.CompositeClient[generated.PathClient, generated.PathClient, blockblob.Client])(f)) return dirClientWithBlob } -func (f *Client) blobClient() *blob.Client { - _, _, blobClient := base.InnerClients((*base.CompositeClient[generated.PathClient, generated.PathClient, blob.Client])(f)) +func (f *Client) blobClient() *blockblob.Client { + _, _, blobClient := base.InnerClients((*base.CompositeClient[generated.PathClient, generated.PathClient, blockblob.Client])(f)) return blobClient } func (f *Client) sharedKey() *exported.SharedKeyCredential { - return base.SharedKeyComposite((*base.CompositeClient[generated.PathClient, generated.PathClient, blob.Client])(f)) + return base.SharedKeyComposite((*base.CompositeClient[generated.PathClient, generated.PathClient, blockblob.Client])(f)) +} + +func (f *Client) getClientOptions() *base.ClientOptions { + return base.GetCompositeClientOptions((*base.CompositeClient[generated.PathClient, generated.PathClient, blockblob.Client])(f)) } // DFSURL returns the URL endpoint used by the Client object. @@ -169,96 +176,143 @@ func (f *Client) BlobURL() string { // Create creates a new file (dfs1). func (f *Client) Create(ctx context.Context, options *CreateOptions) (CreateResponse, error) { - // TODO: format for options should be able to handle the access conditions parameter correctly - return CreateResponse{}, nil + lac, mac, httpHeaders, createOpts, cpkOpts := options.format() + return f.generatedFileClientWithDFS().Create(ctx, createOpts, httpHeaders, lac, mac, nil, cpkOpts) } // Delete deletes a file (dfs1). func (f *Client) Delete(ctx context.Context, options *DeleteOptions) (DeleteResponse, error) { - // TODO: recursive set to false when calling generated code - return DeleteResponse{}, nil + lac, mac, deleteOpts := options.format() + return f.generatedFileClientWithDFS().Delete(ctx, deleteOpts, lac, mac) } // GetProperties gets the properties of a file (blob3) func (f *Client) GetProperties(ctx context.Context, options *GetPropertiesOptions) (GetPropertiesResponse, error) { - // TODO: format blob response to path response - return GetPropertiesResponse{}, nil -} - -// Rename renames a file (dfs1). -func (f *Client) Rename(ctx context.Context, newName string, options *RenameOptions) (RenameResponse, error) { - return RenameResponse{}, nil -} - -// SetExpiry operation sets an expiry time on an existing file. -func (f *Client) SetExpiry(ctx context.Context, expiryType ExpiryType, o *SetExpiryOptions) (SetExpiryResponse, error) { - // TODO: consider using the blob client set expiry - // TODO: call methods in set_expiry.go - return SetExpiryResponse{}, nil -} - -// Upload uploads data to a file. -func (f *Client) Upload(ctx context.Context) { - -} - -// Append appends data to a file. -func (f *Client) Append(ctx context.Context) { - + opts := options.format() + // TODO: format response + add acls, owner, group, permissions to it + return f.blobClient().GetProperties(ctx, opts) } -// Flush flushes previous uploaded data to a file. -func (f *Client) Flush(ctx context.Context) { - +// TODO: implement below +//// Rename renames a file (dfs1). TODO: look into returning a new client possibly or changing the url +//func (f *Client) Rename(ctx context.Context, newName string, options *RenameOptions) (RenameResponse, error) { +// path, err := url.Parse(f.DFSURL()) +// if err != nil { +// return RenameResponse{}, err +// } +// lac, mac, smac, createOpts := options.format(path.Path) +// fileURL := runtime.JoinPaths(f.generatedFileClientWithDFS().Endpoint(), newName) +// // TODO: remove new azcore.Client creation after the API for shallow copying with new client name is implemented +// clOpts := f.getClientOptions() +// azClient, err := azcore.NewClient(shared.FileClient, exported.ModuleVersion, *(base.GetPipelineOptions(clOpts)), &(clOpts.ClientOptions)) +// if err != nil { +// if log.Should(exported.EventError) { +// log.Writef(exported.EventError, err.Error()) +// } +// return RenameResponse{}, err +// } +// blobURL, fileURL := shared.GetURLs(fileURL) +// tempFileClient := (*Client)(base.NewPathClient(fileURL, blobURL, nil, azClient, f.sharedKey(), clOpts)) +// // this tempClient does not have a blobClient +// return tempFileClient.generatedFileClientWithDFS().Create(ctx, createOpts, nil, lac, mac, smac, nil) +//} + +// SetExpiry operation sets an expiry time on an existing file (blob2). +func (f *Client) SetExpiry(ctx context.Context, expiryType SetExpiryType, o *SetExpiryOptions) (SetExpiryResponse, error) { + expMode, opts := expiryType.Format(o) + return f.generatedFileClientWithBlob().SetExpiry(ctx, expMode, opts) } -// Download downloads data from a file. -func (f *Client) Download(ctx context.Context) { - -} +//// Upload uploads data to a file. +//func (f *Client) Upload(ctx context.Context) { +// +//} +// +//// Append appends data to a file. +//func (f *Client) Append(ctx context.Context) { +// +//} +// +//// Flush flushes previous uploaded data to a file. +//func (f *Client) Flush(ctx context.Context) { +// +//} +// +//// Download downloads data from a file. +//func (f *Client) Download(ctx context.Context) { +// +//} // SetAccessControl sets the owner, owning group, and permissions for a file or directory (dfs1). func (f *Client) SetAccessControl(ctx context.Context, options *SetAccessControlOptions) (SetAccessControlResponse, error) { - return SetAccessControlResponse{}, nil -} - -// SetAccessControlRecursive sets the owner, owning group, and permissions for a file or directory (dfs1). -func (f *Client) SetAccessControlRecursive(ctx context.Context, options *SetAccessControlRecursiveOptions) (SetAccessControlRecursiveResponse, error) { - // TODO explicitly pass SetAccessControlRecursiveMode - return SetAccessControlRecursiveResponse{}, nil + opts, lac, mac, err := options.format() + if err != nil { + return SetAccessControlResponse{}, err + } + return f.generatedFileClientWithDFS().SetAccessControl(ctx, opts, lac, mac) } -// UpdateAccessControlRecursive updates the owner, owning group, and permissions for a file or directory (dfs1). -func (f *Client) UpdateAccessControlRecursive(ctx context.Context, options *UpdateAccessControlRecursiveOptions) (UpdateAccessControlRecursiveResponse, error) { - // TODO explicitly pass SetAccessControlRecursiveMode - return SetAccessControlRecursiveResponse{}, nil +// UpdateAccessControl updates the owner, owning group, and permissions for a file or directory (dfs1). +func (f *Client) UpdateAccessControl(ctx context.Context, ACL string, options *UpdateAccessControlOptions) (UpdateAccessControlResponse, error) { + opts, mode := options.format(ACL) + return f.generatedFileClientWithDFS().SetAccessControlRecursive(ctx, mode, opts) } // GetAccessControl gets the owner, owning group, and permissions for a file or directory (dfs1). func (f *Client) GetAccessControl(ctx context.Context, options *GetAccessControlOptions) (GetAccessControlResponse, error) { - return GetAccessControlResponse{}, nil + opts, lac, mac := options.format() + return f.generatedFileClientWithDFS().GetProperties(ctx, opts, lac, mac) } -// RemoveAccessControlRecursive removes the owner, owning group, and permissions for a file or directory (dfs1). -func (f *Client) RemoveAccessControlRecursive(ctx context.Context, options *RemoveAccessControlRecursiveOptions) (RemoveAccessControlRecursiveResponse, error) { - // TODO explicitly pass SetAccessControlRecursiveMode - return SetAccessControlRecursiveResponse{}, nil +// RemoveAccessControl removes the owner, owning group, and permissions for a file or directory (dfs1). +func (f *Client) RemoveAccessControl(ctx context.Context, ACL string, options *RemoveAccessControlOptions) (RemoveAccessControlResponse, error) { + opts, mode := options.format(ACL) + return f.generatedFileClientWithDFS().SetAccessControlRecursive(ctx, mode, opts) } // SetMetadata sets the metadata for a file or directory (blob3). func (f *Client) SetMetadata(ctx context.Context, options *SetMetadataOptions) (SetMetadataResponse, error) { - // TODO: call directly into blob - return SetMetadataResponse{}, nil + opts, metadata := options.format() + return f.blobClient().SetMetadata(ctx, metadata, opts) } // SetHTTPHeaders sets the HTTP headers for a file or directory (blob3). func (f *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 := options.format(httpHeaders) + resp, err := f.blobClient().SetHTTPHeaders(ctx, blobHTTPHeaders, opts) + newResp := SetHTTPHeadersResponse{} + formatSetHTTPHeadersResponse(&newResp, &resp) + return newResp, err } -// UndeletePath restores the specified path that was previously deleted. (dfs op/blob2). -func (f *Client) UndeletePath(ctx context.Context, path string, options *UndeletePathOptions) (UndeletePathResponse, error) { - return UndeletePathResponse{}, nil +// 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.FilePermissions, expiry time.Time, o *GetSASURLOptions) (string, error) { + if f.sharedKey() == nil { + return "", datalakeerror.MissingSharedKeyCredential + } + + urlParts, err := sas.ParseURL(f.BlobURL()) + if err != nil { + return "", err + } + + st := o.format() + + qps, err := sas.DatalakeSignatureValues{ + FilePath: urlParts.PathName, + FilesystemName: urlParts.FilesystemName, + Version: sas.Version, + Permissions: permissions.String(), + StartTime: st, + ExpiryTime: expiry.UTC(), + }.SignWithSharedKey(f.sharedKey()) + + if err != nil { + return "", err + } + + endpoint := f.BlobURL() + "?" + qps.Encode() + + return endpoint, nil } diff --git a/sdk/storage/azdatalake/file/client_test.go b/sdk/storage/azdatalake/file/client_test.go new file mode 100644 index 000000000000..cd786f2a08e3 --- /dev/null +++ b/sdk/storage/azdatalake/file/client_test.go @@ -0,0 +1,2312 @@ +//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 file_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/file" + "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" + "net/http" + "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 validateFileDeleted(_require *require.Assertions, fileClient *file.Client) { + _, err := fileClient.GetAccessControl(context.Background(), nil) + _require.NotNil(err) + + testcommon.ValidateErrorCode(_require, err, datalakeerror.BlobNotFound) +} + +func (s *RecordedTestSuite) TestCreateFileAndDelete() { + _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) + + fileName := testcommon.GenerateFileName(testName) + fClient, err := testcommon.GetFileClient(filesystemName, fileName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + defer testcommon.DeleteFile(context.Background(), _require, fClient) + + resp, err := fClient.Create(context.Background(), nil) + _require.Nil(err) + _require.NotNil(resp) +} + +func (s *RecordedTestSuite) TestCreateFileWithNilAccessConditions() { + _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) + + fileName := testcommon.GenerateFileName(testName) + fClient, err := testcommon.GetFileClient(filesystemName, fileName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + defer testcommon.DeleteFile(context.Background(), _require, fClient) + + resp, err := fClient.Create(context.Background(), nil) + _require.Nil(err) + _require.NotNil(resp) + + createFileOpts := &file.CreateOptions{ + AccessConditions: nil, + } + + resp, err = fClient.Create(context.Background(), createFileOpts) + _require.Nil(err) + _require.NotNil(resp) +} + +func (s *RecordedTestSuite) TestCreateFileIfModifiedSinceTrue() { + _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) + + fileName := testcommon.GenerateFileName(testName) + fClient, err := testcommon.GetFileClient(filesystemName, fileName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + defer testcommon.DeleteFile(context.Background(), _require, fClient) + + resp, err := fClient.Create(context.Background(), nil) + _require.Nil(err) + _require.NotNil(resp) + + currentTime := testcommon.GetRelativeTimeFromAnchor(resp.Date, -10) + + createFileOpts := &file.CreateOptions{ + AccessConditions: &file.AccessConditions{ + ModifiedAccessConditions: &file.ModifiedAccessConditions{ + IfModifiedSince: ¤tTime, + }, + }, + } + + resp, err = fClient.Create(context.Background(), createFileOpts) + _require.Nil(err) + _require.NotNil(resp) +} + +func (s *RecordedTestSuite) TestCreateFileIfModifiedSinceFalse() { + _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) + + fileName := testcommon.GenerateFileName(testName) + fClient, err := testcommon.GetFileClient(filesystemName, fileName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + defer testcommon.DeleteFile(context.Background(), _require, fClient) + + resp, err := fClient.Create(context.Background(), nil) + _require.Nil(err) + _require.NotNil(resp) + + currentTime := testcommon.GetRelativeTimeFromAnchor(resp.Date, 10) + + createFileOpts := &file.CreateOptions{ + AccessConditions: &file.AccessConditions{ + ModifiedAccessConditions: &file.ModifiedAccessConditions{ + IfModifiedSince: ¤tTime, + }, + }, + } + + resp, err = fClient.Create(context.Background(), createFileOpts) + _require.NotNil(err) + testcommon.ValidateErrorCode(_require, err, datalakeerror.ConditionNotMet) +} + +func (s *RecordedTestSuite) TestCreateFileIfUnmodifiedSinceTrue() { + _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) + + fileName := testcommon.GenerateFileName(testName) + fClient, err := testcommon.GetFileClient(filesystemName, fileName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + defer testcommon.DeleteFile(context.Background(), _require, fClient) + + resp, err := fClient.Create(context.Background(), nil) + _require.Nil(err) + _require.NotNil(resp) + + currentTime := testcommon.GetRelativeTimeFromAnchor(resp.Date, 10) + + createFileOpts := &file.CreateOptions{ + AccessConditions: &file.AccessConditions{ + ModifiedAccessConditions: &file.ModifiedAccessConditions{ + IfUnmodifiedSince: ¤tTime, + }, + }, + } + + resp, err = fClient.Create(context.Background(), createFileOpts) + _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) + + fileName := testcommon.GenerateFileName(testName) + fClient, err := testcommon.GetFileClient(filesystemName, fileName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + defer testcommon.DeleteFile(context.Background(), _require, fClient) + + resp, err := fClient.Create(context.Background(), nil) + _require.Nil(err) + _require.NotNil(resp) + + currentTime := testcommon.GetRelativeTimeFromAnchor(resp.Date, -10) + + createFileOpts := &file.CreateOptions{ + AccessConditions: &file.AccessConditions{ + ModifiedAccessConditions: &file.ModifiedAccessConditions{ + IfUnmodifiedSince: ¤tTime, + }, + }, + } + + resp, err = fClient.Create(context.Background(), createFileOpts) + _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) + + fileName := testcommon.GenerateFileName(testName) + fClient, err := testcommon.GetFileClient(filesystemName, fileName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + defer testcommon.DeleteFile(context.Background(), _require, fClient) + + resp, err := fClient.Create(context.Background(), nil) + _require.Nil(err) + _require.NotNil(resp) + + etag := resp.ETag + + createFileOpts := &file.CreateOptions{ + AccessConditions: &file.AccessConditions{ + ModifiedAccessConditions: &file.ModifiedAccessConditions{ + IfMatch: etag, + }, + }, + } + + resp, err = fClient.Create(context.Background(), createFileOpts) + _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) + + fileName := testcommon.GenerateFileName(testName) + fClient, err := testcommon.GetFileClient(filesystemName, fileName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + defer testcommon.DeleteFile(context.Background(), _require, fClient) + + resp, err := fClient.Create(context.Background(), nil) + _require.Nil(err) + _require.NotNil(resp) + + etag := resp.ETag + + createFileOpts := &file.CreateOptions{ + AccessConditions: &file.AccessConditions{ + ModifiedAccessConditions: &file.ModifiedAccessConditions{ + IfNoneMatch: etag, + }, + }, + } + + resp, err = fClient.Create(context.Background(), createFileOpts) + _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) + + createFileOpts := &file.CreateOptions{ + Metadata: testcommon.BasicMetadata, + } + + _, err = fsClient.Create(context.Background(), nil) + _require.Nil(err) + + fileName := testcommon.GenerateFileName(testName) + fClient, err := testcommon.GetFileClient(filesystemName, fileName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + defer testcommon.DeleteFile(context.Background(), _require, fClient) + + resp, err := fClient.Create(context.Background(), createFileOpts) + _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) + + createFileOpts := &file.CreateOptions{ + Metadata: nil, + } + + _, err = fsClient.Create(context.Background(), nil) + _require.Nil(err) + + fileName := testcommon.GenerateFileName(testName) + fClient, err := testcommon.GetFileClient(filesystemName, fileName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + defer testcommon.DeleteFile(context.Background(), _require, fClient) + + resp, err := fClient.Create(context.Background(), createFileOpts) + _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) + + createFileOpts := &file.CreateOptions{ + HTTPHeaders: nil, + } + + _, err = fsClient.Create(context.Background(), nil) + _require.Nil(err) + + fileName := testcommon.GenerateFileName(testName) + fClient, err := testcommon.GetFileClient(filesystemName, fileName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + defer testcommon.DeleteFile(context.Background(), _require, fClient) + + resp, err := fClient.Create(context.Background(), createFileOpts) + _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) + + createFileOpts := &file.CreateOptions{ + HTTPHeaders: &testcommon.BasicHeaders, + } + + _, err = fsClient.Create(context.Background(), nil) + _require.Nil(err) + + fileName := testcommon.GenerateFileName(testName) + fClient, err := testcommon.GetFileClient(filesystemName, fileName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + defer testcommon.DeleteFile(context.Background(), _require, fClient) + + resp, err := fClient.Create(context.Background(), createFileOpts) + _require.Nil(err) + _require.NotNil(resp) +} + +func (s *RecordedTestSuite) TestCreateFileWithExpiryAbsolute() { + _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) + + expiryTimeAbsolute := time.Now().Add(8 * time.Second) + expiry := file.CreationExpiryTypeAbsolute(expiryTimeAbsolute) + createFileOpts := &file.CreateOptions{ + Expiry: expiry, + } + + _, err = fsClient.Create(context.Background(), nil) + _require.Nil(err) + + fileName := testcommon.GenerateFileName(testName) + fClient, err := testcommon.GetFileClient(filesystemName, fileName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + defer testcommon.DeleteFile(context.Background(), _require, fClient) + + resp, err := fClient.Create(context.Background(), createFileOpts) + _require.Nil(err) + _require.NotNil(resp) + + resp1, err := fClient.GetProperties(context.Background(), nil) + _require.Nil(err) + _require.NotNil(resp1.ExpiresOn) + _require.Equal(expiryTimeAbsolute.UTC().Format(http.TimeFormat), (*resp1.ExpiresOn).UTC().Format(http.TimeFormat)) +} + +func (s *RecordedTestSuite) TestCreateFileWithExpiryRelativeToNow() { + _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) + + expiry := file.CreationExpiryTypeRelativeToNow(8 * time.Second) + createFileOpts := &file.CreateOptions{ + Expiry: expiry, + } + + _, err = fsClient.Create(context.Background(), nil) + _require.Nil(err) + + fileName := testcommon.GenerateFileName(testName) + fClient, err := testcommon.GetFileClient(filesystemName, fileName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + resp, err := fClient.Create(context.Background(), createFileOpts) + _require.Nil(err) + _require.NotNil(resp) + + resp1, err := fClient.GetProperties(context.Background(), nil) + _require.Nil(err) + _require.NotNil(resp1.ExpiresOn) + + time.Sleep(time.Second * 10) + _, err = fClient.GetProperties(context.Background(), nil) + testcommon.ValidateErrorCode(_require, err, datalakeerror.BlobNotFound) +} + +func (s *RecordedTestSuite) TestCreateFileWithNeverExpire() { + _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 := &file.CreateOptions{ + Expiry: file.CreationExpiryTypeNever{}, + } + + _, err = fsClient.Create(context.Background(), nil) + _require.Nil(err) + + fileName := testcommon.GenerateFileName(testName) + fClient, err := testcommon.GetFileClient(filesystemName, fileName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + resp, err := fClient.Create(context.Background(), createFileOpts) + _require.Nil(err) + _require.NotNil(resp) + + resp1, err := fClient.GetProperties(context.Background(), nil) + _require.Nil(err) + _require.Nil(resp1.ExpiresOn) +} + +func (s *RecordedTestSuite) TestCreateFileWithLease() { + _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 := &file.CreateOptions{ + ProposedLeaseID: proposedLeaseIDs[0], + LeaseDuration: to.Ptr(int64(15)), + } + + _, err = fsClient.Create(context.Background(), nil) + _require.Nil(err) + + fileName := testcommon.GenerateFileName(testName) + fClient, err := testcommon.GetFileClient(filesystemName, fileName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + resp, err := fClient.Create(context.Background(), createFileOpts) + _require.Nil(err) + _require.NotNil(resp) + + // should fail since leased + _, err = fClient.Create(context.Background(), createFileOpts) + _require.NotNil(err) + + time.Sleep(time.Second * 15) + resp, err = fClient.Create(context.Background(), createFileOpts) + _require.Nil(err) + _require.NotNil(resp) +} + +func (s *RecordedTestSuite) TestCreateFileWithPermissions() { + _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" + defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + + createFileOpts := &file.CreateOptions{ + Permissions: &perms, + } + + _, err = fsClient.Create(context.Background(), nil) + _require.Nil(err) + + fileName := testcommon.GenerateFileName(testName) + fClient, err := testcommon.GetFileClient(filesystemName, fileName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + resp, err := fClient.Create(context.Background(), createFileOpts) + _require.Nil(err) + _require.NotNil(resp) + + //TODO: GetProperties() when you figured out how to add permissions into response +} + +func (s *RecordedTestSuite) TestCreateFileWithOwnerGroupACLUmask() { + _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 := &file.CreateOptions{ + Owner: &owner, + Group: &group, + ACL: &acl, + Umask: &umask, + } + + _, err = fsClient.Create(context.Background(), nil) + _require.Nil(err) + + fileName := testcommon.GenerateFileName(testName) + fClient, err := testcommon.GetFileClient(filesystemName, fileName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + resp, err := fClient.Create(context.Background(), createFileOpts) + _require.Nil(err) + _require.NotNil(resp) + + //TODO: GetProperties() when you figured out how to add o,g, ACL into response +} + +func (s *RecordedTestSuite) TestDeleteFileWithNilAccessConditions() { + _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) + + fileName := testcommon.GenerateFileName(testName) + fClient, err := testcommon.GetFileClient(filesystemName, fileName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + _, err = fClient.Create(context.Background(), nil) + _require.Nil(err) + + deleteOpts := &file.DeleteOptions{ + AccessConditions: nil, + } + + resp, err := fClient.Delete(context.Background(), deleteOpts) + _require.Nil(err) + _require.NotNil(resp) +} + +func (s *RecordedTestSuite) TestDeleteFileIfModifiedSinceTrue() { + _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) + + fileName := testcommon.GenerateFileName(testName) + fClient, err := testcommon.GetFileClient(filesystemName, fileName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + resp, err := fClient.Create(context.Background(), nil) + _require.Nil(err) + + currentTime := testcommon.GetRelativeTimeFromAnchor(resp.Date, -10) + + deleteOpts := &file.DeleteOptions{ + AccessConditions: &file.AccessConditions{ + ModifiedAccessConditions: &file.ModifiedAccessConditions{ + IfModifiedSince: ¤tTime, + }, + }, + } + + resp1, err := fClient.Delete(context.Background(), deleteOpts) + _require.Nil(err) + _require.NotNil(resp1) +} + +func (s *RecordedTestSuite) TestDeleteFileIfModifiedSinceFalse() { + _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) + + fileName := testcommon.GenerateFileName(testName) + fClient, err := testcommon.GetFileClient(filesystemName, fileName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + resp, err := fClient.Create(context.Background(), nil) + _require.Nil(err) + _require.NotNil(resp) + + currentTime := testcommon.GetRelativeTimeFromAnchor(resp.Date, 10) + + deleteOpts := &file.DeleteOptions{ + AccessConditions: &file.AccessConditions{ + ModifiedAccessConditions: &file.ModifiedAccessConditions{ + IfModifiedSince: ¤tTime, + }, + }, + } + + _, err = fClient.Delete(context.Background(), deleteOpts) + _require.NotNil(err) + testcommon.ValidateErrorCode(_require, err, datalakeerror.ConditionNotMet) +} + +func (s *RecordedTestSuite) TestDeleteFileIfUnmodifiedSinceTrue() { + _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) + + fileName := testcommon.GenerateFileName(testName) + fClient, err := testcommon.GetFileClient(filesystemName, fileName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + resp, err := fClient.Create(context.Background(), nil) + _require.Nil(err) + _require.NotNil(resp) + + currentTime := testcommon.GetRelativeTimeFromAnchor(resp.Date, 10) + + deleteOpts := &file.DeleteOptions{ + AccessConditions: &file.AccessConditions{ + ModifiedAccessConditions: &file.ModifiedAccessConditions{ + IfUnmodifiedSince: ¤tTime, + }, + }, + } + + _, err = fClient.Delete(context.Background(), deleteOpts) + _require.Nil(err) + _require.NotNil(resp) +} + +func (s *RecordedTestSuite) TestDeleteFileIfUnmodifiedSinceFalse() { + _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) + + fileName := testcommon.GenerateFileName(testName) + fClient, err := testcommon.GetFileClient(filesystemName, fileName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + resp, err := fClient.Create(context.Background(), nil) + _require.Nil(err) + _require.NotNil(resp) + + currentTime := testcommon.GetRelativeTimeFromAnchor(resp.Date, -10) + + deleteOpts := &file.DeleteOptions{ + AccessConditions: &file.AccessConditions{ + ModifiedAccessConditions: &file.ModifiedAccessConditions{ + IfUnmodifiedSince: ¤tTime, + }, + }, + } + + _, err = fClient.Delete(context.Background(), deleteOpts) + _require.NotNil(err) + + testcommon.ValidateErrorCode(_require, err, datalakeerror.ConditionNotMet) +} + +func (s *RecordedTestSuite) TestDeleteFileIfETagMatch() { + _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) + + fileName := testcommon.GenerateFileName(testName) + fClient, err := testcommon.GetFileClient(filesystemName, fileName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + resp, err := fClient.Create(context.Background(), nil) + _require.Nil(err) + _require.NotNil(resp) + + etag := resp.ETag + + deleteOpts := &file.DeleteOptions{ + AccessConditions: &file.AccessConditions{ + ModifiedAccessConditions: &file.ModifiedAccessConditions{ + IfMatch: etag, + }, + }, + } + + _, err = fClient.Delete(context.Background(), deleteOpts) + _require.Nil(err) + _require.NotNil(resp) +} + +func (s *RecordedTestSuite) TestDeleteFileIfETagMatchFalse() { + _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) + + fileName := testcommon.GenerateFileName(testName) + fClient, err := testcommon.GetFileClient(filesystemName, fileName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + resp, err := fClient.Create(context.Background(), nil) + _require.Nil(err) + _require.NotNil(resp) + + etag := resp.ETag + + deleteOpts := &file.DeleteOptions{ + AccessConditions: &file.AccessConditions{ + ModifiedAccessConditions: &file.ModifiedAccessConditions{ + IfNoneMatch: etag, + }, + }, + } + + _, err = fClient.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) + + fileName := testcommon.GenerateFileName(testName) + fClient, err := testcommon.GetFileClient(filesystemName, fileName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + resp, err := fClient.Create(context.Background(), nil) + _require.Nil(err) + _require.NotNil(resp) + + _, err = fClient.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 := &file.SetAccessControlOptions{ + Owner: &owner, + Group: &group, + ACL: &acl, + } + + _, err = fsClient.Create(context.Background(), nil) + _require.Nil(err) + + fileName := testcommon.GenerateFileName(testName) + fClient, err := testcommon.GetFileClient(filesystemName, fileName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + resp, err := fClient.Create(context.Background(), nil) + _require.Nil(err) + _require.NotNil(resp) + + _, err = fClient.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 := &file.SetAccessControlOptions{ + Owner: &owner, + Group: &group, + ACL: &acl, + AccessConditions: nil, + } + + _, err = fsClient.Create(context.Background(), nil) + _require.Nil(err) + + fileName := testcommon.GenerateFileName(testName) + fClient, err := testcommon.GetFileClient(filesystemName, fileName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + resp, err := fClient.Create(context.Background(), nil) + _require.Nil(err) + _require.NotNil(resp) + + _, err = fClient.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) + + fileName := testcommon.GenerateFileName(testName) + fClient, err := testcommon.GetFileClient(filesystemName, fileName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + resp, err := fClient.Create(context.Background(), nil) + _require.Nil(err) + _require.NotNil(resp) + + currentTime := testcommon.GetRelativeTimeFromAnchor(resp.Date, -10) + opts := &file.SetAccessControlOptions{ + Owner: &owner, + Group: &group, + ACL: &acl, + AccessConditions: &file.AccessConditions{ + ModifiedAccessConditions: &file.ModifiedAccessConditions{ + IfModifiedSince: ¤tTime, + }, + }, + } + + _, err = fClient.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) + + fileName := testcommon.GenerateFileName(testName) + fClient, err := testcommon.GetFileClient(filesystemName, fileName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + resp, err := fClient.Create(context.Background(), nil) + _require.Nil(err) + _require.NotNil(resp) + currentTime := testcommon.GetRelativeTimeFromAnchor(resp.Date, 10) + + opts := &file.SetAccessControlOptions{ + Owner: &owner, + Group: &group, + ACL: &acl, + AccessConditions: &file.AccessConditions{ + ModifiedAccessConditions: &file.ModifiedAccessConditions{ + IfModifiedSince: ¤tTime, + }, + }, + } + + _, err = fClient.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) + + fileName := testcommon.GenerateFileName(testName) + fClient, err := testcommon.GetFileClient(filesystemName, fileName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + resp, err := fClient.Create(context.Background(), nil) + _require.Nil(err) + _require.NotNil(resp) + + currentTime := testcommon.GetRelativeTimeFromAnchor(resp.Date, 10) + opts := &file.SetAccessControlOptions{ + Owner: &owner, + Group: &group, + ACL: &acl, + AccessConditions: &file.AccessConditions{ + ModifiedAccessConditions: &file.ModifiedAccessConditions{ + IfUnmodifiedSince: ¤tTime, + }, + }} + + _, err = fClient.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) + + fileName := testcommon.GenerateFileName(testName) + fClient, err := testcommon.GetFileClient(filesystemName, fileName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + resp, err := fClient.Create(context.Background(), nil) + _require.Nil(err) + _require.NotNil(resp) + + currentTime := testcommon.GetRelativeTimeFromAnchor(resp.Date, -10) + + opts := &file.SetAccessControlOptions{ + Owner: &owner, + Group: &group, + ACL: &acl, + AccessConditions: &file.AccessConditions{ + ModifiedAccessConditions: &file.ModifiedAccessConditions{ + IfUnmodifiedSince: ¤tTime, + }, + }, + } + + _, err = fClient.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) + + fileName := testcommon.GenerateFileName(testName) + fClient, err := testcommon.GetFileClient(filesystemName, fileName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + resp, err := fClient.Create(context.Background(), nil) + _require.Nil(err) + _require.NotNil(resp) + etag := resp.ETag + + opts := &file.SetAccessControlOptions{ + Owner: &owner, + Group: &group, + ACL: &acl, + AccessConditions: &file.AccessConditions{ + ModifiedAccessConditions: &file.ModifiedAccessConditions{ + IfMatch: etag, + }, + }, + } + + _, err = fClient.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) + + fileName := testcommon.GenerateFileName(testName) + fClient, err := testcommon.GetFileClient(filesystemName, fileName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + resp, err := fClient.Create(context.Background(), nil) + _require.Nil(err) + _require.NotNil(resp) + + etag := resp.ETag + opts := &file.SetAccessControlOptions{ + Owner: &owner, + Group: &group, + ACL: &acl, + AccessConditions: &file.AccessConditions{ + ModifiedAccessConditions: &file.ModifiedAccessConditions{ + IfNoneMatch: etag, + }, + }} + + _, err = fClient.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 := &file.CreateOptions{ + ACL: &acl, + } + _, err = fsClient.Create(context.Background(), nil) + _require.Nil(err) + + fileName := testcommon.GenerateFileName(testName) + fClient, err := testcommon.GetFileClient(filesystemName, fileName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + resp, err := fClient.Create(context.Background(), createOpts) + _require.Nil(err) + _require.NotNil(resp) + + getACLResp, err := fClient.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 := &file.CreateOptions{ + ACL: &acl, + } + _, err = fsClient.Create(context.Background(), nil) + _require.Nil(err) + + fileName := testcommon.GenerateFileName(testName) + fClient, err := testcommon.GetFileClient(filesystemName, fileName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + resp, err := fClient.Create(context.Background(), createOpts) + _require.Nil(err) + _require.NotNil(resp) + + // Adding SAS and options + permissions := sas.FilePermissions{ + Read: true, + Add: true, + Write: true, + Create: true, + Delete: true, + } + expiry := time.Now().Add(time.Hour) + + sasURL, err := fClient.GetSASURL(permissions, expiry, nil) + _require.Nil(err) + + fClient2, _ := file.NewClientWithNoCredential(sasURL, nil) + + getACLResp, err := fClient2.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) + + fileName := testcommon.GenerateFileName(testName) + fClient, err := testcommon.GetFileClient(filesystemName, fileName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + resp, err := fClient.Create(context.Background(), nil) + _require.Nil(err) + _require.NotNil(resp) + + // Adding SAS and options + permissions := sas.FilePermissions{ + Read: true, + Add: true, + Write: true, + Create: true, + Delete: true, + } + expiry := time.Now().Add(time.Hour) + + sasURL, err := fClient.GetSASURL(permissions, expiry, nil) + _require.Nil(err) + + fClient2, _ := file.NewClientWithNoCredential(sasURL, nil) + + _, err = fClient2.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 := &file.CreateOptions{ + ACL: &acl, + } + _, err = fsClient.Create(context.Background(), nil) + _require.Nil(err) + + fileName := testcommon.GenerateFileName(testName) + fClient, err := testcommon.GetFileClient(filesystemName, fileName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + resp, err := fClient.Create(context.Background(), createOpts) + _require.Nil(err) + _require.NotNil(resp) + + opts := &file.GetAccessControlOptions{ + AccessConditions: nil, + } + + getACLResp, err := fClient.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 := &file.CreateOptions{ + ACL: &acl, + } + _, err = fsClient.Create(context.Background(), nil) + _require.Nil(err) + + fileName := testcommon.GenerateFileName(testName) + fClient, err := testcommon.GetFileClient(filesystemName, fileName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + resp, err := fClient.Create(context.Background(), createOpts) + _require.Nil(err) + _require.NotNil(resp) + + currentTime := testcommon.GetRelativeTimeFromAnchor(resp.Date, -10) + opts := &file.GetAccessControlOptions{ + AccessConditions: &file.AccessConditions{ + ModifiedAccessConditions: &file.ModifiedAccessConditions{ + IfModifiedSince: ¤tTime, + }, + }, + } + + getACLResp, err := fClient.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 := &file.CreateOptions{ + ACL: &acl, + } + _, err = fsClient.Create(context.Background(), nil) + _require.Nil(err) + + fileName := testcommon.GenerateFileName(testName) + fClient, err := testcommon.GetFileClient(filesystemName, fileName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + resp, err := fClient.Create(context.Background(), createOpts) + _require.Nil(err) + _require.NotNil(resp) + currentTime := testcommon.GetRelativeTimeFromAnchor(resp.Date, 10) + + opts := &file.GetAccessControlOptions{ + AccessConditions: &file.AccessConditions{ + ModifiedAccessConditions: &file.ModifiedAccessConditions{ + IfModifiedSince: ¤tTime, + }, + }, + } + + _, err = fClient.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 := &file.CreateOptions{ + ACL: &acl, + } + _, err = fsClient.Create(context.Background(), nil) + _require.Nil(err) + + fileName := testcommon.GenerateFileName(testName) + fClient, err := testcommon.GetFileClient(filesystemName, fileName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + resp, err := fClient.Create(context.Background(), createOpts) + _require.Nil(err) + _require.NotNil(resp) + + currentTime := testcommon.GetRelativeTimeFromAnchor(resp.Date, 10) + opts := &file.GetAccessControlOptions{ + AccessConditions: &file.AccessConditions{ + ModifiedAccessConditions: &file.ModifiedAccessConditions{ + IfUnmodifiedSince: ¤tTime, + }, + }} + + getACLResp, err := fClient.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 := &file.CreateOptions{ + ACL: &acl, + } + _, err = fsClient.Create(context.Background(), nil) + _require.Nil(err) + + fileName := testcommon.GenerateFileName(testName) + fClient, err := testcommon.GetFileClient(filesystemName, fileName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + resp, err := fClient.Create(context.Background(), createOpts) + _require.Nil(err) + _require.NotNil(resp) + + currentTime := testcommon.GetRelativeTimeFromAnchor(resp.Date, -10) + + opts := &file.GetAccessControlOptions{ + AccessConditions: &file.AccessConditions{ + ModifiedAccessConditions: &file.ModifiedAccessConditions{ + IfUnmodifiedSince: ¤tTime, + }, + }, + } + + _, err = fClient.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 := &file.CreateOptions{ + ACL: &acl, + } + _, err = fsClient.Create(context.Background(), nil) + _require.Nil(err) + + fileName := testcommon.GenerateFileName(testName) + fClient, err := testcommon.GetFileClient(filesystemName, fileName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + resp, err := fClient.Create(context.Background(), createOpts) + _require.Nil(err) + _require.NotNil(resp) + etag := resp.ETag + + opts := &file.GetAccessControlOptions{ + AccessConditions: &file.AccessConditions{ + ModifiedAccessConditions: &file.ModifiedAccessConditions{ + IfMatch: etag, + }, + }, + } + + getACLResp, err := fClient.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 := &file.CreateOptions{ + ACL: &acl, + } + _, err = fsClient.Create(context.Background(), nil) + _require.Nil(err) + + fileName := testcommon.GenerateFileName(testName) + fClient, err := testcommon.GetFileClient(filesystemName, fileName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + resp, err := fClient.Create(context.Background(), createOpts) + _require.Nil(err) + _require.NotNil(resp) + + etag := resp.ETag + opts := &file.GetAccessControlOptions{ + AccessConditions: &file.AccessConditions{ + ModifiedAccessConditions: &file.ModifiedAccessConditions{ + IfNoneMatch: etag, + }, + }} + + _, err = fClient.GetAccessControl(context.Background(), opts) + _require.NotNil(err) + testcommon.ValidateErrorCode(_require, err, datalakeerror.ConditionNotMet) +} + +func (s *RecordedTestSuite) TestUpdateAccessControl() { + _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 := &file.CreateOptions{ + ACL: &acl, + } + _, err = fsClient.Create(context.Background(), nil) + _require.Nil(err) + + fileName := testcommon.GenerateFileName(testName) + fClient, err := testcommon.GetFileClient(filesystemName, fileName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + resp, err := fClient.Create(context.Background(), createOpts) + _require.Nil(err) + _require.NotNil(resp) + + _, err = fClient.UpdateAccessControl(context.Background(), acl1, nil) + _require.Nil(err) + + getACLResp, err := fClient.GetAccessControl(context.Background(), nil) + _require.Nil(err) + _require.Equal(acl1, *getACLResp.ACL) +} + +func (s *RecordedTestSuite) TestRemoveAccessControl() { + _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) + + fileName := testcommon.GenerateFileName(testName) + fClient, err := testcommon.GetFileClient(filesystemName, fileName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + resp, err := fClient.Create(context.Background(), nil) + _require.Nil(err) + _require.NotNil(resp) + + _, err = fClient.RemoveAccessControl(context.Background(), acl, nil) + _require.Nil(err) +} + +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) + + fileName := testcommon.GenerateFileName(testName) + fClient, err := testcommon.GetFileClient(filesystemName, fileName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + defer testcommon.DeleteFile(context.Background(), _require, fClient) + + resp, err := fClient.Create(context.Background(), nil) + _require.Nil(err) + _require.NotNil(resp) + + _, err = fClient.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) + + fileName := testcommon.GenerateFileName(testName) + fClient, err := testcommon.GetFileClient(filesystemName, fileName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + defer testcommon.DeleteFile(context.Background(), _require, fClient) + + resp, err := fClient.Create(context.Background(), nil) + _require.Nil(err) + _require.NotNil(resp) + + opts := &file.SetMetadataOptions{ + Metadata: nil, + } + _, err = fClient.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) + + fileName := testcommon.GenerateFileName(testName) + fClient, err := testcommon.GetFileClient(filesystemName, fileName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + defer testcommon.DeleteFile(context.Background(), _require, fClient) + + resp, err := fClient.Create(context.Background(), nil) + _require.Nil(err) + _require.NotNil(resp) + + opts := &file.SetMetadataOptions{ + Metadata: testcommon.BasicMetadata, + } + _, err = fClient.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) + + fileName := testcommon.GenerateFileName(testName) + fClient, err := testcommon.GetFileClient(filesystemName, fileName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + defer testcommon.DeleteFile(context.Background(), _require, fClient) + + resp, err := fClient.Create(context.Background(), nil) + _require.Nil(err) + _require.NotNil(resp) + + currentTime := testcommon.GetRelativeTimeFromAnchor(resp.Date, -10) + + opts := &file.SetMetadataOptions{ + Metadata: testcommon.BasicMetadata, + AccessConditions: &file.AccessConditions{ + ModifiedAccessConditions: &file.ModifiedAccessConditions{ + IfModifiedSince: ¤tTime, + }, + }, + } + _, err = fClient.SetMetadata(context.Background(), opts) + _require.Nil(err) +} + +func validatePropertiesSet(_require *require.Assertions, fileClient *file.Client, disposition string) { + resp, err := fileClient.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) + + fileName := testcommon.GenerateFileName(testName) + fClient, err := testcommon.GetFileClient(filesystemName, fileName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + resp, err := fClient.Create(context.Background(), nil) + _require.Nil(err) + _require.NotNil(resp) + + _, err = fClient.SetHTTPHeaders(context.Background(), testcommon.BasicHeaders, nil) + _require.Nil(err) + validatePropertiesSet(_require, fClient, *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) + + fileName := testcommon.GenerateFileName(testName) + fClient, err := testcommon.GetFileClient(filesystemName, fileName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + resp, err := fClient.Create(context.Background(), nil) + _require.Nil(err) + _require.NotNil(resp) + + opts := &file.SetHTTPHeadersOptions{ + AccessConditions: nil, + } + + _, err = fClient.SetHTTPHeaders(context.Background(), testcommon.BasicHeaders, opts) + _require.Nil(err) + validatePropertiesSet(_require, fClient, *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) + + fileName := testcommon.GenerateFileName(testName) + fClient, err := testcommon.GetFileClient(filesystemName, fileName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + resp, err := fClient.Create(context.Background(), nil) + _require.Nil(err) + _require.NotNil(resp) + + currentTime := testcommon.GetRelativeTimeFromAnchor(resp.Date, -10) + + opts := &file.SetHTTPHeadersOptions{ + AccessConditions: &file.AccessConditions{ + ModifiedAccessConditions: &file.ModifiedAccessConditions{ + IfModifiedSince: ¤tTime, + }, + }, + } + _, err = fClient.SetHTTPHeaders(context.Background(), testcommon.BasicHeaders, opts) + _require.Nil(err) + validatePropertiesSet(_require, fClient, *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) + + fileName := testcommon.GenerateFileName(testName) + fClient, err := testcommon.GetFileClient(filesystemName, fileName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + resp, err := fClient.Create(context.Background(), nil) + _require.Nil(err) + _require.NotNil(resp) + + currentTime := testcommon.GetRelativeTimeFromAnchor(resp.Date, 10) + + opts := &file.SetHTTPHeadersOptions{ + AccessConditions: &file.AccessConditions{ + ModifiedAccessConditions: &file.ModifiedAccessConditions{ + IfModifiedSince: ¤tTime, + }, + }, + } + _, err = fClient.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) + + fileName := testcommon.GenerateFileName(testName) + fClient, err := testcommon.GetFileClient(filesystemName, fileName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + resp, err := fClient.Create(context.Background(), nil) + _require.Nil(err) + _require.NotNil(resp) + + currentTime := testcommon.GetRelativeTimeFromAnchor(resp.Date, 10) + + opts := &file.SetHTTPHeadersOptions{ + AccessConditions: &file.AccessConditions{ + ModifiedAccessConditions: &file.ModifiedAccessConditions{ + IfUnmodifiedSince: ¤tTime, + }, + }, + } + _, err = fClient.SetHTTPHeaders(context.Background(), testcommon.BasicHeaders, opts) + _require.Nil(err) + validatePropertiesSet(_require, fClient, *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) + + fileName := testcommon.GenerateFileName(testName) + fClient, err := testcommon.GetFileClient(filesystemName, fileName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + resp, err := fClient.Create(context.Background(), nil) + _require.Nil(err) + _require.NotNil(resp) + + currentTime := testcommon.GetRelativeTimeFromAnchor(resp.Date, -10) + + opts := &file.SetHTTPHeadersOptions{ + AccessConditions: &file.AccessConditions{ + ModifiedAccessConditions: &file.ModifiedAccessConditions{ + IfUnmodifiedSince: ¤tTime, + }, + }, + } + _, err = fClient.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) + + fileName := testcommon.GenerateFileName(testName) + fClient, err := testcommon.GetFileClient(filesystemName, fileName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + resp, err := fClient.Create(context.Background(), nil) + _require.Nil(err) + _require.NotNil(resp) + + etag := resp.ETag + + opts := &file.SetHTTPHeadersOptions{ + AccessConditions: &file.AccessConditions{ + ModifiedAccessConditions: &file.ModifiedAccessConditions{ + IfMatch: etag, + }, + }} + _, err = fClient.SetHTTPHeaders(context.Background(), testcommon.BasicHeaders, opts) + _require.Nil(err) + validatePropertiesSet(_require, fClient, *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) + + fileName := testcommon.GenerateFileName(testName) + fClient, err := testcommon.GetFileClient(filesystemName, fileName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + resp, err := fClient.Create(context.Background(), nil) + _require.Nil(err) + _require.NotNil(resp) + + etag := resp.ETag + + opts := &file.SetHTTPHeadersOptions{ + AccessConditions: &file.AccessConditions{ + ModifiedAccessConditions: &file.ModifiedAccessConditions{ + IfNoneMatch: etag, + }, + }, + } + _, err = fClient.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) +// +// fileName := testcommon.GenerateFileName(testName) +// fClient, err := testcommon.GetFileClient(filesystemName, fileName, s.T(), testcommon.TestAccountDatalake, nil) +// _require.NoError(err) +// +// resp, err := fClient.Create(context.Background(), nil) +// _require.Nil(err) +// _require.NotNil(resp) +// +// resp, err = fClient.Rename(context.Background(), "newName", nil) +// _require.Nil(err) +// _require.NotNil(resp) +//} +// +//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) +// +// fileName := testcommon.GenerateFileName(testName) +// fClient, err := testcommon.GetFileClient(filesystemName, fileName, s.T(), testcommon.TestAccountDatalake, nil) +// _require.NoError(err) +// +// resp, err := fClient.Create(context.Background(), nil) +// _require.Nil(err) +// _require.NotNil(resp) +// +// renameFileOpts := &file.RenameOptions{ +// AccessConditions: nil, +// } +// +// resp, err = fClient.Rename(context.Background(), "new"+fileName, renameFileOpts) +// _require.Nil(err) +// _require.NotNil(resp) +//} +// +//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) +// +// fileName := testcommon.GenerateFileName(testName) +// fClient, err := testcommon.GetFileClient(filesystemName, fileName, s.T(), testcommon.TestAccountDatalake, nil) +// _require.NoError(err) +// +// defer testcommon.DeleteFile(context.Background(), _require, fClient) +// +// resp, err := fClient.Create(context.Background(), nil) +// _require.Nil(err) +// _require.NotNil(resp) +// +// currentTime := testcommon.GetRelativeTimeFromAnchor(resp.Date, -10) +// +// createFileOpts := &file.CreateOptions{ +// AccessConditions: &file.AccessConditions{ +// ModifiedAccessConditions: &file.ModifiedAccessConditions{ +// IfModifiedSince: ¤tTime, +// }, +// }, +// } +// +// resp, err = fClient.Create(context.Background(), createFileOpts) +// _require.Nil(err) +// _require.NotNil(resp) +//} +// +//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) +// +// fileName := testcommon.GenerateFileName(testName) +// fClient, err := testcommon.GetFileClient(filesystemName, fileName, s.T(), testcommon.TestAccountDatalake, nil) +// _require.NoError(err) +// +// defer testcommon.DeleteFile(context.Background(), _require, fClient) +// +// resp, err := fClient.Create(context.Background(), nil) +// _require.Nil(err) +// _require.NotNil(resp) +// +// currentTime := testcommon.GetRelativeTimeFromAnchor(resp.Date, 10) +// +// createFileOpts := &file.CreateOptions{ +// AccessConditions: &file.AccessConditions{ +// ModifiedAccessConditions: &file.ModifiedAccessConditions{ +// IfModifiedSince: ¤tTime, +// }, +// }, +// } +// +// resp, err = fClient.Create(context.Background(), createFileOpts) +// _require.NotNil(err) +// testcommon.ValidateErrorCode(_require, err, datalakeerror.ConditionNotMet) +//} +// +//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) +// +// fileName := testcommon.GenerateFileName(testName) +// fClient, err := testcommon.GetFileClient(filesystemName, fileName, s.T(), testcommon.TestAccountDatalake, nil) +// _require.NoError(err) +// +// defer testcommon.DeleteFile(context.Background(), _require, fClient) +// +// resp, err := fClient.Create(context.Background(), nil) +// _require.Nil(err) +// _require.NotNil(resp) +// +// currentTime := testcommon.GetRelativeTimeFromAnchor(resp.Date, 10) +// +// createFileOpts := &file.CreateOptions{ +// AccessConditions: &file.AccessConditions{ +// ModifiedAccessConditions: &file.ModifiedAccessConditions{ +// IfUnmodifiedSince: ¤tTime, +// }, +// }, +// } +// +// resp, err = fClient.Create(context.Background(), createFileOpts) +// _require.Nil(err) +// _require.NotNil(resp) +//} +// +//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) +// +// fileName := testcommon.GenerateFileName(testName) +// fClient, err := testcommon.GetFileClient(filesystemName, fileName, s.T(), testcommon.TestAccountDatalake, nil) +// _require.NoError(err) +// +// defer testcommon.DeleteFile(context.Background(), _require, fClient) +// +// resp, err := fClient.Create(context.Background(), nil) +// _require.Nil(err) +// _require.NotNil(resp) +// +// currentTime := testcommon.GetRelativeTimeFromAnchor(resp.Date, -10) +// +// createFileOpts := &file.CreateOptions{ +// AccessConditions: &file.AccessConditions{ +// ModifiedAccessConditions: &file.ModifiedAccessConditions{ +// IfUnmodifiedSince: ¤tTime, +// }, +// }, +// } +// +// resp, err = fClient.Create(context.Background(), createFileOpts) +// _require.NotNil(err) +// +// testcommon.ValidateErrorCode(_require, err, datalakeerror.ConditionNotMet) +//} +// +//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) +// +// fileName := testcommon.GenerateFileName(testName) +// fClient, err := testcommon.GetFileClient(filesystemName, fileName, s.T(), testcommon.TestAccountDatalake, nil) +// _require.NoError(err) +// +// defer testcommon.DeleteFile(context.Background(), _require, fClient) +// +// resp, err := fClient.Create(context.Background(), nil) +// _require.Nil(err) +// _require.NotNil(resp) +// +// etag := resp.ETag +// +// createFileOpts := &file.CreateOptions{ +// AccessConditions: &file.AccessConditions{ +// ModifiedAccessConditions: &file.ModifiedAccessConditions{ +// IfMatch: etag, +// }, +// }, +// } +// +// resp, err = fClient.Create(context.Background(), createFileOpts) +// _require.Nil(err) +// _require.NotNil(resp) +//} +// +//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) +// +// fileName := testcommon.GenerateFileName(testName) +// fClient, err := testcommon.GetFileClient(filesystemName, fileName, s.T(), testcommon.TestAccountDatalake, nil) +// _require.NoError(err) +// +// defer testcommon.DeleteFile(context.Background(), _require, fClient) +// +// resp, err := fClient.Create(context.Background(), nil) +// _require.Nil(err) +// _require.NotNil(resp) +// +// etag := resp.ETag +// +// createFileOpts := &file.CreateOptions{ +// AccessConditions: &file.AccessConditions{ +// ModifiedAccessConditions: &file.ModifiedAccessConditions{ +// IfNoneMatch: etag, +// }, +// }, +// } +// +// resp, err = fClient.Create(context.Background(), createFileOpts) +// _require.NotNil(err) +// +// testcommon.ValidateErrorCode(_require, err, datalakeerror.ConditionNotMet) +//} diff --git a/sdk/storage/azdatalake/file/constants.go b/sdk/storage/azdatalake/file/constants.go index 60eabcfcce37..c536d01673cf 100644 --- a/sdk/storage/azdatalake/file/constants.go +++ b/sdk/storage/azdatalake/file/constants.go @@ -8,36 +8,55 @@ package file import ( "github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/blob" - "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/internal/generated" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/lease" ) -type ResourceType = generated.PathResourceType +type EncryptionAlgorithmType = blob.EncryptionAlgorithmType -// TODO: consider the possibility of not exposing this and just pass it under the hood const ( - ResourceTypeFile ResourceType = generated.PathResourceTypeFile - ResourceTypeDirectory ResourceType = generated.PathResourceTypeDirectory + EncryptionAlgorithmTypeNone EncryptionAlgorithmType = blob.EncryptionAlgorithmTypeNone + EncryptionAlgorithmTypeAES256 EncryptionAlgorithmType = blob.EncryptionAlgorithmTypeAES256 ) -type RenameMode = generated.PathRenameMode +// responses models: + +type ImmutabilityPolicyMode = blob.ImmutabilityPolicyMode -// TODO: consider the possibility of not exposing this and just pass it under the hood const ( - RenameModeLegacy RenameMode = generated.PathRenameModeLegacy - RenameModePosix RenameMode = generated.PathRenameModePosix + ImmutabilityPolicyModeMutable ImmutabilityPolicyMode = blob.ImmutabilityPolicyModeMutable + ImmutabilityPolicyModeUnlocked ImmutabilityPolicyMode = blob.ImmutabilityPolicyModeUnlocked + ImmutabilityPolicyModeLocked ImmutabilityPolicyMode = blob.ImmutabilityPolicyModeLocked ) -type SetAccessControlRecursiveMode = generated.PathSetAccessControlRecursiveMode +type CopyStatusType = blob.CopyStatusType const ( - SetAccessControlRecursiveModeSet SetAccessControlRecursiveMode = generated.PathSetAccessControlRecursiveModeSet - SetAccessControlRecursiveModeModify SetAccessControlRecursiveMode = generated.PathSetAccessControlRecursiveModeModify - SetAccessControlRecursiveModeRemove SetAccessControlRecursiveMode = generated.PathSetAccessControlRecursiveModeRemove + CopyStatusTypePending CopyStatusType = blob.CopyStatusTypePending + CopyStatusTypeSuccess CopyStatusType = blob.CopyStatusTypeSuccess + CopyStatusTypeAborted CopyStatusType = blob.CopyStatusTypeAborted + CopyStatusTypeFailed CopyStatusType = blob.CopyStatusTypeFailed ) -type EncryptionAlgorithmType = blob.EncryptionAlgorithmType +type LeaseDurationType = lease.DurationType const ( - EncryptionAlgorithmTypeNone EncryptionAlgorithmType = blob.EncryptionAlgorithmTypeNone - EncryptionAlgorithmTypeAES256 EncryptionAlgorithmType = blob.EncryptionAlgorithmTypeAES256 + LeaseDurationTypeInfinite LeaseDurationType = lease.DurationTypeInfinite + LeaseDurationTypeFixed LeaseDurationType = lease.DurationTypeFixed +) + +type LeaseStateType = lease.StateType + +const ( + LeaseStateTypeAvailable LeaseStateType = lease.StateTypeAvailable + LeaseStateTypeLeased LeaseStateType = lease.StateTypeLeased + LeaseStateTypeExpired LeaseStateType = lease.StateTypeExpired + LeaseStateTypeBreaking LeaseStateType = lease.StateTypeBreaking + LeaseStateTypeBroken LeaseStateType = lease.StateTypeBroken +) + +type LeaseStatusType = lease.StatusType + +const ( + LeaseStatusTypeLocked LeaseStatusType = lease.StatusTypeLocked + LeaseStatusTypeUnlocked LeaseStatusType = lease.StatusTypeUnlocked ) diff --git a/sdk/storage/azdatalake/file/models.go b/sdk/storage/azdatalake/file/models.go index d05d0953d430..af88f45bd326 100644 --- a/sdk/storage/azdatalake/file/models.go +++ b/sdk/storage/azdatalake/file/models.go @@ -7,27 +7,33 @@ package file import ( + "errors" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/to" "github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/blob" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/datalakeerror" "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/internal/exported" "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/internal/generated" + "net/http" + "strconv" "time" ) -// CreateOptions contains the optional parameters when calling the Create operation. dfs endpoint. TODO: Design formatter +// CreateOptions contains the optional parameters when calling the Create operation. dfs endpoint. type CreateOptions struct { // AccessConditions contains parameters for accessing the file. AccessConditions *AccessConditions // Metadata is a map of name-value pairs to associate with the file storage object. Metadata map[string]*string // CPKInfo contains a group of parameters for client provided encryption key. - CPKInfo CPKInfo + CPKInfo *CPKInfo // HTTPHeaders contains the HTTP headers for path operations. - HTTPHeaders HTTPHeaders - //PathExpiryOptions *ExpiryOptions - // ExpiresOn specifies the time that the file will expire. - ExpiresOn *time.Time - // LeaseDuration specifies the duration of the lease. - LeaseDuration *time.Duration + HTTPHeaders *HTTPHeaders + // Expiry specifies the type and time of expiry for the file. + Expiry CreationExpiryType + // 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. @@ -42,19 +48,45 @@ 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.PathResourceTypeFile + 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, + if o.Expiry == nil { + createOpts.ExpiryOptions = nil + createOpts.ExpiresOn = nil + } else { + expOpts, expiresOn := o.Expiry.Format() + createOpts.ExpiryOptions = (*generated.PathExpiryOptions)(&expOpts) + createOpts.ExpiresOn = expiresOn + } + 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 = o.HTTPHeaders.formatPathHTTPHeaders() + } + if o.CPKInfo != nil { + cpkOpts = &generated.CPKInfo{ + EncryptionAlgorithm: (*generated.EncryptionAlgorithmType)(o.CPKInfo.EncryptionAlgorithm), + EncryptionKey: o.CPKInfo.EncryptionKey, + EncryptionKeySHA256: o.CPKInfo.EncryptionKeySHA256, + } } - return leaseAccessConditions, modifiedAccessConditions, httpHeaders, nil + return leaseAccessConditions, modifiedAccessConditions, httpHeaders, createOpts, cpkOpts } // DeleteOptions contains the optional parameters when calling the Delete operation. dfs endpoint @@ -63,19 +95,52 @@ type DeleteOptions struct { AccessConditions *AccessConditions } -func (o *DeleteOptions) format() (*generated.LeaseAccessConditions, *generated.ModifiedAccessConditions, error) { +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, nil + return leaseAccessConditions, modifiedAccessConditions, deleteOpts } -// RenameOptions contains the optional parameters when calling the Rename operation. TODO: Design formatter +// RenameOptions contains the optional parameters when calling the Rename operation. type RenameOptions struct { - // SourceModifiedAccessConditions identifies the source path access conditions. - SourceModifiedAccessConditions *SourceModifiedAccessConditions + // 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.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, + } + createOpts.SourceLeaseID = o.SourceAccessConditions.SourceLeaseAccessConditions.LeaseID + 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 @@ -98,6 +163,7 @@ func (o *GetPropertiesOptions) format() *blob.GetPropertiesOptions { } // ===================================== PATH IMPORTS =========================================== + // SetAccessControlOptions contains the optional parameters when calling the SetAccessControl operation. dfs endpoint type SetAccessControlOptions struct { // Owner is the owner of the path. @@ -114,10 +180,13 @@ type SetAccessControlOptions struct { func (o *SetAccessControlOptions) format() (*generated.PathClientSetAccessControlOptions, *generated.LeaseAccessConditions, *generated.ModifiedAccessConditions, error) { if o == nil { - return nil, nil, nil, nil + return nil, nil, nil, datalakeerror.MissingParameters } // call path formatter since we're hitting dfs in this operation leaseAccessConditions, modifiedAccessConditions := exported.FormatPathAccessConditions(o.AccessConditions) + if o.Owner == nil && o.Group == nil && o.ACL == nil && o.Permissions == nil { + return nil, nil, nil, errors.New("at least one parameter should be set for SetAccessControl API") + } return &generated.PathClientSetAccessControlOptions{ Owner: o.Owner, Group: o.Group, @@ -134,76 +203,43 @@ type GetAccessControlOptions struct { AccessConditions *AccessConditions } -func (o *GetAccessControlOptions) format() (*generated.PathClientGetPropertiesOptions, *generated.LeaseAccessConditions, *generated.ModifiedAccessConditions, error) { +func (o *GetAccessControlOptions) format() (*generated.PathClientGetPropertiesOptions, *generated.LeaseAccessConditions, *generated.ModifiedAccessConditions) { action := generated.PathGetPropertiesActionGetAccessControl if o == nil { return &generated.PathClientGetPropertiesOptions{ Action: &action, - }, nil, nil, nil + }, nil, nil } // call path formatter since we're hitting dfs in this operation leaseAccessConditions, modifiedAccessConditions := exported.FormatPathAccessConditions(o.AccessConditions) return &generated.PathClientGetPropertiesOptions{ Upn: o.UPN, Action: &action, - }, leaseAccessConditions, modifiedAccessConditions, nil -} - -// 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 - // 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 + }, leaseAccessConditions, modifiedAccessConditions } -func (o *SetAccessControlRecursiveOptions) format() (*generated.PathClientSetAccessControlRecursiveOptions, error) { - // TODO: design formatter - return nil, nil +// UpdateAccessControlOptions contains the optional parameters when calling the UpdateAccessControlRecursive operation. +type UpdateAccessControlOptions struct { + //placeholder } -// 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 +func (o *UpdateAccessControlOptions) format(ACL string) (*generated.PathClientSetAccessControlRecursiveOptions, generated.PathSetAccessControlRecursiveMode) { + mode := generated.PathSetAccessControlRecursiveModeModify + return &generated.PathClientSetAccessControlRecursiveOptions{ + ACL: &ACL, + }, mode } -func (o *UpdateAccessControlRecursiveOptions) format() (*generated.PathClientSetAccessControlRecursiveOptions, error) { - // TODO: design formatter - similar to SetAccessControlRecursiveOptions - return nil, nil +// RemoveAccessControlOptions contains the optional parameters when calling the RemoveAccessControlRecursive operation. +type RemoveAccessControlOptions struct { + //placeholder } -// 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 +func (o *RemoveAccessControlOptions) format(ACL string) (*generated.PathClientSetAccessControlRecursiveOptions, generated.PathSetAccessControlRecursiveMode) { + mode := generated.PathSetAccessControlRecursiveModeRemove + return &generated.PathClientSetAccessControlRecursiveOptions{ + ACL: &ACL, + }, mode } // SetHTTPHeadersOptions contains the optional parameters for the Client.SetHTTPHeaders method. @@ -211,14 +247,22 @@ type SetHTTPHeadersOptions struct { AccessConditions *AccessConditions } -func (o *SetHTTPHeadersOptions) format() *blob.SetHTTPHeadersOptions { +func (o *SetHTTPHeadersOptions) format(httpHeaders HTTPHeaders) (*blob.SetHTTPHeadersOptions, blob.HTTPHeaders) { + httpHeaderOpts := blob.HTTPHeaders{ + BlobCacheControl: httpHeaders.CacheControl, + BlobContentDisposition: httpHeaders.ContentDisposition, + BlobContentEncoding: httpHeaders.ContentEncoding, + BlobContentLanguage: httpHeaders.ContentLanguage, + BlobContentMD5: httpHeaders.ContentMD5, + BlobContentType: httpHeaders.ContentType, + } if o == nil { - return nil + return nil, httpHeaderOpts } accessConditions := exported.FormatBlobAccessConditions(o.AccessConditions) return &blob.SetHTTPHeadersOptions{ AccessConditions: accessConditions, - } + }, httpHeaderOpts } // HTTPHeaders contains the HTTP headers for path operations. @@ -239,25 +283,24 @@ type HTTPHeaders struct { ContentType *string } -func (o *HTTPHeaders) formatBlobHTTPHeaders() (*blob.HTTPHeaders, error) { - if o == nil { - return nil, nil - } - opts := blob.HTTPHeaders{ - BlobCacheControl: o.CacheControl, - BlobContentDisposition: o.ContentDisposition, - BlobContentEncoding: o.ContentEncoding, - BlobContentLanguage: o.ContentLanguage, - BlobContentMD5: o.ContentMD5, - BlobContentType: o.ContentType, - } - return &opts, nil -} - -func (o *HTTPHeaders) formatPathHTTPHeaders() (*generated.PathHTTPHeaders, error) { +// +//func (o HTTPHeaders) formatBlobHTTPHeaders() blob.HTTPHeaders { +// +// opts := blob.HTTPHeaders{ +// BlobCacheControl: o.CacheControl, +// BlobContentDisposition: o.ContentDisposition, +// BlobContentEncoding: o.ContentEncoding, +// BlobContentLanguage: o.ContentLanguage, +// BlobContentMD5: o.ContentMD5, +// BlobContentType: o.ContentType, +// } +// return opts +//} + +func (o *HTTPHeaders) formatPathHTTPHeaders() *generated.PathHTTPHeaders { // TODO: will be used for file related ops, like append if o == nil { - return nil, nil + return nil } opts := generated.PathHTTPHeaders{ CacheControl: o.CacheControl, @@ -268,32 +311,36 @@ func (o *HTTPHeaders) formatPathHTTPHeaders() (*generated.PathHTTPHeaders, error ContentType: o.ContentType, TransactionalContentHash: o.ContentMD5, } - return &opts, nil + return &opts } // SetMetadataOptions provides set of configurations for Set Metadata on path operation type SetMetadataOptions struct { + Metadata map[string]*string AccessConditions *AccessConditions CPKInfo *CPKInfo CPKScopeInfo *CPKScopeInfo } -func (o *SetMetadataOptions) format() *blob.SetMetadataOptions { +func (o *SetMetadataOptions) format() (*blob.SetMetadataOptions, map[string]*string) { if o == nil { - return nil + return nil, nil } accessConditions := exported.FormatBlobAccessConditions(o.AccessConditions) - return &blob.SetMetadataOptions{ + opts := &blob.SetMetadataOptions{ AccessConditions: accessConditions, - CPKInfo: &blob.CPKInfo{ + } + if o.CPKInfo != nil { + opts.CPKInfo = &blob.CPKInfo{ EncryptionKey: o.CPKInfo.EncryptionKey, EncryptionAlgorithm: o.CPKInfo.EncryptionAlgorithm, EncryptionKeySHA256: o.CPKInfo.EncryptionKeySHA256, - }, - CPKScopeInfo: &blob.CPKScopeInfo{ - EncryptionScope: o.CPKScopeInfo.EncryptionScope, - }, + } + } + if o.CPKScopeInfo != nil { + opts.CPKScopeInfo = (*blob.CPKScopeInfo)(o.CPKScopeInfo) } + return opts, o.Metadata } // CPKInfo contains a group of parameters for the PathClient.Download method. @@ -303,43 +350,87 @@ type CPKInfo struct { EncryptionKeySHA256 *string } -// CPKScopeInfo contains a group of parameters for the PathClient.SetMetadata method. -type CPKScopeInfo struct { - EncryptionScope *string -} - -// UndeletePathOptions contains the optional parameters for the Filesystem.UndeletePath operation. -type UndeletePathOptions struct { - // placeholder +// GetSASURLOptions contains the optional parameters for the Client.GetSASURL method. +type GetSASURLOptions struct { + StartTime *time.Time } -func (o *UndeletePathOptions) format() *UndeletePathOptions { +func (o *GetSASURLOptions) format() time.Time { if o == nil { - return nil + return time.Time{} } - return &UndeletePathOptions{} + + var st time.Time + if o.StartTime != nil { + st = o.StartTime.UTC() + } else { + st = time.Time{} + } + return st +} + +// CreationExpiryType defines values for Create() ExpiryType +type CreationExpiryType interface { + Format() (generated.ExpiryOptions, *string) + notPubliclyImplementable() } -// SourceModifiedAccessConditions identifies the source path access conditions. -type SourceModifiedAccessConditions = generated.SourceModifiedAccessConditions +// CreationExpiryTypeAbsolute defines the absolute time for the blob expiry +type CreationExpiryTypeAbsolute time.Time + +// CreationExpiryTypeRelativeToNow defines the duration relative to now for the blob expiry +type CreationExpiryTypeRelativeToNow time.Duration + +// CreationExpiryTypeNever defines that the blob will be set to never expire +type CreationExpiryTypeNever struct { + // empty struct since NeverExpire expiry type does not require expiry time +} + +func (e CreationExpiryTypeAbsolute) Format() (generated.ExpiryOptions, *string) { + return generated.ExpiryOptionsAbsolute, to.Ptr(time.Time(e).UTC().Format(http.TimeFormat)) + +} + +func (e CreationExpiryTypeAbsolute) notPubliclyImplementable() {} + +func (e CreationExpiryTypeRelativeToNow) Format() (generated.ExpiryOptions, *string) { + return generated.ExpiryOptionsRelativeToNow, to.Ptr(strconv.FormatInt(time.Duration(e).Milliseconds(), 10)) +} + +func (e CreationExpiryTypeRelativeToNow) notPubliclyImplementable() {} + +func (e CreationExpiryTypeNever) Format() (generated.ExpiryOptions, *string) { + return generated.ExpiryOptionsNeverExpire, nil +} + +func (e CreationExpiryTypeNever) notPubliclyImplementable() {} + +// ACLFailedEntry contains the failed ACL entry (response model). +type ACLFailedEntry = generated.ACLFailedEntry + +// SetAccessControlRecursiveResponse contains part of the response data returned by the []OP_AccessControl operations. +type SetAccessControlRecursiveResponse = generated.SetAccessControlRecursiveResponse + +// CPKScopeInfo contains a group of parameters for the PathClient.SetMetadata method. +type CPKScopeInfo blob.CPKScopeInfo // SharedKeyCredential contains an account's name and its primary or secondary key. type SharedKeyCredential = exported.SharedKeyCredential -// ExpiryType defines values for ExpiryType. -type ExpiryType = exported.ExpiryType +// SetExpiryType defines values for ExpiryType. +type SetExpiryType = exported.SetExpiryType -// ExpiryTypeAbsolute defines the absolute time for the expiry. -type ExpiryTypeAbsolute = exported.ExpiryTypeAbsolute +// SetExpiryTypeAbsolute defines the absolute time for the expiry. +type SetExpiryTypeAbsolute = exported.SetExpiryTypeAbsolute -// ExpiryTypeRelativeToNow defines the duration relative to now for the expiry. -type ExpiryTypeRelativeToNow = exported.ExpiryTypeRelativeToNow +// SetExpiryTypeRelativeToNow defines the duration relative to now for the expiry. +type SetExpiryTypeRelativeToNow = exported.SetExpiryTypeRelativeToNow -// ExpiryTypeRelativeToCreation defines the duration relative to creation for the expiry. -type ExpiryTypeRelativeToCreation = exported.ExpiryTypeRelativeToCreation +// SetExpiryTypeRelativeToCreation defines the duration relative to creation for the expiry. +type SetExpiryTypeRelativeToCreation = exported.SetExpiryTypeRelativeToCreation -// ExpiryTypeNever defines that will be set to never expire. -type ExpiryTypeNever = exported.ExpiryTypeNever +// SetExpiryTypeNever defines that will be set to never expire. +type SetExpiryTypeNever = exported.SetExpiryTypeNever // SetExpiryOptions contains the optional parameters for the Client.SetExpiry method. type SetExpiryOptions = exported.SetExpiryOptions @@ -347,8 +438,14 @@ type SetExpiryOptions = exported.SetExpiryOptions // AccessConditions identifies blob-specific access conditions which you optionally set. type AccessConditions = exported.AccessConditions +// SourceAccessConditions identifies blob-specific access conditions which you optionally set. +type SourceAccessConditions = exported.SourceAccessConditions + // LeaseAccessConditions contains optional parameters to access leased entity. type LeaseAccessConditions = exported.LeaseAccessConditions // ModifiedAccessConditions contains a group of parameters for specifying access conditions. type ModifiedAccessConditions = exported.ModifiedAccessConditions + +// SourceModifiedAccessConditions contains a group of parameters for specifying access conditions. +type SourceModifiedAccessConditions = exported.SourceModifiedAccessConditions diff --git a/sdk/storage/azdatalake/file/responses.go b/sdk/storage/azdatalake/file/responses.go index 9222c5c042c3..2e6a3cecee2e 100644 --- a/sdk/storage/azdatalake/file/responses.go +++ b/sdk/storage/azdatalake/file/responses.go @@ -7,8 +7,10 @@ package file import ( + "github.com/Azure/azure-sdk-for-go/sdk/azcore" "github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/blob" "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/internal/generated" + "time" ) // SetExpiryResponse contains the response fields for the SetExpiry operation. @@ -23,29 +25,55 @@ type DeleteResponse = generated.PathClientDeleteResponse // SetAccessControlResponse contains the response fields for the SetAccessControl operation. type SetAccessControlResponse = generated.PathClientSetAccessControlResponse -// SetAccessControlRecursiveResponse contains the response fields for the SetAccessControlRecursive operation. -type SetAccessControlRecursiveResponse = generated.PathClientSetAccessControlRecursiveResponse +// UpdateAccessControlResponse contains the response fields for the UpdateAccessControlRecursive operation. +type UpdateAccessControlResponse = generated.PathClientSetAccessControlRecursiveResponse -// UpdateAccessControlRecursiveResponse contains the response fields for the UpdateAccessControlRecursive operation. -type UpdateAccessControlRecursiveResponse = generated.PathClientSetAccessControlRecursiveResponse - -// RemoveAccessControlRecursiveResponse contains the response fields for the RemoveAccessControlRecursive operation. -type RemoveAccessControlRecursiveResponse = generated.PathClientSetAccessControlRecursiveResponse +// RemoveAccessControlResponse contains the response fields for the RemoveAccessControlRecursive operation. +type RemoveAccessControlResponse = generated.PathClientSetAccessControlRecursiveResponse // GetAccessControlResponse contains the response fields for the GetAccessControl operation. type GetAccessControlResponse = generated.PathClientGetPropertiesResponse // GetPropertiesResponse contains the response fields for the GetProperties operation. -type GetPropertiesResponse = generated.PathClientGetPropertiesResponse +type GetPropertiesResponse = blob.GetPropertiesResponse // SetMetadataResponse contains the response fields for the SetMetadata operation. type SetMetadataResponse = blob.SetMetadataResponse -// SetHTTPHeadersResponse contains the response fields for the SetHTTPHeaders operation. -type SetHTTPHeadersResponse = blob.SetHTTPHeadersResponse - // RenameResponse contains the response fields for the Create operation. type RenameResponse = generated.PathClientCreateResponse -// UndeletePathResponse contains the response from method FilesystemClient.UndeletePath. -type UndeletePathResponse = generated.PathClientUndeleteResponse +//// SetHTTPHeadersResponse contains the response fields for the SetHTTPHeaders operation. +//type SetHTTPHeadersResponse = blob.SetHTTPHeadersResponse + +// we need to remove the blob sequence number from the response + +// SetHTTPHeadersResponse contains the response from method Client.SetHTTPHeaders. +type SetHTTPHeadersResponse struct { + // ClientRequestID contains the information returned from the x-ms-client-request-id header response. + ClientRequestID *string + + // Date contains the information returned from the Date header response. + Date *time.Time + + // ETag contains the information returned from the ETag header response. + ETag *azcore.ETag + + // LastModified contains the information returned from the Last-Modified header response. + LastModified *time.Time + + // RequestID contains the information returned from the x-ms-request-id header response. + RequestID *string + + // Version contains the information returned from the x-ms-version header response. + Version *string +} + +func formatSetHTTPHeadersResponse(r *SetHTTPHeadersResponse, blobResp *blob.SetHTTPHeadersResponse) { + r.ClientRequestID = blobResp.ClientRequestID + r.Date = blobResp.Date + r.ETag = blobResp.ETag + r.LastModified = blobResp.LastModified + r.RequestID = blobResp.RequestID + r.Version = blobResp.Version +} diff --git a/sdk/storage/azdatalake/filesystem/client_test.go b/sdk/storage/azdatalake/filesystem/client_test.go index fa78bef404ad..3615506e870e 100644 --- a/sdk/storage/azdatalake/filesystem/client_test.go +++ b/sdk/storage/azdatalake/filesystem/client_test.go @@ -63,7 +63,7 @@ func validateFilesystemDeleted(_require *require.Assertions, filesystemClient *f _, err := filesystemClient.GetAccessPolicy(context.Background(), nil) _require.NotNil(err) - testcommon.ValidateBlobErrorCode(_require, err, datalakeerror.ContainerNotFound) + testcommon.ValidateErrorCode(_require, err, datalakeerror.ContainerNotFound) } func (s *RecordedTestSuite) TestCreateFilesystem() { @@ -158,7 +158,7 @@ func (s *RecordedTestSuite) TestFilesystemCreateInvalidName() { _, err = fsClient.Create(context.Background(), nil) _require.NotNil(err) - testcommon.ValidateBlobErrorCode(_require, err, datalakeerror.InvalidResourceName) + testcommon.ValidateErrorCode(_require, err, datalakeerror.InvalidResourceName) } func (s *RecordedTestSuite) TestFilesystemCreateNameCollision() { @@ -175,7 +175,7 @@ func (s *RecordedTestSuite) TestFilesystemCreateNameCollision() { _, err = fsClient.Create(context.Background(), nil) _require.NotNil(err) - testcommon.ValidateBlobErrorCode(_require, err, datalakeerror.FilesystemAlreadyExists) + testcommon.ValidateErrorCode(_require, err, datalakeerror.FilesystemAlreadyExists) } func (s *RecordedTestSuite) TestFilesystemGetProperties() { @@ -224,7 +224,7 @@ func (s *RecordedTestSuite) TestFilesystemDeleteNonExistent() { _, err = fsClient.Delete(context.Background(), nil) _require.NotNil(err) - testcommon.ValidateBlobErrorCode(_require, err, datalakeerror.ContainerNotFound) + testcommon.ValidateErrorCode(_require, err, datalakeerror.ContainerNotFound) } func (s *RecordedTestSuite) TestFilesystemDeleteIfModifiedSinceTrue() { @@ -275,7 +275,7 @@ func (s *RecordedTestSuite) TestFilesystemDeleteIfModifiedSinceFalse() { } _, err = fsClient.Delete(context.Background(), &deleteFilesystemOptions) _require.NotNil(err) - testcommon.ValidateBlobErrorCode(_require, err, datalakeerror.ConditionNotMet) + testcommon.ValidateErrorCode(_require, err, datalakeerror.ConditionNotMet) } func (s *RecordedTestSuite) TestFilesystemDeleteIfUnModifiedSinceTrue() { @@ -328,7 +328,7 @@ func (s *RecordedTestSuite) TestFilesystemDeleteIfUnModifiedSinceFalse() { _, err = fsClient.Delete(context.Background(), &deleteFilesystemOptions) _require.NotNil(err) - testcommon.ValidateBlobErrorCode(_require, err, datalakeerror.ConditionNotMet) + testcommon.ValidateErrorCode(_require, err, datalakeerror.ConditionNotMet) } func (s *RecordedTestSuite) TestFilesystemSetMetadataNonEmpty() { @@ -432,7 +432,7 @@ func (s *RecordedTestSuite) TestFilesystemSetMetadataNonExistent() { _, err = fsClient.SetMetadata(context.Background(), nil) _require.NotNil(err) - testcommon.ValidateBlobErrorCode(_require, err, datalakeerror.ContainerNotFound) + testcommon.ValidateErrorCode(_require, err, datalakeerror.ContainerNotFound) } func (s *RecordedTestSuite) TestSetEmptyAccessPolicy() { @@ -731,7 +731,7 @@ func (s *RecordedTestSuite) TestFilesystemSetPermissionsACLMoreThanFive() { _, err = fsClient.SetAccessPolicy(context.Background(), &setAccessPolicyOptions) _require.NotNil(err) - testcommon.ValidateBlobErrorCode(_require, err, datalakeerror.InvalidXMLDocument) + testcommon.ValidateErrorCode(_require, err, datalakeerror.InvalidXMLDocument) } func (s *RecordedTestSuite) TestFilesystemSetPermissionsDeleteAndModifyACL() { @@ -940,7 +940,7 @@ func (s *RecordedTestSuite) TestFilesystemSetPermissionsSignedIdentifierTooLong( _, err = fsClient.SetAccessPolicy(context.Background(), &setAccessPolicyOptions) _require.NotNil(err) - testcommon.ValidateBlobErrorCode(_require, err, datalakeerror.InvalidXMLDocument) + testcommon.ValidateErrorCode(_require, err, datalakeerror.InvalidXMLDocument) } func (s *RecordedTestSuite) TestFilesystemSetPermissionsIfModifiedSinceTrue() { @@ -992,7 +992,7 @@ func (s *RecordedTestSuite) TestFilesystemSetPermissionsIfModifiedSinceFalse() { _, err = fsClient.SetAccessPolicy(context.Background(), &setAccessPolicyOptions) _require.NotNil(err) - testcommon.ValidateBlobErrorCode(_require, err, datalakeerror.ConditionNotMet) + testcommon.ValidateErrorCode(_require, err, datalakeerror.ConditionNotMet) } func (s *RecordedTestSuite) TestFilesystemSetPermissionsIfUnModifiedSinceTrue() { @@ -1044,7 +1044,7 @@ func (s *RecordedTestSuite) TestFilesystemSetPermissionsIfUnModifiedSinceFalse() _, err = fsClient.SetAccessPolicy(context.Background(), &setAccessPolicyOptions) _require.NotNil(err) - testcommon.ValidateBlobErrorCode(_require, err, datalakeerror.ConditionNotMet) + testcommon.ValidateErrorCode(_require, err, datalakeerror.ConditionNotMet) } func (s *RecordedTestSuite) TestSetAccessPoliciesInDifferentTimeFormats() { @@ -1134,7 +1134,7 @@ func (s *RecordedTestSuite) TestSetAccessPolicyWithNullId() { options := filesystem.SetAccessPolicyOptions{FilesystemACL: signedIdentifiers} _, err = fsClient.SetAccessPolicy(context.Background(), &options) _require.NotNil(err) - testcommon.ValidateBlobErrorCode(_require, err, datalakeerror.InvalidXMLDocument) + testcommon.ValidateErrorCode(_require, err, datalakeerror.InvalidXMLDocument) resp1, err := fsClient.GetAccessPolicy(context.Background(), nil) _require.Nil(err) diff --git a/sdk/storage/azdatalake/filesystem/models.go b/sdk/storage/azdatalake/filesystem/models.go index c36a5acf1eb8..e0d6f6ce0b86 100644 --- a/sdk/storage/azdatalake/filesystem/models.go +++ b/sdk/storage/azdatalake/filesystem/models.go @@ -199,6 +199,18 @@ func (o *GetSASURLOptions) format() time.Time { return st } +// UndeletePathOptions contains the optional parameters for the Filesystem.UndeletePath operation. +type UndeletePathOptions struct { + // placeholder +} + +func (o *UndeletePathOptions) format() *UndeletePathOptions { + if o == nil { + return nil + } + return &UndeletePathOptions{} +} + // SharedKeyCredential contains an account's name and its primary or secondary key. type SharedKeyCredential = exported.SharedKeyCredential @@ -216,3 +228,6 @@ type PathList = generated.PathList // Path contains the path properties type Path = generated.Path + +// UndeletePathResponse contains the response from method FilesystemClient.UndeletePath. +type UndeletePathResponse = generated.PathClientUndeleteResponse diff --git a/sdk/storage/azdatalake/internal/base/clients.go b/sdk/storage/azdatalake/internal/base/clients.go index 3ebb6fc7ee69..c80152dc4b83 100644 --- a/sdk/storage/azdatalake/internal/base/clients.go +++ b/sdk/storage/azdatalake/internal/base/clients.go @@ -9,7 +9,7 @@ package base import ( "github.com/Azure/azure-sdk-for-go/sdk/azcore" "github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime" - "github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/blob" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/blockblob" "github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/container" "github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/service" "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/internal/exported" @@ -69,10 +69,10 @@ func NewServiceClient(serviceURL string, serviceURLWithBlobEndpoint string, clie } } -func NewPathClient(dirURL string, dirURLWithBlobEndpoint string, client *blob.Client, azClient *azcore.Client, sharedKey *exported.SharedKeyCredential, options *ClientOptions) *CompositeClient[generated.PathClient, generated.PathClient, blob.Client] { - return &CompositeClient[generated.PathClient, generated.PathClient, blob.Client]{ - innerT: generated.NewPathClient(dirURL, azClient), - innerK: generated.NewPathClient(dirURLWithBlobEndpoint, azClient), +func NewPathClient(pathURL string, pathURLWithBlobEndpoint string, client *blockblob.Client, azClient *azcore.Client, sharedKey *exported.SharedKeyCredential, options *ClientOptions) *CompositeClient[generated.PathClient, generated.PathClient, blockblob.Client] { + return &CompositeClient[generated.PathClient, generated.PathClient, blockblob.Client]{ + innerT: generated.NewPathClient(pathURL, azClient), + innerK: generated.NewPathClient(pathURLWithBlobEndpoint, azClient), sharedKey: sharedKey, innerU: client, options: options, diff --git a/sdk/storage/azdatalake/internal/exported/access_conditions.go b/sdk/storage/azdatalake/internal/exported/access_conditions.go index 974cb1ed628e..9e6fb3850bbd 100644 --- a/sdk/storage/azdatalake/internal/exported/access_conditions.go +++ b/sdk/storage/azdatalake/internal/exported/access_conditions.go @@ -12,12 +12,21 @@ type AccessConditions struct { LeaseAccessConditions *LeaseAccessConditions } +// SourceAccessConditions identifies container-specific access conditions which you optionally set. +type SourceAccessConditions struct { + SourceModifiedAccessConditions *SourceModifiedAccessConditions + SourceLeaseAccessConditions *LeaseAccessConditions +} + // LeaseAccessConditions contains optional parameters to access leased entity. type LeaseAccessConditions = generated.LeaseAccessConditions // ModifiedAccessConditions contains a group of parameters for specifying access conditions. type ModifiedAccessConditions = generated.ModifiedAccessConditions +// SourceModifiedAccessConditions contains a group of parameters for specifying access conditions of a source. +type SourceModifiedAccessConditions = generated.SourceModifiedAccessConditions + // FormatContainerAccessConditions formats FilesystemAccessConditions into container's LeaseAccessConditions and ModifiedAccessConditions. func FormatContainerAccessConditions(b *AccessConditions) *container.AccessConditions { if b == nil { diff --git a/sdk/storage/azdatalake/internal/exported/set_expiry.go b/sdk/storage/azdatalake/internal/exported/set_expiry.go index 041dd8ba60c0..2b8e156c315f 100644 --- a/sdk/storage/azdatalake/internal/exported/set_expiry.go +++ b/sdk/storage/azdatalake/internal/exported/set_expiry.go @@ -15,23 +15,23 @@ import ( "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/internal/generated" ) -// ExpiryType defines values for ExpiryType -type ExpiryType interface { +// SetExpiryType defines values for ExpiryType +type SetExpiryType interface { Format(o *SetExpiryOptions) (generated.ExpiryOptions, *generated.PathClientSetExpiryOptions) notPubliclyImplementable() } -// ExpiryTypeAbsolute defines the absolute time for the blob expiry -type ExpiryTypeAbsolute time.Time +// SetExpiryTypeAbsolute defines the absolute time for the blob expiry +type SetExpiryTypeAbsolute time.Time -// ExpiryTypeRelativeToNow defines the duration relative to now for the blob expiry -type ExpiryTypeRelativeToNow time.Duration +// SetExpiryTypeRelativeToNow defines the duration relative to now for the blob expiry +type SetExpiryTypeRelativeToNow time.Duration -// ExpiryTypeRelativeToCreation defines the duration relative to creation for the blob expiry -type ExpiryTypeRelativeToCreation time.Duration +// SetExpiryTypeRelativeToCreation defines the duration relative to creation for the blob expiry +type SetExpiryTypeRelativeToCreation time.Duration -// ExpiryTypeNever defines that the blob will be set to never expire -type ExpiryTypeNever struct { +// SetExpiryTypeNever defines that the blob will be set to never expire +type SetExpiryTypeNever struct { // empty struct since NeverExpire expiry type does not require expiry time } @@ -40,32 +40,32 @@ type SetExpiryOptions struct { // placeholder for future options } -func (e ExpiryTypeAbsolute) Format(o *SetExpiryOptions) (generated.ExpiryOptions, *generated.PathClientSetExpiryOptions) { +func (e SetExpiryTypeAbsolute) Format(o *SetExpiryOptions) (generated.ExpiryOptions, *generated.PathClientSetExpiryOptions) { return generated.ExpiryOptionsAbsolute, &generated.PathClientSetExpiryOptions{ ExpiresOn: to.Ptr(time.Time(e).UTC().Format(http.TimeFormat)), } } -func (e ExpiryTypeAbsolute) notPubliclyImplementable() {} +func (e SetExpiryTypeAbsolute) notPubliclyImplementable() {} -func (e ExpiryTypeRelativeToNow) Format(o *SetExpiryOptions) (generated.ExpiryOptions, *generated.PathClientSetExpiryOptions) { +func (e SetExpiryTypeRelativeToNow) Format(o *SetExpiryOptions) (generated.ExpiryOptions, *generated.PathClientSetExpiryOptions) { return generated.ExpiryOptionsRelativeToNow, &generated.PathClientSetExpiryOptions{ ExpiresOn: to.Ptr(strconv.FormatInt(time.Duration(e).Milliseconds(), 10)), } } -func (e ExpiryTypeRelativeToNow) notPubliclyImplementable() {} +func (e SetExpiryTypeRelativeToNow) notPubliclyImplementable() {} -func (e ExpiryTypeRelativeToCreation) Format(o *SetExpiryOptions) (generated.ExpiryOptions, *generated.PathClientSetExpiryOptions) { +func (e SetExpiryTypeRelativeToCreation) Format(o *SetExpiryOptions) (generated.ExpiryOptions, *generated.PathClientSetExpiryOptions) { return generated.ExpiryOptionsRelativeToCreation, &generated.PathClientSetExpiryOptions{ ExpiresOn: to.Ptr(strconv.FormatInt(time.Duration(e).Milliseconds(), 10)), } } -func (e ExpiryTypeRelativeToCreation) notPubliclyImplementable() {} +func (e SetExpiryTypeRelativeToCreation) notPubliclyImplementable() {} -func (e ExpiryTypeNever) Format(o *SetExpiryOptions) (generated.ExpiryOptions, *generated.PathClientSetExpiryOptions) { - return generated.ExpiryOptionsNeverExpire, nil +func (e SetExpiryTypeNever) Format(o *SetExpiryOptions) (generated.ExpiryOptions, *generated.PathClientSetExpiryOptions) { + return generated.ExpiryOptionsNeverExpire, &generated.PathClientSetExpiryOptions{} } -func (e ExpiryTypeNever) notPubliclyImplementable() {} +func (e SetExpiryTypeNever) notPubliclyImplementable() {} diff --git a/sdk/storage/azdatalake/internal/testcommon/clients_auth.go b/sdk/storage/azdatalake/internal/testcommon/clients_auth.go index 5988e217e87e..bd1607b2fec4 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/file" "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/filesystem" "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/service" "github.com/stretchr/testify/require" @@ -33,6 +34,23 @@ const ( var BasicMetadata = map[string]*string{"Foo": to.Ptr("bar")} +var ( + DatalakeContentType = "my_type" + DatalakeContentDisposition = "my_disposition" + DatalakeCacheControl = "control" + DatalakeContentLanguage = "my_language" + DatalakeContentEncoding = "my_encoding" +) + +var BasicHeaders = file.HTTPHeaders{ + ContentType: &DatalakeContentType, + ContentDisposition: &DatalakeContentDisposition, + CacheControl: &DatalakeCacheControl, + ContentMD5: nil, + ContentLanguage: &DatalakeContentLanguage, + ContentEncoding: &DatalakeContentEncoding, +} + type TestAccountType string const ( @@ -105,6 +123,23 @@ func GetFilesystemClient(fsName string, t *testing.T, accountType TestAccountTyp return filesystemClient, err } +func GetFileClient(fsName, fName string, t *testing.T, accountType TestAccountType, options *file.ClientOptions) (*file.Client, error) { + if options == nil { + options = &file.ClientOptions{} + } + + SetClientOptions(t, &options.ClientOptions) + + cred, err := GetGenericSharedKeyCredential(accountType) + if err != nil { + return nil, err + } + + fileClient, err := file.NewClientWithSharedKeyCredential("https://"+cred.AccountName()+".dfs.core.windows.net/"+fsName+"/"+fName, cred, options) + + return fileClient, err +} + func ServiceGetFilesystemClient(filesystemName string, s *service.Client) *filesystem.Client { return s.NewFilesystemClient(filesystemName) } @@ -114,6 +149,11 @@ func DeleteFilesystem(ctx context.Context, _require *require.Assertions, filesys _require.Nil(err) } +func DeleteFile(ctx context.Context, _require *require.Assertions, fileClient *file.Client) { + _, err := fileClient.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 71534c98af95..fcb537b98c52 100644 --- a/sdk/storage/azdatalake/internal/testcommon/common.go +++ b/sdk/storage/azdatalake/internal/testcommon/common.go @@ -23,6 +23,10 @@ func GenerateFilesystemName(testName string) string { return FilesystemPrefix + GenerateEntityName(testName) } +func GenerateFileName(testName string) string { + return FilePrefix + GenerateEntityName(testName) +} + func GenerateEntityName(testName string) string { return strings.ReplaceAll(strings.ReplaceAll(strings.ToLower(testName), "/", ""), "test", "") } @@ -62,7 +66,7 @@ func GetRequiredEnv(name string) (string, error) { } } -func ValidateBlobErrorCode(_require *require.Assertions, err error, code bloberror.Code) { +func ValidateErrorCode(_require *require.Assertions, err error, code bloberror.Code) { _require.NotNil(err) var responseErr *azcore.ResponseError errors.As(err, &responseErr) diff --git a/sdk/storage/azdatalake/service/client_test.go b/sdk/storage/azdatalake/service/client_test.go index c222bac865d8..a9541d4356a4 100644 --- a/sdk/storage/azdatalake/service/client_test.go +++ b/sdk/storage/azdatalake/service/client_test.go @@ -307,7 +307,7 @@ func (s *ServiceRecordedTestsSuite) TestAccountDeleteRetentionPolicyDaysTooLarge _, err = svcClient.SetProperties(context.Background(), &service.SetPropertiesOptions{DeleteRetentionPolicy: &service.RetentionPolicy{Enabled: &enabled, Days: &days}}) _require.NotNil(err) - testcommon.ValidateBlobErrorCode(_require, err, datalakeerror.InvalidXMLDocument) + testcommon.ValidateErrorCode(_require, err, datalakeerror.InvalidXMLDocument) } } @@ -321,7 +321,7 @@ func (s *ServiceRecordedTestsSuite) TestAccountDeleteRetentionPolicyDaysOmitted( _, err = svcClient.SetProperties(context.Background(), &service.SetPropertiesOptions{DeleteRetentionPolicy: &service.RetentionPolicy{Enabled: &enabled}}) _require.NotNil(err) - testcommon.ValidateBlobErrorCode(_require, err, datalakeerror.InvalidXMLDocument) + testcommon.ValidateErrorCode(_require, err, datalakeerror.InvalidXMLDocument) } func (s *ServiceRecordedTestsSuite) TestSASServiceClient() { @@ -495,7 +495,7 @@ func (s *ServiceRecordedTestsSuite) TestSASFilesystemClient() { _, err = fsClient2.Create(context.Background(), &filesystem.CreateOptions{Metadata: testcommon.BasicMetadata}) _require.NotNil(err) - testcommon.ValidateBlobErrorCode(_require, err, datalakeerror.AuthorizationFailure) + testcommon.ValidateErrorCode(_require, err, datalakeerror.AuthorizationFailure) } func (s *ServiceRecordedTestsSuite) TestSASFilesystem2() { @@ -526,7 +526,7 @@ func (s *ServiceRecordedTestsSuite) TestSASFilesystem2() { // filesystem metadata and properties can't be read or written with SAS auth _, err = fsClient1.GetProperties(context.Background(), nil) _require.Error(err) - testcommon.ValidateBlobErrorCode(_require, err, datalakeerror.AuthorizationFailure) + testcommon.ValidateErrorCode(_require, err, datalakeerror.AuthorizationFailure) start = time.Now().Add(-5 * time.Minute).UTC() opts = filesystem.GetSASURLOptions{StartTime: &start} @@ -540,7 +540,7 @@ func (s *ServiceRecordedTestsSuite) TestSASFilesystem2() { // filesystems can't be created, deleted, or listed with SAS auth _, err = fsClient2.Create(context.Background(), nil) _require.Error(err) - testcommon.ValidateBlobErrorCode(_require, err, datalakeerror.AuthorizationFailure) + testcommon.ValidateErrorCode(_require, err, datalakeerror.AuthorizationFailure) } func (s *ServiceRecordedTestsSuite) TestListFilesystemsBasic() { From 68d465fdc9891b3861ef07b12ae57295c5b2d6d5 Mon Sep 17 00:00:00 2001 From: Tamer Sherif <69483382+tasherif-msft@users.noreply.github.com> Date: Mon, 24 Jul 2023 10:59:33 -0700 Subject: [PATCH 09/16] [AzDatalake] Cleanup + Improvements (#21222) * Enable gocritic during linting (#20715) Enabled gocritic's evalOrder to catch dependencies on undefined behavior on return statements. Updated to latest version of golangci-lint. Fixed issue in azblob flagged by latest linter. * Cosmos DB: Enable merge support (#20716) * Adding header and value * Wiring and tests * format * Fixing value * change log * [azservicebus, azeventhubs] Stress test and logging improvement (#20710) Logging improvements: * Updating the logging to print more tracing information (per-link) in prep for the bigger release coming up. * Trimming out some of the verbose logging, seeing if I can get it a bit more reasonable. Stress tests: * Add a timestamp to the log name we generate and also default to append, not overwrite. * Use 0.5 cores, 0.5GB as our baseline. Some pods use more and I'll tune them more later. * update proxy version (#20712) Co-authored-by: Scott Beddall * Return an error when you try to send a message that's too large. (#20721) This now works just like the message batch - you'll get an ErrMessageTooLarge if you attempt to send a message that's too large for the link's configured size. NOTE: there's a patch to `internal/go-amqp/Sender.go` to match what's in go-amqp's main so it returns a programmatically useful error when the message is too large. Fixes #20647 * Changes in test that is failing in pipeline (#20693) * [azservicebus, azeventhubs] Treat 'entity full' as a fatal error (#20722) When the remote entity is full we get a resource-limit-exceeded condition. This isn't something we should keep retrying on and it's best to just abort and let the user know immediately, rather than hoping it might eventually clear out. This affected both Event Hubs and Service Bus. Fixes #20647 * [azservicebus/azeventhubs] Redirect stderr and stdout to tee (#20726) * Update changelog with latest features (#20730) * Update changelog with latest features Prepare for upcoming release. * bump minor version * pass along the artifact name so we can override it later (#20732) Co-authored-by: scbedd <45376673+scbedd@users.noreply.github.com> * [azeventhubs] Fixing checkpoint store race condition (#20727) The checkpoint store wasn't guarding against multiple owners claiming for the first time - fixing this by using IfNoneMatch Fixes #20717 * Fix azidentity troubleshooting guide link (#20736) * [Release] sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/0.1.0 (#20437) * [Release] sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/0.1.0 generation from spec commit: 85fb4ac6f8bfefd179e6c2632976a154b5c9ff04 * client factory * fix * fix * update * add sdk/resourcemanager/postgresql/armpostgresql live test (#20685) * add sdk/resourcemanager/postgresql/armpostgresql live test * update assets.json * set subscriptionId default value * format * add sdk/resourcemanager/eventhub/armeventhub live test (#20686) * add sdk/resourcemanager/eventhub/armeventhub live test * update assets * add sdk/resourcemanager/compute/armcompute live test (#20048) * add sdk/resourcemanager/compute/armcompute live test * skus filter * fix subscriptionId default value * fix * gofmt * update recording * sdk/resourcemanager/network/armnetwork live test (#20331) * sdk/resourcemanager/network/armnetwork live test * update subscriptionId default value * update recording * add sdk/resourcemanager/cosmos/armcosmos live test (#20705) * add sdk/resourcemanager/cosmos/armcosmos live test * update assets.json * update assets.json * update assets.json * update assets.json * Increment package version after release of azcore (#20740) * [azeventhubs] Improperly resetting etag in the checkpoint store (#20737) We shouldn't be resetting the etag to nil - it's what we use to enforce a "single winner" when doing ownership claims. The bug here was two-fold: I had bad logic in my previous claim ownership, which I fixed in a previous PR, but we need to reflect that same constraint properly in our in-memory checkpoint store for these tests. * Eng workflows sync and branch cleanup additions (#20743) Co-authored-by: James Suplizio * [azeventhubs] Latest start position can also be inclusive (ie, get the latest message) (#20744) * Update GitHubEventProcessor version and remove pull_request_review procesing (#20751) Co-authored-by: James Suplizio * Rename DisableAuthorityValidationAndInstanceDiscovery (#20746) * fix (#20707) * AzFile (#20739) * azfile: Fixing connection string parsing logic (#20798) * Fixing connection string parse logic * Update README * [azadmin] fix flaky test (#20758) * fix flaky test * charles suggestion * Prepare azidentity v1.3.0 for release (#20756) * Fix broken podman link (#20801) Co-authored-by: Wes Haggard * [azquery] update doc comments (#20755) * update doc comments * update statistics and visualization generation * prep-for-release * Fixed contribution section (#20752) Co-authored-by: Bob Tabor * [azeventhubs,azservicebus] Some API cleanup, renames (#20754) * Adding options to UpdateCheckpoint(), just for future potential expansion * Make Offset an int64, not a *int64 (it's not optional, it'll always come back with ReceivedEvents) * Adding more logging into the checkpoint store. * Point all imports at the production go-amqp * Add supporting features to enable distributed tracing (#20301) (#20708) * Add supporting features to enable distributed tracing This includes new internal pipeline policies and other supporting types. See the changelog for a full description. Added some missing doc comments. * fix linter issue * add net.peer.name trace attribute sequence custom HTTP header policy before logging policy. sequence logging policy after HTTP trace policy. keep body download policy at the end. * add span for iterating over pages * Restore ARM CAE support for azcore beta (#20657) This reverts commit 902097226ff3fe2fc6c3e7fc50d3478350253614. * Upgrade to stable azcore (#20808) * Increment package version after release of data/azcosmos (#20807) * Updating changelog (#20810) * Add fake package to azcore (#20711) * Add fake package to azcore This is the supporting infrastructure for the generated SDK fakes. * fix doc comment * Updating CHANGELOG.md (#20809) * changelog (#20811) * Increment package version after release of storage/azfile (#20813) * Update changelog (azblob) (#20815) * Updating CHANGELOG.md * Update the changelog with correct version * [azquery] migration guide (#20742) * migration guide * Charles feedback * Richard feedback --------- Co-authored-by: Charles Lowell <10964656+chlowell@users.noreply.github.com> * Increment package version after release of monitor/azquery (#20820) * [keyvault] prep for release (#20819) * prep for release * perf tests * update date * fixed datalake errors + moved to internal path * delegation key + constants * removed test * further cleanup * renamed support and client fixes * added tests * handle error for rename * fixed response formatting * cleanup --------- Co-authored-by: Joel Hendrix Co-authored-by: Matias Quaranta Co-authored-by: Richard Park <51494936+richardpark-msft@users.noreply.github.com> Co-authored-by: Azure SDK Bot <53356347+azure-sdk@users.noreply.github.com> Co-authored-by: Scott Beddall Co-authored-by: siminsavani-msft <77068571+siminsavani-msft@users.noreply.github.com> Co-authored-by: scbedd <45376673+scbedd@users.noreply.github.com> Co-authored-by: Charles Lowell <10964656+chlowell@users.noreply.github.com> Co-authored-by: Peng Jiahui <46921893+Alancere@users.noreply.github.com> Co-authored-by: James Suplizio Co-authored-by: Sourav Gupta <98318303+souravgupta-msft@users.noreply.github.com> Co-authored-by: gracewilcox <43627800+gracewilcox@users.noreply.github.com> Co-authored-by: Wes Haggard Co-authored-by: Bob Tabor Co-authored-by: Bob Tabor --- sdk/storage/azdatalake/assets.json | 2 +- sdk/storage/azdatalake/common.go | 45 ++ .../azdatalake/datalakeerror/error_codes.go | 240 ++++---- sdk/storage/azdatalake/directory/client.go | 17 +- sdk/storage/azdatalake/directory/constants.go | 33 +- sdk/storage/azdatalake/directory/models.go | 214 +------ sdk/storage/azdatalake/directory/responses.go | 25 +- sdk/storage/azdatalake/file/client.go | 130 ++-- sdk/storage/azdatalake/file/client_test.go | 554 +++++++++--------- sdk/storage/azdatalake/file/constants.go | 54 +- sdk/storage/azdatalake/file/models.go | 260 ++------ sdk/storage/azdatalake/file/responses.go | 59 +- sdk/storage/azdatalake/filesystem/client.go | 58 +- .../azdatalake/filesystem/client_test.go | 6 +- .../azdatalake/filesystem/constants.go | 45 -- .../azdatalake/filesystem/responses.go | 8 +- sdk/storage/azdatalake/go.mod | 2 +- sdk/storage/azdatalake/go.sum | 4 +- .../azdatalake/internal/base/clients.go | 50 +- .../azdatalake/internal/exported/exported.go | 19 + .../azdatalake/internal/exported/path.go | 1 - .../exported/user_delegation_credential.go | 4 +- .../internal/generated/user_delegation_key.go | 144 +++++ .../azdatalake/internal/path/constants.go | 35 ++ .../azdatalake/internal/path/models.go | 243 ++++++++ .../azdatalake/internal/path/responses.go | 269 +++++++++ .../azdatalake/internal/testcommon/common.go | 4 +- sdk/storage/azdatalake/lease/constants.go | 51 -- sdk/storage/azdatalake/service/client.go | 75 +-- sdk/storage/azdatalake/service/client_test.go | 33 +- sdk/storage/azdatalake/service/models.go | 30 +- sdk/storage/azdatalake/service/responses.go | 7 +- 32 files changed, 1538 insertions(+), 1183 deletions(-) delete mode 100644 sdk/storage/azdatalake/internal/exported/path.go create mode 100644 sdk/storage/azdatalake/internal/generated/user_delegation_key.go create mode 100644 sdk/storage/azdatalake/internal/path/constants.go create mode 100644 sdk/storage/azdatalake/internal/path/models.go create mode 100644 sdk/storage/azdatalake/internal/path/responses.go delete mode 100644 sdk/storage/azdatalake/lease/constants.go diff --git a/sdk/storage/azdatalake/assets.json b/sdk/storage/azdatalake/assets.json index e712ffb1d71d..0f87599cacfb 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_820b86faa9" + "Tag": "go/storage/azdatalake_db1de4a48b" } \ No newline at end of file diff --git a/sdk/storage/azdatalake/common.go b/sdk/storage/azdatalake/common.go index fc67050f51ee..6baefa3c6857 100644 --- a/sdk/storage/azdatalake/common.go +++ b/sdk/storage/azdatalake/common.go @@ -7,6 +7,7 @@ package azdatalake import ( + "github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/lease" "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/internal/exported" "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/sas" ) @@ -34,3 +35,47 @@ func ParseURL(u string) (URLParts, error) { // 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 = exported.HTTPRange + +// ===================================== LEASE CONSTANTS ============================================================ + +// StatusType defines values for StatusType +type StatusType = lease.StatusType + +const ( + StatusTypeLocked StatusType = lease.StatusTypeLocked + StatusTypeUnlocked StatusType = lease.StatusTypeUnlocked +) + +// PossibleStatusTypeValues returns the possible values for the StatusType const type. +func PossibleStatusTypeValues() []StatusType { + return lease.PossibleStatusTypeValues() +} + +// DurationType defines values for DurationType +type DurationType = lease.DurationType + +const ( + DurationTypeInfinite DurationType = lease.DurationTypeInfinite + DurationTypeFixed DurationType = lease.DurationTypeFixed +) + +// PossibleDurationTypeValues returns the possible values for the DurationType const type. +func PossibleDurationTypeValues() []DurationType { + return lease.PossibleDurationTypeValues() +} + +// StateType defines values for StateType +type StateType = lease.StateType + +const ( + StateTypeAvailable StateType = lease.StateTypeAvailable + StateTypeLeased StateType = lease.StateTypeLeased + StateTypeExpired StateType = lease.StateTypeExpired + StateTypeBreaking StateType = lease.StateTypeBreaking + StateTypeBroken StateType = lease.StateTypeBroken +) + +// PossibleStateTypeValues returns the possible values for the StateType const type. +func PossibleStateTypeValues() []StateType { + return lease.PossibleStateTypeValues() +} diff --git a/sdk/storage/azdatalake/datalakeerror/error_codes.go b/sdk/storage/azdatalake/datalakeerror/error_codes.go index a40e54cebe37..b482c9b3f929 100644 --- a/sdk/storage/azdatalake/datalakeerror/error_codes.go +++ b/sdk/storage/azdatalake/datalakeerror/error_codes.go @@ -15,7 +15,7 @@ import ( // HasCode returns true if the provided error is an *azcore.ResponseError // with its ErrorCode field equal to one of the specified Codes. -func HasCode(err error, codes ...Code) bool { +func HasCode(err error, codes ...StorageErrorCode) bool { var respErr *azcore.ResponseError if !errors.As(err, &respErr) { return false @@ -32,23 +32,16 @@ func HasCode(err error, codes ...Code) bool { type StorageErrorCode string -// Code - Error codes returned by the service -type Code = bloberror.Code - +// dfs errors const ( ContentLengthMustBeZero StorageErrorCode = "ContentLengthMustBeZero" - PathAlreadyExists StorageErrorCode = "PathAlreadyExists" InvalidFlushPosition StorageErrorCode = "InvalidFlushPosition" InvalidPropertyName StorageErrorCode = "InvalidPropertyName" InvalidSourceURI StorageErrorCode = "InvalidSourceUri" UnsupportedRestVersion StorageErrorCode = "UnsupportedRestVersion" - FileSystemNotFound StorageErrorCode = "FilesystemNotFound" - PathNotFound StorageErrorCode = "PathNotFound" RenameDestinationParentPathNotFound StorageErrorCode = "RenameDestinationParentPathNotFound" SourcePathNotFound StorageErrorCode = "SourcePathNotFound" DestinationPathIsBeingDeleted StorageErrorCode = "DestinationPathIsBeingDeleted" - FileSystemAlreadyExists StorageErrorCode = "FilesystemAlreadyExists" - FileSystemBeingDeleted StorageErrorCode = "FilesystemBeingDeleted" InvalidDestinationPath StorageErrorCode = "InvalidDestinationPath" InvalidRenameSourcePath StorageErrorCode = "InvalidRenameSourcePath" InvalidSourceOrDestinationResourceType StorageErrorCode = "InvalidSourceOrDestinationResourceType" @@ -58,121 +51,122 @@ const ( SourcePathIsBeingDeleted StorageErrorCode = "SourcePathIsBeingDeleted" ) +// (converted) blob errors - these errors are what we expect after we do a replace on the error string using the ConvertBlobError function const ( - AccountAlreadyExists Code = "AccountAlreadyExists" - AccountBeingCreated Code = "AccountBeingCreated" - AccountIsDisabled Code = "AccountIsDisabled" - AppendPositionConditionNotMet Code = "AppendPositionConditionNotMet" - AuthenticationFailed Code = "AuthenticationFailed" - AuthorizationFailure Code = "AuthorizationFailure" - AuthorizationPermissionMismatch Code = "AuthorizationPermissionMismatch" - AuthorizationProtocolMismatch Code = "AuthorizationProtocolMismatch" - AuthorizationResourceTypeMismatch Code = "AuthorizationResourceTypeMismatch" - AuthorizationServiceMismatch Code = "AuthorizationServiceMismatch" - AuthorizationSourceIPMismatch Code = "AuthorizationSourceIPMismatch" - BlobAlreadyExists Code = "BlobAlreadyExists" - PathArchived Code = "BlobArchived" - PathBeingRehydrated Code = "BlobBeingRehydrated" - PathImmutableDueToPolicy Code = "BlobImmutableDueToPolicy" - PathNotArchived Code = "BlobNotArchived" - BlobNotFound Code = "BlobNotFound" - PathOverwritten Code = "BlobOverwritten" - PathTierInadequateForContentLength Code = "BlobTierInadequateForContentLength" - PathUsesCustomerSpecifiedEncryption Code = "BlobUsesCustomerSpecifiedEncryption" - BlockCountExceedsLimit Code = "BlockCountExceedsLimit" - BlockListTooLong Code = "BlockListTooLong" - CannotChangeToLowerTier Code = "CannotChangeToLowerTier" - CannotVerifyCopySource Code = "CannotVerifyCopySource" - ConditionHeadersNotSupported Code = "ConditionHeadersNotSupported" - ConditionNotMet Code = "ConditionNotMet" - FilesystemAlreadyExists Code = "ContainerAlreadyExists" - ContainerBeingDeleted Code = "ContainerBeingDeleted" - ContainerDisabled Code = "ContainerDisabled" - ContainerNotFound Code = "ContainerNotFound" - ContentLengthLargerThanTierLimit Code = "ContentLengthLargerThanTierLimit" - CopyAcrossAccountsNotSupported Code = "CopyAcrossAccountsNotSupported" - CopyIDMismatch Code = "CopyIdMismatch" - EmptyMetadataKey Code = "EmptyMetadataKey" - FeatureVersionMismatch Code = "FeatureVersionMismatch" - IncrementalCopyPathMismatch Code = "IncrementalCopyBlobMismatch" - IncrementalCopyOfEralierVersionSnapshotNotAllowed Code = "IncrementalCopyOfEralierVersionSnapshotNotAllowed" - IncrementalCopySourceMustBeSnapshot Code = "IncrementalCopySourceMustBeSnapshot" - InfiniteLeaseDurationRequired Code = "InfiniteLeaseDurationRequired" - InsufficientAccountPermissions Code = "InsufficientAccountPermissions" - InternalError Code = "InternalError" - InvalidAuthenticationInfo Code = "InvalidAuthenticationInfo" - InvalidBlobOrBlock Code = "InvalidBlobOrBlock" - InvalidPathTier Code = "InvalidBlobTier" - InvalidPathType Code = "InvalidBlobType" - InvalidBlockID Code = "InvalidBlockId" - InvalidBlockList Code = "InvalidBlockList" - InvalidHTTPVerb Code = "InvalidHttpVerb" - InvalidHeaderValue Code = "InvalidHeaderValue" - InvalidInput Code = "InvalidInput" - InvalidMD5 Code = "InvalidMd5" - InvalidMetadata Code = "InvalidMetadata" - InvalidOperation Code = "InvalidOperation" - InvalidPageRange Code = "InvalidPageRange" - InvalidQueryParameterValue Code = "InvalidQueryParameterValue" - InvalidRange Code = "InvalidRange" - InvalidResourceName Code = "InvalidResourceName" - InvalidSourcePathType Code = "InvalidSourceBlobType" - InvalidSourcePathURL Code = "InvalidSourceBlobUrl" - InvalidURI Code = "InvalidUri" - InvalidVersionForPageBlobOperation Code = "InvalidVersionForPageBlobOperation" - InvalidXMLDocument Code = "InvalidXmlDocument" - InvalidXMLNodeValue Code = "InvalidXmlNodeValue" - LeaseAlreadyBroken Code = "LeaseAlreadyBroken" - LeaseAlreadyPresent Code = "LeaseAlreadyPresent" - LeaseIDMismatchWithBlobOperation Code = "LeaseIdMismatchWithBlobOperation" - LeaseIDMismatchWithContainerOperation Code = "LeaseIdMismatchWithContainerOperation" - LeaseIDMismatchWithLeaseOperation Code = "LeaseIdMismatchWithLeaseOperation" - LeaseIDMissing Code = "LeaseIdMissing" - LeaseIsBreakingAndCannotBeAcquired Code = "LeaseIsBreakingAndCannotBeAcquired" - LeaseIsBreakingAndCannotBeChanged Code = "LeaseIsBreakingAndCannotBeChanged" - LeaseIsBrokenAndCannotBeRenewed Code = "LeaseIsBrokenAndCannotBeRenewed" - LeaseLost Code = "LeaseLost" - LeaseNotPresentWithBlobOperation Code = "LeaseNotPresentWithBlobOperation" - LeaseNotPresentWithContainerOperation Code = "LeaseNotPresentWithContainerOperation" - LeaseNotPresentWithLeaseOperation Code = "LeaseNotPresentWithLeaseOperation" - MD5Mismatch Code = "Md5Mismatch" - CRC64Mismatch Code = "Crc64Mismatch" - MaxBlobSizeConditionNotMet Code = "MaxBlobSizeConditionNotMet" - MetadataTooLarge Code = "MetadataTooLarge" - MissingContentLengthHeader Code = "MissingContentLengthHeader" - MissingRequiredHeader Code = "MissingRequiredHeader" - MissingRequiredQueryParameter Code = "MissingRequiredQueryParameter" - MissingRequiredXMLNode Code = "MissingRequiredXmlNode" - MultipleConditionHeadersNotSupported Code = "MultipleConditionHeadersNotSupported" - NoAuthenticationInformation Code = "NoAuthenticationInformation" - NoPendingCopyOperation Code = "NoPendingCopyOperation" - OperationNotAllowedOnIncrementalCopyBlob Code = "OperationNotAllowedOnIncrementalCopyBlob" - OperationTimedOut Code = "OperationTimedOut" - OutOfRangeInput Code = "OutOfRangeInput" - OutOfRangeQueryParameterValue Code = "OutOfRangeQueryParameterValue" - PendingCopyOperation Code = "PendingCopyOperation" - PreviousSnapshotCannotBeNewer Code = "PreviousSnapshotCannotBeNewer" - PreviousSnapshotNotFound Code = "PreviousSnapshotNotFound" - PreviousSnapshotOperationNotSupported Code = "PreviousSnapshotOperationNotSupported" - RequestBodyTooLarge Code = "RequestBodyTooLarge" - RequestURLFailedToParse Code = "RequestUrlFailedToParse" - ResourceAlreadyExists Code = "ResourceAlreadyExists" - ResourceNotFound Code = "ResourceNotFound" - ResourceTypeMismatch Code = "ResourceTypeMismatch" - SequenceNumberConditionNotMet Code = "SequenceNumberConditionNotMet" - SequenceNumberIncrementTooLarge Code = "SequenceNumberIncrementTooLarge" - ServerBusy Code = "ServerBusy" - SnapshotCountExceeded Code = "SnapshotCountExceeded" - SnapshotOperationRateExceeded Code = "SnapshotOperationRateExceeded" - SnapshotsPresent Code = "SnapshotsPresent" - SourceConditionNotMet Code = "SourceConditionNotMet" - SystemInUse Code = "SystemInUse" - TargetConditionNotMet Code = "TargetConditionNotMet" - UnauthorizedBlobOverwrite Code = "UnauthorizedBlobOverwrite" - UnsupportedHTTPVerb Code = "UnsupportedHttpVerb" - UnsupportedHeader Code = "UnsupportedHeader" - UnsupportedQueryParameter Code = "UnsupportedQueryParameter" - UnsupportedXMLNode Code = "UnsupportedXmlNode" + AccountAlreadyExists StorageErrorCode = "AccountAlreadyExists" + AccountBeingCreated StorageErrorCode = "AccountBeingCreated" + AccountIsDisabled StorageErrorCode = "AccountIsDisabled" + AppendPositionConditionNotMet StorageErrorCode = "AppendPositionConditionNotMet" + AuthenticationFailed StorageErrorCode = "AuthenticationFailed" + AuthorizationFailure StorageErrorCode = "AuthorizationFailure" + AuthorizationPermissionMismatch StorageErrorCode = "AuthorizationPermissionMismatch" + AuthorizationProtocolMismatch StorageErrorCode = "AuthorizationProtocolMismatch" + AuthorizationResourceTypeMismatch StorageErrorCode = "AuthorizationResourceTypeMismatch" + AuthorizationServiceMismatch StorageErrorCode = "AuthorizationServiceMismatch" + AuthorizationSourceIPMismatch StorageErrorCode = "AuthorizationSourceIPMismatch" + PathAlreadyExists StorageErrorCode = "PathAlreadyExists" + PathArchived StorageErrorCode = "PathArchived" + PathBeingRehydrated StorageErrorCode = "PathBeingRehydrated" + PathImmutableDueToPolicy StorageErrorCode = "PathImmutableDueToPolicy" + PathNotArchived StorageErrorCode = "PathNotArchived" + PathNotFound StorageErrorCode = "PathNotFound" + PathOverwritten StorageErrorCode = "PathOverwritten" + PathTierInadequateForContentLength StorageErrorCode = "PathTierInadequateForContentLength" + PathUsesCustomerSpecifiedEncryption StorageErrorCode = "PathUsesCustomerSpecifiedEncryption" + BlockCountExceedsLimit StorageErrorCode = "BlockCountExceedsLimit" + BlockListTooLong StorageErrorCode = "BlockListTooLong" + CannotChangeToLowerTier StorageErrorCode = "CannotChangeToLowerTier" + CannotVerifyCopySource StorageErrorCode = "CannotVerifyCopySource" + ConditionHeadersNotSupported StorageErrorCode = "ConditionHeadersNotSupported" + ConditionNotMet StorageErrorCode = "ConditionNotMet" + FilesystemAlreadyExists StorageErrorCode = "FilesystemAlreadyExists" + FilesystemBeingDeleted StorageErrorCode = "FilesystemBeingDeleted" + FilesystemDisabled StorageErrorCode = "FilesystemDisabled" + FilesystemNotFound StorageErrorCode = "FilesystemNotFound" + ContentLengthLargerThanTierLimit StorageErrorCode = "ContentLengthLargerThanTierLimit" + CopyAcrossAccountsNotSupported StorageErrorCode = "CopyAcrossAccountsNotSupported" + CopyIDMismatch StorageErrorCode = "CopyIdMismatch" + EmptyMetadataKey StorageErrorCode = "EmptyMetadataKey" + FeatureVersionMismatch StorageErrorCode = "FeatureVersionMismatch" + IncrementalCopyPathMismatch StorageErrorCode = "IncrementalCopyPathMismatch" + IncrementalCopyOfEarlierVersionSnapshotNotAllowed StorageErrorCode = "IncrementalCopyOfEarlierVersionSnapshotNotAllowed" + IncrementalCopySourceMustBeSnapshot StorageErrorCode = "IncrementalCopySourceMustBeSnapshot" + InfiniteLeaseDurationRequired StorageErrorCode = "InfiniteLeaseDurationRequired" + InsufficientAccountPermissions StorageErrorCode = "InsufficientAccountPermissions" + InternalError StorageErrorCode = "InternalError" + InvalidAuthenticationInfo StorageErrorCode = "InvalidAuthenticationInfo" + InvalidPathOrBlock StorageErrorCode = "InvalidPathOrBlock" + InvalidPathTier StorageErrorCode = "InvalidPathTier" + InvalidPathType StorageErrorCode = "InvalidPathType" + InvalidBlockID StorageErrorCode = "InvalidBlockId" + InvalidBlockList StorageErrorCode = "InvalidBlockList" + InvalidHTTPVerb StorageErrorCode = "InvalidHttpVerb" + InvalidHeaderValue StorageErrorCode = "InvalidHeaderValue" + InvalidInput StorageErrorCode = "InvalidInput" + InvalidMD5 StorageErrorCode = "InvalidMd5" + InvalidMetadata StorageErrorCode = "InvalidMetadata" + InvalidOperation StorageErrorCode = "InvalidOperation" + InvalidPageRange StorageErrorCode = "InvalidPageRange" + InvalidQueryParameterValue StorageErrorCode = "InvalidQueryParameterValue" + InvalidRange StorageErrorCode = "InvalidRange" + InvalidResourceName StorageErrorCode = "InvalidResourceName" + InvalidSourcePathType StorageErrorCode = "InvalidSourcePathType" + InvalidSourcePathURL StorageErrorCode = "InvalidSourcePathUrl" + InvalidURI StorageErrorCode = "InvalidUri" + InvalidVersionForPagePathOperation StorageErrorCode = "InvalidVersionForPagePathOperation" + InvalidXMLDocument StorageErrorCode = "InvalidXmlDocument" + InvalidXMLNodeValue StorageErrorCode = "InvalidXmlNodeValue" + LeaseAlreadyBroken StorageErrorCode = "LeaseAlreadyBroken" + LeaseAlreadyPresent StorageErrorCode = "LeaseAlreadyPresent" + LeaseIDMismatchWithPathOperation StorageErrorCode = "LeaseIdMismatchWithPathOperation" + LeaseIDMismatchWithFilesystemOperation StorageErrorCode = "LeaseIdMismatchWithFilesystemOperation" + LeaseIDMismatchWithLeaseOperation StorageErrorCode = "LeaseIdMismatchWithLeaseOperation" + LeaseIDMissing StorageErrorCode = "LeaseIdMissing" + LeaseIsBreakingAndCannotBeAcquired StorageErrorCode = "LeaseIsBreakingAndCannotBeAcquired" + LeaseIsBreakingAndCannotBeChanged StorageErrorCode = "LeaseIsBreakingAndCannotBeChanged" + LeaseIsBrokenAndCannotBeRenewed StorageErrorCode = "LeaseIsBrokenAndCannotBeRenewed" + LeaseLost StorageErrorCode = "LeaseLost" + LeaseNotPresentWithPathOperation StorageErrorCode = "LeaseNotPresentWithPathOperation" + LeaseNotPresentWithFilesystemOperation StorageErrorCode = "LeaseNotPresentWithFilesystemOperation" + LeaseNotPresentWithLeaseOperation StorageErrorCode = "LeaseNotPresentWithLeaseOperation" + MD5Mismatch StorageErrorCode = "Md5Mismatch" + CRC64Mismatch StorageErrorCode = "Crc64Mismatch" + MaxPathSizeConditionNotMet StorageErrorCode = "MaxPathSizeConditionNotMet" + MetadataTooLarge StorageErrorCode = "MetadataTooLarge" + MissingContentLengthHeader StorageErrorCode = "MissingContentLengthHeader" + MissingRequiredHeader StorageErrorCode = "MissingRequiredHeader" + MissingRequiredQueryParameter StorageErrorCode = "MissingRequiredQueryParameter" + MissingRequiredXMLNode StorageErrorCode = "MissingRequiredXmlNode" + MultipleConditionHeadersNotSupported StorageErrorCode = "MultipleConditionHeadersNotSupported" + NoAuthenticationInformation StorageErrorCode = "NoAuthenticationInformation" + NoPendingCopyOperation StorageErrorCode = "NoPendingCopyOperation" + OperationNotAllowedOnIncrementalCopyPath StorageErrorCode = "OperationNotAllowedOnIncrementalCopyPath" + OperationTimedOut StorageErrorCode = "OperationTimedOut" + OutOfRangeInput StorageErrorCode = "OutOfRangeInput" + OutOfRangeQueryParameterValue StorageErrorCode = "OutOfRangeQueryParameterValue" + PendingCopyOperation StorageErrorCode = "PendingCopyOperation" + PreviousSnapshotCannotBeNewer StorageErrorCode = "PreviousSnapshotCannotBeNewer" + PreviousSnapshotNotFound StorageErrorCode = "PreviousSnapshotNotFound" + PreviousSnapshotOperationNotSupported StorageErrorCode = "PreviousSnapshotOperationNotSupported" + RequestBodyTooLarge StorageErrorCode = "RequestBodyTooLarge" + RequestURLFailedToParse StorageErrorCode = "RequestUrlFailedToParse" + ResourceAlreadyExists StorageErrorCode = "ResourceAlreadyExists" + ResourceNotFound StorageErrorCode = "ResourceNotFound" + ResourceTypeMismatch StorageErrorCode = "ResourceTypeMismatch" + SequenceNumberConditionNotMet StorageErrorCode = "SequenceNumberConditionNotMet" + SequenceNumberIncrementTooLarge StorageErrorCode = "SequenceNumberIncrementTooLarge" + ServerBusy StorageErrorCode = "ServerBusy" + SnapshotCountExceeded StorageErrorCode = "SnapshotCountExceeded" + SnapshotOperationRateExceeded StorageErrorCode = "SnapshotOperationRateExceeded" + SnapshotsPresent StorageErrorCode = "SnapshotsPresent" + SourceConditionNotMet StorageErrorCode = "SourceConditionNotMet" + SystemInUse StorageErrorCode = "SystemInUse" + TargetConditionNotMet StorageErrorCode = "TargetConditionNotMet" + UnauthorizedPathOverwrite StorageErrorCode = "UnauthorizedPathOverwrite" + UnsupportedHTTPVerb StorageErrorCode = "UnsupportedHttpVerb" + UnsupportedHeader StorageErrorCode = "UnsupportedHeader" + UnsupportedQueryParameter StorageErrorCode = "UnsupportedQueryParameter" + UnsupportedXMLNode StorageErrorCode = "UnsupportedXmlNode" ) var ( diff --git a/sdk/storage/azdatalake/directory/client.go b/sdk/storage/azdatalake/directory/client.go index b48045888290..b1e0fc9dec56 100644 --- a/sdk/storage/azdatalake/directory/client.go +++ b/sdk/storage/azdatalake/directory/client.go @@ -50,7 +50,7 @@ func NewClient(directoryURL string, cred azcore.TokenCredential, options *Client ClientOptions: options.ClientOptions, } blobClient, _ := blockblob.NewClient(blobURL, cred, &blobClientOpts) - dirClient := base.NewPathClient(directoryURL, blobURL, blobClient, azClient, nil, (*base.ClientOptions)(conOptions)) + dirClient := base.NewPathClient(directoryURL, blobURL, blobClient, azClient, nil, &cred, (*base.ClientOptions)(conOptions)) return (*Client)(dirClient), nil } @@ -78,7 +78,7 @@ func NewClientWithNoCredential(directoryURL string, options *ClientOptions) (*Cl ClientOptions: options.ClientOptions, } blobClient, _ := blockblob.NewClientWithNoCredential(blobURL, &blobClientOpts) - dirClient := base.NewPathClient(directoryURL, blobURL, blobClient, azClient, nil, (*base.ClientOptions)(conOptions)) + dirClient := base.NewPathClient(directoryURL, blobURL, blobClient, azClient, nil, nil, (*base.ClientOptions)(conOptions)) return (*Client)(dirClient), nil } @@ -113,7 +113,7 @@ func NewClientWithSharedKeyCredential(directoryURL string, cred *SharedKeyCreden return nil, err } blobClient, _ := blockblob.NewClientWithSharedKeyCredential(blobURL, blobSharedKey, &blobClientOpts) - dirClient := base.NewPathClient(directoryURL, blobURL, blobClient, azClient, cred, (*base.ClientOptions)(conOptions)) + dirClient := base.NewPathClient(directoryURL, blobURL, blobClient, azClient, cred, nil, (*base.ClientOptions)(conOptions)) return (*Client)(dirClient), nil } @@ -158,6 +158,10 @@ func (d *Client) sharedKey() *exported.SharedKeyCredential { return base.SharedKeyComposite((*base.CompositeClient[generated.PathClient, generated.PathClient, blockblob.Client])(d)) } +func (d *Client) identityCredential() *azcore.TokenCredential { + return base.IdentityCredentialComposite((*base.CompositeClient[generated.PathClient, generated.PathClient, blockblob.Client])(d)) +} + // DFSURL returns the URL endpoint used by the Client object. func (d *Client) DFSURL() string { return d.generatedDirClientWithDFS().Endpoint() @@ -168,6 +172,8 @@ func (d *Client) BlobURL() string { return d.generatedDirClientWithBlob().Endpoint() } +//TODO: create method to get file client - this will require block blob to have a method to get another block blob + // Create creates a new directory (dfs1). func (d *Client) Create(ctx context.Context, options *CreateOptions) (CreateResponse, error) { return CreateResponse{}, nil @@ -230,8 +236,3 @@ func (d *Client) SetHTTPHeaders(ctx context.Context, httpHeaders HTTPHeaders, op // TODO: call into blob return SetHTTPHeadersResponse{}, nil } - -// UndeletePath restores the specified path that was previously deleted. (dfs op/blob2). -func (d *Client) UndeletePath(ctx context.Context, path string, options *UndeletePathOptions) (UndeletePathResponse, error) { - return UndeletePathResponse{}, nil -} diff --git a/sdk/storage/azdatalake/directory/constants.go b/sdk/storage/azdatalake/directory/constants.go index ca7d9525c6ac..99aae6d16704 100644 --- a/sdk/storage/azdatalake/directory/constants.go +++ b/sdk/storage/azdatalake/directory/constants.go @@ -7,37 +7,12 @@ package directory import ( - "github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/blob" - "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/internal/generated" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/internal/path" ) -type ResourceType = generated.PathResourceType +type EncryptionAlgorithmType = path.EncryptionAlgorithmType -// TODO: consider the possibility of not exposing this and just pass it under the hood const ( - ResourceTypeFile ResourceType = generated.PathResourceTypeFile - ResourceTypeDirectory ResourceType = generated.PathResourceTypeDirectory -) - -type RenameMode = generated.PathRenameMode - -// TODO: consider the possibility of not exposing this and just pass it under the hood -const ( - RenameModeLegacy RenameMode = generated.PathRenameModeLegacy - RenameModePosix RenameMode = generated.PathRenameModePosix -) - -type SetAccessControlRecursiveMode = generated.PathSetAccessControlRecursiveMode - -const ( - SetAccessControlRecursiveModeSet SetAccessControlRecursiveMode = generated.PathSetAccessControlRecursiveModeSet - SetAccessControlRecursiveModeModify SetAccessControlRecursiveMode = generated.PathSetAccessControlRecursiveModeModify - SetAccessControlRecursiveModeRemove SetAccessControlRecursiveMode = generated.PathSetAccessControlRecursiveModeRemove -) - -type EncryptionAlgorithmType = blob.EncryptionAlgorithmType - -const ( - EncryptionAlgorithmTypeNone EncryptionAlgorithmType = blob.EncryptionAlgorithmTypeNone - EncryptionAlgorithmTypeAES256 EncryptionAlgorithmType = blob.EncryptionAlgorithmTypeAES256 + EncryptionAlgorithmTypeNone EncryptionAlgorithmType = path.EncryptionAlgorithmTypeNone + EncryptionAlgorithmTypeAES256 EncryptionAlgorithmType = path.EncryptionAlgorithmTypeAES256 ) diff --git a/sdk/storage/azdatalake/directory/models.go b/sdk/storage/azdatalake/directory/models.go index d8ad23d234f9..ff71be61b95d 100644 --- a/sdk/storage/azdatalake/directory/models.go +++ b/sdk/storage/azdatalake/directory/models.go @@ -7,9 +7,9 @@ package directory import ( - "github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/blob" "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" ) @@ -73,80 +73,8 @@ type RenameOptions struct { AccessConditions *AccessConditions } -// GetPropertiesOptions contains the optional parameters for the Client.GetProperties method -type GetPropertiesOptions struct { - AccessConditions *AccessConditions - CPKInfo *CPKInfo -} - -func (o *GetPropertiesOptions) format() *blob.GetPropertiesOptions { - if o == nil { - return nil - } - accessConditions := exported.FormatBlobAccessConditions(o.AccessConditions) - return &blob.GetPropertiesOptions{ - AccessConditions: accessConditions, - CPKInfo: &blob.CPKInfo{ - EncryptionKey: o.CPKInfo.EncryptionKey, - EncryptionAlgorithm: o.CPKInfo.EncryptionAlgorithm, - EncryptionKeySHA256: o.CPKInfo.EncryptionKeySHA256, - }, - } -} - // ===================================== PATH IMPORTS =========================================== -// SetAccessControlOptions contains the optional parameters when calling the SetAccessControl operation. dfs endpoint -type SetAccessControlOptions struct { - // Owner is the owner of the path. - Owner *string - // Group is the owning group of the path. - Group *string - // ACL is the access control list for the path. - ACL *string - // Permissions is the octal representation of the permissions for user, group and mask. - Permissions *string - // AccessConditions contains parameters for accessing the path. - AccessConditions *AccessConditions -} - -func (o *SetAccessControlOptions) format() (*generated.PathClientSetAccessControlOptions, *generated.LeaseAccessConditions, *generated.ModifiedAccessConditions, error) { - if o == nil { - return nil, nil, nil, nil - } - // call path formatter since we're hitting dfs in this operation - leaseAccessConditions, modifiedAccessConditions := exported.FormatPathAccessConditions(o.AccessConditions) - return &generated.PathClientSetAccessControlOptions{ - Owner: o.Owner, - Group: o.Group, - ACL: o.ACL, - Permissions: o.Permissions, - }, leaseAccessConditions, modifiedAccessConditions, nil -} - -// GetAccessControlOptions contains the optional parameters when calling the GetAccessControl operation. -type GetAccessControlOptions struct { - // UPN is the user principal name. - UPN *bool - // AccessConditions contains parameters for accessing the path. - AccessConditions *AccessConditions -} - -func (o *GetAccessControlOptions) format() (*generated.PathClientGetPropertiesOptions, *generated.LeaseAccessConditions, *generated.ModifiedAccessConditions, error) { - action := generated.PathGetPropertiesActionGetAccessControl - if o == nil { - return &generated.PathClientGetPropertiesOptions{ - Action: &action, - }, nil, nil, nil - } - // call path formatter since we're hitting dfs in this operation - leaseAccessConditions, modifiedAccessConditions := exported.FormatPathAccessConditions(o.AccessConditions) - return &generated.PathClientGetPropertiesOptions{ - Upn: o.UPN, - Action: &action, - }, leaseAccessConditions, modifiedAccessConditions, nil -} - // 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. @@ -204,131 +132,49 @@ func (o *RemoveAccessControlRecursiveOptions) format() (*generated.PathClientSet return nil, nil } -// SetHTTPHeadersOptions contains the optional parameters for the Client.SetHTTPHeaders method. -type SetHTTPHeadersOptions struct { - AccessConditions *AccessConditions -} +// ================================= path imports ================================== -func (o *SetHTTPHeadersOptions) format() *blob.SetHTTPHeadersOptions { - if o == nil { - return nil - } - accessConditions := exported.FormatBlobAccessConditions(o.AccessConditions) - return &blob.SetHTTPHeadersOptions{ - AccessConditions: accessConditions, - } -} - -// HTTPHeaders contains the HTTP headers for path operations. -type HTTPHeaders struct { - // Optional. Sets the path's cache control. If specified, this property is stored with the path and returned with a read request. - CacheControl *string - // Optional. Sets the path's Content-Disposition header. - ContentDisposition *string - // Optional. Sets the path's content encoding. If specified, this property is stored with the blobpath and returned with a read - // request. - ContentEncoding *string - // Optional. Set the path's content language. If specified, this property is stored with the path and returned with a read - // request. - ContentLanguage *string - // Specify the transactional md5 for the body, to be validated by the service. - ContentMD5 []byte - // Optional. Sets the path's content type. If specified, this property is stored with the path and returned with a read request. - ContentType *string -} - -func (o *HTTPHeaders) formatBlobHTTPHeaders() (*blob.HTTPHeaders, error) { - if o == nil { - return nil, nil - } - opts := blob.HTTPHeaders{ - BlobCacheControl: o.CacheControl, - BlobContentDisposition: o.ContentDisposition, - BlobContentEncoding: o.ContentEncoding, - BlobContentLanguage: o.ContentLanguage, - BlobContentMD5: o.ContentMD5, - BlobContentType: o.ContentType, - } - return &opts, nil -} - -func (o *HTTPHeaders) formatPathHTTPHeaders() (*generated.PathHTTPHeaders, error) { - // TODO: will be used for file related ops, like append - if o == nil { - return nil, nil - } - opts := generated.PathHTTPHeaders{ - CacheControl: o.CacheControl, - ContentDisposition: o.ContentDisposition, - ContentEncoding: o.ContentEncoding, - ContentLanguage: o.ContentLanguage, - ContentMD5: o.ContentMD5, - ContentType: o.ContentType, - TransactionalContentHash: o.ContentMD5, - } - return &opts, nil -} +// GetPropertiesOptions contains the optional parameters for the Client.GetProperties method +type GetPropertiesOptions = path.GetPropertiesOptions -// SetMetadataOptions provides set of configurations for Set Metadata on path operation -type SetMetadataOptions struct { - AccessConditions *AccessConditions - CPKInfo *CPKInfo - CPKScopeInfo *CPKScopeInfo -} +// SetAccessControlOptions contains the optional parameters when calling the SetAccessControl operation. dfs endpoint +type SetAccessControlOptions = path.SetAccessControlOptions -func (o *SetMetadataOptions) format() *blob.SetMetadataOptions { - if o == nil { - return nil - } - accessConditions := exported.FormatBlobAccessConditions(o.AccessConditions) - return &blob.SetMetadataOptions{ - AccessConditions: accessConditions, - CPKInfo: &blob.CPKInfo{ - EncryptionKey: o.CPKInfo.EncryptionKey, - EncryptionAlgorithm: o.CPKInfo.EncryptionAlgorithm, - EncryptionKeySHA256: o.CPKInfo.EncryptionKeySHA256, - }, - CPKScopeInfo: &blob.CPKScopeInfo{ - EncryptionScope: o.CPKScopeInfo.EncryptionScope, - }, - } -} +// GetAccessControlOptions contains the optional parameters when calling the GetAccessControl operation. +type GetAccessControlOptions = path.GetAccessControlOptions // CPKInfo contains a group of parameters for the PathClient.Download method. -type CPKInfo struct { - EncryptionAlgorithm *EncryptionAlgorithmType - EncryptionKey *string - EncryptionKeySHA256 *string -} +type CPKInfo = path.CPKInfo -// CPKScopeInfo contains a group of parameters for the PathClient.SetMetadata method. -type CPKScopeInfo struct { - EncryptionScope *string -} +// GetSASURLOptions contains the optional parameters for the Client.GetSASURL method. +type GetSASURLOptions = path.GetSASURLOptions -// UndeletePathOptions contains the optional parameters for the Filesystem.UndeletePath operation. -type UndeletePathOptions struct { - // placeholder -} +// SetHTTPHeadersOptions contains the optional parameters for the Client.SetHTTPHeaders method. +type SetHTTPHeadersOptions = path.SetHTTPHeadersOptions -func (o *UndeletePathOptions) format() *UndeletePathOptions { - if o == nil { - return nil - } - return &UndeletePathOptions{} -} +// HTTPHeaders contains the HTTP headers for path operations. +type HTTPHeaders = path.HTTPHeaders -// SourceModifiedAccessConditions identifies the source path access conditions. -type SourceModifiedAccessConditions = generated.SourceModifiedAccessConditions +// SetMetadataOptions provides set of configurations for Set Metadata on path operation +type SetMetadataOptions = path.SetMetadataOptions // SharedKeyCredential contains an account's name and its primary or secondary key. -type SharedKeyCredential = exported.SharedKeyCredential +type SharedKeyCredential = path.SharedKeyCredential // AccessConditions identifies blob-specific access conditions which you optionally set. -type AccessConditions = exported.AccessConditions +type AccessConditions = path.AccessConditions + +// SourceAccessConditions identifies blob-specific access conditions which you optionally set. +type SourceAccessConditions = path.SourceAccessConditions // LeaseAccessConditions contains optional parameters to access leased entity. -type LeaseAccessConditions = exported.LeaseAccessConditions +type LeaseAccessConditions = path.LeaseAccessConditions // ModifiedAccessConditions contains a group of parameters for specifying access conditions. -type ModifiedAccessConditions = exported.ModifiedAccessConditions +type ModifiedAccessConditions = path.ModifiedAccessConditions + +// SourceModifiedAccessConditions contains a group of parameters for specifying access conditions. +type SourceModifiedAccessConditions = path.SourceModifiedAccessConditions + +// CPKScopeInfo contains a group of parameters for the PathClient.SetMetadata method. +type CPKScopeInfo path.CPKScopeInfo diff --git a/sdk/storage/azdatalake/directory/responses.go b/sdk/storage/azdatalake/directory/responses.go index 6a4f34714df9..e87136e9b0a6 100644 --- a/sdk/storage/azdatalake/directory/responses.go +++ b/sdk/storage/azdatalake/directory/responses.go @@ -7,8 +7,8 @@ package directory import ( - "github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/blob" "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/internal/generated" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/internal/path" ) // CreateResponse contains the response fields for the Create operation. @@ -20,9 +20,6 @@ type DeleteResponse = generated.PathClientDeleteResponse // RenameResponse contains the response fields for the Create operation. type RenameResponse = generated.PathClientCreateResponse -// SetAccessControlResponse contains the response fields for the SetAccessControl operation. -type SetAccessControlResponse = generated.PathClientSetAccessControlResponse - // SetAccessControlRecursiveResponse contains the response fields for the SetAccessControlRecursive operation. type SetAccessControlRecursiveResponse = generated.PathClientSetAccessControlRecursiveResponse @@ -32,17 +29,19 @@ type UpdateAccessControlRecursiveResponse = generated.PathClientSetAccessControl // RemoveAccessControlRecursiveResponse contains the response fields for the RemoveAccessControlRecursive operation. type RemoveAccessControlRecursiveResponse = generated.PathClientSetAccessControlRecursiveResponse +// ========================================== path imports =========================================================== + +// SetAccessControlResponse contains the response fields for the SetAccessControl operation. +type SetAccessControlResponse = path.SetAccessControlResponse + +// SetHTTPHeadersResponse contains the response from method Client.SetHTTPHeaders. +type SetHTTPHeadersResponse = path.SetHTTPHeadersResponse + // GetAccessControlResponse contains the response fields for the GetAccessControl operation. -type GetAccessControlResponse = generated.PathClientGetPropertiesResponse +type GetAccessControlResponse = path.GetAccessControlResponse // GetPropertiesResponse contains the response fields for the GetProperties operation. -type GetPropertiesResponse = generated.PathClientGetPropertiesResponse +type GetPropertiesResponse = path.GetPropertiesResponse // SetMetadataResponse contains the response fields for the SetMetadata operation. -type SetMetadataResponse = blob.SetMetadataResponse - -// SetHTTPHeadersResponse contains the response fields for the SetHTTPHeaders operation. -type SetHTTPHeadersResponse = blob.SetHTTPHeadersResponse - -// UndeletePathResponse contains the response from method FilesystemClient.UndeletePath. -type UndeletePathResponse = generated.PathClientUndeleteResponse +type SetMetadataResponse = path.SetMetadataResponse diff --git a/sdk/storage/azdatalake/file/client.go b/sdk/storage/azdatalake/file/client.go index 9d3e9da012ff..5909aa475aea 100644 --- a/sdk/storage/azdatalake/file/client.go +++ b/sdk/storage/azdatalake/file/client.go @@ -16,8 +16,12 @@ import ( "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" ) @@ -52,7 +56,7 @@ func NewClient(fileURL string, cred azcore.TokenCredential, options *ClientOptio ClientOptions: options.ClientOptions, } blobClient, _ := blockblob.NewClient(blobURL, cred, &blobClientOpts) - fileClient := base.NewPathClient(fileURL, blobURL, blobClient, azClient, nil, (*base.ClientOptions)(conOptions)) + fileClient := base.NewPathClient(fileURL, blobURL, blobClient, azClient, nil, &cred, (*base.ClientOptions)(conOptions)) return (*Client)(fileClient), nil } @@ -80,7 +84,7 @@ func NewClientWithNoCredential(fileURL string, options *ClientOptions) (*Client, ClientOptions: options.ClientOptions, } blobClient, _ := blockblob.NewClientWithNoCredential(blobURL, &blobClientOpts) - fileClient := base.NewPathClient(fileURL, blobURL, blobClient, azClient, nil, (*base.ClientOptions)(conOptions)) + fileClient := base.NewPathClient(fileURL, blobURL, blobClient, azClient, nil, nil, (*base.ClientOptions)(conOptions)) return (*Client)(fileClient), nil } @@ -115,7 +119,7 @@ func NewClientWithSharedKeyCredential(fileURL string, cred *SharedKeyCredential, return nil, err } blobClient, _ := blockblob.NewClientWithSharedKeyCredential(blobURL, blobSharedKey, &blobClientOpts) - fileClient := base.NewPathClient(fileURL, blobURL, blobClient, azClient, cred, (*base.ClientOptions)(conOptions)) + fileClient := base.NewPathClient(fileURL, blobURL, blobClient, azClient, cred, nil, (*base.ClientOptions)(conOptions)) return (*Client)(fileClient), nil } @@ -160,6 +164,10 @@ func (f *Client) sharedKey() *exported.SharedKeyCredential { return base.SharedKeyComposite((*base.CompositeClient[generated.PathClient, generated.PathClient, blockblob.Client])(f)) } +func (f *Client) identityCredential() *azcore.TokenCredential { + return base.IdentityCredentialComposite((*base.CompositeClient[generated.PathClient, generated.PathClient, blockblob.Client])(f)) +} + func (f *Client) getClientOptions() *base.ClientOptions { return base.GetCompositeClientOptions((*base.CompositeClient[generated.PathClient, generated.PathClient, blockblob.Client])(f)) } @@ -177,50 +185,73 @@ func (f *Client) BlobURL() string { // Create creates a new file (dfs1). func (f *Client) Create(ctx context.Context, options *CreateOptions) (CreateResponse, error) { lac, mac, httpHeaders, createOpts, cpkOpts := options.format() - return f.generatedFileClientWithDFS().Create(ctx, createOpts, httpHeaders, lac, mac, nil, cpkOpts) + resp, err := f.generatedFileClientWithDFS().Create(ctx, createOpts, httpHeaders, lac, mac, nil, cpkOpts) + err = exported.ConvertToDFSError(err) + return resp, err } // Delete deletes a file (dfs1). func (f *Client) Delete(ctx context.Context, options *DeleteOptions) (DeleteResponse, error) { lac, mac, deleteOpts := options.format() - return f.generatedFileClientWithDFS().Delete(ctx, deleteOpts, lac, mac) + resp, err := f.generatedFileClientWithDFS().Delete(ctx, deleteOpts, lac, mac) + err = exported.ConvertToDFSError(err) + return resp, err } // GetProperties gets the properties of a file (blob3) func (f *Client) GetProperties(ctx context.Context, options *GetPropertiesOptions) (GetPropertiesResponse, error) { - opts := options.format() - // TODO: format response + add acls, owner, group, permissions to it - return f.blobClient().GetProperties(ctx, opts) + opts := path.FormatGetPropertiesOptions(options) + var respFromCtx *http.Response + ctxWithResp := runtime.WithCaptureResponse(ctx, &respFromCtx) + resp, err := f.blobClient().GetProperties(ctxWithResp, opts) + newResp := path.FormatGetPropertiesResponse(&resp, respFromCtx) + err = exported.ConvertToDFSError(err) + return newResp, err } -// TODO: implement below -//// Rename renames a file (dfs1). TODO: look into returning a new client possibly or changing the url -//func (f *Client) Rename(ctx context.Context, newName string, options *RenameOptions) (RenameResponse, error) { -// path, err := url.Parse(f.DFSURL()) -// if err != nil { -// return RenameResponse{}, err -// } -// lac, mac, smac, createOpts := options.format(path.Path) -// fileURL := runtime.JoinPaths(f.generatedFileClientWithDFS().Endpoint(), newName) -// // TODO: remove new azcore.Client creation after the API for shallow copying with new client name is implemented -// clOpts := f.getClientOptions() -// azClient, err := azcore.NewClient(shared.FileClient, exported.ModuleVersion, *(base.GetPipelineOptions(clOpts)), &(clOpts.ClientOptions)) -// if err != nil { -// if log.Should(exported.EventError) { -// log.Writef(exported.EventError, err.Error()) -// } -// return RenameResponse{}, err -// } -// blobURL, fileURL := shared.GetURLs(fileURL) -// tempFileClient := (*Client)(base.NewPathClient(fileURL, blobURL, nil, azClient, f.sharedKey(), clOpts)) -// // this tempClient does not have a blobClient -// return tempFileClient.generatedFileClientWithDFS().Create(ctx, createOpts, nil, lac, mac, smac, nil) -//} +func (f *Client) renamePathInURL(newName string) (string, string, string) { + endpoint := f.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(f.DFSURL()) + return parsedNewURL.Path, newPathURL, newBlobURL +} + +// 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) + var newBlobClient *blockblob.Client + var err error + if f.identityCredential() != nil { + newBlobClient, err = blockblob.NewClient(newBlobURL, *f.identityCredential(), nil) + } else if f.sharedKey() != nil { + blobSharedKey, _ := f.sharedKey().ConvertToBlobSharedKey() + newBlobClient, err = blockblob.NewClientWithSharedKeyCredential(newBlobURL, blobSharedKey, nil) + } else { + newBlobClient, err = blockblob.NewClientWithNoCredential(newBlobURL, nil) + } + if err != nil { + return RenameResponse{}, err + } + newFileClient := (*Client)(base.NewPathClient(newPathURL, newBlobURL, newBlobClient, f.generatedFileClientWithDFS().InternalClient().WithClientName(shared.FileClient), f.sharedKey(), f.identityCredential(), f.getClientOptions())) + resp, err := newFileClient.generatedFileClientWithDFS().Create(ctx, createOpts, nil, lac, mac, smac, nil) + return RenameResponse{ + Response: resp, + NewFileClient: newFileClient, + }, exported.ConvertToDFSError(err) +} // SetExpiry operation sets an expiry time on an existing file (blob2). func (f *Client) SetExpiry(ctx context.Context, expiryType SetExpiryType, o *SetExpiryOptions) (SetExpiryResponse, error) { expMode, opts := expiryType.Format(o) - return f.generatedFileClientWithBlob().SetExpiry(ctx, expMode, opts) + resp, err := f.generatedFileClientWithBlob().SetExpiry(ctx, expMode, opts) + err = exported.ConvertToDFSError(err) + return resp, err } //// Upload uploads data to a file. @@ -245,43 +276,54 @@ func (f *Client) SetExpiry(ctx context.Context, expiryType SetExpiryType, o *Set // SetAccessControl sets the owner, owning group, and permissions for a file or directory (dfs1). func (f *Client) SetAccessControl(ctx context.Context, options *SetAccessControlOptions) (SetAccessControlResponse, error) { - opts, lac, mac, err := options.format() + opts, lac, mac, err := path.FormatSetAccessControlOptions(options) if err != nil { return SetAccessControlResponse{}, err } - return f.generatedFileClientWithDFS().SetAccessControl(ctx, opts, lac, mac) + resp, err := f.generatedFileClientWithDFS().SetAccessControl(ctx, opts, lac, mac) + err = exported.ConvertToDFSError(err) + return resp, err } // UpdateAccessControl updates the owner, owning group, and permissions for a file or directory (dfs1). func (f *Client) UpdateAccessControl(ctx context.Context, ACL string, options *UpdateAccessControlOptions) (UpdateAccessControlResponse, error) { opts, mode := options.format(ACL) - return f.generatedFileClientWithDFS().SetAccessControlRecursive(ctx, mode, opts) + resp, err := f.generatedFileClientWithDFS().SetAccessControlRecursive(ctx, mode, opts) + err = exported.ConvertToDFSError(err) + return resp, err } // GetAccessControl gets the owner, owning group, and permissions for a file or directory (dfs1). func (f *Client) GetAccessControl(ctx context.Context, options *GetAccessControlOptions) (GetAccessControlResponse, error) { - opts, lac, mac := options.format() - return f.generatedFileClientWithDFS().GetProperties(ctx, opts, lac, mac) + opts, lac, mac := path.FormatGetAccessControlOptions(options) + resp, err := f.generatedFileClientWithDFS().GetProperties(ctx, opts, lac, mac) + err = exported.ConvertToDFSError(err) + return resp, err } // RemoveAccessControl removes the owner, owning group, and permissions for a file or directory (dfs1). func (f *Client) RemoveAccessControl(ctx context.Context, ACL string, options *RemoveAccessControlOptions) (RemoveAccessControlResponse, error) { opts, mode := options.format(ACL) - return f.generatedFileClientWithDFS().SetAccessControlRecursive(ctx, mode, opts) + resp, err := f.generatedFileClientWithDFS().SetAccessControlRecursive(ctx, mode, opts) + err = exported.ConvertToDFSError(err) + return resp, err } // SetMetadata sets the metadata for a file or directory (blob3). func (f *Client) SetMetadata(ctx context.Context, options *SetMetadataOptions) (SetMetadataResponse, error) { - opts, metadata := options.format() - return f.blobClient().SetMetadata(ctx, metadata, opts) + opts, metadata := path.FormatSetMetadataOptions(options) + resp, err := f.blobClient().SetMetadata(ctx, metadata, opts) + err = exported.ConvertToDFSError(err) + return resp, err } // SetHTTPHeaders sets the HTTP headers for a file or directory (blob3). func (f *Client) SetHTTPHeaders(ctx context.Context, httpHeaders HTTPHeaders, options *SetHTTPHeadersOptions) (SetHTTPHeadersResponse, error) { - opts, blobHTTPHeaders := options.format(httpHeaders) + opts, blobHTTPHeaders := path.FormatSetHTTPHeadersOptions(options, httpHeaders) resp, err := f.blobClient().SetHTTPHeaders(ctx, blobHTTPHeaders, opts) newResp := SetHTTPHeadersResponse{} - formatSetHTTPHeadersResponse(&newResp, &resp) + path.FormatSetHTTPHeadersResponse(&newResp, &resp) + err = exported.ConvertToDFSError(err) return newResp, err } @@ -293,11 +335,12 @@ func (f *Client) GetSASURL(permissions sas.FilePermissions, expiry time.Time, o } urlParts, err := sas.ParseURL(f.BlobURL()) + err = exported.ConvertToDFSError(err) if err != nil { return "", err } - st := o.format() + st := path.FormatGetSASURLOptions(o) qps, err := sas.DatalakeSignatureValues{ FilePath: urlParts.PathName, @@ -308,6 +351,7 @@ func (f *Client) GetSASURL(permissions sas.FilePermissions, expiry time.Time, o ExpiryTime: expiry.UTC(), }.SignWithSharedKey(f.sharedKey()) + err = exported.ConvertToDFSError(err) if err != nil { return "", err } diff --git a/sdk/storage/azdatalake/file/client_test.go b/sdk/storage/azdatalake/file/client_test.go index cd786f2a08e3..f9b2ccdacf71 100644 --- a/sdk/storage/azdatalake/file/client_test.go +++ b/sdk/storage/azdatalake/file/client_test.go @@ -64,7 +64,7 @@ func validateFileDeleted(_require *require.Assertions, fileClient *file.Client) _, err := fileClient.GetAccessControl(context.Background(), nil) _require.NotNil(err) - testcommon.ValidateErrorCode(_require, err, datalakeerror.BlobNotFound) + testcommon.ValidateErrorCode(_require, err, datalakeerror.PathNotFound) } func (s *RecordedTestSuite) TestCreateFileAndDelete() { @@ -518,7 +518,7 @@ func (s *RecordedTestSuite) TestCreateFileWithExpiryRelativeToNow() { time.Sleep(time.Second * 10) _, err = fClient.GetProperties(context.Background(), nil) - testcommon.ValidateErrorCode(_require, err, datalakeerror.BlobNotFound) + testcommon.ValidateErrorCode(_require, err, datalakeerror.PathNotFound) } func (s *RecordedTestSuite) TestCreateFileWithNeverExpire() { @@ -593,10 +593,12 @@ func (s *RecordedTestSuite) TestCreateFileWithPermissions() { 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 := &file.CreateOptions{ Permissions: &perms, + Umask: &umask, } _, err = fsClient.Create(context.Background(), nil) @@ -610,7 +612,10 @@ func (s *RecordedTestSuite) TestCreateFileWithPermissions() { _require.Nil(err) _require.NotNil(resp) - //TODO: GetProperties() when you figured out how to add permissions into response + resp2, err := fClient.GetProperties(context.Background(), nil) + _require.Nil(err) + _require.NotNil(resp2) + _require.Equal("rwxrwxrwx", *resp2.Permissions) } func (s *RecordedTestSuite) TestCreateFileWithOwnerGroupACLUmask() { @@ -644,7 +649,6 @@ func (s *RecordedTestSuite) TestCreateFileWithOwnerGroupACLUmask() { _require.Nil(err) _require.NotNil(resp) - //TODO: GetProperties() when you figured out how to add o,g, ACL into response } func (s *RecordedTestSuite) TestDeleteFileWithNilAccessConditions() { @@ -2033,280 +2037,268 @@ func (s *RecordedTestSuite) TestSetHTTPHeadersIfETagMatchFalse() { 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) -// -// fileName := testcommon.GenerateFileName(testName) -// fClient, err := testcommon.GetFileClient(filesystemName, fileName, s.T(), testcommon.TestAccountDatalake, nil) -// _require.NoError(err) -// -// resp, err := fClient.Create(context.Background(), nil) -// _require.Nil(err) -// _require.NotNil(resp) -// -// resp, err = fClient.Rename(context.Background(), "newName", nil) -// _require.Nil(err) -// _require.NotNil(resp) -//} -// -//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) -// -// fileName := testcommon.GenerateFileName(testName) -// fClient, err := testcommon.GetFileClient(filesystemName, fileName, s.T(), testcommon.TestAccountDatalake, nil) -// _require.NoError(err) -// -// resp, err := fClient.Create(context.Background(), nil) -// _require.Nil(err) -// _require.NotNil(resp) -// -// renameFileOpts := &file.RenameOptions{ -// AccessConditions: nil, -// } -// -// resp, err = fClient.Rename(context.Background(), "new"+fileName, renameFileOpts) -// _require.Nil(err) -// _require.NotNil(resp) -//} -// -//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) -// -// fileName := testcommon.GenerateFileName(testName) -// fClient, err := testcommon.GetFileClient(filesystemName, fileName, s.T(), testcommon.TestAccountDatalake, nil) -// _require.NoError(err) -// -// defer testcommon.DeleteFile(context.Background(), _require, fClient) -// -// resp, err := fClient.Create(context.Background(), nil) -// _require.Nil(err) -// _require.NotNil(resp) -// -// currentTime := testcommon.GetRelativeTimeFromAnchor(resp.Date, -10) -// -// createFileOpts := &file.CreateOptions{ -// AccessConditions: &file.AccessConditions{ -// ModifiedAccessConditions: &file.ModifiedAccessConditions{ -// IfModifiedSince: ¤tTime, -// }, -// }, -// } -// -// resp, err = fClient.Create(context.Background(), createFileOpts) -// _require.Nil(err) -// _require.NotNil(resp) -//} -// -//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) -// -// fileName := testcommon.GenerateFileName(testName) -// fClient, err := testcommon.GetFileClient(filesystemName, fileName, s.T(), testcommon.TestAccountDatalake, nil) -// _require.NoError(err) -// -// defer testcommon.DeleteFile(context.Background(), _require, fClient) -// -// resp, err := fClient.Create(context.Background(), nil) -// _require.Nil(err) -// _require.NotNil(resp) -// -// currentTime := testcommon.GetRelativeTimeFromAnchor(resp.Date, 10) -// -// createFileOpts := &file.CreateOptions{ -// AccessConditions: &file.AccessConditions{ -// ModifiedAccessConditions: &file.ModifiedAccessConditions{ -// IfModifiedSince: ¤tTime, -// }, -// }, -// } -// -// resp, err = fClient.Create(context.Background(), createFileOpts) -// _require.NotNil(err) -// testcommon.ValidateErrorCode(_require, err, datalakeerror.ConditionNotMet) -//} -// -//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) -// -// fileName := testcommon.GenerateFileName(testName) -// fClient, err := testcommon.GetFileClient(filesystemName, fileName, s.T(), testcommon.TestAccountDatalake, nil) -// _require.NoError(err) -// -// defer testcommon.DeleteFile(context.Background(), _require, fClient) -// -// resp, err := fClient.Create(context.Background(), nil) -// _require.Nil(err) -// _require.NotNil(resp) -// -// currentTime := testcommon.GetRelativeTimeFromAnchor(resp.Date, 10) -// -// createFileOpts := &file.CreateOptions{ -// AccessConditions: &file.AccessConditions{ -// ModifiedAccessConditions: &file.ModifiedAccessConditions{ -// IfUnmodifiedSince: ¤tTime, -// }, -// }, -// } -// -// resp, err = fClient.Create(context.Background(), createFileOpts) -// _require.Nil(err) -// _require.NotNil(resp) -//} -// -//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) -// -// fileName := testcommon.GenerateFileName(testName) -// fClient, err := testcommon.GetFileClient(filesystemName, fileName, s.T(), testcommon.TestAccountDatalake, nil) -// _require.NoError(err) -// -// defer testcommon.DeleteFile(context.Background(), _require, fClient) -// -// resp, err := fClient.Create(context.Background(), nil) -// _require.Nil(err) -// _require.NotNil(resp) -// -// currentTime := testcommon.GetRelativeTimeFromAnchor(resp.Date, -10) -// -// createFileOpts := &file.CreateOptions{ -// AccessConditions: &file.AccessConditions{ -// ModifiedAccessConditions: &file.ModifiedAccessConditions{ -// IfUnmodifiedSince: ¤tTime, -// }, -// }, -// } -// -// resp, err = fClient.Create(context.Background(), createFileOpts) -// _require.NotNil(err) -// -// testcommon.ValidateErrorCode(_require, err, datalakeerror.ConditionNotMet) -//} -// -//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) -// -// fileName := testcommon.GenerateFileName(testName) -// fClient, err := testcommon.GetFileClient(filesystemName, fileName, s.T(), testcommon.TestAccountDatalake, nil) -// _require.NoError(err) -// -// defer testcommon.DeleteFile(context.Background(), _require, fClient) -// -// resp, err := fClient.Create(context.Background(), nil) -// _require.Nil(err) -// _require.NotNil(resp) -// -// etag := resp.ETag -// -// createFileOpts := &file.CreateOptions{ -// AccessConditions: &file.AccessConditions{ -// ModifiedAccessConditions: &file.ModifiedAccessConditions{ -// IfMatch: etag, -// }, -// }, -// } -// -// resp, err = fClient.Create(context.Background(), createFileOpts) -// _require.Nil(err) -// _require.NotNil(resp) -//} -// -//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) -// -// fileName := testcommon.GenerateFileName(testName) -// fClient, err := testcommon.GetFileClient(filesystemName, fileName, s.T(), testcommon.TestAccountDatalake, nil) -// _require.NoError(err) -// -// defer testcommon.DeleteFile(context.Background(), _require, fClient) -// -// resp, err := fClient.Create(context.Background(), nil) -// _require.Nil(err) -// _require.NotNil(resp) -// -// etag := resp.ETag -// -// createFileOpts := &file.CreateOptions{ -// AccessConditions: &file.AccessConditions{ -// ModifiedAccessConditions: &file.ModifiedAccessConditions{ -// IfNoneMatch: etag, -// }, -// }, -// } -// -// resp, err = fClient.Create(context.Background(), createFileOpts) -// _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) + + fileName := testcommon.GenerateFileName(testName) + fClient, err := testcommon.GetFileClient(filesystemName, fileName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + resp, err := fClient.Create(context.Background(), nil) + _require.Nil(err) + _require.NotNil(resp) + + resp1, err := fClient.Rename(context.Background(), "newName", nil) + _require.Nil(err) + _require.NotNil(resp1) + _require.Contains(resp1.NewFileClient.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) + + fileName := testcommon.GenerateFileName(testName) + fClient, err := testcommon.GetFileClient(filesystemName, fileName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + resp, err := fClient.Create(context.Background(), nil) + _require.Nil(err) + _require.NotNil(resp) + + renameFileOpts := &file.RenameOptions{ + AccessConditions: nil, + } + + resp1, err := fClient.Rename(context.Background(), "newName", renameFileOpts) + _require.Nil(err) + _require.NotNil(resp1) + _require.Contains(resp1.NewFileClient.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) + + fileName := testcommon.GenerateFileName(testName) + fClient, err := testcommon.GetFileClient(filesystemName, fileName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + resp, err := fClient.Create(context.Background(), nil) + _require.Nil(err) + _require.NotNil(resp) + + currentTime := testcommon.GetRelativeTimeFromAnchor(resp.Date, -10) + + renameFileOpts := &file.RenameOptions{ + SourceAccessConditions: &file.SourceAccessConditions{ + SourceModifiedAccessConditions: &file.SourceModifiedAccessConditions{ + SourceIfModifiedSince: ¤tTime, + }, + }, + } + resp1, err := fClient.Rename(context.Background(), "newName", renameFileOpts) + _require.Nil(err) + _require.NotNil(resp1) + _require.Contains(resp1.NewFileClient.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) + + fileName := testcommon.GenerateFileName(testName) + fClient, err := testcommon.GetFileClient(filesystemName, fileName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + resp, err := fClient.Create(context.Background(), nil) + _require.Nil(err) + _require.NotNil(resp) + + currentTime := testcommon.GetRelativeTimeFromAnchor(resp.Date, 10) + + renameFileOpts := &file.RenameOptions{ + SourceAccessConditions: &file.SourceAccessConditions{ + SourceModifiedAccessConditions: &file.SourceModifiedAccessConditions{ + SourceIfModifiedSince: ¤tTime, + }, + }, + } + + _, err = fClient.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) + + fileName := testcommon.GenerateFileName(testName) + fClient, err := testcommon.GetFileClient(filesystemName, fileName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + resp, err := fClient.Create(context.Background(), nil) + _require.Nil(err) + _require.NotNil(resp) + + currentTime := testcommon.GetRelativeTimeFromAnchor(resp.Date, 10) + + renameFileOpts := &file.RenameOptions{ + SourceAccessConditions: &file.SourceAccessConditions{ + SourceModifiedAccessConditions: &file.SourceModifiedAccessConditions{ + SourceIfUnmodifiedSince: ¤tTime, + }, + }, + } + + resp1, err := fClient.Rename(context.Background(), "newName", renameFileOpts) + _require.NotNil(resp1) + _require.Contains(resp1.NewFileClient.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) + + fileName := testcommon.GenerateFileName(testName) + fClient, err := testcommon.GetFileClient(filesystemName, fileName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + resp, err := fClient.Create(context.Background(), nil) + _require.Nil(err) + _require.NotNil(resp) + + currentTime := testcommon.GetRelativeTimeFromAnchor(resp.Date, -10) + + renameFileOpts := &file.RenameOptions{ + SourceAccessConditions: &file.SourceAccessConditions{ + SourceModifiedAccessConditions: &file.SourceModifiedAccessConditions{ + SourceIfUnmodifiedSince: ¤tTime, + }, + }, + } + + _, err = fClient.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) + + fileName := testcommon.GenerateFileName(testName) + fClient, err := testcommon.GetFileClient(filesystemName, fileName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + resp, err := fClient.Create(context.Background(), nil) + _require.Nil(err) + _require.NotNil(resp) + + etag := resp.ETag + + renameFileOpts := &file.RenameOptions{ + SourceAccessConditions: &file.SourceAccessConditions{ + SourceModifiedAccessConditions: &file.SourceModifiedAccessConditions{ + SourceIfMatch: etag, + }, + }, + } + + resp1, err := fClient.Rename(context.Background(), "newName", renameFileOpts) + _require.NotNil(resp1) + _require.Contains(resp1.NewFileClient.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) + + fileName := testcommon.GenerateFileName(testName) + fClient, err := testcommon.GetFileClient(filesystemName, fileName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + resp, err := fClient.Create(context.Background(), nil) + _require.Nil(err) + _require.NotNil(resp) + + etag := resp.ETag + + renameFileOpts := &file.RenameOptions{ + SourceAccessConditions: &file.SourceAccessConditions{ + SourceModifiedAccessConditions: &file.SourceModifiedAccessConditions{ + SourceIfNoneMatch: etag, + }, + }, + } + + _, err = fClient.Rename(context.Background(), "newName", renameFileOpts) + _require.NotNil(err) + testcommon.ValidateErrorCode(_require, err, datalakeerror.SourceConditionNotMet) +} diff --git a/sdk/storage/azdatalake/file/constants.go b/sdk/storage/azdatalake/file/constants.go index c536d01673cf..2345c88d547b 100644 --- a/sdk/storage/azdatalake/file/constants.go +++ b/sdk/storage/azdatalake/file/constants.go @@ -7,56 +7,32 @@ package file import ( - "github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/blob" - "github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/lease" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/internal/path" ) -type EncryptionAlgorithmType = blob.EncryptionAlgorithmType +type EncryptionAlgorithmType = path.EncryptionAlgorithmType const ( - EncryptionAlgorithmTypeNone EncryptionAlgorithmType = blob.EncryptionAlgorithmTypeNone - EncryptionAlgorithmTypeAES256 EncryptionAlgorithmType = blob.EncryptionAlgorithmTypeAES256 + EncryptionAlgorithmTypeNone EncryptionAlgorithmType = path.EncryptionAlgorithmTypeNone + EncryptionAlgorithmTypeAES256 EncryptionAlgorithmType = path.EncryptionAlgorithmTypeAES256 ) -// responses models: +// response models: -type ImmutabilityPolicyMode = blob.ImmutabilityPolicyMode +type ImmutabilityPolicyMode = path.ImmutabilityPolicyMode const ( - ImmutabilityPolicyModeMutable ImmutabilityPolicyMode = blob.ImmutabilityPolicyModeMutable - ImmutabilityPolicyModeUnlocked ImmutabilityPolicyMode = blob.ImmutabilityPolicyModeUnlocked - ImmutabilityPolicyModeLocked ImmutabilityPolicyMode = blob.ImmutabilityPolicyModeLocked + ImmutabilityPolicyModeMutable ImmutabilityPolicyMode = path.ImmutabilityPolicyModeMutable + ImmutabilityPolicyModeUnlocked ImmutabilityPolicyMode = path.ImmutabilityPolicyModeUnlocked + ImmutabilityPolicyModeLocked ImmutabilityPolicyMode = path.ImmutabilityPolicyModeLocked ) -type CopyStatusType = blob.CopyStatusType +// CopyStatusType defines values for CopyStatusType +type CopyStatusType = path.CopyStatusType const ( - CopyStatusTypePending CopyStatusType = blob.CopyStatusTypePending - CopyStatusTypeSuccess CopyStatusType = blob.CopyStatusTypeSuccess - CopyStatusTypeAborted CopyStatusType = blob.CopyStatusTypeAborted - CopyStatusTypeFailed CopyStatusType = blob.CopyStatusTypeFailed -) - -type LeaseDurationType = lease.DurationType - -const ( - LeaseDurationTypeInfinite LeaseDurationType = lease.DurationTypeInfinite - LeaseDurationTypeFixed LeaseDurationType = lease.DurationTypeFixed -) - -type LeaseStateType = lease.StateType - -const ( - LeaseStateTypeAvailable LeaseStateType = lease.StateTypeAvailable - LeaseStateTypeLeased LeaseStateType = lease.StateTypeLeased - LeaseStateTypeExpired LeaseStateType = lease.StateTypeExpired - LeaseStateTypeBreaking LeaseStateType = lease.StateTypeBreaking - LeaseStateTypeBroken LeaseStateType = lease.StateTypeBroken -) - -type LeaseStatusType = lease.StatusType - -const ( - LeaseStatusTypeLocked LeaseStatusType = lease.StatusTypeLocked - LeaseStatusTypeUnlocked LeaseStatusType = lease.StatusTypeUnlocked + CopyStatusTypePending CopyStatusType = path.CopyStatusTypePending + CopyStatusTypeSuccess CopyStatusType = path.CopyStatusTypeSuccess + CopyStatusTypeAborted CopyStatusType = path.CopyStatusTypeAborted + CopyStatusTypeFailed CopyStatusType = path.CopyStatusTypeFailed ) diff --git a/sdk/storage/azdatalake/file/models.go b/sdk/storage/azdatalake/file/models.go index af88f45bd326..a4f8b994ff1d 100644 --- a/sdk/storage/azdatalake/file/models.go +++ b/sdk/storage/azdatalake/file/models.go @@ -7,12 +7,10 @@ package file import ( - "errors" "github.com/Azure/azure-sdk-for-go/sdk/azcore/to" - "github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/blob" - "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/datalakeerror" "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" "net/http" "strconv" "time" @@ -77,7 +75,7 @@ func (o *CreateOptions) format() (*generated.LeaseAccessConditions, *generated.M var cpkOpts *generated.CPKInfo if o.HTTPHeaders != nil { - httpHeaders = o.HTTPHeaders.formatPathHTTPHeaders() + httpHeaders = path.FormatPathHTTPHeaders(o.HTTPHeaders) } if o.CPKInfo != nil { cpkOpts = &generated.CPKInfo{ @@ -127,6 +125,9 @@ func (o *RenameOptions) format(path string) (*generated.LeaseAccessConditions, * } 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, @@ -134,90 +135,14 @@ func (o *RenameOptions) format(path string) (*generated.LeaseAccessConditions, * SourceIfNoneMatch: o.SourceAccessConditions.SourceModifiedAccessConditions.SourceIfNoneMatch, SourceIfUnmodifiedSince: o.SourceAccessConditions.SourceModifiedAccessConditions.SourceIfUnmodifiedSince, } - createOpts.SourceLeaseID = o.SourceAccessConditions.SourceLeaseAccessConditions.LeaseID 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 - CPKInfo *CPKInfo -} - -func (o *GetPropertiesOptions) format() *blob.GetPropertiesOptions { - if o == nil { - return nil - } - accessConditions := exported.FormatBlobAccessConditions(o.AccessConditions) - return &blob.GetPropertiesOptions{ - AccessConditions: accessConditions, - CPKInfo: &blob.CPKInfo{ - EncryptionKey: o.CPKInfo.EncryptionKey, - EncryptionAlgorithm: o.CPKInfo.EncryptionAlgorithm, - EncryptionKeySHA256: o.CPKInfo.EncryptionKeySHA256, - }, - } -} - // ===================================== PATH IMPORTS =========================================== -// SetAccessControlOptions contains the optional parameters when calling the SetAccessControl operation. dfs endpoint -type SetAccessControlOptions struct { - // Owner is the owner of the path. - Owner *string - // Group is the owning group of the path. - Group *string - // ACL is the access control list for the path. - ACL *string - // Permissions is the octal representation of the permissions for user, group and mask. - Permissions *string - // AccessConditions contains parameters for accessing the path. - AccessConditions *AccessConditions -} - -func (o *SetAccessControlOptions) format() (*generated.PathClientSetAccessControlOptions, *generated.LeaseAccessConditions, *generated.ModifiedAccessConditions, error) { - if o == nil { - return nil, nil, nil, datalakeerror.MissingParameters - } - // call path formatter since we're hitting dfs in this operation - leaseAccessConditions, modifiedAccessConditions := exported.FormatPathAccessConditions(o.AccessConditions) - if o.Owner == nil && o.Group == nil && o.ACL == nil && o.Permissions == nil { - return nil, nil, nil, errors.New("at least one parameter should be set for SetAccessControl API") - } - return &generated.PathClientSetAccessControlOptions{ - Owner: o.Owner, - Group: o.Group, - ACL: o.ACL, - Permissions: o.Permissions, - }, leaseAccessConditions, modifiedAccessConditions, nil -} - -// GetAccessControlOptions contains the optional parameters when calling the GetAccessControl operation. -type GetAccessControlOptions struct { - // UPN is the user principal name. - UPN *bool - // AccessConditions contains parameters for accessing the path. - AccessConditions *AccessConditions -} - -func (o *GetAccessControlOptions) format() (*generated.PathClientGetPropertiesOptions, *generated.LeaseAccessConditions, *generated.ModifiedAccessConditions) { - action := generated.PathGetPropertiesActionGetAccessControl - if o == nil { - return &generated.PathClientGetPropertiesOptions{ - Action: &action, - }, nil, nil - } - // call path formatter since we're hitting dfs in this operation - leaseAccessConditions, modifiedAccessConditions := exported.FormatPathAccessConditions(o.AccessConditions) - return &generated.PathClientGetPropertiesOptions{ - Upn: o.UPN, - Action: &action, - }, leaseAccessConditions, modifiedAccessConditions -} - // UpdateAccessControlOptions contains the optional parameters when calling the UpdateAccessControlRecursive operation. type UpdateAccessControlOptions struct { //placeholder @@ -242,133 +167,6 @@ func (o *RemoveAccessControlOptions) format(ACL string) (*generated.PathClientSe }, mode } -// SetHTTPHeadersOptions contains the optional parameters for the Client.SetHTTPHeaders method. -type SetHTTPHeadersOptions struct { - AccessConditions *AccessConditions -} - -func (o *SetHTTPHeadersOptions) format(httpHeaders HTTPHeaders) (*blob.SetHTTPHeadersOptions, blob.HTTPHeaders) { - httpHeaderOpts := blob.HTTPHeaders{ - BlobCacheControl: httpHeaders.CacheControl, - BlobContentDisposition: httpHeaders.ContentDisposition, - BlobContentEncoding: httpHeaders.ContentEncoding, - BlobContentLanguage: httpHeaders.ContentLanguage, - BlobContentMD5: httpHeaders.ContentMD5, - BlobContentType: httpHeaders.ContentType, - } - if o == nil { - return nil, httpHeaderOpts - } - accessConditions := exported.FormatBlobAccessConditions(o.AccessConditions) - return &blob.SetHTTPHeadersOptions{ - AccessConditions: accessConditions, - }, httpHeaderOpts -} - -// HTTPHeaders contains the HTTP headers for path operations. -type HTTPHeaders struct { - // Optional. Sets the path's cache control. If specified, this property is stored with the path and returned with a read request. - CacheControl *string - // Optional. Sets the path's Content-Disposition header. - ContentDisposition *string - // Optional. Sets the path's content encoding. If specified, this property is stored with the blobpath and returned with a read - // request. - ContentEncoding *string - // Optional. Set the path's content language. If specified, this property is stored with the path and returned with a read - // request. - ContentLanguage *string - // Specify the transactional md5 for the body, to be validated by the service. - ContentMD5 []byte - // Optional. Sets the path's content type. If specified, this property is stored with the path and returned with a read request. - ContentType *string -} - -// -//func (o HTTPHeaders) formatBlobHTTPHeaders() blob.HTTPHeaders { -// -// opts := blob.HTTPHeaders{ -// BlobCacheControl: o.CacheControl, -// BlobContentDisposition: o.ContentDisposition, -// BlobContentEncoding: o.ContentEncoding, -// BlobContentLanguage: o.ContentLanguage, -// BlobContentMD5: o.ContentMD5, -// BlobContentType: o.ContentType, -// } -// return opts -//} - -func (o *HTTPHeaders) formatPathHTTPHeaders() *generated.PathHTTPHeaders { - // TODO: will be used for file related ops, like append - if o == nil { - return nil - } - opts := generated.PathHTTPHeaders{ - CacheControl: o.CacheControl, - ContentDisposition: o.ContentDisposition, - ContentEncoding: o.ContentEncoding, - ContentLanguage: o.ContentLanguage, - ContentMD5: o.ContentMD5, - ContentType: o.ContentType, - TransactionalContentHash: o.ContentMD5, - } - return &opts -} - -// SetMetadataOptions provides set of configurations for Set Metadata on path operation -type SetMetadataOptions struct { - Metadata map[string]*string - AccessConditions *AccessConditions - CPKInfo *CPKInfo - CPKScopeInfo *CPKScopeInfo -} - -func (o *SetMetadataOptions) format() (*blob.SetMetadataOptions, map[string]*string) { - if o == nil { - return nil, nil - } - accessConditions := exported.FormatBlobAccessConditions(o.AccessConditions) - opts := &blob.SetMetadataOptions{ - AccessConditions: accessConditions, - } - if o.CPKInfo != nil { - opts.CPKInfo = &blob.CPKInfo{ - EncryptionKey: o.CPKInfo.EncryptionKey, - EncryptionAlgorithm: o.CPKInfo.EncryptionAlgorithm, - EncryptionKeySHA256: o.CPKInfo.EncryptionKeySHA256, - } - } - if o.CPKScopeInfo != nil { - opts.CPKScopeInfo = (*blob.CPKScopeInfo)(o.CPKScopeInfo) - } - return opts, o.Metadata -} - -// CPKInfo contains a group of parameters for the PathClient.Download method. -type CPKInfo struct { - EncryptionAlgorithm *EncryptionAlgorithmType - EncryptionKey *string - EncryptionKeySHA256 *string -} - -// GetSASURLOptions contains the optional parameters for the Client.GetSASURL method. -type GetSASURLOptions struct { - StartTime *time.Time -} - -func (o *GetSASURLOptions) format() time.Time { - if o == nil { - return time.Time{} - } - - var st time.Time - if o.StartTime != nil { - st = o.StartTime.UTC() - } else { - st = time.Time{} - } - return st -} - // CreationExpiryType defines values for Create() ExpiryType type CreationExpiryType interface { Format() (generated.ExpiryOptions, *string) @@ -411,12 +209,6 @@ type ACLFailedEntry = generated.ACLFailedEntry // SetAccessControlRecursiveResponse contains part of the response data returned by the []OP_AccessControl operations. type SetAccessControlRecursiveResponse = generated.SetAccessControlRecursiveResponse -// CPKScopeInfo contains a group of parameters for the PathClient.SetMetadata method. -type CPKScopeInfo blob.CPKScopeInfo - -// SharedKeyCredential contains an account's name and its primary or secondary key. -type SharedKeyCredential = exported.SharedKeyCredential - // SetExpiryType defines values for ExpiryType. type SetExpiryType = exported.SetExpiryType @@ -435,17 +227,49 @@ type SetExpiryTypeNever = exported.SetExpiryTypeNever // SetExpiryOptions contains the optional parameters for the Client.SetExpiry method. type SetExpiryOptions = exported.SetExpiryOptions +// ================================= path imports ================================== + +// GetPropertiesOptions contains the optional parameters for the Client.GetProperties method +type GetPropertiesOptions = path.GetPropertiesOptions + +// SetAccessControlOptions contains the optional parameters when calling the SetAccessControl operation. dfs endpoint +type SetAccessControlOptions = path.SetAccessControlOptions + +// GetAccessControlOptions contains the optional parameters when calling the GetAccessControl operation. +type GetAccessControlOptions = path.GetAccessControlOptions + +// CPKInfo contains a group of parameters for the PathClient.Download method. +type CPKInfo = path.CPKInfo + +// GetSASURLOptions contains the optional parameters for the Client.GetSASURL method. +type GetSASURLOptions = path.GetSASURLOptions + +// SetHTTPHeadersOptions contains the optional parameters for the Client.SetHTTPHeaders method. +type SetHTTPHeadersOptions = path.SetHTTPHeadersOptions + +// HTTPHeaders contains the HTTP headers for path operations. +type HTTPHeaders = path.HTTPHeaders + +// SetMetadataOptions provides set of configurations for Set Metadata on path operation +type SetMetadataOptions = path.SetMetadataOptions + +// SharedKeyCredential contains an account's name and its primary or secondary key. +type SharedKeyCredential = path.SharedKeyCredential + // AccessConditions identifies blob-specific access conditions which you optionally set. -type AccessConditions = exported.AccessConditions +type AccessConditions = path.AccessConditions // SourceAccessConditions identifies blob-specific access conditions which you optionally set. -type SourceAccessConditions = exported.SourceAccessConditions +type SourceAccessConditions = path.SourceAccessConditions // LeaseAccessConditions contains optional parameters to access leased entity. -type LeaseAccessConditions = exported.LeaseAccessConditions +type LeaseAccessConditions = path.LeaseAccessConditions // ModifiedAccessConditions contains a group of parameters for specifying access conditions. -type ModifiedAccessConditions = exported.ModifiedAccessConditions +type ModifiedAccessConditions = path.ModifiedAccessConditions // SourceModifiedAccessConditions contains a group of parameters for specifying access conditions. -type SourceModifiedAccessConditions = exported.SourceModifiedAccessConditions +type SourceModifiedAccessConditions = path.SourceModifiedAccessConditions + +// CPKScopeInfo contains a group of parameters for the PathClient.SetMetadata method. +type CPKScopeInfo path.CPKScopeInfo diff --git a/sdk/storage/azdatalake/file/responses.go b/sdk/storage/azdatalake/file/responses.go index 2e6a3cecee2e..3116edab7355 100644 --- a/sdk/storage/azdatalake/file/responses.go +++ b/sdk/storage/azdatalake/file/responses.go @@ -7,10 +7,8 @@ package file import ( - "github.com/Azure/azure-sdk-for-go/sdk/azcore" - "github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/blob" "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/internal/generated" - "time" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/internal/path" ) // SetExpiryResponse contains the response fields for the SetExpiry operation. @@ -22,58 +20,31 @@ type CreateResponse = generated.PathClientCreateResponse // DeleteResponse contains the response fields for the Delete operation. type DeleteResponse = generated.PathClientDeleteResponse -// SetAccessControlResponse contains the response fields for the SetAccessControl operation. -type SetAccessControlResponse = generated.PathClientSetAccessControlResponse - // UpdateAccessControlResponse contains the response fields for the UpdateAccessControlRecursive operation. type UpdateAccessControlResponse = generated.PathClientSetAccessControlRecursiveResponse // RemoveAccessControlResponse contains the response fields for the RemoveAccessControlRecursive operation. type RemoveAccessControlResponse = generated.PathClientSetAccessControlRecursiveResponse -// GetAccessControlResponse contains the response fields for the GetAccessControl operation. -type GetAccessControlResponse = generated.PathClientGetPropertiesResponse - -// GetPropertiesResponse contains the response fields for the GetProperties operation. -type GetPropertiesResponse = blob.GetPropertiesResponse - -// SetMetadataResponse contains the response fields for the SetMetadata operation. -type SetMetadataResponse = blob.SetMetadataResponse - // RenameResponse contains the response fields for the Create operation. -type RenameResponse = generated.PathClientCreateResponse +type RenameResponse struct { + Response generated.PathClientCreateResponse + NewFileClient *Client +} -//// SetHTTPHeadersResponse contains the response fields for the SetHTTPHeaders operation. -//type SetHTTPHeadersResponse = blob.SetHTTPHeadersResponse +// ========================================== path imports =========================================================== -// we need to remove the blob sequence number from the response +// SetAccessControlResponse contains the response fields for the SetAccessControl operation. +type SetAccessControlResponse = path.SetAccessControlResponse // SetHTTPHeadersResponse contains the response from method Client.SetHTTPHeaders. -type SetHTTPHeadersResponse struct { - // ClientRequestID contains the information returned from the x-ms-client-request-id header response. - ClientRequestID *string - - // Date contains the information returned from the Date header response. - Date *time.Time - - // ETag contains the information returned from the ETag header response. - ETag *azcore.ETag +type SetHTTPHeadersResponse = path.SetHTTPHeadersResponse - // LastModified contains the information returned from the Last-Modified header response. - LastModified *time.Time - - // RequestID contains the information returned from the x-ms-request-id header response. - RequestID *string +// GetAccessControlResponse contains the response fields for the GetAccessControl operation. +type GetAccessControlResponse = path.GetAccessControlResponse - // Version contains the information returned from the x-ms-version header response. - Version *string -} +// GetPropertiesResponse contains the response fields for the GetProperties operation. +type GetPropertiesResponse = path.GetPropertiesResponse -func formatSetHTTPHeadersResponse(r *SetHTTPHeadersResponse, blobResp *blob.SetHTTPHeadersResponse) { - r.ClientRequestID = blobResp.ClientRequestID - r.Date = blobResp.Date - r.ETag = blobResp.ETag - r.LastModified = blobResp.LastModified - r.RequestID = blobResp.RequestID - r.Version = blobResp.Version -} +// SetMetadataResponse contains the response fields for the SetMetadata operation. +type SetMetadataResponse = path.SetMetadataResponse diff --git a/sdk/storage/azdatalake/filesystem/client.go b/sdk/storage/azdatalake/filesystem/client.go index 0f182909cb69..c0a8146de2ad 100644 --- a/sdk/storage/azdatalake/filesystem/client.go +++ b/sdk/storage/azdatalake/filesystem/client.go @@ -14,6 +14,8 @@ import ( "github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/container" "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake" "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/file" "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" @@ -54,7 +56,7 @@ func NewClient(filesystemURL string, cred azcore.TokenCredential, options *Clien ClientOptions: options.ClientOptions, } blobContainerClient, _ := container.NewClient(containerURL, cred, &containerClientOpts) - fsClient := base.NewFilesystemClient(filesystemURL, containerURL, blobContainerClient, azClient, nil, (*base.ClientOptions)(conOptions)) + fsClient := base.NewFilesystemClient(filesystemURL, containerURL, blobContainerClient, azClient, nil, &cred, (*base.ClientOptions)(conOptions)) return (*Client)(fsClient), nil } @@ -81,7 +83,7 @@ func NewClientWithNoCredential(filesystemURL string, options *ClientOptions) (*C ClientOptions: options.ClientOptions, } blobContainerClient, _ := container.NewClientWithNoCredential(containerURL, &containerClientOpts) - fsClient := base.NewFilesystemClient(filesystemURL, containerURL, blobContainerClient, azClient, nil, (*base.ClientOptions)(conOptions)) + fsClient := base.NewFilesystemClient(filesystemURL, containerURL, blobContainerClient, azClient, nil, nil, (*base.ClientOptions)(conOptions)) return (*Client)(fsClient), nil } @@ -115,7 +117,7 @@ func NewClientWithSharedKeyCredential(filesystemURL string, cred *SharedKeyCrede return nil, err } blobContainerClient, _ := container.NewClientWithSharedKeyCredential(containerURL, blobSharedKey, &containerClientOpts) - fsClient := base.NewFilesystemClient(filesystemURL, containerURL, blobContainerClient, azClient, cred, (*base.ClientOptions)(conOptions)) + fsClient := base.NewFilesystemClient(filesystemURL, containerURL, blobContainerClient, azClient, cred, nil, (*base.ClientOptions)(conOptions)) return (*Client)(fsClient), nil } @@ -151,11 +153,19 @@ func (fs *Client) generatedFSClientWithBlob() *generated.FileSystemClient { return fsClientWithBlob } +func (fs *Client) getClientOptions() *base.ClientOptions { + return base.GetCompositeClientOptions((*base.CompositeClient[generated.FileSystemClient, generated.FileSystemClient, container.Client])(fs)) +} + func (fs *Client) containerClient() *container.Client { _, _, containerClient := base.InnerClients((*base.CompositeClient[generated.FileSystemClient, generated.FileSystemClient, container.Client])(fs)) return containerClient } +func (f *Client) identityCredential() *azcore.TokenCredential { + return base.IdentityCredentialComposite((*base.CompositeClient[generated.FileSystemClient, generated.FileSystemClient, container.Client])(f)) +} + func (fs *Client) sharedKey() *exported.SharedKeyCredential { return base.SharedKeyComposite((*base.CompositeClient[generated.FileSystemClient, generated.FileSystemClient, container.Client])(fs)) } @@ -170,16 +180,36 @@ func (fs *Client) BlobURL() string { return fs.generatedFSClientWithBlob().Endpoint() } +// NewDirectoryClient creates a new directory.Client object by concatenating directory path to the end of this Client's URL. +// The new directory.Client uses the same request policy pipeline as the Client. +func (fs *Client) NewDirectoryClient(directoryPath string) *directory.Client { + dirURL := runtime.JoinPaths(fs.generatedFSClientWithDFS().Endpoint(), directoryPath) + dirURL, blobURL := shared.GetURLs(dirURL) + return (*directory.Client)(base.NewPathClient(dirURL, blobURL, fs.containerClient().NewBlockBlobClient(directoryPath), fs.generatedFSClientWithDFS().InternalClient().WithClientName(shared.DirectoryClient), fs.sharedKey(), fs.identityCredential(), fs.getClientOptions())) +} + +// NewFileClient creates a new file.Client object by concatenating file path to the end of this Client's URL. +// The new file.Client uses the same request policy pipeline as the Client. +func (fs *Client) NewFileClient(filePath string) *file.Client { + fileURL := runtime.JoinPaths(fs.generatedFSClientWithDFS().Endpoint(), filePath) + fileURL, blobURL := shared.GetURLs(filePath) + return (*file.Client)(base.NewPathClient(fileURL, blobURL, fs.containerClient().NewBlockBlobClient(filePath), fs.generatedFSClientWithDFS().InternalClient().WithClientName(shared.FileClient), fs.sharedKey(), fs.identityCredential(), fs.getClientOptions())) +} + // Create creates a new filesystem under the specified account. (blob3). func (fs *Client) Create(ctx context.Context, options *CreateOptions) (CreateResponse, error) { opts := options.format() - return fs.containerClient().Create(ctx, opts) + resp, err := fs.containerClient().Create(ctx, opts) + err = exported.ConvertToDFSError(err) + return resp, err } // Delete deletes the specified filesystem and any files or directories it contains. (blob3). func (fs *Client) Delete(ctx context.Context, options *DeleteOptions) (DeleteResponse, error) { opts := options.format() - return fs.containerClient().Delete(ctx, opts) + resp, err := fs.containerClient().Delete(ctx, opts) + err = exported.ConvertToDFSError(err) + return resp, err } // GetProperties returns all user-defined metadata, standard HTTP properties, and system properties for the filesystem. (blob3). @@ -189,19 +219,24 @@ func (fs *Client) GetProperties(ctx context.Context, options *GetPropertiesOptio resp, err := fs.containerClient().GetProperties(ctx, opts) // TODO: find a cleaner way to not use lease from blob package formatFilesystemProperties(&newResp, &resp) + err = exported.ConvertToDFSError(err) return newResp, err } // SetMetadata sets one or more user-defined name-value pairs for the specified filesystem. (blob3). func (fs *Client) SetMetadata(ctx context.Context, options *SetMetadataOptions) (SetMetadataResponse, error) { opts := options.format() - return fs.containerClient().SetMetadata(ctx, opts) + resp, err := fs.containerClient().SetMetadata(ctx, opts) + err = exported.ConvertToDFSError(err) + return resp, err } // SetAccessPolicy sets the permissions for the specified filesystem or the files and directories under it. (blob3). func (fs *Client) SetAccessPolicy(ctx context.Context, options *SetAccessPolicyOptions) (SetAccessPolicyResponse, error) { opts := options.format() - return fs.containerClient().SetAccessPolicy(ctx, opts) + resp, err := fs.containerClient().SetAccessPolicy(ctx, opts) + err = exported.ConvertToDFSError(err) + return resp, err } // GetAccessPolicy returns the permissions for the specified filesystem or the files and directories under it. (blob3). @@ -210,6 +245,7 @@ func (fs *Client) GetAccessPolicy(ctx context.Context, options *GetAccessPolicyO newResp := GetAccessPolicyResponse{} resp, err := fs.containerClient().GetAccessPolicy(ctx, opts) formatGetAccessPolicyResponse(&newResp, &resp) + err = exported.ConvertToDFSError(err) return newResp, err } @@ -229,14 +265,17 @@ func (fs *Client) NewListPathsPager(recursive bool, options *ListPathsOptions) * var err error if page == nil { req, err = fs.generatedFSClientWithDFS().ListPathsCreateRequest(ctx, recursive, &listOptions) + err = exported.ConvertToDFSError(err) } else { listOptions.Continuation = page.Continuation req, err = fs.generatedFSClientWithDFS().ListPathsCreateRequest(ctx, recursive, &listOptions) + err = exported.ConvertToDFSError(err) } if err != nil { return ListPathsSegmentResponse{}, err } resp, err := fs.generatedFSClientWithDFS().InternalClient().Pipeline().Do(req) + err = exported.ConvertToDFSError(err) if err != nil { return ListPathsSegmentResponse{}, err } @@ -261,14 +300,17 @@ func (fs *Client) NewListDeletedPathsPager(options *ListDeletedPathsOptions) *ru var err error if page == nil { req, err = fs.generatedFSClientWithDFS().ListBlobHierarchySegmentCreateRequest(ctx, &listOptions) + err = exported.ConvertToDFSError(err) } else { listOptions.Marker = page.NextMarker req, err = fs.generatedFSClientWithDFS().ListBlobHierarchySegmentCreateRequest(ctx, &listOptions) + err = exported.ConvertToDFSError(err) } if err != nil { return ListDeletedPathsSegmentResponse{}, err } resp, err := fs.generatedFSClientWithDFS().InternalClient().Pipeline().Do(req) + err = exported.ConvertToDFSError(err) if err != nil { return ListDeletedPathsSegmentResponse{}, err } @@ -288,6 +330,7 @@ func (fs *Client) GetSASURL(permissions sas.FilesystemPermissions, expiry time.T } st := o.format() urlParts, err := azdatalake.ParseURL(fs.BlobURL()) + err = exported.ConvertToDFSError(err) if err != nil { return "", err } @@ -299,6 +342,7 @@ func (fs *Client) GetSASURL(permissions sas.FilesystemPermissions, expiry time.T StartTime: st, ExpiryTime: expiry.UTC(), }.SignWithSharedKey(fs.sharedKey()) + err = exported.ConvertToDFSError(err) if err != nil { return "", err } diff --git a/sdk/storage/azdatalake/filesystem/client_test.go b/sdk/storage/azdatalake/filesystem/client_test.go index 3615506e870e..37df43b164fe 100644 --- a/sdk/storage/azdatalake/filesystem/client_test.go +++ b/sdk/storage/azdatalake/filesystem/client_test.go @@ -63,7 +63,7 @@ func validateFilesystemDeleted(_require *require.Assertions, filesystemClient *f _, err := filesystemClient.GetAccessPolicy(context.Background(), nil) _require.NotNil(err) - testcommon.ValidateErrorCode(_require, err, datalakeerror.ContainerNotFound) + testcommon.ValidateErrorCode(_require, err, datalakeerror.FilesystemNotFound) } func (s *RecordedTestSuite) TestCreateFilesystem() { @@ -224,7 +224,7 @@ func (s *RecordedTestSuite) TestFilesystemDeleteNonExistent() { _, err = fsClient.Delete(context.Background(), nil) _require.NotNil(err) - testcommon.ValidateErrorCode(_require, err, datalakeerror.ContainerNotFound) + testcommon.ValidateErrorCode(_require, err, datalakeerror.FilesystemNotFound) } func (s *RecordedTestSuite) TestFilesystemDeleteIfModifiedSinceTrue() { @@ -432,7 +432,7 @@ func (s *RecordedTestSuite) TestFilesystemSetMetadataNonExistent() { _, err = fsClient.SetMetadata(context.Background(), nil) _require.NotNil(err) - testcommon.ValidateErrorCode(_require, err, datalakeerror.ContainerNotFound) + testcommon.ValidateErrorCode(_require, err, datalakeerror.FilesystemNotFound) } func (s *RecordedTestSuite) TestSetEmptyAccessPolicy() { diff --git a/sdk/storage/azdatalake/filesystem/constants.go b/sdk/storage/azdatalake/filesystem/constants.go index f7ff23ec01cd..3e0c373b87a1 100644 --- a/sdk/storage/azdatalake/filesystem/constants.go +++ b/sdk/storage/azdatalake/filesystem/constants.go @@ -7,7 +7,6 @@ package filesystem import "github.com/Azure/azure-sdk-for-go/sdk/storage/azblob" -import "github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/lease" // PublicAccessType defines values for AccessType - private (default) or file or filesystem. type PublicAccessType = azblob.PublicAccessType @@ -16,47 +15,3 @@ const ( File PublicAccessType = azblob.PublicAccessTypeBlob Filesystem PublicAccessType = azblob.PublicAccessTypeContainer ) - -// TODO: figure out a way to import this from datalake rather than blob again - -// StatusType defines values for StatusType -type StatusType = lease.StatusType - -const ( - StatusTypeLocked StatusType = lease.StatusTypeLocked - StatusTypeUnlocked StatusType = lease.StatusTypeUnlocked -) - -// PossibleStatusTypeValues returns the possible values for the StatusType const type. -func PossibleStatusTypeValues() []StatusType { - return lease.PossibleStatusTypeValues() -} - -// DurationType defines values for DurationType -type DurationType = lease.DurationType - -const ( - DurationTypeInfinite DurationType = lease.DurationTypeInfinite - DurationTypeFixed DurationType = lease.DurationTypeFixed -) - -// PossibleDurationTypeValues returns the possible values for the DurationType const type. -func PossibleDurationTypeValues() []DurationType { - return lease.PossibleDurationTypeValues() -} - -// StateType defines values for StateType -type StateType = lease.StateType - -const ( - StateTypeAvailable StateType = lease.StateTypeAvailable - StateTypeLeased StateType = lease.StateTypeLeased - StateTypeExpired StateType = lease.StateTypeExpired - StateTypeBreaking StateType = lease.StateTypeBreaking - StateTypeBroken StateType = lease.StateTypeBroken -) - -// PossibleStateTypeValues returns the possible values for the StateType const type. -func PossibleStateTypeValues() []StateType { - return lease.PossibleStateTypeValues() -} diff --git a/sdk/storage/azdatalake/filesystem/responses.go b/sdk/storage/azdatalake/filesystem/responses.go index 9a2112657bcc..d32f0aed538d 100644 --- a/sdk/storage/azdatalake/filesystem/responses.go +++ b/sdk/storage/azdatalake/filesystem/responses.go @@ -9,6 +9,7 @@ package filesystem import ( "github.com/Azure/azure-sdk-for-go/sdk/azcore" "github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/container" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake" "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/internal/generated" "time" ) @@ -98,13 +99,13 @@ type GetPropertiesResponse struct { LastModified *time.Time // LeaseDuration contains the information returned from the x-ms-lease-duration header response. - LeaseDuration *DurationType + LeaseDuration *azdatalake.DurationType // LeaseState contains the information returned from the x-ms-lease-state header response. - LeaseState *StateType + LeaseState *azdatalake.StateType // LeaseStatus contains the information returned from the x-ms-lease-status header response. - LeaseStatus *StatusType + LeaseStatus *azdatalake.StatusType // Metadata contains the information returned from the x-ms-meta header response. Metadata map[string]*string @@ -116,6 +117,7 @@ type GetPropertiesResponse struct { Version *string } +// removes the blob prefix in access type func formatFilesystemProperties(r *GetPropertiesResponse, contResp *container.GetPropertiesResponse) { r.PublicAccess = contResp.BlobPublicAccess r.ClientRequestID = contResp.ClientRequestID diff --git a/sdk/storage/azdatalake/go.mod b/sdk/storage/azdatalake/go.mod index b1b48ee155fd..17498bc501b5 100644 --- a/sdk/storage/azdatalake/go.mod +++ b/sdk/storage/azdatalake/go.mod @@ -3,7 +3,7 @@ module github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake go 1.18 require ( - github.com/Azure/azure-sdk-for-go/sdk/azcore v1.6.1 + github.com/Azure/azure-sdk-for-go/sdk/azcore v1.7.0 github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0 github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.0.0 github.com/stretchr/testify v1.7.1 diff --git a/sdk/storage/azdatalake/go.sum b/sdk/storage/azdatalake/go.sum index 911682659b2b..3482ec48d6a5 100644 --- a/sdk/storage/azdatalake/go.sum +++ b/sdk/storage/azdatalake/go.sum @@ -1,5 +1,5 @@ -github.com/Azure/azure-sdk-for-go/sdk/azcore v1.6.1 h1:SEy2xmstIphdPwNBUi7uhvjyjhVKISfwjfOJmuy7kg4= -github.com/Azure/azure-sdk-for-go/sdk/azcore v1.6.1/go.mod h1:bjGvMhVMb+EEm3VRNQawDMUyMMjo+S5ewNjflkep/0Q= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.7.0 h1:8q4SaHjFsClSvuVne0ID/5Ka8u3fcIHyqkLjcFpNRHQ= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.7.0/go.mod h1:bjGvMhVMb+EEm3VRNQawDMUyMMjo+S5ewNjflkep/0Q= github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.1.0 h1:QkAcEIAKbNL4KoFr4SathZPhDhF4mVwpBMFlYjyAqy8= github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0 h1:sXr+ck84g/ZlZUOZiNELInmMgOsuGwdjjVkEIde0OtY= github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0/go.mod h1:okt5dMMTOFjX/aovMlrjvvXoPMBVSPzk9185BT0+eZM= diff --git a/sdk/storage/azdatalake/internal/base/clients.go b/sdk/storage/azdatalake/internal/base/clients.go index c80152dc4b83..cab52ce400b2 100644 --- a/sdk/storage/azdatalake/internal/base/clients.go +++ b/sdk/storage/azdatalake/internal/base/clients.go @@ -36,9 +36,10 @@ type CompositeClient[T, K, U any] struct { // generated client with blob innerK *K // blob client - innerU *U - sharedKey *exported.SharedKeyCredential - options *ClientOptions + innerU *U + sharedKey *exported.SharedKeyCredential + identityCred *azcore.TokenCredential + options *ClientOptions } func InnerClients[T, K, U any](client *CompositeClient[T, K, U]) (*T, *K, *U) { @@ -49,33 +50,40 @@ func SharedKeyComposite[T, K, U any](client *CompositeClient[T, K, U]) *exported return client.sharedKey } -func NewFilesystemClient(fsURL string, fsURLWithBlobEndpoint string, client *container.Client, azClient *azcore.Client, sharedKey *exported.SharedKeyCredential, options *ClientOptions) *CompositeClient[generated.FileSystemClient, generated.FileSystemClient, container.Client] { +func IdentityCredentialComposite[T, K, U any](client *CompositeClient[T, K, U]) *azcore.TokenCredential { + return client.identityCred +} + +func NewFilesystemClient(fsURL string, fsURLWithBlobEndpoint string, client *container.Client, azClient *azcore.Client, sharedKey *exported.SharedKeyCredential, identityCred *azcore.TokenCredential, options *ClientOptions) *CompositeClient[generated.FileSystemClient, generated.FileSystemClient, container.Client] { return &CompositeClient[generated.FileSystemClient, generated.FileSystemClient, container.Client]{ - innerT: generated.NewFilesystemClient(fsURL, azClient), - innerK: generated.NewFilesystemClient(fsURLWithBlobEndpoint, azClient), - sharedKey: sharedKey, - innerU: client, - options: options, + innerT: generated.NewFilesystemClient(fsURL, azClient), + innerK: generated.NewFilesystemClient(fsURLWithBlobEndpoint, azClient), + sharedKey: sharedKey, + identityCred: identityCred, + innerU: client, + options: options, } } -func NewServiceClient(serviceURL string, serviceURLWithBlobEndpoint string, client *service.Client, azClient *azcore.Client, sharedKey *exported.SharedKeyCredential, options *ClientOptions) *CompositeClient[generated.ServiceClient, generated.ServiceClient, service.Client] { +func NewServiceClient(serviceURL string, serviceURLWithBlobEndpoint string, client *service.Client, azClient *azcore.Client, sharedKey *exported.SharedKeyCredential, identityCred *azcore.TokenCredential, options *ClientOptions) *CompositeClient[generated.ServiceClient, generated.ServiceClient, service.Client] { return &CompositeClient[generated.ServiceClient, generated.ServiceClient, service.Client]{ - innerT: generated.NewServiceClient(serviceURL, azClient), - innerK: generated.NewServiceClient(serviceURLWithBlobEndpoint, azClient), - sharedKey: sharedKey, - innerU: client, - options: options, + innerT: generated.NewServiceClient(serviceURL, azClient), + innerK: generated.NewServiceClient(serviceURLWithBlobEndpoint, azClient), + sharedKey: sharedKey, + identityCred: identityCred, + innerU: client, + options: options, } } -func NewPathClient(pathURL string, pathURLWithBlobEndpoint string, client *blockblob.Client, azClient *azcore.Client, sharedKey *exported.SharedKeyCredential, options *ClientOptions) *CompositeClient[generated.PathClient, generated.PathClient, blockblob.Client] { +func NewPathClient(pathURL string, pathURLWithBlobEndpoint string, client *blockblob.Client, azClient *azcore.Client, sharedKey *exported.SharedKeyCredential, identityCred *azcore.TokenCredential, options *ClientOptions) *CompositeClient[generated.PathClient, generated.PathClient, blockblob.Client] { return &CompositeClient[generated.PathClient, generated.PathClient, blockblob.Client]{ - innerT: generated.NewPathClient(pathURL, azClient), - innerK: generated.NewPathClient(pathURLWithBlobEndpoint, azClient), - sharedKey: sharedKey, - innerU: client, - options: options, + innerT: generated.NewPathClient(pathURL, azClient), + innerK: generated.NewPathClient(pathURLWithBlobEndpoint, azClient), + sharedKey: sharedKey, + identityCred: identityCred, + innerU: client, + options: options, } } diff --git a/sdk/storage/azdatalake/internal/exported/exported.go b/sdk/storage/azdatalake/internal/exported/exported.go index 6a91ea05453a..ab0c5ebea4cf 100644 --- a/sdk/storage/azdatalake/internal/exported/exported.go +++ b/sdk/storage/azdatalake/internal/exported/exported.go @@ -7,8 +7,11 @@ package exported import ( + "errors" "fmt" + "github.com/Azure/azure-sdk-for-go/sdk/azcore" "strconv" + "strings" ) const SnapshotTimeFormat = "2006-01-02T15:04:05.0000000Z07:00" @@ -33,3 +36,19 @@ func FormatHTTPRange(r HTTPRange) *string { dataRange := fmt.Sprintf("bytes=%v-%s", r.Offset, endOffset) return &dataRange } + +func ConvertToDFSError(err error) error { + if err == nil { + return nil + } + var responseErr *azcore.ResponseError + isRespErr := errors.As(err, &responseErr) + if isRespErr { + responseErr.ErrorCode = strings.Replace(responseErr.ErrorCode, "blob", "path", -1) + responseErr.ErrorCode = strings.Replace(responseErr.ErrorCode, "Blob", "Path", -1) + responseErr.ErrorCode = strings.Replace(responseErr.ErrorCode, "container", "filesystem", -1) + responseErr.ErrorCode = strings.Replace(responseErr.ErrorCode, "Container", "Filesystem", -1) + return responseErr + } + return err +} diff --git a/sdk/storage/azdatalake/internal/exported/path.go b/sdk/storage/azdatalake/internal/exported/path.go deleted file mode 100644 index eabd8aa3ddaa..000000000000 --- a/sdk/storage/azdatalake/internal/exported/path.go +++ /dev/null @@ -1 +0,0 @@ -package exported diff --git a/sdk/storage/azdatalake/internal/exported/user_delegation_credential.go b/sdk/storage/azdatalake/internal/exported/user_delegation_credential.go index 91b933bf5737..047e265e046e 100644 --- a/sdk/storage/azdatalake/internal/exported/user_delegation_credential.go +++ b/sdk/storage/azdatalake/internal/exported/user_delegation_credential.go @@ -10,7 +10,7 @@ import ( "crypto/hmac" "crypto/sha256" "encoding/base64" - "github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/service" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/internal/generated" ) // NewUserDelegationCredential creates a new UserDelegationCredential using a Storage account's Name and a user delegation Key from it @@ -22,7 +22,7 @@ func NewUserDelegationCredential(accountName string, udk UserDelegationKey) *Use } // UserDelegationKey contains UserDelegationKey. -type UserDelegationKey = service.UserDelegationKey +type UserDelegationKey = generated.UserDelegationKey // UserDelegationCredential contains an account's name and its user delegation key. type UserDelegationCredential struct { diff --git a/sdk/storage/azdatalake/internal/generated/user_delegation_key.go b/sdk/storage/azdatalake/internal/generated/user_delegation_key.go new file mode 100644 index 000000000000..367765fa19cd --- /dev/null +++ b/sdk/storage/azdatalake/internal/generated/user_delegation_key.go @@ -0,0 +1,144 @@ +//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 generated + +import ( + "context" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/policy" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime" + "net/http" + "strconv" + "time" +) + +// KeyInfo - Key information +type KeyInfo struct { + // REQUIRED; The date-time the key expires in ISO 8601 UTC time + Expiry *string `xml:"Expiry"` + + // REQUIRED; The date-time the key is active in ISO 8601 UTC time + Start *string `xml:"Start"` +} + +// ServiceClientGetUserDelegationKeyOptions contains the optional parameters for the ServiceClient.GetUserDelegationKey method. +type ServiceClientGetUserDelegationKeyOptions struct { + // Provides a client-generated, opaque value with a 1 KB character limit that is recorded in the analytics logs when storage + // analytics logging is enabled. + RequestID *string + // The timeout parameter is expressed in seconds. For more information, see Setting Timeouts for Blob Service Operations. + // [https://docs.microsoft.com/en-us/rest/api/storageservices/fileservices/setting-timeouts-for-blob-service-operations] + Timeout *int32 +} + +// ServiceClientGetUserDelegationKeyResponse contains the response from method ServiceClient.GetUserDelegationKey. +type ServiceClientGetUserDelegationKeyResponse struct { + UserDelegationKey + // ClientRequestID contains the information returned from the x-ms-client-request-id header response. + ClientRequestID *string `xml:"ClientRequestID"` + + // Date contains the information returned from the Date header response. + Date *time.Time `xml:"Date"` + + // RequestID contains the information returned from the x-ms-request-id header response. + RequestID *string `xml:"RequestID"` + + // Version contains the information returned from the x-ms-version header response. + Version *string `xml:"Version"` +} + +// UserDelegationKey - A user delegation key +type UserDelegationKey struct { + // REQUIRED; The date-time the key expires + SignedExpiry *time.Time `xml:"SignedExpiry"` + + // REQUIRED; The Azure Active Directory object ID in GUID format. + SignedOID *string `xml:"SignedOid"` + + // REQUIRED; Abbreviation of the Azure Storage service that accepts the key + SignedService *string `xml:"SignedService"` + + // REQUIRED; The date-time the key is active + SignedStart *time.Time `xml:"SignedStart"` + + // REQUIRED; The Azure Active Directory tenant ID in GUID format + SignedTID *string `xml:"SignedTid"` + + // REQUIRED; The service version that created the key + SignedVersion *string `xml:"SignedVersion"` + + // REQUIRED; The key as a base64 string + Value *string `xml:"Value"` +} + +// GetUserDelegationKey - Retrieves a user delegation key for the Blob service. This is only a valid operation when using +// bearer token authentication. +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2020-10-02 +// - keyInfo - Key information +// - options - ServiceClientGetUserDelegationKeyOptions contains the optional parameters for the ServiceClient.GetUserDelegationKey +// method. +func (client *ServiceClient) GetUserDelegationKey(ctx context.Context, keyInfo KeyInfo, options *ServiceClientGetUserDelegationKeyOptions) (ServiceClientGetUserDelegationKeyResponse, error) { + req, err := client.getUserDelegationKeyCreateRequest(ctx, keyInfo, options) + if err != nil { + return ServiceClientGetUserDelegationKeyResponse{}, err + } + resp, err := client.internal.Pipeline().Do(req) + if err != nil { + return ServiceClientGetUserDelegationKeyResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusOK) { + return ServiceClientGetUserDelegationKeyResponse{}, runtime.NewResponseError(resp) + } + return client.getUserDelegationKeyHandleResponse(resp) +} + +// getUserDelegationKeyCreateRequest creates the GetUserDelegationKey request. +func (client *ServiceClient) getUserDelegationKeyCreateRequest(ctx context.Context, keyInfo KeyInfo, options *ServiceClientGetUserDelegationKeyOptions) (*policy.Request, error) { + req, err := runtime.NewRequest(ctx, http.MethodPost, client.endpoint) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("restype", "service") + reqQP.Set("comp", "userdelegationkey") + if options != nil && options.Timeout != nil { + reqQP.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + } + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["x-ms-version"] = []string{"2020-10-02"} + if options != nil && options.RequestID != nil { + req.Raw().Header["x-ms-client-request-id"] = []string{*options.RequestID} + } + req.Raw().Header["Accept"] = []string{"application/xml"} + return req, runtime.MarshalAsXML(req, keyInfo) +} + +// getUserDelegationKeyHandleResponse handles the GetUserDelegationKey response. +func (client *ServiceClient) getUserDelegationKeyHandleResponse(resp *http.Response) (ServiceClientGetUserDelegationKeyResponse, error) { + result := ServiceClientGetUserDelegationKeyResponse{} + if val := resp.Header.Get("x-ms-client-request-id"); val != "" { + result.ClientRequestID = &val + } + if val := resp.Header.Get("x-ms-request-id"); val != "" { + result.RequestID = &val + } + if val := resp.Header.Get("x-ms-version"); val != "" { + result.Version = &val + } + if val := resp.Header.Get("Date"); val != "" { + date, err := time.Parse(time.RFC1123, val) + if err != nil { + return ServiceClientGetUserDelegationKeyResponse{}, err + } + result.Date = &date + } + if err := runtime.UnmarshalAsXML(resp, &result.UserDelegationKey); err != nil { + return ServiceClientGetUserDelegationKeyResponse{}, err + } + return result, nil +} diff --git a/sdk/storage/azdatalake/internal/path/constants.go b/sdk/storage/azdatalake/internal/path/constants.go new file mode 100644 index 000000000000..7dd11049e38e --- /dev/null +++ b/sdk/storage/azdatalake/internal/path/constants.go @@ -0,0 +1,35 @@ +//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 path + +import "github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/blob" + +// EncryptionAlgorithmType defines values for EncryptionAlgorithmType. +type EncryptionAlgorithmType = blob.EncryptionAlgorithmType + +const ( + EncryptionAlgorithmTypeNone EncryptionAlgorithmType = blob.EncryptionAlgorithmTypeNone + EncryptionAlgorithmTypeAES256 EncryptionAlgorithmType = blob.EncryptionAlgorithmTypeAES256 +) + +type ImmutabilityPolicyMode = blob.ImmutabilityPolicyMode + +const ( + ImmutabilityPolicyModeMutable ImmutabilityPolicyMode = blob.ImmutabilityPolicyModeMutable + ImmutabilityPolicyModeUnlocked ImmutabilityPolicyMode = blob.ImmutabilityPolicyModeUnlocked + ImmutabilityPolicyModeLocked ImmutabilityPolicyMode = blob.ImmutabilityPolicyModeLocked +) + +// CopyStatusType defines values for CopyStatusType +type CopyStatusType = blob.CopyStatusType + +const ( + CopyStatusTypePending CopyStatusType = blob.CopyStatusTypePending + CopyStatusTypeSuccess CopyStatusType = blob.CopyStatusTypeSuccess + CopyStatusTypeAborted CopyStatusType = blob.CopyStatusTypeAborted + CopyStatusTypeFailed CopyStatusType = blob.CopyStatusTypeFailed +) diff --git a/sdk/storage/azdatalake/internal/path/models.go b/sdk/storage/azdatalake/internal/path/models.go new file mode 100644 index 000000000000..893bc9d40d19 --- /dev/null +++ b/sdk/storage/azdatalake/internal/path/models.go @@ -0,0 +1,243 @@ +//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 path + +import ( + "errors" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/blob" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/datalakeerror" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/internal/exported" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/internal/generated" + "time" +) + +// GetPropertiesOptions contains the optional parameters for the Client.GetProperties method +type GetPropertiesOptions struct { + AccessConditions *AccessConditions + CPKInfo *CPKInfo +} + +func FormatGetPropertiesOptions(o *GetPropertiesOptions) *blob.GetPropertiesOptions { + if o == nil { + return nil + } + accessConditions := exported.FormatBlobAccessConditions(o.AccessConditions) + return &blob.GetPropertiesOptions{ + AccessConditions: accessConditions, + CPKInfo: &blob.CPKInfo{ + EncryptionKey: o.CPKInfo.EncryptionKey, + EncryptionAlgorithm: o.CPKInfo.EncryptionAlgorithm, + EncryptionKeySHA256: o.CPKInfo.EncryptionKeySHA256, + }, + } +} + +// ===================================== PATH IMPORTS =========================================== + +// SetAccessControlOptions contains the optional parameters when calling the SetAccessControl operation. dfs endpoint +type SetAccessControlOptions struct { + // Owner is the owner of the path. + Owner *string + // Group is the owning group of the path. + Group *string + // ACL is the access control list for the path. + ACL *string + // Permissions is the octal representation of the permissions for user, group and mask. + Permissions *string + // AccessConditions contains parameters for accessing the path. + AccessConditions *AccessConditions +} + +func FormatSetAccessControlOptions(o *SetAccessControlOptions) (*generated.PathClientSetAccessControlOptions, *generated.LeaseAccessConditions, *generated.ModifiedAccessConditions, error) { + if o == nil { + return nil, nil, nil, datalakeerror.MissingParameters + } + // call path formatter since we're hitting dfs in this operation + leaseAccessConditions, modifiedAccessConditions := exported.FormatPathAccessConditions(o.AccessConditions) + if o.Owner == nil && o.Group == nil && o.ACL == nil && o.Permissions == nil { + return nil, nil, nil, errors.New("at least one parameter should be set for SetAccessControl API") + } + return &generated.PathClientSetAccessControlOptions{ + Owner: o.Owner, + Group: o.Group, + ACL: o.ACL, + Permissions: o.Permissions, + }, leaseAccessConditions, modifiedAccessConditions, nil +} + +// GetAccessControlOptions contains the optional parameters when calling the GetAccessControl operation. +type GetAccessControlOptions struct { + // UPN is the user principal name. + UPN *bool + // AccessConditions contains parameters for accessing the path. + AccessConditions *AccessConditions +} + +func FormatGetAccessControlOptions(o *GetAccessControlOptions) (*generated.PathClientGetPropertiesOptions, *generated.LeaseAccessConditions, *generated.ModifiedAccessConditions) { + action := generated.PathGetPropertiesActionGetAccessControl + if o == nil { + return &generated.PathClientGetPropertiesOptions{ + Action: &action, + }, nil, nil + } + // call path formatter since we're hitting dfs in this operation + leaseAccessConditions, modifiedAccessConditions := exported.FormatPathAccessConditions(o.AccessConditions) + return &generated.PathClientGetPropertiesOptions{ + Upn: o.UPN, + Action: &action, + }, leaseAccessConditions, modifiedAccessConditions +} + +// CPKInfo contains a group of parameters for the PathClient.Download method. +type CPKInfo struct { + EncryptionAlgorithm *EncryptionAlgorithmType + EncryptionKey *string + EncryptionKeySHA256 *string +} + +// GetSASURLOptions contains the optional parameters for the Client.GetSASURL method. +type GetSASURLOptions struct { + StartTime *time.Time +} + +func FormatGetSASURLOptions(o *GetSASURLOptions) time.Time { + if o == nil { + return time.Time{} + } + + var st time.Time + if o.StartTime != nil { + st = o.StartTime.UTC() + } else { + st = time.Time{} + } + return st +} + +// SetHTTPHeadersOptions contains the optional parameters for the Client.SetHTTPHeaders method. +type SetHTTPHeadersOptions struct { + AccessConditions *AccessConditions +} + +func FormatSetHTTPHeadersOptions(o *SetHTTPHeadersOptions, httpHeaders HTTPHeaders) (*blob.SetHTTPHeadersOptions, blob.HTTPHeaders) { + httpHeaderOpts := blob.HTTPHeaders{ + BlobCacheControl: httpHeaders.CacheControl, + BlobContentDisposition: httpHeaders.ContentDisposition, + BlobContentEncoding: httpHeaders.ContentEncoding, + BlobContentLanguage: httpHeaders.ContentLanguage, + BlobContentMD5: httpHeaders.ContentMD5, + BlobContentType: httpHeaders.ContentType, + } + if o == nil { + return nil, httpHeaderOpts + } + accessConditions := exported.FormatBlobAccessConditions(o.AccessConditions) + return &blob.SetHTTPHeadersOptions{ + AccessConditions: accessConditions, + }, httpHeaderOpts +} + +// HTTPHeaders contains the HTTP headers for path operations. +type HTTPHeaders struct { + // Sets the path's cache control. If specified, this property is stored with the path and returned with a read request. + CacheControl *string + // Sets the path's Content-Disposition header. + ContentDisposition *string + // Sets the path's content encoding. If specified, this property is stored with the blobpath and returned with a read + // request. + ContentEncoding *string + // Set the path's content language. If specified, this property is stored with the path and returned with a read + // request. + ContentLanguage *string + // Specify the transactional md5 for the body, to be validated by the service. + ContentMD5 []byte + // Sets the path's content type. If specified, this property is stored with the path and returned with a read request. + ContentType *string +} + +// +//func (o HTTPHeaders) formatBlobHTTPHeaders() blob.HTTPHeaders { +// +// opts := blob.HTTPHeaders{ +// BlobCacheControl: o.CacheControl, +// BlobContentDisposition: o.ContentDisposition, +// BlobContentEncoding: o.ContentEncoding, +// BlobContentLanguage: o.ContentLanguage, +// BlobContentMD5: o.ContentMD5, +// BlobContentType: o.ContentType, +// } +// return opts +//} + +func FormatPathHTTPHeaders(o *HTTPHeaders) *generated.PathHTTPHeaders { + // TODO: will be used for file related ops, like append + if o == nil { + return nil + } + opts := generated.PathHTTPHeaders{ + CacheControl: o.CacheControl, + ContentDisposition: o.ContentDisposition, + ContentEncoding: o.ContentEncoding, + ContentLanguage: o.ContentLanguage, + ContentMD5: o.ContentMD5, + ContentType: o.ContentType, + TransactionalContentHash: o.ContentMD5, + } + return &opts +} + +// SetMetadataOptions provides set of configurations for Set Metadata on path operation +type SetMetadataOptions struct { + Metadata map[string]*string + AccessConditions *AccessConditions + CPKInfo *CPKInfo + CPKScopeInfo *CPKScopeInfo +} + +func FormatSetMetadataOptions(o *SetMetadataOptions) (*blob.SetMetadataOptions, map[string]*string) { + if o == nil { + return nil, nil + } + accessConditions := exported.FormatBlobAccessConditions(o.AccessConditions) + opts := &blob.SetMetadataOptions{ + AccessConditions: accessConditions, + } + if o.CPKInfo != nil { + opts.CPKInfo = &blob.CPKInfo{ + EncryptionKey: o.CPKInfo.EncryptionKey, + EncryptionAlgorithm: o.CPKInfo.EncryptionAlgorithm, + EncryptionKeySHA256: o.CPKInfo.EncryptionKeySHA256, + } + } + if o.CPKScopeInfo != nil { + opts.CPKScopeInfo = (*blob.CPKScopeInfo)(o.CPKScopeInfo) + } + return opts, o.Metadata +} + +// ========================================= constants ========================================= + +// SharedKeyCredential contains an account's name and its primary or secondary key. +type SharedKeyCredential = exported.SharedKeyCredential + +// AccessConditions identifies access conditions which you optionally set. +type AccessConditions = exported.AccessConditions + +// SourceAccessConditions identifies source access conditions which you optionally set. +type SourceAccessConditions = exported.SourceAccessConditions + +// LeaseAccessConditions contains optional parameters to access leased entity. +type LeaseAccessConditions = exported.LeaseAccessConditions + +// ModifiedAccessConditions contains a group of parameters for specifying access conditions. +type ModifiedAccessConditions = exported.ModifiedAccessConditions + +// SourceModifiedAccessConditions contains a group of parameters for specifying access conditions. +type SourceModifiedAccessConditions = exported.SourceModifiedAccessConditions + +// CPKScopeInfo contains a group of parameters for the Client.SetMetadata() method. +type CPKScopeInfo blob.CPKScopeInfo diff --git a/sdk/storage/azdatalake/internal/path/responses.go b/sdk/storage/azdatalake/internal/path/responses.go new file mode 100644 index 000000000000..915d7b104374 --- /dev/null +++ b/sdk/storage/azdatalake/internal/path/responses.go @@ -0,0 +1,269 @@ +//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 path + +import ( + "github.com/Azure/azure-sdk-for-go/sdk/azcore" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/blob" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/internal/generated" + "net/http" + "time" +) + +// SetAccessControlResponse contains the response fields for the SetAccessControl operation. +type SetAccessControlResponse = generated.PathClientSetAccessControlResponse + +// GetAccessControlResponse contains the response fields for the GetAccessControl operation. +type GetAccessControlResponse = generated.PathClientGetPropertiesResponse + +// TODO: removed BlobSequenceNumber, BlobCommittedBlockCount and BlobType headers from the original response: + +// GetPropertiesResponse contains the response fields for the GetProperties operation. +type GetPropertiesResponse struct { + // AcceptRanges contains the information returned from the Accept-Ranges header response. + AcceptRanges *string + + // AccessTier contains the information returned from the x-ms-access-tier header response. + AccessTier *string + + // AccessTierChangeTime contains the information returned from the x-ms-access-tier-change-time header response. + AccessTierChangeTime *time.Time + + // AccessTierInferred contains the information returned from the x-ms-access-tier-inferred header response. + AccessTierInferred *bool + + // ArchiveStatus contains the information returned from the x-ms-archive-status header response. + ArchiveStatus *string + + // CacheControl contains the information returned from the Cache-Control header response. + CacheControl *string + + // ClientRequestID contains the information returned from the x-ms-client-request-id header response. + ClientRequestID *string + + // ContentDisposition contains the information returned from the Content-Disposition header response. + ContentDisposition *string + + // ContentEncoding contains the information returned from the Content-Encoding header response. + ContentEncoding *string + + // ContentLanguage contains the information returned from the Content-Language header response. + ContentLanguage *string + + // ContentLength contains the information returned from the Content-Length header response. + ContentLength *int64 + + // ContentMD5 contains the information returned from the Content-MD5 header response. + ContentMD5 []byte + + // ContentType contains the information returned from the Content-Type header response. + ContentType *string + + // CopyCompletionTime contains the information returned from the x-ms-copy-completion-time header response. + CopyCompletionTime *time.Time + + // CopyID contains the information returned from the x-ms-copy-id header response. + CopyID *string + + // CopyProgress contains the information returned from the x-ms-copy-progress header response. + CopyProgress *string + + // CopySource contains the information returned from the x-ms-copy-source header response. + CopySource *string + + // CopyStatus contains the information returned from the x-ms-copy-status header response. + CopyStatus *CopyStatusType + + // CopyStatusDescription contains the information returned from the x-ms-copy-status-description header response. + CopyStatusDescription *string + + // CreationTime contains the information returned from the x-ms-creation-time header response. + CreationTime *time.Time + + // Date contains the information returned from the Date header response. + Date *time.Time + + // DestinationSnapshot contains the information returned from the x-ms-copy-destination-snapshot header response. + DestinationSnapshot *string + + // ETag contains the information returned from the ETag header response. + ETag *azcore.ETag + + // EncryptionKeySHA256 contains the information returned from the x-ms-encryption-key-sha256 header response. + EncryptionKeySHA256 *string + + // EncryptionScope contains the information returned from the x-ms-encryption-scope header response. + EncryptionScope *string + + // ExpiresOn contains the information returned from the x-ms-expiry-time header response. + ExpiresOn *time.Time + + // ImmutabilityPolicyExpiresOn contains the information returned from the x-ms-immutability-policy-until-date header response. + ImmutabilityPolicyExpiresOn *time.Time + + // ImmutabilityPolicyMode contains the information returned from the x-ms-immutability-policy-mode header response. + ImmutabilityPolicyMode *ImmutabilityPolicyMode + + // IsCurrentVersion contains the information returned from the x-ms-is-current-version header response. + IsCurrentVersion *bool + + // IsIncrementalCopy contains the information returned from the x-ms-incremental-copy header response. + IsIncrementalCopy *bool + + // IsSealed contains the information returned from the x-ms-blob-sealed header response. + IsSealed *bool + + // IsServerEncrypted contains the information returned from the x-ms-server-encrypted header response. + IsServerEncrypted *bool + + // LastAccessed contains the information returned from the x-ms-last-access-time header response. + LastAccessed *time.Time + + // LastModified contains the information returned from the Last-Modified header response. + LastModified *time.Time + + // LeaseDuration contains the information returned from the x-ms-lease-duration header response. + LeaseDuration *azdatalake.DurationType + + // LeaseState contains the information returned from the x-ms-lease-state header response. + LeaseState *azdatalake.StateType + + // LeaseStatus contains the information returned from the x-ms-lease-status header response. + LeaseStatus *azdatalake.StatusType + + // LegalHold contains the information returned from the x-ms-legal-hold header response. + LegalHold *bool + + // Metadata contains the information returned from the x-ms-meta header response. + Metadata map[string]*string + + // ObjectReplicationPolicyID contains the information returned from the x-ms-or-policy-id header response. + ObjectReplicationPolicyID *string + + // ObjectReplicationRules contains the information returned from the x-ms-or header response. + ObjectReplicationRules map[string]*string + + // RehydratePriority contains the information returned from the x-ms-rehydrate-priority header response. + RehydratePriority *string + + // RequestID contains the information returned from the x-ms-request-id header response. + RequestID *string + + // TagCount contains the information returned from the x-ms-tag-count header response. + TagCount *int64 + + // Version contains the information returned from the x-ms-version header response. + Version *string + + // VersionID contains the information returned from the x-ms-version-id header response. + VersionID *string + + // Owner contains the information returned from the x-ms-owner header response. + Owner *string + + // Group contains the information returned from the x-ms-group header response. + Group *string + + // Permissions contains the information returned from the x-ms-permissions header response. + Permissions *string +} + +func FormatGetPropertiesResponse(r *blob.GetPropertiesResponse, rawResponse *http.Response) GetPropertiesResponse { + newResp := GetPropertiesResponse{} + newResp.AcceptRanges = r.AcceptRanges + newResp.AccessTier = r.AccessTier + newResp.AccessTierChangeTime = r.AccessTierChangeTime + newResp.AccessTierInferred = r.AccessTierInferred + newResp.ArchiveStatus = r.ArchiveStatus + newResp.CacheControl = r.CacheControl + newResp.ClientRequestID = r.ClientRequestID + newResp.ContentDisposition = r.ContentDisposition + newResp.ContentEncoding = r.ContentEncoding + newResp.ContentLanguage = r.ContentLanguage + newResp.ContentLength = r.ContentLength + newResp.ContentMD5 = r.ContentMD5 + newResp.ContentType = r.ContentType + newResp.CopyCompletionTime = r.CopyCompletionTime + newResp.CopyID = r.CopyID + newResp.CopyProgress = r.CopyProgress + newResp.CopySource = r.CopySource + newResp.CopyStatus = r.CopyStatus + newResp.CopyStatusDescription = r.CopyStatusDescription + newResp.CreationTime = r.CreationTime + newResp.Date = r.Date + newResp.DestinationSnapshot = r.DestinationSnapshot + newResp.ETag = r.ETag + newResp.EncryptionKeySHA256 = r.EncryptionKeySHA256 + newResp.EncryptionScope = r.EncryptionScope + newResp.ExpiresOn = r.ExpiresOn + newResp.ImmutabilityPolicyExpiresOn = r.ImmutabilityPolicyExpiresOn + newResp.ImmutabilityPolicyMode = r.ImmutabilityPolicyMode + newResp.IsCurrentVersion = r.IsCurrentVersion + newResp.IsIncrementalCopy = r.IsIncrementalCopy + newResp.IsSealed = r.IsSealed + newResp.IsServerEncrypted = r.IsServerEncrypted + newResp.LastAccessed = r.LastAccessed + newResp.LastModified = r.LastModified + newResp.LeaseDuration = r.LeaseDuration + newResp.LeaseState = r.LeaseState + newResp.LeaseStatus = r.LeaseStatus + newResp.LegalHold = r.LegalHold + newResp.Metadata = r.Metadata + newResp.ObjectReplicationPolicyID = r.ObjectReplicationPolicyID + newResp.ObjectReplicationRules = r.ObjectReplicationRules + newResp.RehydratePriority = r.RehydratePriority + newResp.RequestID = r.RequestID + newResp.TagCount = r.TagCount + newResp.Version = r.Version + newResp.VersionID = r.VersionID + if val := rawResponse.Header.Get("x-ms-owner"); val != "" { + newResp.Owner = &val + } + if val := rawResponse.Header.Get("x-ms-group"); val != "" { + newResp.Group = &val + } + if val := rawResponse.Header.Get("x-ms-permissions"); val != "" { + newResp.Permissions = &val + } + return newResp +} + +// SetMetadataResponse contains the response fields for the SetMetadata operation. +type SetMetadataResponse = blob.SetMetadataResponse + +// SetHTTPHeadersResponse contains the response from method Client.SetHTTPHeaders. +type SetHTTPHeadersResponse struct { + // ClientRequestID contains the information returned from the x-ms-client-request-id header response. + ClientRequestID *string + + // Date contains the information returned from the Date header response. + Date *time.Time + + // ETag contains the information returned from the ETag header response. + ETag *azcore.ETag + + // LastModified contains the information returned from the Last-Modified header response. + LastModified *time.Time + + // RequestID contains the information returned from the x-ms-request-id header response. + RequestID *string + + // Version contains the information returned from the x-ms-version header response. + Version *string +} + +// removes blob sequence number from response + +func FormatSetHTTPHeadersResponse(r *SetHTTPHeadersResponse, blobResp *blob.SetHTTPHeadersResponse) { + r.ClientRequestID = blobResp.ClientRequestID + r.Date = blobResp.Date + r.ETag = blobResp.ETag + r.LastModified = blobResp.LastModified + r.RequestID = blobResp.RequestID + r.Version = blobResp.Version +} diff --git a/sdk/storage/azdatalake/internal/testcommon/common.go b/sdk/storage/azdatalake/internal/testcommon/common.go index fcb537b98c52..1314309c5ac2 100644 --- a/sdk/storage/azdatalake/internal/testcommon/common.go +++ b/sdk/storage/azdatalake/internal/testcommon/common.go @@ -4,7 +4,7 @@ import ( "errors" "github.com/Azure/azure-sdk-for-go/sdk/azcore" "github.com/Azure/azure-sdk-for-go/sdk/internal/recording" - "github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/bloberror" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/datalakeerror" "github.com/stretchr/testify/require" "os" "strings" @@ -66,7 +66,7 @@ func GetRequiredEnv(name string) (string, error) { } } -func ValidateErrorCode(_require *require.Assertions, err error, code bloberror.Code) { +func ValidateErrorCode(_require *require.Assertions, err error, code datalakeerror.StorageErrorCode) { _require.NotNil(err) var responseErr *azcore.ResponseError errors.As(err, &responseErr) diff --git a/sdk/storage/azdatalake/lease/constants.go b/sdk/storage/azdatalake/lease/constants.go deleted file mode 100644 index 04df4d58e7b1..000000000000 --- a/sdk/storage/azdatalake/lease/constants.go +++ /dev/null @@ -1,51 +0,0 @@ -//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 lease - -import "github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/lease" - -// StatusType defines values for StatusType -type StatusType = lease.StatusType - -const ( - StatusTypeLocked StatusType = lease.StatusTypeLocked - StatusTypeUnlocked StatusType = lease.StatusTypeUnlocked -) - -// PossibleStatusTypeValues returns the possible values for the StatusType const type. -func PossibleStatusTypeValues() []StatusType { - return lease.PossibleStatusTypeValues() -} - -// DurationType defines values for DurationType -type DurationType = lease.DurationType - -const ( - DurationTypeInfinite DurationType = lease.DurationTypeInfinite - DurationTypeFixed DurationType = lease.DurationTypeFixed -) - -// PossibleDurationTypeValues returns the possible values for the DurationType const type. -func PossibleDurationTypeValues() []DurationType { - return lease.PossibleDurationTypeValues() -} - -// StateType defines values for StateType -type StateType = lease.StateType - -const ( - StateTypeAvailable StateType = lease.StateTypeAvailable - StateTypeLeased StateType = lease.StateTypeLeased - StateTypeExpired StateType = lease.StateTypeExpired - StateTypeBreaking StateType = lease.StateTypeBreaking - StateTypeBroken StateType = lease.StateTypeBroken -) - -// PossibleStateTypeValues returns the possible values for the StateType const type. -func PossibleStateTypeValues() []StateType { - return lease.PossibleStateTypeValues() -} diff --git a/sdk/storage/azdatalake/service/client.go b/sdk/storage/azdatalake/service/client.go index 9b7e8721c8db..33e96821f3bd 100644 --- a/sdk/storage/azdatalake/service/client.go +++ b/sdk/storage/azdatalake/service/client.go @@ -11,14 +11,15 @@ import ( "github.com/Azure/azure-sdk-for-go/sdk/azcore" "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/internal/log" "github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/service" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake" "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/filesystem" "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/shared" "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/sas" + "strings" "time" ) @@ -53,7 +54,7 @@ func NewClient(serviceURL string, cred azcore.TokenCredential, options *ClientOp ClientOptions: options.ClientOptions, } blobSvcClient, _ := service.NewClient(blobServiceURL, cred, &blobServiceClientOpts) - svcClient := base.NewServiceClient(datalakeServiceURL, blobServiceURL, blobSvcClient, azClient, nil, (*base.ClientOptions)(conOptions)) + svcClient := base.NewServiceClient(datalakeServiceURL, blobServiceURL, blobSvcClient, azClient, nil, &cred, (*base.ClientOptions)(conOptions)) return (*Client)(svcClient), nil } @@ -79,7 +80,7 @@ func NewClientWithNoCredential(serviceURL string, options *ClientOptions) (*Clie ClientOptions: options.ClientOptions, } blobSvcClient, _ := service.NewClientWithNoCredential(blobServiceURL, &blobServiceClientOpts) - svcClient := base.NewServiceClient(datalakeServiceURL, blobServiceURL, blobSvcClient, azClient, nil, (*base.ClientOptions)(conOptions)) + svcClient := base.NewServiceClient(datalakeServiceURL, blobServiceURL, blobSvcClient, azClient, nil, nil, (*base.ClientOptions)(conOptions)) return (*Client)(svcClient), nil } @@ -113,7 +114,7 @@ func NewClientWithSharedKeyCredential(serviceURL string, cred *SharedKeyCredenti return nil, err } blobSvcClient, _ := service.NewClientWithSharedKeyCredential(blobServiceURL, blobSharedKey, &blobServiceClientOpts) - svcClient := base.NewServiceClient(datalakeServiceURL, blobServiceURL, blobSvcClient, azClient, cred, (*base.ClientOptions)(conOptions)) + svcClient := base.NewServiceClient(datalakeServiceURL, blobServiceURL, blobSvcClient, azClient, cred, nil, (*base.ClientOptions)(conOptions)) return (*Client)(svcClient), nil } @@ -142,35 +143,29 @@ func (s *Client) getClientOptions() *base.ClientOptions { return base.GetCompositeClientOptions((*base.CompositeClient[generated.ServiceClient, generated.ServiceClient, service.Client])(s)) } -// NewFilesystemClient creates a new share.Client object by concatenating shareName to the end of this Client's URL. -// The new share.Client uses the same request policy pipeline as the Client. +// NewFilesystemClient creates a new filesystem.Client object by concatenating filesystemName to the end of this Client's URL. +// The new filesystem.Client uses the same request policy pipeline as the Client. func (s *Client) NewFilesystemClient(filesystemName string) *filesystem.Client { filesystemURL := runtime.JoinPaths(s.generatedServiceClientWithDFS().Endpoint(), filesystemName) - // TODO: remove new azcore.Client creation after the API for shallow copying with new client name is implemented - clOpts := s.getClientOptions() - azClient, err := azcore.NewClient(shared.FilesystemClient, exported.ModuleVersion, *(base.GetPipelineOptions(clOpts)), &(clOpts.ClientOptions)) - if err != nil { - if log.Should(exported.EventError) { - log.Writef(exported.EventError, err.Error()) - } - return nil - } filesystemURL, containerURL := shared.GetURLs(filesystemURL) - return (*filesystem.Client)(base.NewFilesystemClient(filesystemURL, containerURL, s.serviceClient().NewContainerClient(filesystemName), azClient, s.sharedKey(), clOpts)) + return (*filesystem.Client)(base.NewFilesystemClient(filesystemURL, containerURL, s.serviceClient().NewContainerClient(filesystemName), s.generatedServiceClientWithDFS().InternalClient().WithClientName(shared.FilesystemClient), s.sharedKey(), s.identityCredential(), s.getClientOptions())) } -// NewDirectoryClient creates a new share.Client object by concatenating shareName to the end of this Client's URL. -// The new share.Client uses the same request policy pipeline as the Client. -func (s *Client) NewDirectoryClient(directoryName string) *filesystem.Client { - // TODO: implement once dir client is implemented - return nil -} +// GetUserDelegationCredential obtains a UserDelegationKey object using the base ServiceURL object. +// OAuth is required for this call, as well as any role that can delegate access to the storage account. +func (s *Client) GetUserDelegationCredential(ctx context.Context, info KeyInfo, o *GetUserDelegationCredentialOptions) (*UserDelegationCredential, error) { + url, err := azdatalake.ParseURL(s.BlobURL()) + if err != nil { + return nil, err + } -// NewFileClient creates a new share.Client object by concatenating shareName to the end of this Client's URL. -// The new share.Client uses the same request policy pipeline as the Client. -func (s *Client) NewFileClient(fileName string) *filesystem.Client { - // TODO: implement once file client is implemented - return nil + getUserDelegationKeyOptions := o.format() + udk, err := s.generatedServiceClientWithBlob().GetUserDelegationKey(ctx, info, getUserDelegationKeyOptions) + if err != nil { + return nil, err + } + + return exported.NewUserDelegationCredential(strings.Split(url.Host, ".")[0], udk.UserDelegationKey), nil } func (s *Client) generatedServiceClientWithDFS() *generated.ServiceClient { @@ -192,6 +187,10 @@ func (s *Client) sharedKey() *exported.SharedKeyCredential { return base.SharedKeyComposite((*base.CompositeClient[generated.ServiceClient, generated.ServiceClient, service.Client])(s)) } +func (s *Client) identityCredential() *azcore.TokenCredential { + return base.IdentityCredentialComposite((*base.CompositeClient[generated.ServiceClient, generated.ServiceClient, service.Client])(s)) +} + // DFSURL returns the URL endpoint used by the Client object. func (s *Client) DFSURL() string { return s.generatedServiceClientWithDFS().Endpoint() @@ -206,6 +205,7 @@ func (s *Client) BlobURL() string { func (s *Client) CreateFilesystem(ctx context.Context, filesystem string, options *CreateFilesystemOptions) (CreateFilesystemResponse, error) { filesystemClient := s.NewFilesystemClient(filesystem) resp, err := filesystemClient.Create(ctx, options) + err = exported.ConvertToDFSError(err) return resp, err } @@ -213,19 +213,24 @@ func (s *Client) CreateFilesystem(ctx context.Context, filesystem string, option func (s *Client) DeleteFilesystem(ctx context.Context, filesystem string, options *DeleteFilesystemOptions) (DeleteFilesystemResponse, error) { filesystemClient := s.NewFilesystemClient(filesystem) resp, err := filesystemClient.Delete(ctx, options) + err = exported.ConvertToDFSError(err) return resp, err } // SetProperties sets properties for a storage account's File service endpoint. (blob3) func (s *Client) SetProperties(ctx context.Context, options *SetPropertiesOptions) (SetPropertiesResponse, error) { opts := options.format() - return s.serviceClient().SetProperties(ctx, opts) + resp, err := s.serviceClient().SetProperties(ctx, opts) + err = exported.ConvertToDFSError(err) + return resp, err } // GetProperties gets properties for a storage account's File service endpoint. (blob3) func (s *Client) GetProperties(ctx context.Context, options *GetPropertiesOptions) (GetPropertiesResponse, error) { opts := options.format() - return s.serviceClient().GetProperties(ctx, opts) + resp, err := s.serviceClient().GetProperties(ctx, opts) + err = exported.ConvertToDFSError(err) + return resp, err } @@ -244,6 +249,7 @@ func (s *Client) NewListFilesystemsPager(options *ListFilesystemsOptions) *runti } newPage := ListFilesystemsResponse{} currPage, err := page.blobPager.NextPage(context.TODO()) + err = exported.ConvertToDFSError(err) if err != nil { return newPage, err } @@ -265,12 +271,7 @@ func (s *Client) NewListFilesystemsPager(options *ListFilesystemsOptions) *runti func (s *Client) GetSASURL(resources sas.AccountResourceTypes, permissions sas.AccountPermissions, expiry time.Time, o *GetSASURLOptions) (string, error) { // format all options to blob service options res, perms, opts := o.format(resources, permissions) - return s.serviceClient().GetSASURL(res, perms, expiry, opts) + resp, err := s.serviceClient().GetSASURL(res, perms, expiry, opts) + err = exported.ConvertToDFSError(err) + return resp, err } - -// TODO: Figure out how we can convert from blob delegation key to one defined in datalake -//// GetUserDelegationCredential obtains a UserDelegationKey object using the base ServiceURL object. -//// OAuth is required for this call, as well as any role that can delegate access to the storage account. -//func (s *Client) GetUserDelegationCredential(ctx context.Context, info KeyInfo, o *GetUserDelegationCredentialOptions) (*UserDelegationCredential, error) { -// return s.serviceClient().GetUserDelegationCredential(ctx, info, o) -//} diff --git a/sdk/storage/azdatalake/service/client_test.go b/sdk/storage/azdatalake/service/client_test.go index a9541d4356a4..53fd574b31a7 100644 --- a/sdk/storage/azdatalake/service/client_test.go +++ b/sdk/storage/azdatalake/service/client_test.go @@ -16,7 +16,6 @@ import ( "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/filesystem" "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/internal/shared" "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/internal/testcommon" - "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/lease" "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/sas" "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/service" "github.com/stretchr/testify/require" @@ -465,6 +464,28 @@ func (s *ServiceUnrecordedTestsSuite) TestNoSharedKeyCredError() { } +func (s *ServiceRecordedTestsSuite) TestGetFilesystemClient() { + _require := require.New(s.T()) + testName := s.T().Name() + accountName := os.Getenv("AZURE_STORAGE_ACCOUNT_NAME") + accountKey := os.Getenv("AZURE_STORAGE_ACCOUNT_KEY") + cred, err := azdatalake.NewSharedKeyCredential(accountName, accountKey) + _require.Nil(err) + + serviceClient, err := service.NewClientWithSharedKeyCredential(fmt.Sprintf("https://%s.blob.core.windows.net/", accountName), cred, nil) + _require.Nil(err) + + fsName := testcommon.GenerateFilesystemName(testName + "1") + fsClient := serviceClient.NewFilesystemClient(fsName) + + defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + _, err = fsClient.Create(context.Background(), nil) + _require.Nil(err) + + _, err = fsClient.GetProperties(context.Background(), nil) + _require.Nil(err) +} + func (s *ServiceRecordedTestsSuite) TestSASFilesystemClient() { _require := require.New(s.T()) testName := s.T().Name() @@ -554,7 +575,7 @@ func (s *ServiceRecordedTestsSuite) TestListFilesystemsBasic() { } fsName := testcommon.GenerateFilesystemName(testName) - fsClient := testcommon.ServiceGetFilesystemClient(fsName, svcClient) + fsClient := svcClient.NewFilesystemClient(fsName) _, err = fsClient.Create(context.Background(), &filesystem.CreateOptions{Metadata: md}) defer func(fsClient *filesystem.Client, ctx context.Context, options *filesystem.DeleteOptions) { _, err := fsClient.Delete(ctx, options) @@ -578,8 +599,8 @@ func (s *ServiceRecordedTestsSuite) TestListFilesystemsBasic() { _require.NotNil(ctnr.Properties) _require.NotNil(ctnr.Properties.LastModified) _require.NotNil(ctnr.Properties.ETag) - _require.Equal(*ctnr.Properties.LeaseStatus, lease.StatusTypeUnlocked) - _require.Equal(*ctnr.Properties.LeaseState, lease.StateTypeAvailable) + _require.Equal(*ctnr.Properties.LeaseStatus, azdatalake.StatusTypeUnlocked) + _require.Equal(*ctnr.Properties.LeaseState, azdatalake.StateTypeAvailable) _require.Nil(ctnr.Properties.LeaseDuration) _require.Nil(ctnr.Properties.PublicAccess) _require.NotNil(ctnr.Metadata) @@ -639,8 +660,8 @@ func (s *ServiceRecordedTestsSuite) TestListFilesystemsBasicUsingConnectionStrin _require.NotNil(ctnr.Properties) _require.NotNil(ctnr.Properties.LastModified) _require.NotNil(ctnr.Properties.ETag) - _require.Equal(*ctnr.Properties.LeaseStatus, lease.StatusTypeUnlocked) - _require.Equal(*ctnr.Properties.LeaseState, lease.StateTypeAvailable) + _require.Equal(*ctnr.Properties.LeaseStatus, azdatalake.StatusTypeUnlocked) + _require.Equal(*ctnr.Properties.LeaseState, azdatalake.StateTypeAvailable) _require.Nil(ctnr.Properties.LeaseDuration) _require.Nil(ctnr.Properties.PublicAccess) _require.NotNil(ctnr.Metadata) diff --git a/sdk/storage/azdatalake/service/models.go b/sdk/storage/azdatalake/service/models.go index 7f8fb9c9bb6b..5efbd2b8c927 100644 --- a/sdk/storage/azdatalake/service/models.go +++ b/sdk/storage/azdatalake/service/models.go @@ -7,15 +7,18 @@ package service import ( - "github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/lease" "github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/service" "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/filesystem" "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/sas" "time" ) import blobSAS "github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/sas" +// KeyInfo contains KeyInfo struct. +type KeyInfo = generated.KeyInfo + type CreateFilesystemOptions = filesystem.CreateOptions type DeleteFilesystemOptions = filesystem.DeleteOptions @@ -44,11 +47,17 @@ type StaticWebsite = service.StaticWebsite // SharedKeyCredential contains an account's name and its primary or secondary key. type SharedKeyCredential = exported.SharedKeyCredential -// GetUserDelegationCredentialOptions contains the optional parameters for the Client.GetUserDelegationCredential method. -type GetUserDelegationCredentialOptions = service.GetUserDelegationCredentialOptions +// PublicAccessType defines values for AccessType - private (default) or file or filesystem. +type PublicAccessType = filesystem.PublicAccessType -// KeyInfo contains KeyInfo struct. -type KeyInfo = service.KeyInfo +// GetUserDelegationCredentialOptions contains optional parameters for Service.GetUserDelegationKey method. +type GetUserDelegationCredentialOptions struct { + // placeholder for future options +} + +func (o *GetUserDelegationCredentialOptions) format() *generated.ServiceClientGetUserDelegationKeyOptions { + return nil +} // UserDelegationCredential contains an account's name and its user delegation key. type UserDelegationCredential = exported.UserDelegationCredential @@ -179,14 +188,3 @@ func (o *GetSASURLOptions) format(resources sas.AccountResourceTypes, permission StartTime: o.StartTime, } } - -// listing response models -// TODO: find another way to import these - -type LeaseDurationType = lease.DurationType - -type LeaseStateType = lease.StateType - -type LeaseStatusType = lease.StatusType - -type PublicAccessType = filesystem.PublicAccessType diff --git a/sdk/storage/azdatalake/service/responses.go b/sdk/storage/azdatalake/service/responses.go index 377532f3488f..6a6cecd23b81 100644 --- a/sdk/storage/azdatalake/service/responses.go +++ b/sdk/storage/azdatalake/service/responses.go @@ -13,6 +13,7 @@ import ( "github.com/Azure/azure-sdk-for-go/sdk/azcore" "github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime" "github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/service" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake" "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/filesystem" "time" ) @@ -86,9 +87,9 @@ type FilesystemProperties struct { // Indicates if version level worm is enabled on this container. IsImmutableStorageWithVersioningEnabled *bool - LeaseDuration *LeaseDurationType - LeaseState *LeaseStateType - LeaseStatus *LeaseStatusType + LeaseDuration *azdatalake.DurationType + LeaseState *azdatalake.StateType + LeaseStatus *azdatalake.StatusType PreventEncryptionScopeOverride *bool PublicAccess *PublicAccessType RemainingRetentionDays *int32 From ad288fb4ded41218fca403a0ff45ccfe1e10d0c6 Mon Sep 17 00:00:00 2001 From: Tamer Sherif <69483382+tasherif-msft@users.noreply.github.com> Date: Thu, 27 Jul 2023 13:46:57 -0700 Subject: [PATCH 10/16] [AzDatalake] File Client Upload/Download Support (#21261) * Enable gocritic during linting (#20715) Enabled gocritic's evalOrder to catch dependencies on undefined behavior on return statements. Updated to latest version of golangci-lint. Fixed issue in azblob flagged by latest linter. * Cosmos DB: Enable merge support (#20716) * Adding header and value * Wiring and tests * format * Fixing value * change log * [azservicebus, azeventhubs] Stress test and logging improvement (#20710) Logging improvements: * Updating the logging to print more tracing information (per-link) in prep for the bigger release coming up. * Trimming out some of the verbose logging, seeing if I can get it a bit more reasonable. Stress tests: * Add a timestamp to the log name we generate and also default to append, not overwrite. * Use 0.5 cores, 0.5GB as our baseline. Some pods use more and I'll tune them more later. * update proxy version (#20712) Co-authored-by: Scott Beddall * Return an error when you try to send a message that's too large. (#20721) This now works just like the message batch - you'll get an ErrMessageTooLarge if you attempt to send a message that's too large for the link's configured size. NOTE: there's a patch to `internal/go-amqp/Sender.go` to match what's in go-amqp's main so it returns a programmatically useful error when the message is too large. Fixes #20647 * Changes in test that is failing in pipeline (#20693) * [azservicebus, azeventhubs] Treat 'entity full' as a fatal error (#20722) When the remote entity is full we get a resource-limit-exceeded condition. This isn't something we should keep retrying on and it's best to just abort and let the user know immediately, rather than hoping it might eventually clear out. This affected both Event Hubs and Service Bus. Fixes #20647 * [azservicebus/azeventhubs] Redirect stderr and stdout to tee (#20726) * Update changelog with latest features (#20730) * Update changelog with latest features Prepare for upcoming release. * bump minor version * pass along the artifact name so we can override it later (#20732) Co-authored-by: scbedd <45376673+scbedd@users.noreply.github.com> * [azeventhubs] Fixing checkpoint store race condition (#20727) The checkpoint store wasn't guarding against multiple owners claiming for the first time - fixing this by using IfNoneMatch Fixes #20717 * Fix azidentity troubleshooting guide link (#20736) * [Release] sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/0.1.0 (#20437) * [Release] sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/0.1.0 generation from spec commit: 85fb4ac6f8bfefd179e6c2632976a154b5c9ff04 * client factory * fix * fix * update * add sdk/resourcemanager/postgresql/armpostgresql live test (#20685) * add sdk/resourcemanager/postgresql/armpostgresql live test * update assets.json * set subscriptionId default value * format * add sdk/resourcemanager/eventhub/armeventhub live test (#20686) * add sdk/resourcemanager/eventhub/armeventhub live test * update assets * add sdk/resourcemanager/compute/armcompute live test (#20048) * add sdk/resourcemanager/compute/armcompute live test * skus filter * fix subscriptionId default value * fix * gofmt * update recording * sdk/resourcemanager/network/armnetwork live test (#20331) * sdk/resourcemanager/network/armnetwork live test * update subscriptionId default value * update recording * add sdk/resourcemanager/cosmos/armcosmos live test (#20705) * add sdk/resourcemanager/cosmos/armcosmos live test * update assets.json * update assets.json * update assets.json * update assets.json * Increment package version after release of azcore (#20740) * [azeventhubs] Improperly resetting etag in the checkpoint store (#20737) We shouldn't be resetting the etag to nil - it's what we use to enforce a "single winner" when doing ownership claims. The bug here was two-fold: I had bad logic in my previous claim ownership, which I fixed in a previous PR, but we need to reflect that same constraint properly in our in-memory checkpoint store for these tests. * Eng workflows sync and branch cleanup additions (#20743) Co-authored-by: James Suplizio * [azeventhubs] Latest start position can also be inclusive (ie, get the latest message) (#20744) * Update GitHubEventProcessor version and remove pull_request_review procesing (#20751) Co-authored-by: James Suplizio * Rename DisableAuthorityValidationAndInstanceDiscovery (#20746) * fix (#20707) * AzFile (#20739) * azfile: Fixing connection string parsing logic (#20798) * Fixing connection string parse logic * Update README * [azadmin] fix flaky test (#20758) * fix flaky test * charles suggestion * Prepare azidentity v1.3.0 for release (#20756) * Fix broken podman link (#20801) Co-authored-by: Wes Haggard * [azquery] update doc comments (#20755) * update doc comments * update statistics and visualization generation * prep-for-release * Fixed contribution section (#20752) Co-authored-by: Bob Tabor * [azeventhubs,azservicebus] Some API cleanup, renames (#20754) * Adding options to UpdateCheckpoint(), just for future potential expansion * Make Offset an int64, not a *int64 (it's not optional, it'll always come back with ReceivedEvents) * Adding more logging into the checkpoint store. * Point all imports at the production go-amqp * Add supporting features to enable distributed tracing (#20301) (#20708) * Add supporting features to enable distributed tracing This includes new internal pipeline policies and other supporting types. See the changelog for a full description. Added some missing doc comments. * fix linter issue * add net.peer.name trace attribute sequence custom HTTP header policy before logging policy. sequence logging policy after HTTP trace policy. keep body download policy at the end. * add span for iterating over pages * Restore ARM CAE support for azcore beta (#20657) This reverts commit 902097226ff3fe2fc6c3e7fc50d3478350253614. * Upgrade to stable azcore (#20808) * Increment package version after release of data/azcosmos (#20807) * Updating changelog (#20810) * Add fake package to azcore (#20711) * Add fake package to azcore This is the supporting infrastructure for the generated SDK fakes. * fix doc comment * Updating CHANGELOG.md (#20809) * changelog (#20811) * Increment package version after release of storage/azfile (#20813) * Update changelog (azblob) (#20815) * Updating CHANGELOG.md * Update the changelog with correct version * [azquery] migration guide (#20742) * migration guide * Charles feedback * Richard feedback --------- Co-authored-by: Charles Lowell <10964656+chlowell@users.noreply.github.com> * Increment package version after release of monitor/azquery (#20820) * [keyvault] prep for release (#20819) * prep for release * perf tests * update date * added all upload methods * added more tests for upload stream * added more tests * added downloaders * added more tests * cleanup * feedback --------- Co-authored-by: Joel Hendrix Co-authored-by: Matias Quaranta Co-authored-by: Richard Park <51494936+richardpark-msft@users.noreply.github.com> Co-authored-by: Azure SDK Bot <53356347+azure-sdk@users.noreply.github.com> Co-authored-by: Scott Beddall Co-authored-by: siminsavani-msft <77068571+siminsavani-msft@users.noreply.github.com> Co-authored-by: scbedd <45376673+scbedd@users.noreply.github.com> Co-authored-by: Charles Lowell <10964656+chlowell@users.noreply.github.com> Co-authored-by: Peng Jiahui <46921893+Alancere@users.noreply.github.com> Co-authored-by: James Suplizio Co-authored-by: Sourav Gupta <98318303+souravgupta-msft@users.noreply.github.com> Co-authored-by: gracewilcox <43627800+gracewilcox@users.noreply.github.com> Co-authored-by: Wes Haggard Co-authored-by: Bob Tabor Co-authored-by: Bob Tabor --- sdk/storage/azdatalake/file/chunkwriting.go | 193 +++++ sdk/storage/azdatalake/file/client.go | 184 +++- sdk/storage/azdatalake/file/client_test.go | 792 ++++++++++++++++++ sdk/storage/azdatalake/file/constants.go | 12 + sdk/storage/azdatalake/file/mmf_unix.go | 38 + sdk/storage/azdatalake/file/mmf_windows.go | 56 ++ sdk/storage/azdatalake/file/models.go | 413 +++++++++ sdk/storage/azdatalake/file/responses.go | 223 +++++ sdk/storage/azdatalake/file/retry_reader.go | 191 +++++ sdk/storage/azdatalake/filesystem/client.go | 4 +- .../exported/shared_key_credential.go | 2 +- .../exported/transfer_validation_option.go | 56 ++ .../azdatalake/internal/generated/models.go | 15 + .../azdatalake/internal/path/constants.go | 12 +- .../azdatalake/internal/path/models.go | 29 +- .../internal/shared/batch_transfer.go | 77 ++ .../azdatalake/internal/testcommon/common.go | 20 + sdk/storage/azdatalake/sas/service.go | 6 +- 18 files changed, 2277 insertions(+), 46 deletions(-) create mode 100644 sdk/storage/azdatalake/file/chunkwriting.go create mode 100644 sdk/storage/azdatalake/file/mmf_unix.go create mode 100644 sdk/storage/azdatalake/file/mmf_windows.go create mode 100644 sdk/storage/azdatalake/file/retry_reader.go create mode 100644 sdk/storage/azdatalake/internal/exported/transfer_validation_option.go create mode 100644 sdk/storage/azdatalake/internal/generated/models.go create mode 100644 sdk/storage/azdatalake/internal/shared/batch_transfer.go diff --git a/sdk/storage/azdatalake/file/chunkwriting.go b/sdk/storage/azdatalake/file/chunkwriting.go new file mode 100644 index 000000000000..289b042d1646 --- /dev/null +++ b/sdk/storage/azdatalake/file/chunkwriting.go @@ -0,0 +1,193 @@ +//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 file + +import ( + "bytes" + "context" + "errors" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/streaming" + "io" + "sync" +) + +// chunkWriter provides methods to upload chunks that represent a file to a server. +// This allows us to provide a local implementation that fakes the server for hermetic testing. +type chunkWriter interface { + AppendData(context.Context, int64, io.ReadSeekCloser, *AppendDataOptions) (AppendDataResponse, error) + FlushData(context.Context, int64, *FlushDataOptions) (FlushDataResponse, error) +} + +// bufferManager provides an abstraction for the management of buffers. +// this is mostly for testing purposes, but does allow for different implementations without changing the algorithm. +type bufferManager[T ~[]byte] interface { + // Acquire returns the channel that contains the pool of buffers. + Acquire() <-chan T + + // Release releases the buffer back to the pool for reuse/cleanup. + Release(T) + + // Grow grows the number of buffers, up to the predefined max. + // It returns the total number of buffers or an error. + // No error is returned if the number of buffers has reached max. + // This is called only from the reading goroutine. + Grow() (int, error) + + // Free cleans up all buffers. + Free() +} + +// copyFromReader copies a source io.Reader to file storage using concurrent uploads. +func copyFromReader[T ~[]byte](ctx context.Context, src io.Reader, dst chunkWriter, options UploadStreamOptions, getBufferManager func(maxBuffers int, bufferSize int64) bufferManager[T]) error { + options.setDefaults() + actualSize := int64(0) + wg := sync.WaitGroup{} // Used to know when all outgoing chunks have finished processing + errCh := make(chan error, 1) // contains the first error encountered during processing + var err error + + buffers := getBufferManager(int(options.Concurrency), options.ChunkSize) + defer buffers.Free() + + // this controls the lifetime of the uploading goroutines. + // if an error is encountered, cancel() is called which will terminate all uploads. + // NOTE: the ordering is important here. cancel MUST execute before + // cleaning up the buffers so that any uploading goroutines exit first, + // releasing their buffers back to the pool for cleanup. + ctx, cancel := context.WithCancel(ctx) + defer cancel() + + // This goroutine grabs a buffer, reads from the stream into the buffer, + // then creates a goroutine to upload/stage the chunk. + for chunkNum := uint32(0); true; chunkNum++ { + var buffer T + select { + case buffer = <-buffers.Acquire(): + // got a buffer + default: + // no buffer available; allocate a new buffer if possible + if _, err := buffers.Grow(); err != nil { + return err + } + + // either grab the newly allocated buffer or wait for one to become available + buffer = <-buffers.Acquire() + } + + var n int + n, err = io.ReadFull(src, buffer) + + if n > 0 { + // some data was read, upload it + wg.Add(1) // We're posting a buffer to be sent + + // NOTE: we must pass chunkNum as an arg to our goroutine else + // it's captured by reference and can change underneath us! + go func(chunkNum uint32) { + // Upload the outgoing chunk, matching the number of bytes read + offset := int64(chunkNum) * options.ChunkSize + appendDataOpts := options.getAppendDataOptions() + actualSize += int64(len(buffer[:n])) + _, err := dst.AppendData(ctx, offset, streaming.NopCloser(bytes.NewReader(buffer[:n])), appendDataOpts) + if err != nil { + select { + case errCh <- err: + // error was set + default: + // some other error is already set + } + cancel() + } + buffers.Release(buffer) // The goroutine reading from the stream can reuse this buffer now + + // signal that the chunk has been staged. + // we MUST do this after attempting to write to errCh + // to avoid it racing with the reading goroutine. + wg.Done() + }(chunkNum) + } else { + // nothing was read so the buffer is empty, send it back for reuse/clean-up. + buffers.Release(buffer) + } + + if err != nil { // The reader is done, no more outgoing buffers + if errors.Is(err, io.EOF) || errors.Is(err, io.ErrUnexpectedEOF) { + // these are expected errors, we don't surface those + err = nil + } else { + // some other error happened, terminate any outstanding uploads + cancel() + } + break + } + } + + wg.Wait() // Wait for all outgoing chunks to complete + + if err != nil { + // there was an error reading from src, favor this error over any error during staging + return err + } + + select { + case err = <-errCh: + // there was an error during staging + return err + default: + // no error was encountered + } + + // All chunks uploaded, return nil error + flushOpts := options.getFlushDataOptions() + _, err = dst.FlushData(ctx, actualSize, flushOpts) + return err +} + +// mmbPool implements the bufferManager interface. +// it uses anonymous memory mapped files for buffers. +// don't use this type directly, use newMMBPool() instead. +type mmbPool struct { + buffers chan mmb + count int + max int + size int64 +} + +func newMMBPool(maxBuffers int, bufferSize int64) bufferManager[mmb] { + return &mmbPool{ + buffers: make(chan mmb, maxBuffers), + max: maxBuffers, + size: bufferSize, + } +} + +func (pool *mmbPool) Acquire() <-chan mmb { + return pool.buffers +} + +func (pool *mmbPool) Grow() (int, error) { + if pool.count < pool.max { + buffer, err := newMMB(pool.size) + if err != nil { + return 0, err + } + pool.buffers <- buffer + pool.count++ + } + return pool.count, nil +} + +func (pool *mmbPool) Release(buffer mmb) { + pool.buffers <- buffer +} + +func (pool *mmbPool) Free() { + for i := 0; i < pool.count; i++ { + buffer := <-pool.buffers + buffer.delete() + } + pool.count = 0 +} diff --git a/sdk/storage/azdatalake/file/client.go b/sdk/storage/azdatalake/file/client.go index 5909aa475aea..0fae799fb965 100644 --- a/sdk/storage/azdatalake/file/client.go +++ b/sdk/storage/azdatalake/file/client.go @@ -7,11 +7,16 @@ package file import ( + "bytes" "context" + "errors" "github.com/Azure/azure-sdk-for-go/sdk/azcore" "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/azcore/streaming" + "github.com/Azure/azure-sdk-for-go/sdk/internal/log" "github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/blockblob" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake" "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" @@ -19,9 +24,12 @@ import ( "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" + "io" "net/http" "net/url" + "os" "strings" + "sync" "time" ) @@ -254,26 +262,6 @@ func (f *Client) SetExpiry(ctx context.Context, expiryType SetExpiryType, o *Set return resp, err } -//// Upload uploads data to a file. -//func (f *Client) Upload(ctx context.Context) { -// -//} -// -//// Append appends data to a file. -//func (f *Client) Append(ctx context.Context) { -// -//} -// -//// Flush flushes previous uploaded data to a file. -//func (f *Client) Flush(ctx context.Context) { -// -//} -// -//// Download downloads data from a file. -//func (f *Client) Download(ctx context.Context) { -// -//} - // SetAccessControl sets the owner, owning group, and permissions for a file or directory (dfs1). func (f *Client) SetAccessControl(ctx context.Context, options *SetAccessControlOptions) (SetAccessControlResponse, error) { opts, lac, mac, err := path.FormatSetAccessControlOptions(options) @@ -360,3 +348,159 @@ func (f *Client) GetSASURL(permissions sas.FilePermissions, expiry time.Time, o return endpoint, nil } + +func (f *Client) AppendData(ctx context.Context, offset int64, body io.ReadSeekCloser, options *AppendDataOptions) (AppendDataResponse, error) { + appendDataOptions, leaseAccessConditions, httpsHeaders, cpkInfo, err := options.format(offset, body) + if err != nil { + return AppendDataResponse{}, err + } + + resp, err := f.generatedFileClientWithDFS().AppendData(ctx, body, appendDataOptions, httpsHeaders, leaseAccessConditions, cpkInfo) + return resp, exported.ConvertToDFSError(err) +} + +func (f *Client) FlushData(ctx context.Context, offset int64, options *FlushDataOptions) (FlushDataResponse, error) { + flushDataOpts, modifiedAccessConditions, leaseAccessConditions, httpHeaderOpts, cpkInfoOpts, err := options.format(offset) + if err != nil { + return FlushDataResponse{}, err + } + + resp, err := f.generatedFileClientWithDFS().FlushData(ctx, flushDataOpts, httpHeaderOpts, leaseAccessConditions, modifiedAccessConditions, cpkInfoOpts) + return resp, exported.ConvertToDFSError(err) +} + +// Concurrent Upload Functions ----------------------------------------------------------------------------------------- + +// uploadFromReader uploads a buffer in chunks to an Azure file. +func (f *Client) uploadFromReader(ctx context.Context, reader io.ReaderAt, actualSize int64, o *uploadFromReaderOptions) error { + if actualSize > MaxFileSize { + return errors.New("buffer is too large to upload to a file") + } + if o.ChunkSize == 0 { + o.ChunkSize = MaxUpdateRangeBytes + } + + if log.Should(exported.EventUpload) { + urlParts, err := azdatalake.ParseURL(f.DFSURL()) + if err == nil { + log.Writef(exported.EventUpload, "file name %s actual size %v chunk-size %v chunk-count %v", + urlParts.PathName, actualSize, o.ChunkSize, ((actualSize-1)/o.ChunkSize)+1) + } + } + + progress := int64(0) + progressLock := &sync.Mutex{} + + err := shared.DoBatchTransfer(ctx, &shared.BatchTransferOptions{ + OperationName: "uploadFromReader", + TransferSize: actualSize, + ChunkSize: o.ChunkSize, + Concurrency: o.Concurrency, + Operation: func(ctx context.Context, offset int64, chunkSize int64) error { + // This function is called once per file range. + // It is passed this file's offset within the buffer and its count of bytes + // Prepare to read the proper range/section of the buffer + if chunkSize < o.ChunkSize { + // this is the last file range. Its actual size might be less + // than the calculated size due to rounding up of the payload + // size to fit in a whole number of chunks. + chunkSize = actualSize - offset + } + var body io.ReadSeeker = io.NewSectionReader(reader, offset, chunkSize) + if o.Progress != nil { + chunkProgress := int64(0) + body = streaming.NewRequestProgress(streaming.NopCloser(body), + func(bytesTransferred int64) { + diff := bytesTransferred - chunkProgress + chunkProgress = bytesTransferred + progressLock.Lock() // 1 goroutine at a time gets progress report + progress += diff + o.Progress(progress) + progressLock.Unlock() + }) + } + + uploadRangeOptions := o.getAppendDataOptions() + _, err := f.AppendData(ctx, offset, streaming.NopCloser(body), uploadRangeOptions) + return exported.ConvertToDFSError(err) + }, + }) + + if err != nil { + return exported.ConvertToDFSError(err) + } + // All appends were successful, call to flush + flushOpts := o.getFlushDataOptions() + _, err = f.FlushData(ctx, actualSize, flushOpts) + return exported.ConvertToDFSError(err) +} + +// UploadBuffer uploads a buffer in chunks to an Azure file. +func (f *Client) UploadBuffer(ctx context.Context, buffer []byte, options *UploadBufferOptions) error { + uploadOptions := uploadFromReaderOptions{} + if options != nil { + uploadOptions = *options + } + return exported.ConvertToDFSError(f.uploadFromReader(ctx, bytes.NewReader(buffer), int64(len(buffer)), &uploadOptions)) +} + +// UploadFile uploads a file in chunks to an Azure file. +func (f *Client) UploadFile(ctx context.Context, file *os.File, options *UploadFileOptions) error { + stat, err := file.Stat() + if err != nil { + return err + } + uploadOptions := uploadFromReaderOptions{} + if options != nil { + uploadOptions = *options + } + return exported.ConvertToDFSError(f.uploadFromReader(ctx, file, stat.Size(), &uploadOptions)) +} + +// UploadStream copies the file held in io.Reader to the file at fileClient. +// A Context deadline or cancellation will cause this to error. +func (f *Client) UploadStream(ctx context.Context, body io.Reader, options *UploadStreamOptions) error { + if options == nil { + options = &UploadStreamOptions{} + } + + err := copyFromReader(ctx, body, f, *options, newMMBPool) + return exported.ConvertToDFSError(err) +} + +// DownloadStream reads a range of bytes from a blob. The response also includes the blob's properties and metadata. +// For more information, see https://docs.microsoft.com/rest/api/storageservices/get-blob. +func (f *Client) DownloadStream(ctx context.Context, o *DownloadStreamOptions) (DownloadStreamResponse, error) { + if o == nil { + o = &DownloadStreamOptions{} + } + opts := o.format() + resp, err := f.blobClient().DownloadStream(ctx, opts) + newResp := FormatDownloadStreamResponse(&resp) + fullResp := DownloadStreamResponse{ + client: f, + DownloadResponse: newResp, + getInfo: httpGetterInfo{Range: o.Range, ETag: newResp.ETag}, + cpkInfo: o.CPKInfo, + cpkScope: o.CPKScopeInfo, + } + + return fullResp, exported.ConvertToDFSError(err) +} + +// DownloadBuffer downloads an Azure blob to a buffer with parallel. +func (f *Client) DownloadBuffer(ctx context.Context, buffer []byte, o *DownloadBufferOptions) (int64, error) { + opts := o.format() + val, err := f.blobClient().DownloadBuffer(ctx, shared.NewBytesWriter(buffer), opts) + return val, exported.ConvertToDFSError(err) +} + +// DownloadFile downloads an Azure blob to a local file. +// The file would be truncated if the size doesn't match. +func (f *Client) DownloadFile(ctx context.Context, file *os.File, o *DownloadFileOptions) (int64, error) { + opts := o.format() + val, err := f.blobClient().DownloadFile(ctx, file, opts) + return val, exported.ConvertToDFSError(err) +} + +// TODO: add undelete diff --git a/sdk/storage/azdatalake/file/client_test.go b/sdk/storage/azdatalake/file/client_test.go index f9b2ccdacf71..09e50c55615c 100644 --- a/sdk/storage/azdatalake/file/client_test.go +++ b/sdk/storage/azdatalake/file/client_test.go @@ -7,16 +7,25 @@ package file_test import ( + "bytes" "context" + "crypto/md5" + "encoding/binary" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/streaming" "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/file" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/internal/shared" "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" + "hash/crc64" + "io" + "math/rand" "net/http" + "os" "testing" "time" ) @@ -2302,3 +2311,786 @@ func (s *RecordedTestSuite) TestRenameFileIfETagMatchFalse() { _require.NotNil(err) testcommon.ValidateErrorCode(_require, err, datalakeerror.SourceConditionNotMet) } + +func (s *RecordedTestSuite) TestFileUploadDownloadStream() { + _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) + + var fileSize int64 = 100 * 1024 * 1024 + fileName := testcommon.GenerateFileName(testName) + fClient, err := testcommon.GetFileClient(filesystemName, fileName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + resp, err := fClient.Create(context.Background(), nil) + _require.Nil(err) + _require.NotNil(resp) + + content := make([]byte, fileSize) + _, err = rand.Read(content) + _require.NoError(err) + md5Value := md5.Sum(content) + contentMD5 := md5Value[:] + + err = fClient.UploadStream(context.Background(), streaming.NopCloser(bytes.NewReader(content)), &file.UploadStreamOptions{ + Concurrency: 5, + ChunkSize: 4 * 1024 * 1024, + }) + _require.NoError(err) + + gResp2, err := fClient.GetProperties(context.Background(), nil) + _require.NoError(err) + _require.Equal(*gResp2.ContentLength, fileSize) + + dResp, err := fClient.DownloadStream(context.Background(), nil) + _require.NoError(err) + + data, err := io.ReadAll(dResp.Body) + _require.NoError(err) + + downloadedMD5Value := md5.Sum(data) + downloadedContentMD5 := downloadedMD5Value[:] + + _require.EqualValues(downloadedContentMD5, contentMD5) + +} + +func (s *RecordedTestSuite) TestFileUploadDownloadSmallStream() { + _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) + + var fileSize int64 = 10 * 1024 + fileName := testcommon.GenerateFileName(testName) + fClient, err := testcommon.GetFileClient(filesystemName, fileName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + resp, err := fClient.Create(context.Background(), nil) + _require.Nil(err) + _require.NotNil(resp) + + content := make([]byte, fileSize) + _, err = rand.Read(content) + _require.NoError(err) + md5Value := md5.Sum(content) + contentMD5 := md5Value[:] + + err = fClient.UploadStream(context.Background(), streaming.NopCloser(bytes.NewReader(content)), &file.UploadStreamOptions{ + Concurrency: 5, + ChunkSize: 2 * 1024, + }) + _require.NoError(err) + + gResp2, err := fClient.GetProperties(context.Background(), nil) + _require.NoError(err) + _require.Equal(*gResp2.ContentLength, fileSize) + + dResp, err := fClient.DownloadStream(context.Background(), nil) + _require.NoError(err) + + data, err := io.ReadAll(dResp.Body) + _require.NoError(err) + + downloadedMD5Value := md5.Sum(data) + downloadedContentMD5 := downloadedMD5Value[:] + + _require.EqualValues(downloadedContentMD5, contentMD5) +} + +func (s *RecordedTestSuite) TestFileUploadTinyStream() { + _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) + + var fileSize int64 = 4 + fileName := testcommon.GenerateFileName(testName) + fClient, err := testcommon.GetFileClient(filesystemName, fileName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + resp, err := fClient.Create(context.Background(), nil) + _require.Nil(err) + _require.NotNil(resp) + + content := make([]byte, fileSize) + _, err = rand.Read(content) + _require.NoError(err) + md5Value := md5.Sum(content) + contentMD5 := md5Value[:] + + err = fClient.UploadStream(context.Background(), streaming.NopCloser(bytes.NewReader(content)), &file.UploadStreamOptions{ + Concurrency: 5, + ChunkSize: 2 * 1024, + }) + _require.NoError(err) + + gResp2, err := fClient.GetProperties(context.Background(), nil) + _require.NoError(err) + _require.Equal(*gResp2.ContentLength, fileSize) + + dResp, err := fClient.DownloadStream(context.Background(), nil) + _require.NoError(err) + + data, err := io.ReadAll(dResp.Body) + _require.NoError(err) + + downloadedMD5Value := md5.Sum(data) + downloadedContentMD5 := downloadedMD5Value[:] + + _require.EqualValues(downloadedContentMD5, contentMD5) +} + +func (s *RecordedTestSuite) TestFileUploadFile() { + _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) + + var fileSize int64 = 100 * 1024 * 1024 + fileName := testcommon.GenerateFileName(testName) + fClient, err := testcommon.GetFileClient(filesystemName, fileName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + resp, err := fClient.Create(context.Background(), nil) + _require.Nil(err) + _require.NotNil(resp) + + // create local file + content := make([]byte, fileSize) + _, err = rand.Read(content) + _require.NoError(err) + err = os.WriteFile("testFile", content, 0644) + _require.NoError(err) + + defer func() { + err = os.Remove("testFile") + _require.NoError(err) + }() + + fh, err := os.Open("testFile") + _require.NoError(err) + + defer func(fh *os.File) { + err := fh.Close() + _require.NoError(err) + }(fh) + + hash := md5.New() + _, err = io.Copy(hash, fh) + _require.NoError(err) + contentMD5 := hash.Sum(nil) + + err = fClient.UploadFile(context.Background(), fh, &file.UploadFileOptions{ + Concurrency: 5, + ChunkSize: 4 * 1024 * 1024, + }) + _require.NoError(err) + + gResp2, err := fClient.GetProperties(context.Background(), nil) + _require.NoError(err) + _require.Equal(*gResp2.ContentLength, fileSize) + + dResp, err := fClient.DownloadStream(context.Background(), nil) + _require.NoError(err) + + data, err := io.ReadAll(dResp.Body) + _require.NoError(err) + + downloadedMD5Value := md5.Sum(data) + downloadedContentMD5 := downloadedMD5Value[:] + + _require.EqualValues(downloadedContentMD5, contentMD5) +} + +func (s *RecordedTestSuite) TestSmallFileUploadFile() { + _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) + + var fileSize int64 = 10 * 1024 + fileName := testcommon.GenerateFileName(testName) + fClient, err := testcommon.GetFileClient(filesystemName, fileName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + resp, err := fClient.Create(context.Background(), nil) + _require.Nil(err) + _require.NotNil(resp) + + // create local file + content := make([]byte, fileSize) + _, err = rand.Read(content) + _require.NoError(err) + err = os.WriteFile("testFile", content, 0644) + _require.NoError(err) + + defer func() { + err = os.Remove("testFile") + _require.NoError(err) + }() + + fh, err := os.Open("testFile") + _require.NoError(err) + + defer func(fh *os.File) { + err := fh.Close() + _require.NoError(err) + }(fh) + + hash := md5.New() + _, err = io.Copy(hash, fh) + _require.NoError(err) + contentMD5 := hash.Sum(nil) + + err = fClient.UploadFile(context.Background(), fh, &file.UploadFileOptions{ + Concurrency: 5, + ChunkSize: 2 * 1024, + }) + _require.NoError(err) + + gResp2, err := fClient.GetProperties(context.Background(), nil) + _require.NoError(err) + _require.Equal(*gResp2.ContentLength, fileSize) + + dResp, err := fClient.DownloadStream(context.Background(), nil) + _require.NoError(err) + + data, err := io.ReadAll(dResp.Body) + _require.NoError(err) + + downloadedMD5Value := md5.Sum(data) + downloadedContentMD5 := downloadedMD5Value[:] + + _require.EqualValues(downloadedContentMD5, contentMD5) +} + +func (s *RecordedTestSuite) TestTinyFileUploadFile() { + _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) + + var fileSize int64 = 10 + fileName := testcommon.GenerateFileName(testName) + fClient, err := testcommon.GetFileClient(filesystemName, fileName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + resp, err := fClient.Create(context.Background(), nil) + _require.Nil(err) + _require.NotNil(resp) + + // create local file + content := make([]byte, fileSize) + _, err = rand.Read(content) + _require.NoError(err) + err = os.WriteFile("testFile", content, 0644) + _require.NoError(err) + + defer func() { + err = os.Remove("testFile") + _require.NoError(err) + }() + + fh, err := os.Open("testFile") + _require.NoError(err) + + defer func(fh *os.File) { + err := fh.Close() + _require.NoError(err) + }(fh) + + hash := md5.New() + _, err = io.Copy(hash, fh) + _require.NoError(err) + contentMD5 := hash.Sum(nil) + + err = fClient.UploadFile(context.Background(), fh, &file.UploadFileOptions{ + ChunkSize: 2, + }) + _require.NoError(err) + + gResp2, err := fClient.GetProperties(context.Background(), nil) + _require.NoError(err) + _require.Equal(*gResp2.ContentLength, fileSize) + + dResp, err := fClient.DownloadStream(context.Background(), nil) + _require.NoError(err) + + data, err := io.ReadAll(dResp.Body) + _require.NoError(err) + + downloadedMD5Value := md5.Sum(data) + downloadedContentMD5 := downloadedMD5Value[:] + + _require.EqualValues(downloadedContentMD5, contentMD5) +} + +func (s *RecordedTestSuite) TestFileUploadBuffer() { + _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) + + var fileSize int64 = 100 * 1024 * 1024 + fileName := testcommon.GenerateFileName(testName) + fClient, err := testcommon.GetFileClient(filesystemName, fileName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + resp, err := fClient.Create(context.Background(), nil) + _require.Nil(err) + _require.NotNil(resp) + + content := make([]byte, fileSize) + _, err = rand.Read(content) + _require.NoError(err) + md5Value := md5.Sum(content) + contentMD5 := md5Value[:] + + err = fClient.UploadBuffer(context.Background(), content, &file.UploadBufferOptions{ + Concurrency: 5, + ChunkSize: 4 * 1024 * 1024, + }) + _require.NoError(err) + gResp2, err := fClient.GetProperties(context.Background(), nil) + _require.NoError(err) + _require.Equal(*gResp2.ContentLength, fileSize) + + dResp, err := fClient.DownloadStream(context.Background(), nil) + _require.NoError(err) + + data, err := io.ReadAll(dResp.Body) + _require.NoError(err) + + downloadedMD5Value := md5.Sum(data) + downloadedContentMD5 := downloadedMD5Value[:] + + _require.EqualValues(downloadedContentMD5, contentMD5) +} + +func (s *RecordedTestSuite) TestFileUploadSmallBuffer() { + _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) + + var fileSize int64 = 10 * 1024 + fileName := testcommon.GenerateFileName(testName) + fClient, err := testcommon.GetFileClient(filesystemName, fileName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + resp, err := fClient.Create(context.Background(), nil) + _require.Nil(err) + _require.NotNil(resp) + + content := make([]byte, fileSize) + _, err = rand.Read(content) + _require.NoError(err) + md5Value := md5.Sum(content) + contentMD5 := md5Value[:] + + err = fClient.UploadBuffer(context.Background(), content, &file.UploadBufferOptions{ + Concurrency: 5, + ChunkSize: 2 * 1024, + }) + _require.NoError(err) + gResp2, err := fClient.GetProperties(context.Background(), nil) + _require.NoError(err) + _require.Equal(*gResp2.ContentLength, fileSize) + + dResp, err := fClient.DownloadStream(context.Background(), nil) + _require.NoError(err) + + data, err := io.ReadAll(dResp.Body) + _require.NoError(err) + + downloadedMD5Value := md5.Sum(data) + downloadedContentMD5 := downloadedMD5Value[:] + + _require.EqualValues(downloadedContentMD5, contentMD5) +} + +func (s *RecordedTestSuite) TestFileAppendAndFlushData() { + _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) + + srcFileName := "src" + testcommon.GenerateFileName(testName) + + srcFClient, err := testcommon.GetFileClient(filesystemName, srcFileName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + resp, err := srcFClient.Create(context.Background(), nil) + _require.Nil(err) + _require.NotNil(resp) + + contentSize := 1024 * 8 // 8KB + rsc, _ := testcommon.GenerateData(contentSize) + + _, err = srcFClient.AppendData(context.Background(), 0, rsc, nil) + _require.NoError(err) + + _, err = srcFClient.FlushData(context.Background(), int64(contentSize), nil) + _require.NoError(err) + + gResp2, err := srcFClient.GetProperties(context.Background(), nil) + _require.NoError(err) + _require.Equal(*gResp2.ContentLength, int64(contentSize)) +} + +func (s *RecordedTestSuite) TestFileAppendAndFlushDataWithValidation() { + _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) + + srcFileName := "src" + testcommon.GenerateFileName(testName) + + srcFClient, err := testcommon.GetFileClient(filesystemName, srcFileName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + resp, err := srcFClient.Create(context.Background(), nil) + _require.Nil(err) + _require.NotNil(resp) + + contentSize := 1024 * 8 // 8KB + content := make([]byte, contentSize) + body := bytes.NewReader(content) + rsc := streaming.NopCloser(body) + contentCRC64 := crc64.Checksum(content, shared.CRC64Table) + + opts := &file.AppendDataOptions{ + TransactionalValidation: file.TransferValidationTypeComputeCRC64(), + } + putResp, err := srcFClient.AppendData(context.Background(), 0, rsc, opts) + _require.Nil(err) + // _require.Equal(putResp.RawResponse.StatusCode, 201) + _require.NotNil(putResp.ContentCRC64) + _require.EqualValues(binary.LittleEndian.Uint64(putResp.ContentCRC64), contentCRC64) + + _, err = srcFClient.FlushData(context.Background(), int64(contentSize), nil) + _require.NoError(err) + + gResp2, err := srcFClient.GetProperties(context.Background(), nil) + _require.NoError(err) + _require.Equal(*gResp2.ContentLength, int64(contentSize)) +} + +func (s *RecordedTestSuite) TestFileDownloadFile() { + _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) + + var fileSize int64 = 100 * 1024 * 1024 + fileName := testcommon.GenerateFileName(testName) + fClient, err := testcommon.GetFileClient(filesystemName, fileName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + resp, err := fClient.Create(context.Background(), nil) + _require.Nil(err) + _require.NotNil(resp) + + content := make([]byte, fileSize) + _, err = rand.Read(content) + _require.NoError(err) + md5Value := md5.Sum(content) + contentMD5 := md5Value[:] + + err = fClient.UploadBuffer(context.Background(), content, &file.UploadBufferOptions{ + Concurrency: 5, + ChunkSize: 4 * 1024 * 1024, + }) + _require.NoError(err) + + destFileName := "BigFile-downloaded.bin" + destFile, err := os.Create(destFileName) + _require.NoError(err) + defer func(name string) { + err = os.Remove(name) + _require.NoError(err) + }(destFileName) + defer func(destFile *os.File) { + err = destFile.Close() + _require.NoError(err) + }(destFile) + + cnt, err := fClient.DownloadFile(context.Background(), destFile, &file.DownloadFileOptions{ + ChunkSize: 10 * 1024 * 1024, + Concurrency: 5, + }) + _require.NoError(err) + _require.Equal(cnt, fileSize) + + hash := md5.New() + _, err = io.Copy(hash, destFile) + _require.NoError(err) + downloadedContentMD5 := hash.Sum(nil) + + _require.EqualValues(downloadedContentMD5, contentMD5) + + gResp2, err := fClient.GetProperties(context.Background(), nil) + _require.NoError(err) + _require.Equal(*gResp2.ContentLength, fileSize) +} + +func (s *RecordedTestSuite) TestFileUploadDownloadSmallFile() { + _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) + + var fileSize int64 = 10 * 1024 + fileName := testcommon.GenerateFileName(testName) + fClient, err := testcommon.GetFileClient(filesystemName, fileName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + resp, err := fClient.Create(context.Background(), nil) + _require.Nil(err) + _require.NotNil(resp) + + // create local file + _, content := testcommon.GenerateData(int(fileSize)) + srcFileName := "testFileUpload" + err = os.WriteFile(srcFileName, content, 0644) + _require.NoError(err) + defer func() { + err = os.Remove(srcFileName) + _require.NoError(err) + }() + fh, err := os.Open(srcFileName) + _require.NoError(err) + defer func(fh *os.File) { + err := fh.Close() + _require.NoError(err) + }(fh) + + srcHash := md5.New() + _, err = io.Copy(srcHash, fh) + _require.NoError(err) + contentMD5 := srcHash.Sum(nil) + + err = fClient.UploadFile(context.Background(), fh, &file.UploadFileOptions{ + Concurrency: 5, + ChunkSize: 2 * 1024, + }) + _require.NoError(err) + + destFileName := "SmallFile-downloaded.bin" + destFile, err := os.Create(destFileName) + _require.NoError(err) + defer func(name string) { + err = os.Remove(name) + _require.NoError(err) + }(destFileName) + defer func(destFile *os.File) { + err = destFile.Close() + _require.NoError(err) + }(destFile) + + cnt, err := fClient.DownloadFile(context.Background(), destFile, &file.DownloadFileOptions{ + ChunkSize: 2 * 1024, + Concurrency: 5, + }) + _require.NoError(err) + _require.Equal(cnt, fileSize) + + destHash := md5.New() + _, err = io.Copy(destHash, destFile) + _require.NoError(err) + downloadedContentMD5 := destHash.Sum(nil) + + _require.EqualValues(downloadedContentMD5, contentMD5) + + gResp2, err := fClient.GetProperties(context.Background(), nil) + _require.NoError(err) + _require.Equal(*gResp2.ContentLength, fileSize) +} + +func (s *RecordedTestSuite) TestFileUploadDownloadWithProgress() { + _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) + + var fileSize int64 = 10 * 1024 + fileName := testcommon.GenerateFileName(testName) + fClient, err := testcommon.GetFileClient(filesystemName, fileName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + resp, err := fClient.Create(context.Background(), nil) + _require.Nil(err) + _require.NotNil(resp) + + _, content := testcommon.GenerateData(int(fileSize)) + md5Value := md5.Sum(content) + contentMD5 := md5Value[:] + + bytesUploaded := int64(0) + err = fClient.UploadBuffer(context.Background(), content, &file.UploadBufferOptions{ + Concurrency: 5, + ChunkSize: 2 * 1024, + Progress: func(bytesTransferred int64) { + _require.GreaterOrEqual(bytesTransferred, bytesUploaded) + bytesUploaded = bytesTransferred + }, + }) + _require.NoError(err) + _require.Equal(bytesUploaded, fileSize) + + destBuffer := make([]byte, fileSize) + bytesDownloaded := int64(0) + cnt, err := fClient.DownloadBuffer(context.Background(), destBuffer, &file.DownloadBufferOptions{ + ChunkSize: 2 * 1024, + Concurrency: 5, + Progress: func(bytesTransferred int64) { + _require.GreaterOrEqual(bytesTransferred, bytesDownloaded) + bytesDownloaded = bytesTransferred + }, + }) + _require.NoError(err) + _require.Equal(cnt, fileSize) + _require.Equal(bytesDownloaded, fileSize) + + downloadedMD5Value := md5.Sum(destBuffer) + downloadedContentMD5 := downloadedMD5Value[:] + + _require.EqualValues(downloadedContentMD5, contentMD5) + + gResp2, err := fClient.GetProperties(context.Background(), nil) + _require.NoError(err) + _require.Equal(*gResp2.ContentLength, fileSize) +} + +func (s *RecordedTestSuite) TestFileDownloadBuffer() { + _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) + + var fileSize int64 = 100 * 1024 * 1024 + fileName := testcommon.GenerateFileName(testName) + fClient, err := testcommon.GetFileClient(filesystemName, fileName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + resp, err := fClient.Create(context.Background(), nil) + _require.Nil(err) + _require.NotNil(resp) + + content := make([]byte, fileSize) + _, err = rand.Read(content) + _require.NoError(err) + md5Value := md5.Sum(content) + contentMD5 := md5Value[:] + + err = fClient.UploadBuffer(context.Background(), content, &file.UploadBufferOptions{ + Concurrency: 5, + ChunkSize: 4 * 1024 * 1024, + }) + _require.NoError(err) + + destBuffer := make([]byte, fileSize) + cnt, err := fClient.DownloadBuffer(context.Background(), destBuffer, &file.DownloadBufferOptions{ + ChunkSize: 10 * 1024 * 1024, + Concurrency: 5, + }) + _require.NoError(err) + _require.Equal(cnt, fileSize) + + downloadedMD5Value := md5.Sum(destBuffer) + downloadedContentMD5 := downloadedMD5Value[:] + + _require.EqualValues(downloadedContentMD5, contentMD5) + + gResp2, err := fClient.GetProperties(context.Background(), nil) + _require.NoError(err) + _require.Equal(*gResp2.ContentLength, fileSize) +} + +// TODO tests all uploads/downloads with other opts diff --git a/sdk/storage/azdatalake/file/constants.go b/sdk/storage/azdatalake/file/constants.go index 2345c88d547b..7dd13f5de226 100644 --- a/sdk/storage/azdatalake/file/constants.go +++ b/sdk/storage/azdatalake/file/constants.go @@ -7,6 +7,7 @@ package file import ( + "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/internal/exported" "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/internal/path" ) @@ -36,3 +37,14 @@ const ( CopyStatusTypeAborted CopyStatusType = path.CopyStatusTypeAborted CopyStatusTypeFailed CopyStatusType = path.CopyStatusTypeFailed ) + +// TransferValidationType abstracts the various mechanisms used to verify a transfer. +type TransferValidationType = exported.TransferValidationType + +// TransferValidationTypeCRC64 is a TransferValidationType used to provide a precomputed crc64. +type TransferValidationTypeCRC64 = exported.TransferValidationTypeCRC64 + +// TransferValidationTypeComputeCRC64 is a TransferValidationType that indicates a CRC64 should be computed during transfer. +func TransferValidationTypeComputeCRC64() TransferValidationType { + return exported.TransferValidationTypeComputeCRC64() +} diff --git a/sdk/storage/azdatalake/file/mmf_unix.go b/sdk/storage/azdatalake/file/mmf_unix.go new file mode 100644 index 000000000000..4c8ed223dbae --- /dev/null +++ b/sdk/storage/azdatalake/file/mmf_unix.go @@ -0,0 +1,38 @@ +//go:build go1.18 && (linux || darwin || dragonfly || freebsd || openbsd || netbsd || solaris || aix) +// +build go1.18 +// +build linux darwin dragonfly freebsd openbsd netbsd solaris aix + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See License.txt in the project root for license information. + +package file + +import ( + "fmt" + "os" + "syscall" +) + +// mmb is a memory mapped buffer +type mmb []byte + +// newMMB creates a new memory mapped buffer with the specified size +func newMMB(size int64) (mmb, error) { + prot, flags := syscall.PROT_READ|syscall.PROT_WRITE, syscall.MAP_ANON|syscall.MAP_PRIVATE + addr, err := syscall.Mmap(-1, 0, int(size), prot, flags) + if err != nil { + return nil, os.NewSyscallError("Mmap", err) + } + return mmb(addr), nil +} + +// delete cleans up the memory mapped buffer +func (m *mmb) delete() { + err := syscall.Munmap(*m) + *m = nil + if err != nil { + // if we get here, there is likely memory corruption. + // please open an issue https://github.com/Azure/azure-sdk-for-go/issues + panic(fmt.Sprintf("Munmap error: %v", err)) + } +} diff --git a/sdk/storage/azdatalake/file/mmf_windows.go b/sdk/storage/azdatalake/file/mmf_windows.go new file mode 100644 index 000000000000..b59e6b415776 --- /dev/null +++ b/sdk/storage/azdatalake/file/mmf_windows.go @@ -0,0 +1,56 @@ +//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 file + +import ( + "fmt" + "os" + "reflect" + "syscall" + "unsafe" +) + +// mmb is a memory mapped buffer +type mmb []byte + +// newMMB creates a new memory mapped buffer with the specified size +func newMMB(size int64) (mmb, error) { + const InvalidHandleValue = ^uintptr(0) // -1 + + prot, access := uint32(syscall.PAGE_READWRITE), uint32(syscall.FILE_MAP_WRITE) + hMMF, err := syscall.CreateFileMapping(syscall.Handle(InvalidHandleValue), nil, prot, uint32(size>>32), uint32(size&0xffffffff), nil) + if err != nil { + return nil, os.NewSyscallError("CreateFileMapping", err) + } + defer func() { + _ = syscall.CloseHandle(hMMF) + }() + + addr, err := syscall.MapViewOfFile(hMMF, access, 0, 0, uintptr(size)) + if err != nil { + return nil, os.NewSyscallError("MapViewOfFile", err) + } + + m := mmb{} + h := (*reflect.SliceHeader)(unsafe.Pointer(&m)) + h.Data = addr + h.Len = int(size) + h.Cap = h.Len + return m, nil +} + +// delete cleans up the memory mapped buffer +func (m *mmb) delete() { + addr := uintptr(unsafe.Pointer(&(([]byte)(*m)[0]))) + *m = mmb{} + err := syscall.UnmapViewOfFile(addr) + if err != nil { + // if we get here, there is likely memory corruption. + // please open an issue https://github.com/Azure/azure-sdk-for-go/issues + panic(fmt.Sprintf("UnmapViewOfFile error: %v", err)) + } +} diff --git a/sdk/storage/azdatalake/file/models.go b/sdk/storage/azdatalake/file/models.go index a4f8b994ff1d..1f628860bded 100644 --- a/sdk/storage/azdatalake/file/models.go +++ b/sdk/storage/azdatalake/file/models.go @@ -7,15 +7,33 @@ package file import ( + "errors" "github.com/Azure/azure-sdk-for-go/sdk/azcore/to" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/blob" "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" + "io" "net/http" "strconv" "time" ) +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 + + // 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. type CreateOptions struct { // AccessConditions contains parameters for accessing the file. @@ -167,6 +185,401 @@ func (o *RemoveAccessControlOptions) format(ACL string) (*generated.PathClientSe }, mode } +type HTTPRange = exported.HTTPRange + +// 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 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. + Progress func(bytesTransferred int64) + // Concurrency indicates the maximum number of chunks to upload in parallel (default is 5) + Concurrency uint16 + // AccessConditions contains optional parameters to access leased entity. + AccessConditions *AccessConditions + // HTTPHeaders contains the optional path HTTP headers to set when the file is created. + HTTPHeaders *HTTPHeaders + // CPKInfo contains optional parameters to perform encryption using customer-provided key. + CPKInfo *CPKInfo +} + +// 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 int64 + // Concurrency indicates the maximum number of chunks to upload in parallel (default is 5) + Concurrency uint16 + // AccessConditions contains optional parameters to access leased entity. + AccessConditions *AccessConditions + // HTTPHeaders contains the optional path HTTP headers to set when the file is created. + HTTPHeaders *HTTPHeaders + // CPKInfo contains optional parameters to perform encryption using customer-provided key. + CPKInfo *CPKInfo +} + +// UploadBufferOptions provides set of configurations for Client.UploadBuffer operation. +type UploadBufferOptions = uploadFromReaderOptions + +// UploadFileOptions provides set of configurations for Client.UploadFile operation. +type UploadFileOptions = uploadFromReaderOptions + +// FlushDataOptions contains the optional parameters for the Client.FlushData method. +type FlushDataOptions struct { + AccessConditions *AccessConditions + // HTTPHeaders contains the optional path HTTP headers to set when the file is created. + // CPKInfo contains optional parameters to perform encryption using customer-provided key. + CPKInfo *CPKInfo + HTTPHeaders *HTTPHeaders + Close *bool + RetainUncommittedData *bool +} + +func (o *FlushDataOptions) format(offset int64) (*generated.PathClientFlushDataOptions, *generated.ModifiedAccessConditions, *generated.LeaseAccessConditions, *generated.PathHTTPHeaders, *generated.CPKInfo, error) { + defaultRetainUncommitted := false + defaultClose := false + contentLength := int64(0) + + var httpHeaderOpts *generated.PathHTTPHeaders + var leaseAccessConditions *generated.LeaseAccessConditions + var modifiedAccessConditions *generated.ModifiedAccessConditions + var cpkInfoOpts *generated.CPKInfo + flushDataOpts := &generated.PathClientFlushDataOptions{ContentLength: &contentLength, Position: &offset} + + if o == nil { + flushDataOpts.RetainUncommittedData = &defaultRetainUncommitted + flushDataOpts.Close = &defaultClose + return flushDataOpts, nil, nil, nil, nil, nil + } + + if o != nil { + if o.RetainUncommittedData == nil { + flushDataOpts.RetainUncommittedData = &defaultRetainUncommitted + } else { + flushDataOpts.RetainUncommittedData = o.RetainUncommittedData + } + if o.Close == nil { + flushDataOpts.Close = &defaultClose + } else { + flushDataOpts.Close = o.Close + } + leaseAccessConditions, modifiedAccessConditions = exported.FormatPathAccessConditions(o.AccessConditions) + if o.HTTPHeaders != nil { + httpHeaderOpts := generated.PathHTTPHeaders{} + httpHeaderOpts.ContentMD5 = o.HTTPHeaders.ContentMD5 + httpHeaderOpts.ContentType = o.HTTPHeaders.ContentType + httpHeaderOpts.CacheControl = o.HTTPHeaders.CacheControl + httpHeaderOpts.ContentDisposition = o.HTTPHeaders.ContentDisposition + httpHeaderOpts.ContentEncoding = o.HTTPHeaders.ContentEncoding + } + if o.CPKInfo != nil { + cpkInfoOpts := generated.CPKInfo{} + cpkInfoOpts.EncryptionKey = o.CPKInfo.EncryptionKey + cpkInfoOpts.EncryptionKeySHA256 = o.CPKInfo.EncryptionKeySHA256 + cpkInfoOpts.EncryptionAlgorithm = o.CPKInfo.EncryptionAlgorithm + } + } + return flushDataOpts, modifiedAccessConditions, leaseAccessConditions, httpHeaderOpts, cpkInfoOpts, nil +} + +// AppendDataOptions contains the optional parameters for the Client.UploadRange method. +type AppendDataOptions struct { + // TransactionalValidation specifies the transfer validation type to use. + // The default is nil (no transfer validation). + TransactionalValidation TransferValidationType + // LeaseAccessConditions contains optional parameters to access leased entity. + LeaseAccessConditions *LeaseAccessConditions + // HTTPHeaders contains the optional path HTTP headers to set when the file is created. + HTTPHeaders *HTTPHeaders + // CPKInfo contains optional parameters to perform encryption using customer-provided key. + CPKInfo *CPKInfo +} + +func (o *AppendDataOptions) format(offset int64, body io.ReadSeekCloser) (*generated.PathClientAppendDataOptions, *generated.LeaseAccessConditions, *generated.PathHTTPHeaders, *generated.CPKInfo, error) { + if offset < 0 || body == nil { + return nil, nil, nil, nil, errors.New("invalid argument: offset must be >= 0 and body must not be nil") + } + + count, err := shared.ValidateSeekableStreamAt0AndGetCount(body) + if err != nil { + return nil, nil, nil, nil, err + } + + if count == 0 { + return nil, nil, nil, nil, errors.New("invalid argument: body must contain readable data whose size is > 0") + } + + appendDataOptions := &generated.PathClientAppendDataOptions{} + httpRange := exported.FormatHTTPRange(HTTPRange{ + Offset: offset, + Count: count, + }) + if httpRange != nil { + appendDataOptions.Position = &offset + appendDataOptions.ContentLength = &count + } + + var leaseAccessConditions *LeaseAccessConditions + var httpHeaderOpts *generated.PathHTTPHeaders + var cpkInfoOpts *generated.CPKInfo + + if o != nil { + leaseAccessConditions = o.LeaseAccessConditions + if o.HTTPHeaders != nil { + httpHeaderOpts := generated.PathHTTPHeaders{} + httpHeaderOpts.ContentMD5 = o.HTTPHeaders.ContentMD5 + httpHeaderOpts.ContentType = o.HTTPHeaders.ContentType + httpHeaderOpts.CacheControl = o.HTTPHeaders.CacheControl + httpHeaderOpts.ContentDisposition = o.HTTPHeaders.ContentDisposition + httpHeaderOpts.ContentEncoding = o.HTTPHeaders.ContentEncoding + } + if o.CPKInfo != nil { + cpkInfoOpts := generated.CPKInfo{} + cpkInfoOpts.EncryptionKey = o.CPKInfo.EncryptionKey + cpkInfoOpts.EncryptionKeySHA256 = o.CPKInfo.EncryptionKeySHA256 + cpkInfoOpts.EncryptionAlgorithm = o.CPKInfo.EncryptionAlgorithm + } + } + if o != nil && o.TransactionalValidation != nil { + _, err = o.TransactionalValidation.Apply(body, appendDataOptions) + if err != nil { + return nil, nil, nil, nil, err + } + } + + return appendDataOptions, leaseAccessConditions, httpHeaderOpts, cpkInfoOpts, nil +} + +func (u *UploadStreamOptions) setDefaults() { + if u.Concurrency == 0 { + u.Concurrency = 1 + } + + if u.ChunkSize < _1MiB { + u.ChunkSize = _1MiB + } +} + +func (u *uploadFromReaderOptions) getAppendDataOptions() *AppendDataOptions { + if u == nil { + return nil + } + leaseAccessConditions, _ := exported.FormatPathAccessConditions(u.AccessConditions) + return &AppendDataOptions{ + LeaseAccessConditions: leaseAccessConditions, + HTTPHeaders: u.HTTPHeaders, + CPKInfo: u.CPKInfo, + } +} + +func (u *uploadFromReaderOptions) getFlushDataOptions() *FlushDataOptions { + if u == nil { + return nil + } + return &FlushDataOptions{ + AccessConditions: u.AccessConditions, + HTTPHeaders: u.HTTPHeaders, + CPKInfo: u.CPKInfo, + } +} + +func (u *UploadStreamOptions) getAppendDataOptions() *AppendDataOptions { + if u == nil { + return nil + } + leaseAccessConditions, _ := exported.FormatPathAccessConditions(u.AccessConditions) + return &AppendDataOptions{ + LeaseAccessConditions: leaseAccessConditions, + HTTPHeaders: u.HTTPHeaders, + CPKInfo: u.CPKInfo, + } +} + +func (u *UploadStreamOptions) getFlushDataOptions() *FlushDataOptions { + if u == nil { + return nil + } + return &FlushDataOptions{ + AccessConditions: u.AccessConditions, + HTTPHeaders: u.HTTPHeaders, + CPKInfo: u.CPKInfo, + } +} + +// DownloadStreamOptions contains the optional parameters for the Client.Download method. +type DownloadStreamOptions struct { + // When set to true and specified together with the Range, the service returns the MD5 hash for the range, as long as the + // range is less than or equal to 4 MB in size. + RangeGetContentMD5 *bool + + // Range specifies a range of bytes. The default value is all bytes. + Range *HTTPRange + + AccessConditions *AccessConditions + CPKInfo *CPKInfo + CPKScopeInfo *CPKScopeInfo +} + +func (o *DownloadStreamOptions) format() *blob.DownloadStreamOptions { + if o == nil { + return nil + } + + downloadStreamOptions := &blob.DownloadStreamOptions{} + if o.Range != nil { + downloadStreamOptions.Range = blob.HTTPRange{ + Offset: o.Range.Offset, + Count: o.Range.Count, + } + } + if o.CPKInfo != nil { + downloadStreamOptions.CPKInfo = &blob.CPKInfo{ + EncryptionKey: o.CPKInfo.EncryptionKey, + EncryptionKeySHA256: o.CPKInfo.EncryptionKeySHA256, + EncryptionAlgorithm: (*blob.EncryptionAlgorithmType)(o.CPKInfo.EncryptionAlgorithm), + } + } + + downloadStreamOptions.RangeGetContentMD5 = o.RangeGetContentMD5 + downloadStreamOptions.AccessConditions = exported.FormatBlobAccessConditions(o.AccessConditions) + downloadStreamOptions.CPKScopeInfo = (*blob.CPKScopeInfo)(o.CPKScopeInfo) + return downloadStreamOptions +} + +// DownloadBufferOptions contains the optional parameters for the DownloadBuffer method. +type DownloadBufferOptions struct { + // Range specifies a range of bytes. The default value is all bytes. + Range *HTTPRange + + // ChunkSize specifies the block size to use for each parallel download; the default size is DefaultDownloadBlockSize. + ChunkSize int64 + + // Progress is a function that is invoked periodically as bytes are received. + Progress func(bytesTransferred int64) + + // BlobAccessConditions indicates the access conditions used when making HTTP GET requests against the blob. + AccessConditions *AccessConditions + + // CPKInfo contains a group of parameters for client provided encryption key. + CPKInfo *CPKInfo + + // CPKScopeInfo contains a group of parameters for client provided encryption scope. + CPKScopeInfo *CPKScopeInfo + + // Concurrency indicates the maximum number of blocks to download in parallel (0=default). + Concurrency uint16 + + // RetryReaderOptionsPerChunk is used when downloading each block. + RetryReaderOptionsPerChunk *RetryReaderOptions +} + +func (o *DownloadBufferOptions) format() *blob.DownloadBufferOptions { + if o == nil { + return nil + } + + downloadBufferOptions := &blob.DownloadBufferOptions{} + if o.Range != nil { + downloadBufferOptions.Range = blob.HTTPRange{ + Offset: o.Range.Offset, + Count: o.Range.Count, + } + } + if o.CPKInfo != nil { + downloadBufferOptions.CPKInfo = &blob.CPKInfo{ + EncryptionKey: o.CPKInfo.EncryptionKey, + EncryptionKeySHA256: o.CPKInfo.EncryptionKeySHA256, + EncryptionAlgorithm: (*blob.EncryptionAlgorithmType)(o.CPKInfo.EncryptionAlgorithm), + } + } + + downloadBufferOptions.AccessConditions = exported.FormatBlobAccessConditions(o.AccessConditions) + downloadBufferOptions.CPKScopeInfo = (*blob.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.EarlyCloseAsError = o.RetryReaderOptionsPerChunk.EarlyCloseAsError + downloadBufferOptions.RetryReaderOptionsPerBlock.MaxRetries = o.RetryReaderOptionsPerChunk.MaxRetries + } + + return downloadBufferOptions +} + +// DownloadFileOptions contains the optional parameters for the Client.DownloadFile method. +type DownloadFileOptions struct { + // Range specifies a range of bytes. The default value is all bytes. + Range *HTTPRange + + // ChunkSize specifies the block size to use for each parallel download; the default size is DefaultDownloadBlockSize. + ChunkSize int64 + + // Progress is a function that is invoked periodically as bytes are received. + Progress func(bytesTransferred int64) + + // BlobAccessConditions indicates the access conditions used when making HTTP GET requests against the blob. + AccessConditions *AccessConditions + + // ClientProvidedKeyOptions indicates the client provided key by name and/or by value to encrypt/decrypt data. + CPKInfo *CPKInfo + CPKScopeInfo *CPKScopeInfo + + // Concurrency indicates the maximum number of blocks to download in parallel. The default value is 5. + Concurrency uint16 + + // RetryReaderOptionsPerChunk is used when downloading each block. + RetryReaderOptionsPerChunk *RetryReaderOptions +} + +func (o *DownloadFileOptions) format() *blob.DownloadFileOptions { + if o == nil { + return nil + } + + downloadFileOptions := &blob.DownloadFileOptions{} + if o.Range != nil { + downloadFileOptions.Range = blob.HTTPRange{ + Offset: o.Range.Offset, + Count: o.Range.Count, + } + } + if o.CPKInfo != nil { + downloadFileOptions.CPKInfo = &blob.CPKInfo{ + EncryptionKey: o.CPKInfo.EncryptionKey, + EncryptionKeySHA256: o.CPKInfo.EncryptionKeySHA256, + EncryptionAlgorithm: (*blob.EncryptionAlgorithmType)(o.CPKInfo.EncryptionAlgorithm), + } + } + + downloadFileOptions.AccessConditions = exported.FormatBlobAccessConditions(o.AccessConditions) + downloadFileOptions.CPKScopeInfo = (*blob.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.EarlyCloseAsError = o.RetryReaderOptionsPerChunk.EarlyCloseAsError + downloadFileOptions.RetryReaderOptionsPerBlock.MaxRetries = o.RetryReaderOptionsPerChunk.MaxRetries + } + + return downloadFileOptions +} + // CreationExpiryType defines values for Create() ExpiryType type CreationExpiryType interface { Format() (generated.ExpiryOptions, *string) diff --git a/sdk/storage/azdatalake/file/responses.go b/sdk/storage/azdatalake/file/responses.go index 3116edab7355..a518ee58f376 100644 --- a/sdk/storage/azdatalake/file/responses.go +++ b/sdk/storage/azdatalake/file/responses.go @@ -7,8 +7,14 @@ package file import ( + "context" + "github.com/Azure/azure-sdk-for-go/sdk/azcore" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/blob" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake" "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/internal/generated" "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/internal/path" + "io" + "time" ) // SetExpiryResponse contains the response fields for the SetExpiry operation. @@ -26,12 +32,229 @@ type UpdateAccessControlResponse = generated.PathClientSetAccessControlRecursive // RemoveAccessControlResponse contains the response fields for the RemoveAccessControlRecursive operation. type RemoveAccessControlResponse = generated.PathClientSetAccessControlRecursiveResponse +// AppendDataResponse contains the response from method Client.AppendData. +type AppendDataResponse = generated.PathClientAppendDataResponse + +// FlushDataResponse contains the response from method Client.FlushData. +type FlushDataResponse = generated.PathClientFlushDataResponse + // RenameResponse contains the response fields for the Create operation. type RenameResponse struct { Response generated.PathClientCreateResponse NewFileClient *Client } +// DownloadStreamResponse contains the response from the DownloadStream method. +// To read from the stream, read from the Body field, or call the NewRetryReader method. +type DownloadStreamResponse struct { + DownloadResponse + client *Client + getInfo httpGetterInfo + cpkInfo *CPKInfo + cpkScope *CPKScopeInfo +} + +// NewRetryReader constructs new RetryReader stream for reading data. If a connection fails while +// reading, it will make additional requests to reestablish a connection and continue reading. +// Pass nil for options to accept the default options. +// Callers of this method should not access the DownloadStreamResponse.Body field. +func (r *DownloadStreamResponse) NewRetryReader(ctx context.Context, options *RetryReaderOptions) *RetryReader { + if options == nil { + options = &RetryReaderOptions{} + } + + return newRetryReader(ctx, r.Body, r.getInfo, func(ctx context.Context, getInfo httpGetterInfo) (io.ReadCloser, error) { + accessConditions := &AccessConditions{ + ModifiedAccessConditions: &ModifiedAccessConditions{IfMatch: getInfo.ETag}, + } + options := DownloadStreamOptions{ + Range: getInfo.Range, + AccessConditions: accessConditions, + CPKInfo: r.cpkInfo, + CPKScopeInfo: r.cpkScope, + } + resp, err := r.client.DownloadStream(ctx, &options) + if err != nil { + return nil, err + } + return resp.Body, err + }, *options) +} + +// DownloadResponse contains the response fields for the GetProperties operation. +type DownloadResponse struct { + // AcceptRanges contains the information returned from the Accept-Ranges header response. + AcceptRanges *string + + // Body contains the streaming response. + Body io.ReadCloser + + // CacheControl contains the information returned from the Cache-Control header response. + CacheControl *string + + // ClientRequestID contains the information returned from the x-ms-client-request-id header response. + ClientRequestID *string + + // ContentCRC64 contains the information returned from the x-ms-content-crc64 header response. + ContentCRC64 []byte + + // ContentDisposition contains the information returned from the Content-Disposition header response. + ContentDisposition *string + + // ContentEncoding contains the information returned from the Content-Encoding header response. + ContentEncoding *string + + // ContentLanguage contains the information returned from the Content-Language header response. + ContentLanguage *string + + // ContentLength contains the information returned from the Content-Length header response. + ContentLength *int64 + + // ContentMD5 contains the information returned from the Content-MD5 header response. + ContentMD5 []byte + + // ContentRange contains the information returned from the Content-Range header response. + ContentRange *string + + // ContentType contains the information returned from the Content-Type header response. + ContentType *string + + // CopyCompletionTime contains the information returned from the x-ms-copy-completion-time header response. + CopyCompletionTime *time.Time + + // CopyID contains the information returned from the x-ms-copy-id header response. + CopyID *string + + // CopyProgress contains the information returned from the x-ms-copy-progress header response. + CopyProgress *string + + // CopySource contains the information returned from the x-ms-copy-source header response. + CopySource *string + + // CopyStatus contains the information returned from the x-ms-copy-status header response. + CopyStatus *CopyStatusType + + // CopyStatusDescription contains the information returned from the x-ms-copy-status-description header response. + CopyStatusDescription *string + + // Date contains the information returned from the Date header response. + Date *time.Time + + // ETag contains the information returned from the ETag header response. + ETag *azcore.ETag + + // EncryptionKeySHA256 contains the information returned from the x-ms-encryption-key-sha256 header response. + EncryptionKeySHA256 *string + + // EncryptionScope contains the information returned from the x-ms-encryption-scope header response. + EncryptionScope *string + + // ErrorCode contains the information returned from the x-ms-error-code header response. + ErrorCode *string + + // ImmutabilityPolicyExpiresOn contains the information returned from the x-ms-immutability-policy-until-date header response. + ImmutabilityPolicyExpiresOn *time.Time + + // ImmutabilityPolicyMode contains the information returned from the x-ms-immutability-policy-mode header response. + ImmutabilityPolicyMode *ImmutabilityPolicyMode + + // IsCurrentVersion contains the information returned from the x-ms-is-current-version header response. + IsCurrentVersion *bool + + // IsSealed contains the information returned from the x-ms-blob-sealed header response. + IsSealed *bool + + // IsServerEncrypted contains the information returned from the x-ms-server-encrypted header response. + IsServerEncrypted *bool + + // LastAccessed contains the information returned from the x-ms-last-access-time header response. + LastAccessed *time.Time + + // LastModified contains the information returned from the Last-Modified header response. + LastModified *time.Time + + // LeaseDuration contains the information returned from the x-ms-lease-duration header response. + LeaseDuration *azdatalake.DurationType + + // LeaseState contains the information returned from the x-ms-lease-state header response. + LeaseState *azdatalake.StateType + + // LeaseStatus contains the information returned from the x-ms-lease-status header response. + LeaseStatus *azdatalake.StatusType + + // LegalHold contains the information returned from the x-ms-legal-hold header response. + LegalHold *bool + + // Metadata contains the information returned from the x-ms-meta header response. + Metadata map[string]*string + + // ObjectReplicationPolicyID contains the information returned from the x-ms-or-policy-id header response. + ObjectReplicationPolicyID *string + + // ObjectReplicationRules contains the information returned from the x-ms-or header response. + ObjectReplicationRules map[string]*string + + // RequestID contains the information returned from the x-ms-request-id header response. + RequestID *string + + // TagCount contains the information returned from the x-ms-tag-count header response. + TagCount *int64 + + // Version contains the information returned from the x-ms-version header response. + Version *string + + // VersionID contains the information returned from the x-ms-version-id header response. + VersionID *string +} + +func FormatDownloadStreamResponse(r *blob.DownloadStreamResponse) DownloadResponse { + newResp := DownloadResponse{} + if r != nil { + newResp.AcceptRanges = r.AcceptRanges + newResp.Body = r.Body + newResp.ContentCRC64 = r.ContentCRC64 + newResp.ContentRange = r.ContentRange + newResp.CacheControl = r.CacheControl + newResp.ErrorCode = r.ErrorCode + newResp.ClientRequestID = r.ClientRequestID + newResp.ContentDisposition = r.ContentDisposition + newResp.ContentEncoding = r.ContentEncoding + newResp.ContentLanguage = r.ContentLanguage + newResp.ContentLength = r.ContentLength + newResp.ContentMD5 = r.ContentMD5 + newResp.ContentType = r.ContentType + newResp.CopyCompletionTime = r.CopyCompletionTime + newResp.CopyID = r.CopyID + newResp.CopyProgress = r.CopyProgress + newResp.CopySource = r.CopySource + newResp.CopyStatus = r.CopyStatus + newResp.CopyStatusDescription = r.CopyStatusDescription + newResp.Date = r.Date + newResp.ETag = r.ETag + newResp.EncryptionKeySHA256 = r.EncryptionKeySHA256 + newResp.EncryptionScope = r.EncryptionScope + newResp.ImmutabilityPolicyExpiresOn = r.ImmutabilityPolicyExpiresOn + newResp.ImmutabilityPolicyMode = r.ImmutabilityPolicyMode + newResp.IsCurrentVersion = r.IsCurrentVersion + newResp.IsSealed = r.IsSealed + newResp.IsServerEncrypted = r.IsServerEncrypted + newResp.LastAccessed = r.LastAccessed + newResp.LastModified = r.LastModified + newResp.LeaseDuration = r.LeaseDuration + newResp.LeaseState = r.LeaseState + newResp.LeaseStatus = r.LeaseStatus + newResp.LegalHold = r.LegalHold + newResp.Metadata = r.Metadata + newResp.ObjectReplicationPolicyID = r.ObjectReplicationPolicyID + newResp.ObjectReplicationRules = r.DownloadResponse.ObjectReplicationRules + newResp.RequestID = r.RequestID + newResp.TagCount = r.TagCount + newResp.Version = r.Version + newResp.VersionID = r.VersionID + } + return newResp +} + // ========================================== path imports =========================================================== // SetAccessControlResponse contains the response fields for the SetAccessControl operation. diff --git a/sdk/storage/azdatalake/file/retry_reader.go b/sdk/storage/azdatalake/file/retry_reader.go new file mode 100644 index 000000000000..66e3f35edf0d --- /dev/null +++ b/sdk/storage/azdatalake/file/retry_reader.go @@ -0,0 +1,191 @@ +//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 file + +import ( + "context" + "github.com/Azure/azure-sdk-for-go/sdk/azcore" + "io" + "net" + "strings" + "sync" +) + +// HTTPGetter is a function type that refers to a method that performs an HTTP GET operation. +type httpGetter func(ctx context.Context, i httpGetterInfo) (io.ReadCloser, error) + +// HTTPGetterInfo is passed to an HTTPGetter function passing it parameters +// that should be used to make an HTTP GET request. +type httpGetterInfo struct { + Range *HTTPRange + + // ETag specifies the resource's etag that should be used when creating + // the HTTP GET request's If-Match header + ETag *azcore.ETag +} + +// RetryReaderOptions configures the retry reader's behavior. +// Zero-value fields will have their specified default values applied during use. +// This allows for modification of a subset of fields. +type RetryReaderOptions struct { + // MaxRetries specifies the maximum number of attempts a failed read will be retried + // before producing an error. + // The default value is three. + MaxRetries int32 + + // OnFailedRead, when non-nil, is called after any failure to read. Expected usage is diagnostic logging. + OnFailedRead func(failureCount int32, lastError error, rnge HTTPRange, willRetry bool) + + // EarlyCloseAsError can be set to true to prevent retries after "read on closed response body". By default, + // retryReader has the following special behaviour: closing the response body before it is all read is treated as a + // retryable error. This is to allow callers to force a retry by closing the body from another goroutine (e.g. if the = + // read is too slow, caller may want to force a retry in the hope that the retry will be quicker). If + // TreatEarlyCloseAsError is true, then retryReader's special behaviour is suppressed, and "read on closed body" is instead + // treated as a fatal (non-retryable) error. + // Note that setting TreatEarlyCloseAsError only guarantees that Closing will produce a fatal error if the Close happens + // from the same "thread" (goroutine) as Read. Concurrent Close calls from other goroutines may instead produce network errors + // which will be retried. + // The default value is false. + EarlyCloseAsError bool + + doInjectError bool + doInjectErrorRound int32 + injectedError error +} + +// RetryReader attempts to read from response, and if there is a retry-able network error +// returned during reading, it will retry according to retry reader option through executing +// user defined action with provided data to get a new response, and continue the overall reading process +// through reading from the new response. +// RetryReader implements the io.ReadCloser interface. +type RetryReader struct { + ctx context.Context + info httpGetterInfo + retryReaderOptions RetryReaderOptions + getter httpGetter + countWasBounded bool + + // we support Close-ing during Reads (from other goroutines), so we protect the shared state, which is response + responseMu *sync.Mutex + response io.ReadCloser +} + +// newRetryReader creates a retry reader. +func newRetryReader(ctx context.Context, initialResponse io.ReadCloser, info httpGetterInfo, getter httpGetter, o RetryReaderOptions) *RetryReader { + if o.MaxRetries < 1 { + o.MaxRetries = 3 + } + return &RetryReader{ + ctx: ctx, + getter: getter, + info: info, + countWasBounded: info.Range.Count != CountToEnd, + response: initialResponse, + responseMu: &sync.Mutex{}, + retryReaderOptions: o, + } +} + +// setResponse function +func (s *RetryReader) setResponse(r io.ReadCloser) { + s.responseMu.Lock() + defer s.responseMu.Unlock() + s.response = r +} + +// Read from retry reader +func (s *RetryReader) Read(p []byte) (n int, err error) { + for try := int32(0); ; try++ { + //fmt.Println(try) // Comment out for debugging. + if s.countWasBounded && s.info.Range.Count == CountToEnd { + // User specified an original count and the remaining bytes are 0, return 0, EOF + return 0, io.EOF + } + + s.responseMu.Lock() + resp := s.response + s.responseMu.Unlock() + if resp == nil { // We don't have a response stream to read from, try to get one. + newResponse, err := s.getter(s.ctx, s.info) + if err != nil { + return 0, err + } + // Successful GET; this is the network stream we'll read from. + s.setResponse(newResponse) + resp = newResponse + } + n, err := resp.Read(p) // Read from the stream (this will return non-nil err if forceRetry is called, from another goroutine, while it is running) + + // Injection mechanism for testing. + if s.retryReaderOptions.doInjectError && try == s.retryReaderOptions.doInjectErrorRound { + if s.retryReaderOptions.injectedError != nil { + err = s.retryReaderOptions.injectedError + } else { + err = &net.DNSError{IsTemporary: true} + } + } + + // We successfully read data or end EOF. + if err == nil || err == io.EOF { + s.info.Range.Offset += int64(n) // Increments the start offset in case we need to make a new HTTP request in the future + if s.info.Range.Count != CountToEnd { + s.info.Range.Count -= int64(n) // Decrement the count in case we need to make a new HTTP request in the future + } + return n, err // Return the return to the caller + } + _ = s.Close() + + s.setResponse(nil) // Our stream is no longer good + + // Check the retry count and error code, and decide whether to retry. + retriesExhausted := try >= s.retryReaderOptions.MaxRetries + _, isNetError := err.(net.Error) + isUnexpectedEOF := err == io.ErrUnexpectedEOF + willRetry := (isNetError || isUnexpectedEOF || s.wasRetryableEarlyClose(err)) && !retriesExhausted + + // Notify, for logging purposes, of any failures + if s.retryReaderOptions.OnFailedRead != nil { + failureCount := try + 1 // because try is zero-based + s.retryReaderOptions.OnFailedRead(failureCount, err, *s.info.Range, willRetry) + } + + if willRetry { + continue + // Loop around and try to get and read from new stream. + } + return n, err // Not retryable, or retries exhausted, so just return + } +} + +// By default, we allow early Closing, from another concurrent goroutine, to be used to force a retry +// Is this safe, to close early from another goroutine? Early close ultimately ends up calling +// net.Conn.Close, and that is documented as "Any blocked Read or Write operations will be unblocked and return errors" +// which is exactly the behaviour we want. +// NOTE: that if caller has forced an early Close from a separate goroutine (separate from the Read) +// then there are two different types of error that may happen - either the one we check for here, +// or a net.Error (due to closure of connection). Which one happens depends on timing. We only need this routine +// to check for one, since the other is a net.Error, which our main Read retry loop is already handing. +func (s *RetryReader) wasRetryableEarlyClose(err error) bool { + if s.retryReaderOptions.EarlyCloseAsError { + return false // user wants all early closes to be errors, and so not retryable + } + // unfortunately, http.errReadOnClosedResBody is private, so the best we can do here is to check for its text + return strings.HasSuffix(err.Error(), ReadOnClosedBodyMessage) +} + +// ReadOnClosedBodyMessage of retry reader +const ReadOnClosedBodyMessage = "read on closed response body" + +// Close retry reader +func (s *RetryReader) Close() error { + s.responseMu.Lock() + defer s.responseMu.Unlock() + if s.response != nil { + return s.response.Close() + } + return nil +} diff --git a/sdk/storage/azdatalake/filesystem/client.go b/sdk/storage/azdatalake/filesystem/client.go index c0a8146de2ad..c0c7ee5b8086 100644 --- a/sdk/storage/azdatalake/filesystem/client.go +++ b/sdk/storage/azdatalake/filesystem/client.go @@ -162,8 +162,8 @@ func (fs *Client) containerClient() *container.Client { return containerClient } -func (f *Client) identityCredential() *azcore.TokenCredential { - return base.IdentityCredentialComposite((*base.CompositeClient[generated.FileSystemClient, generated.FileSystemClient, container.Client])(f)) +func (fs *Client) identityCredential() *azcore.TokenCredential { + return base.IdentityCredentialComposite((*base.CompositeClient[generated.FileSystemClient, generated.FileSystemClient, container.Client])(fs)) } func (fs *Client) sharedKey() *exported.SharedKeyCredential { diff --git a/sdk/storage/azdatalake/internal/exported/shared_key_credential.go b/sdk/storage/azdatalake/internal/exported/shared_key_credential.go index 63539ea0b10a..d54cdc3a0b76 100644 --- a/sdk/storage/azdatalake/internal/exported/shared_key_credential.go +++ b/sdk/storage/azdatalake/internal/exported/shared_key_credential.go @@ -182,7 +182,7 @@ func (c *SharedKeyCredential) buildCanonicalizedResource(u *url.URL) (string, er // Join the sorted key values separated by ',' // Then prepend "keyName:"; then add this string to the buffer - cr.WriteString("\n" + paramName + ":" + strings.Join(paramValues, ",")) + cr.WriteString("\n" + strings.ToLower(paramName) + ":" + strings.Join(paramValues, ",")) } } return cr.String(), nil diff --git a/sdk/storage/azdatalake/internal/exported/transfer_validation_option.go b/sdk/storage/azdatalake/internal/exported/transfer_validation_option.go new file mode 100644 index 000000000000..85430ebd1c7e --- /dev/null +++ b/sdk/storage/azdatalake/internal/exported/transfer_validation_option.go @@ -0,0 +1,56 @@ +//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 exported + +import ( + "bytes" + "encoding/binary" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/streaming" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/internal/generated" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/internal/shared" + "hash/crc64" + "io" +) + +// TransferValidationType abstracts the various mechanisms used to verify a transfer. +type TransferValidationType interface { + Apply(io.ReadSeekCloser, generated.TransactionalContentSetter) (io.ReadSeekCloser, error) + notPubliclyImplementable() +} + +// TransferValidationTypeCRC64 is a TransferValidationType used to provide a precomputed CRC64. +type TransferValidationTypeCRC64 uint64 + +func (c TransferValidationTypeCRC64) Apply(rsc io.ReadSeekCloser, cfg generated.TransactionalContentSetter) (io.ReadSeekCloser, error) { + buf := make([]byte, 8) + binary.LittleEndian.PutUint64(buf, uint64(c)) + cfg.SetCRC64(buf) + return rsc, nil +} + +func (TransferValidationTypeCRC64) notPubliclyImplementable() {} + +// TransferValidationTypeComputeCRC64 is a TransferValidationType that indicates a CRC64 should be computed during transfer. +func TransferValidationTypeComputeCRC64() TransferValidationType { + return transferValidationTypeFn(func(rsc io.ReadSeekCloser, cfg generated.TransactionalContentSetter) (io.ReadSeekCloser, error) { + buf, err := io.ReadAll(rsc) + if err != nil { + return nil, err + } + + crc := crc64.Checksum(buf, shared.CRC64Table) + return TransferValidationTypeCRC64(crc).Apply(streaming.NopCloser(bytes.NewReader(buf)), cfg) + }) +} + +type transferValidationTypeFn func(io.ReadSeekCloser, generated.TransactionalContentSetter) (io.ReadSeekCloser, error) + +func (t transferValidationTypeFn) Apply(rsc io.ReadSeekCloser, cfg generated.TransactionalContentSetter) (io.ReadSeekCloser, error) { + return t(rsc, cfg) +} + +func (transferValidationTypeFn) notPubliclyImplementable() {} diff --git a/sdk/storage/azdatalake/internal/generated/models.go b/sdk/storage/azdatalake/internal/generated/models.go new file mode 100644 index 000000000000..b3f86d5973cb --- /dev/null +++ b/sdk/storage/azdatalake/internal/generated/models.go @@ -0,0 +1,15 @@ +//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 generated + +type TransactionalContentSetter interface { + SetCRC64([]byte) +} + +func (a *PathClientAppendDataOptions) SetCRC64(v []byte) { + a.TransactionalContentCRC64 = v +} diff --git a/sdk/storage/azdatalake/internal/path/constants.go b/sdk/storage/azdatalake/internal/path/constants.go index 7dd11049e38e..ce070f694d23 100644 --- a/sdk/storage/azdatalake/internal/path/constants.go +++ b/sdk/storage/azdatalake/internal/path/constants.go @@ -6,14 +6,16 @@ package path -import "github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/blob" +import ( + "github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/blob" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/internal/generated" +) -// EncryptionAlgorithmType defines values for EncryptionAlgorithmType. -type EncryptionAlgorithmType = blob.EncryptionAlgorithmType +type EncryptionAlgorithmType = generated.EncryptionAlgorithmType const ( - EncryptionAlgorithmTypeNone EncryptionAlgorithmType = blob.EncryptionAlgorithmTypeNone - EncryptionAlgorithmTypeAES256 EncryptionAlgorithmType = blob.EncryptionAlgorithmTypeAES256 + EncryptionAlgorithmTypeNone EncryptionAlgorithmType = generated.EncryptionAlgorithmTypeNone + EncryptionAlgorithmTypeAES256 EncryptionAlgorithmType = generated.EncryptionAlgorithmTypeAES256 ) type ImmutabilityPolicyMode = blob.ImmutabilityPolicyMode diff --git a/sdk/storage/azdatalake/internal/path/models.go b/sdk/storage/azdatalake/internal/path/models.go index 893bc9d40d19..f476fcae518f 100644 --- a/sdk/storage/azdatalake/internal/path/models.go +++ b/sdk/storage/azdatalake/internal/path/models.go @@ -30,7 +30,7 @@ func FormatGetPropertiesOptions(o *GetPropertiesOptions) *blob.GetPropertiesOpti AccessConditions: accessConditions, CPKInfo: &blob.CPKInfo{ EncryptionKey: o.CPKInfo.EncryptionKey, - EncryptionAlgorithm: o.CPKInfo.EncryptionAlgorithm, + EncryptionAlgorithm: (*blob.EncryptionAlgorithmType)(o.CPKInfo.EncryptionAlgorithm), EncryptionKeySHA256: o.CPKInfo.EncryptionKeySHA256, }, } @@ -159,19 +159,18 @@ type HTTPHeaders struct { ContentType *string } -// -//func (o HTTPHeaders) formatBlobHTTPHeaders() blob.HTTPHeaders { -// -// opts := blob.HTTPHeaders{ -// BlobCacheControl: o.CacheControl, -// BlobContentDisposition: o.ContentDisposition, -// BlobContentEncoding: o.ContentEncoding, -// BlobContentLanguage: o.ContentLanguage, -// BlobContentMD5: o.ContentMD5, -// BlobContentType: o.ContentType, -// } -// return opts -//} +func FormatBlobHTTPHeaders(o *HTTPHeaders) *blob.HTTPHeaders { + + opts := &blob.HTTPHeaders{ + BlobCacheControl: o.CacheControl, + BlobContentDisposition: o.ContentDisposition, + BlobContentEncoding: o.ContentEncoding, + BlobContentLanguage: o.ContentLanguage, + BlobContentMD5: o.ContentMD5, + BlobContentType: o.ContentType, + } + return opts +} func FormatPathHTTPHeaders(o *HTTPHeaders) *generated.PathHTTPHeaders { // TODO: will be used for file related ops, like append @@ -209,7 +208,7 @@ func FormatSetMetadataOptions(o *SetMetadataOptions) (*blob.SetMetadataOptions, if o.CPKInfo != nil { opts.CPKInfo = &blob.CPKInfo{ EncryptionKey: o.CPKInfo.EncryptionKey, - EncryptionAlgorithm: o.CPKInfo.EncryptionAlgorithm, + EncryptionAlgorithm: (*blob.EncryptionAlgorithmType)(o.CPKInfo.EncryptionAlgorithm), EncryptionKeySHA256: o.CPKInfo.EncryptionKeySHA256, } } diff --git a/sdk/storage/azdatalake/internal/shared/batch_transfer.go b/sdk/storage/azdatalake/internal/shared/batch_transfer.go new file mode 100644 index 000000000000..ec5541bfbb13 --- /dev/null +++ b/sdk/storage/azdatalake/internal/shared/batch_transfer.go @@ -0,0 +1,77 @@ +//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 shared + +import ( + "context" + "errors" +) + +// BatchTransferOptions identifies options used by doBatchTransfer. +type BatchTransferOptions struct { + TransferSize int64 + ChunkSize int64 + Concurrency uint16 + Operation func(ctx context.Context, offset int64, chunkSize int64) error + OperationName string +} + +// DoBatchTransfer helps to execute operations in a batch manner. +// Can be used by users to customize batch works (for other scenarios that the SDK does not provide) +func DoBatchTransfer(ctx context.Context, o *BatchTransferOptions) error { + if o.ChunkSize == 0 { + return errors.New("ChunkSize cannot be 0") + } + + if o.Concurrency == 0 { + o.Concurrency = 5 // default concurrency + } + + // Prepare and do parallel operations. + numChunks := uint16(((o.TransferSize - 1) / o.ChunkSize) + 1) + operationChannel := make(chan func() error, o.Concurrency) // Create the channel that release 'concurrency' goroutines concurrently + operationResponseChannel := make(chan error, numChunks) // Holds each response + ctx, cancel := context.WithCancel(ctx) + defer cancel() + + // Create the goroutines that process each operation (in parallel). + for g := uint16(0); g < o.Concurrency; g++ { + //grIndex := g + go func() { + for f := range operationChannel { + err := f() + operationResponseChannel <- err + } + }() + } + + // Add each chunk's operation to the channel. + for chunkNum := uint16(0); chunkNum < numChunks; chunkNum++ { + curChunkSize := o.ChunkSize + + if chunkNum == numChunks-1 { // Last chunk + curChunkSize = o.TransferSize - (int64(chunkNum) * o.ChunkSize) // Remove size of all transferred chunks from total + } + offset := int64(chunkNum) * o.ChunkSize + operationChannel <- func() error { + return o.Operation(ctx, offset, curChunkSize) + } + } + close(operationChannel) + + // Wait for the operations to complete. + var firstErr error = nil + for chunkNum := uint16(0); chunkNum < numChunks; chunkNum++ { + responseError := <-operationResponseChannel + // record the first error (the original error which should cause the other chunks to fail with canceled context) + if responseError != nil && firstErr == nil { + cancel() // As soon as any operation fails, cancel all remaining operation calls + firstErr = responseError + } + } + return firstErr +} diff --git a/sdk/storage/azdatalake/internal/testcommon/common.go b/sdk/storage/azdatalake/internal/testcommon/common.go index 1314309c5ac2..36af75cc92a7 100644 --- a/sdk/storage/azdatalake/internal/testcommon/common.go +++ b/sdk/storage/azdatalake/internal/testcommon/common.go @@ -1,11 +1,14 @@ package testcommon import ( + "bytes" "errors" "github.com/Azure/azure-sdk-for-go/sdk/azcore" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/streaming" "github.com/Azure/azure-sdk-for-go/sdk/internal/recording" "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/datalakeerror" "github.com/stretchr/testify/require" + "io" "os" "strings" "testing" @@ -80,3 +83,20 @@ func ValidateErrorCode(_require *require.Assertions, err error, code datalakeerr func GetRelativeTimeFromAnchor(anchorTime *time.Time, amount time.Duration) time.Time { return anchorTime.Add(amount * time.Second) } + +const random64BString string = "2SDgZj6RkKYzJpu04sweQek4uWHO8ndPnYlZ0tnFS61hjnFZ5IkvIGGY44eKABov" + +func GenerateData(sizeInBytes int) (io.ReadSeekCloser, []byte) { + data := make([]byte, sizeInBytes) + _len := len(random64BString) + if sizeInBytes > _len { + count := sizeInBytes / _len + if sizeInBytes%_len != 0 { + count = count + 1 + } + copy(data[:], strings.Repeat(random64BString, count)) + } else { + copy(data[:], random64BString) + } + return streaming.NopCloser(bytes.NewReader(data)), data +} diff --git a/sdk/storage/azdatalake/sas/service.go b/sdk/storage/azdatalake/sas/service.go index 86a292028276..92ccaa8101a3 100644 --- a/sdk/storage/azdatalake/sas/service.go +++ b/sdk/storage/azdatalake/sas/service.go @@ -55,7 +55,7 @@ func getDirectoryDepth(path string) string { // SignWithSharedKey uses an account's SharedKeyCredential to sign this signature values to produce the proper SAS query parameters. func (v DatalakeSignatureValues) SignWithSharedKey(sharedKeyCredential *SharedKeyCredential) (QueryParameters, error) { - if v.ExpiryTime.IsZero() || v.Permissions == "" { + if v.Identifier == "" && v.ExpiryTime.IsZero() || v.Permissions == "" { return QueryParameters{}, errors.New("service SAS is missing at least one of these: ExpiryTime or Permissions") } @@ -118,7 +118,6 @@ func (v DatalakeSignatureValues) SignWithSharedKey(sharedKeyCredential *SharedKe // Container/Blob-specific SAS parameters resource: resource, - identifier: v.Identifier, cacheControl: v.CacheControl, contentDisposition: v.ContentDisposition, contentEncoding: v.ContentEncoding, @@ -129,7 +128,8 @@ func (v DatalakeSignatureValues) SignWithSharedKey(sharedKeyCredential *SharedKe unauthorizedObjectID: v.UnauthorizedObjectID, correlationID: v.CorrelationID, // Calculated SAS signature - signature: signature, + signature: signature, + identifier: signedIdentifier, } return p, nil From 757507a034b401c0f9fe65efc6df83e3d3b92be1 Mon Sep 17 00:00:00 2001 From: Tamer Sherif <69483382+tasherif-msft@users.noreply.github.com> Date: Mon, 31 Jul 2023 09:13:29 -0700 Subject: [PATCH 11/16] [AzDatalake] Directory Client Implementation (#21283) * Enable gocritic during linting (#20715) Enabled gocritic's evalOrder to catch dependencies on undefined behavior on return statements. Updated to latest version of golangci-lint. Fixed issue in azblob flagged by latest linter. * Cosmos DB: Enable merge support (#20716) * Adding header and value * Wiring and tests * format * Fixing value * change log * [azservicebus, azeventhubs] Stress test and logging improvement (#20710) Logging improvements: * Updating the logging to print more tracing information (per-link) in prep for the bigger release coming up. * Trimming out some of the verbose logging, seeing if I can get it a bit more reasonable. Stress tests: * Add a timestamp to the log name we generate and also default to append, not overwrite. * Use 0.5 cores, 0.5GB as our baseline. Some pods use more and I'll tune them more later. * update proxy version (#20712) Co-authored-by: Scott Beddall * Return an error when you try to send a message that's too large. (#20721) This now works just like the message batch - you'll get an ErrMessageTooLarge if you attempt to send a message that's too large for the link's configured size. NOTE: there's a patch to `internal/go-amqp/Sender.go` to match what's in go-amqp's main so it returns a programmatically useful error when the message is too large. Fixes #20647 * Changes in test that is failing in pipeline (#20693) * [azservicebus, azeventhubs] Treat 'entity full' as a fatal error (#20722) When the remote entity is full we get a resource-limit-exceeded condition. This isn't something we should keep retrying on and it's best to just abort and let the user know immediately, rather than hoping it might eventually clear out. This affected both Event Hubs and Service Bus. Fixes #20647 * [azservicebus/azeventhubs] Redirect stderr and stdout to tee (#20726) * Update changelog with latest features (#20730) * Update changelog with latest features Prepare for upcoming release. * bump minor version * pass along the artifact name so we can override it later (#20732) Co-authored-by: scbedd <45376673+scbedd@users.noreply.github.com> * [azeventhubs] Fixing checkpoint store race condition (#20727) The checkpoint store wasn't guarding against multiple owners claiming for the first time - fixing this by using IfNoneMatch Fixes #20717 * Fix azidentity troubleshooting guide link (#20736) * [Release] sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/0.1.0 (#20437) * [Release] sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/0.1.0 generation from spec commit: 85fb4ac6f8bfefd179e6c2632976a154b5c9ff04 * client factory * fix * fix * update * add sdk/resourcemanager/postgresql/armpostgresql live test (#20685) * add sdk/resourcemanager/postgresql/armpostgresql live test * update assets.json * set subscriptionId default value * format * add sdk/resourcemanager/eventhub/armeventhub live test (#20686) * add sdk/resourcemanager/eventhub/armeventhub live test * update assets * add sdk/resourcemanager/compute/armcompute live test (#20048) * add sdk/resourcemanager/compute/armcompute live test * skus filter * fix subscriptionId default value * fix * gofmt * update recording * sdk/resourcemanager/network/armnetwork live test (#20331) * sdk/resourcemanager/network/armnetwork live test * update subscriptionId default value * update recording * add sdk/resourcemanager/cosmos/armcosmos live test (#20705) * add sdk/resourcemanager/cosmos/armcosmos live test * update assets.json * update assets.json * update assets.json * update assets.json * Increment package version after release of azcore (#20740) * [azeventhubs] Improperly resetting etag in the checkpoint store (#20737) We shouldn't be resetting the etag to nil - it's what we use to enforce a "single winner" when doing ownership claims. The bug here was two-fold: I had bad logic in my previous claim ownership, which I fixed in a previous PR, but we need to reflect that same constraint properly in our in-memory checkpoint store for these tests. * Eng workflows sync and branch cleanup additions (#20743) Co-authored-by: James Suplizio * [azeventhubs] Latest start position can also be inclusive (ie, get the latest message) (#20744) * Update GitHubEventProcessor version and remove pull_request_review procesing (#20751) Co-authored-by: James Suplizio * Rename DisableAuthorityValidationAndInstanceDiscovery (#20746) * fix (#20707) * AzFile (#20739) * azfile: Fixing connection string parsing logic (#20798) * Fixing connection string parse logic * Update README * [azadmin] fix flaky test (#20758) * fix flaky test * charles suggestion * Prepare azidentity v1.3.0 for release (#20756) * Fix broken podman link (#20801) Co-authored-by: Wes Haggard * [azquery] update doc comments (#20755) * update doc comments * update statistics and visualization generation * prep-for-release * Fixed contribution section (#20752) Co-authored-by: Bob Tabor * [azeventhubs,azservicebus] Some API cleanup, renames (#20754) * Adding options to UpdateCheckpoint(), just for future potential expansion * Make Offset an int64, not a *int64 (it's not optional, it'll always come back with ReceivedEvents) * Adding more logging into the checkpoint store. * Point all imports at the production go-amqp * Add supporting features to enable distributed tracing (#20301) (#20708) * Add supporting features to enable distributed tracing This includes new internal pipeline policies and other supporting types. See the changelog for a full description. Added some missing doc comments. * fix linter issue * add net.peer.name trace attribute sequence custom HTTP header policy before logging policy. sequence logging policy after HTTP trace policy. keep body download policy at the end. * add span for iterating over pages * Restore ARM CAE support for azcore beta (#20657) This reverts commit 902097226ff3fe2fc6c3e7fc50d3478350253614. * Upgrade to stable azcore (#20808) * Increment package version after release of data/azcosmos (#20807) * Updating changelog (#20810) * Add fake package to azcore (#20711) * Add fake package to azcore This is the supporting infrastructure for the generated SDK fakes. * fix doc comment * Updating CHANGELOG.md (#20809) * changelog (#20811) * Increment package version after release of storage/azfile (#20813) * Update changelog (azblob) (#20815) * Updating CHANGELOG.md * Update the changelog with correct version * [azquery] migration guide (#20742) * migration guide * Charles feedback * Richard feedback --------- Co-authored-by: Charles Lowell <10964656+chlowell@users.noreply.github.com> * Increment package version after release of monitor/azquery (#20820) * [keyvault] prep for release (#20819) * prep for release * perf tests * update date * added dir methods * small fixes * added rescursive set acl methods * recursive support * added sas and tests --------- Co-authored-by: Joel Hendrix Co-authored-by: Matias Quaranta Co-authored-by: Richard Park <51494936+richardpark-msft@users.noreply.github.com> Co-authored-by: Azure SDK Bot <53356347+azure-sdk@users.noreply.github.com> Co-authored-by: Scott Beddall Co-authored-by: siminsavani-msft <77068571+siminsavani-msft@users.noreply.github.com> Co-authored-by: scbedd <45376673+scbedd@users.noreply.github.com> Co-authored-by: Charles Lowell <10964656+chlowell@users.noreply.github.com> Co-authored-by: Peng Jiahui <46921893+Alancere@users.noreply.github.com> Co-authored-by: James Suplizio Co-authored-by: Sourav Gupta <98318303+souravgupta-msft@users.noreply.github.com> Co-authored-by: gracewilcox <43627800+gracewilcox@users.noreply.github.com> Co-authored-by: Wes Haggard Co-authored-by: Bob Tabor Co-authored-by: Bob Tabor --- sdk/storage/azdatalake/assets.json | 2 +- sdk/storage/azdatalake/directory/client.go | 203 +- .../azdatalake/directory/client_test.go | 2215 +++++++++++++++++ sdk/storage/azdatalake/directory/models.go | 131 +- sdk/storage/azdatalake/directory/responses.go | 5 +- sdk/storage/azdatalake/file/client.go | 6 +- sdk/storage/azdatalake/file/models.go | 110 +- sdk/storage/azdatalake/filesystem/client.go | 6 +- .../azdatalake/internal/exported/exported.go | 6 +- .../azdatalake/internal/generated/autorest.md | 19 +- .../internal/generated/zz_path_client.go | 12 +- .../internal/generated/zz_service_client.go | 4 +- .../azdatalake/internal/path/models.go | 56 +- .../internal/testcommon/clients_auth.go | 23 + .../azdatalake/internal/testcommon/common.go | 5 + 15 files changed, 2582 insertions(+), 221 deletions(-) create mode 100644 sdk/storage/azdatalake/directory/client_test.go 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", "") } From 58726b90a5fbe53d05249917918b5ba5ee64c199 Mon Sep 17 00:00:00 2001 From: Tamer Sherif <69483382+tasherif-msft@users.noreply.github.com> Date: Tue, 1 Aug 2023 11:22:32 -0700 Subject: [PATCH 12/16] [AzDatalake] Lease Clients Implementation (#21297) * Enable gocritic during linting (#20715) Enabled gocritic's evalOrder to catch dependencies on undefined behavior on return statements. Updated to latest version of golangci-lint. Fixed issue in azblob flagged by latest linter. * Cosmos DB: Enable merge support (#20716) * Adding header and value * Wiring and tests * format * Fixing value * change log * [azservicebus, azeventhubs] Stress test and logging improvement (#20710) Logging improvements: * Updating the logging to print more tracing information (per-link) in prep for the bigger release coming up. * Trimming out some of the verbose logging, seeing if I can get it a bit more reasonable. Stress tests: * Add a timestamp to the log name we generate and also default to append, not overwrite. * Use 0.5 cores, 0.5GB as our baseline. Some pods use more and I'll tune them more later. * update proxy version (#20712) Co-authored-by: Scott Beddall * Return an error when you try to send a message that's too large. (#20721) This now works just like the message batch - you'll get an ErrMessageTooLarge if you attempt to send a message that's too large for the link's configured size. NOTE: there's a patch to `internal/go-amqp/Sender.go` to match what's in go-amqp's main so it returns a programmatically useful error when the message is too large. Fixes #20647 * Changes in test that is failing in pipeline (#20693) * [azservicebus, azeventhubs] Treat 'entity full' as a fatal error (#20722) When the remote entity is full we get a resource-limit-exceeded condition. This isn't something we should keep retrying on and it's best to just abort and let the user know immediately, rather than hoping it might eventually clear out. This affected both Event Hubs and Service Bus. Fixes #20647 * [azservicebus/azeventhubs] Redirect stderr and stdout to tee (#20726) * Update changelog with latest features (#20730) * Update changelog with latest features Prepare for upcoming release. * bump minor version * pass along the artifact name so we can override it later (#20732) Co-authored-by: scbedd <45376673+scbedd@users.noreply.github.com> * [azeventhubs] Fixing checkpoint store race condition (#20727) The checkpoint store wasn't guarding against multiple owners claiming for the first time - fixing this by using IfNoneMatch Fixes #20717 * Fix azidentity troubleshooting guide link (#20736) * [Release] sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/0.1.0 (#20437) * [Release] sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/0.1.0 generation from spec commit: 85fb4ac6f8bfefd179e6c2632976a154b5c9ff04 * client factory * fix * fix * update * add sdk/resourcemanager/postgresql/armpostgresql live test (#20685) * add sdk/resourcemanager/postgresql/armpostgresql live test * update assets.json * set subscriptionId default value * format * add sdk/resourcemanager/eventhub/armeventhub live test (#20686) * add sdk/resourcemanager/eventhub/armeventhub live test * update assets * add sdk/resourcemanager/compute/armcompute live test (#20048) * add sdk/resourcemanager/compute/armcompute live test * skus filter * fix subscriptionId default value * fix * gofmt * update recording * sdk/resourcemanager/network/armnetwork live test (#20331) * sdk/resourcemanager/network/armnetwork live test * update subscriptionId default value * update recording * add sdk/resourcemanager/cosmos/armcosmos live test (#20705) * add sdk/resourcemanager/cosmos/armcosmos live test * update assets.json * update assets.json * update assets.json * update assets.json * Increment package version after release of azcore (#20740) * [azeventhubs] Improperly resetting etag in the checkpoint store (#20737) We shouldn't be resetting the etag to nil - it's what we use to enforce a "single winner" when doing ownership claims. The bug here was two-fold: I had bad logic in my previous claim ownership, which I fixed in a previous PR, but we need to reflect that same constraint properly in our in-memory checkpoint store for these tests. * Eng workflows sync and branch cleanup additions (#20743) Co-authored-by: James Suplizio * [azeventhubs] Latest start position can also be inclusive (ie, get the latest message) (#20744) * Update GitHubEventProcessor version and remove pull_request_review procesing (#20751) Co-authored-by: James Suplizio * Rename DisableAuthorityValidationAndInstanceDiscovery (#20746) * fix (#20707) * AzFile (#20739) * azfile: Fixing connection string parsing logic (#20798) * Fixing connection string parse logic * Update README * [azadmin] fix flaky test (#20758) * fix flaky test * charles suggestion * Prepare azidentity v1.3.0 for release (#20756) * Fix broken podman link (#20801) Co-authored-by: Wes Haggard * [azquery] update doc comments (#20755) * update doc comments * update statistics and visualization generation * prep-for-release * Fixed contribution section (#20752) Co-authored-by: Bob Tabor * [azeventhubs,azservicebus] Some API cleanup, renames (#20754) * Adding options to UpdateCheckpoint(), just for future potential expansion * Make Offset an int64, not a *int64 (it's not optional, it'll always come back with ReceivedEvents) * Adding more logging into the checkpoint store. * Point all imports at the production go-amqp * Add supporting features to enable distributed tracing (#20301) (#20708) * Add supporting features to enable distributed tracing This includes new internal pipeline policies and other supporting types. See the changelog for a full description. Added some missing doc comments. * fix linter issue * add net.peer.name trace attribute sequence custom HTTP header policy before logging policy. sequence logging policy after HTTP trace policy. keep body download policy at the end. * add span for iterating over pages * Restore ARM CAE support for azcore beta (#20657) This reverts commit 902097226ff3fe2fc6c3e7fc50d3478350253614. * Upgrade to stable azcore (#20808) * Increment package version after release of data/azcosmos (#20807) * Updating changelog (#20810) * Add fake package to azcore (#20711) * Add fake package to azcore This is the supporting infrastructure for the generated SDK fakes. * fix doc comment * Updating CHANGELOG.md (#20809) * changelog (#20811) * Increment package version after release of storage/azfile (#20813) * Update changelog (azblob) (#20815) * Updating CHANGELOG.md * Update the changelog with correct version * [azquery] migration guide (#20742) * migration guide * Charles feedback * Richard feedback --------- Co-authored-by: Charles Lowell <10964656+chlowell@users.noreply.github.com> * Increment package version after release of monitor/azquery (#20820) * [keyvault] prep for release (#20819) * prep for release * perf tests * update date * lease implementation and tests * tests * handled errors * nit --------- Co-authored-by: Joel Hendrix Co-authored-by: Matias Quaranta Co-authored-by: Richard Park <51494936+richardpark-msft@users.noreply.github.com> Co-authored-by: Azure SDK Bot <53356347+azure-sdk@users.noreply.github.com> Co-authored-by: Scott Beddall Co-authored-by: siminsavani-msft <77068571+siminsavani-msft@users.noreply.github.com> Co-authored-by: scbedd <45376673+scbedd@users.noreply.github.com> Co-authored-by: Charles Lowell <10964656+chlowell@users.noreply.github.com> Co-authored-by: Peng Jiahui <46921893+Alancere@users.noreply.github.com> Co-authored-by: James Suplizio Co-authored-by: Sourav Gupta <98318303+souravgupta-msft@users.noreply.github.com> Co-authored-by: gracewilcox <43627800+gracewilcox@users.noreply.github.com> Co-authored-by: Wes Haggard Co-authored-by: Bob Tabor Co-authored-by: Bob Tabor --- sdk/storage/azdatalake/assets.json | 2 +- sdk/storage/azdatalake/directory/client.go | 4 +- sdk/storage/azdatalake/file/client.go | 4 +- sdk/storage/azdatalake/filesystem/client.go | 4 +- .../internal/testcommon/clients_auth.go | 14 + .../lease/{filesystem_client.go => client.go} | 41 +- sdk/storage/azdatalake/lease/client_test.go | 560 ++++++++++++++++++ sdk/storage/azdatalake/lease/models.go | 40 ++ sdk/storage/azdatalake/lease/path_client.go | 48 +- sdk/storage/azdatalake/service/client.go | 4 +- 10 files changed, 689 insertions(+), 32 deletions(-) rename sdk/storage/azdatalake/lease/{filesystem_client.go => client.go} (66%) create mode 100644 sdk/storage/azdatalake/lease/client_test.go diff --git a/sdk/storage/azdatalake/assets.json b/sdk/storage/azdatalake/assets.json index 67a2df2961e2..89fb3cdc8b61 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_9dd1cc3e0e" + "Tag": "go/storage/azdatalake_78f150eb1d" } \ No newline at end of file diff --git a/sdk/storage/azdatalake/directory/client.go b/sdk/storage/azdatalake/directory/client.go index 8c998a0f812b..da7982ab0b62 100644 --- a/sdk/storage/azdatalake/directory/client.go +++ b/sdk/storage/azdatalake/directory/client.go @@ -219,14 +219,14 @@ func (d *Client) renamePathInURL(newName string) (string, string, string) { 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)) + newBlobURL, newPathURL := 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) { - newPathWithoutURL, newBlobURL, newPathURL := d.renamePathInURL(newName) + newPathWithoutURL, newPathURL, newBlobURL := d.renamePathInURL(newName) lac, mac, smac, createOpts := path.FormatRenameOptions(options, newPathWithoutURL) var newBlobClient *blockblob.Client var err error diff --git a/sdk/storage/azdatalake/file/client.go b/sdk/storage/azdatalake/file/client.go index 7400838cf7fb..ca83eeecf698 100644 --- a/sdk/storage/azdatalake/file/client.go +++ b/sdk/storage/azdatalake/file/client.go @@ -224,14 +224,14 @@ func (f *Client) renamePathInURL(newName string) (string, string, string) { 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)) + newBlobURL, newPathURL := shared.GetURLs(runtime.JoinPaths(firstPart, newName)) parsedNewURL, _ := url.Parse(f.DFSURL()) return parsedNewURL.Path, newPathURL, newBlobURL } // Rename renames a file (dfs1) func (f *Client) Rename(ctx context.Context, newName string, options *RenameOptions) (RenameResponse, error) { - newPathWithoutURL, newBlobURL, newPathURL := f.renamePathInURL(newName) + newPathWithoutURL, newPathURL, newBlobURL := f.renamePathInURL(newName) lac, mac, smac, createOpts := path.FormatRenameOptions(options, newPathWithoutURL) var newBlobClient *blockblob.Client var err error diff --git a/sdk/storage/azdatalake/filesystem/client.go b/sdk/storage/azdatalake/filesystem/client.go index 6c21c0ed364e..46f6c22f06bb 100644 --- a/sdk/storage/azdatalake/filesystem/client.go +++ b/sdk/storage/azdatalake/filesystem/client.go @@ -184,7 +184,7 @@ func (fs *Client) BlobURL() string { // The new directory.Client uses the same request policy pipeline as the Client. func (fs *Client) NewDirectoryClient(directoryPath string) *directory.Client { dirURL := runtime.JoinPaths(fs.generatedFSClientWithDFS().Endpoint(), directoryPath) - dirURL, blobURL := shared.GetURLs(dirURL) + blobURL, dirURL := shared.GetURLs(dirURL) return (*directory.Client)(base.NewPathClient(dirURL, blobURL, fs.containerClient().NewBlockBlobClient(directoryPath), fs.generatedFSClientWithDFS().InternalClient().WithClientName(shared.DirectoryClient), fs.sharedKey(), fs.identityCredential(), fs.getClientOptions())) } @@ -192,7 +192,7 @@ func (fs *Client) NewDirectoryClient(directoryPath string) *directory.Client { // The new file.Client uses the same request policy pipeline as the Client. func (fs *Client) NewFileClient(filePath string) *file.Client { fileURL := runtime.JoinPaths(fs.generatedFSClientWithDFS().Endpoint(), filePath) - fileURL, blobURL := shared.GetURLs(filePath) + blobURL, fileURL := shared.GetURLs(fileURL) return (*file.Client)(base.NewPathClient(fileURL, blobURL, fs.containerClient().NewBlockBlobClient(filePath), fs.generatedFSClientWithDFS().InternalClient().WithClientName(shared.FileClient), fs.sharedKey(), fs.identityCredential(), fs.getClientOptions())) } diff --git a/sdk/storage/azdatalake/internal/testcommon/clients_auth.go b/sdk/storage/azdatalake/internal/testcommon/clients_auth.go index 20c2d683daa5..93a91257b1b8 100644 --- a/sdk/storage/azdatalake/internal/testcommon/clients_auth.go +++ b/sdk/storage/azdatalake/internal/testcommon/clients_auth.go @@ -141,6 +141,20 @@ func GetFileClient(fsName, fName string, t *testing.T, accountType TestAccountTy return fileClient, err } +func CreateNewFile(ctx context.Context, _require *require.Assertions, fileName string, filesystemClient *filesystem.Client) *file.Client { + fileClient := filesystemClient.NewFileClient(fileName) + _, err := fileClient.Create(ctx, nil) + _require.Nil(err) + return fileClient +} + +func CreateNewDir(ctx context.Context, _require *require.Assertions, dirName string, filesystemClient *filesystem.Client) *directory.Client { + dirClient := filesystemClient.NewDirectoryClient(dirName) + _, err := dirClient.Create(ctx, nil) + _require.Nil(err) + return dirClient +} + func GetDirClient(fsName, dirName string, t *testing.T, accountType TestAccountType, options *directory.ClientOptions) (*directory.Client, error) { if options == nil { options = &directory.ClientOptions{} diff --git a/sdk/storage/azdatalake/lease/filesystem_client.go b/sdk/storage/azdatalake/lease/client.go similarity index 66% rename from sdk/storage/azdatalake/lease/filesystem_client.go rename to sdk/storage/azdatalake/lease/client.go index 110171d15990..d59dfcf1a7da 100644 --- a/sdk/storage/azdatalake/lease/filesystem_client.go +++ b/sdk/storage/azdatalake/lease/client.go @@ -8,28 +8,36 @@ package lease import ( "context" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/container" "github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/lease" "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/filesystem" + "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" ) // FilesystemClient provides lease functionality for the underlying filesystem client. type FilesystemClient struct { - leaseID *string containerClient *lease.ContainerClient + leaseID *string } // FilesystemClientOptions contains the optional values when creating a FilesystemClient. -type FilesystemClientOptions struct { - // LeaseID contains a caller-provided lease ID. - LeaseID *string -} +type FilesystemClientOptions = lease.ContainerClientOptions // NewFilesystemClient creates a filesystem lease client for the provided filesystem client. // - client - an instance of a filesystem client // - options - client options; pass nil to accept the default values func NewFilesystemClient(client *filesystem.Client, options *FilesystemClientOptions) (*FilesystemClient, error) { - // TODO: set up container lease client - return nil, nil + _, _, containerClient := base.InnerClients((*base.CompositeClient[generated.FileSystemClient, generated.FileSystemClient, container.Client])(client)) + containerLeaseClient, err := lease.NewContainerClient(containerClient, options) + if err != nil { + return nil, exported.ConvertToDFSError(err) + } + return &FilesystemClient{ + containerClient: containerLeaseClient, + leaseID: containerLeaseClient.LeaseID(), + }, nil } // LeaseID returns leaseID of the client. @@ -42,7 +50,8 @@ func (c *FilesystemClient) LeaseID() *string { // For more information, see https://docs.microsoft.com/rest/api/storageservices/lease-blob. func (c *FilesystemClient) AcquireLease(ctx context.Context, duration int32, o *FilesystemAcquireOptions) (FilesystemAcquireResponse, error) { opts := o.format() - return c.containerClient.AcquireLease(ctx, duration, opts) + resp, err := c.containerClient.AcquireLease(ctx, duration, opts) + return resp, exported.ConvertToDFSError(err) } // BreakLease breaks the filesystem's previously-acquired lease (if it exists). Pass the LeaseBreakDefault (-1) @@ -50,25 +59,33 @@ func (c *FilesystemClient) AcquireLease(ctx context.Context, duration int32, o * // For more information, see https://docs.microsoft.com/rest/api/storageservices/lease-blob. func (c *FilesystemClient) BreakLease(ctx context.Context, o *FilesystemBreakOptions) (FilesystemBreakResponse, error) { opts := o.format() - return c.containerClient.BreakLease(ctx, opts) + resp, err := c.containerClient.BreakLease(ctx, opts) + return resp, exported.ConvertToDFSError(err) } // ChangeLease changes the filesystem's lease ID. // For more information, see https://docs.microsoft.com/rest/api/storageservices/lease-blob. func (c *FilesystemClient) ChangeLease(ctx context.Context, proposedLeaseID string, o *FilesystemChangeOptions) (FilesystemChangeResponse, error) { opts := o.format() - return c.containerClient.ChangeLease(ctx, proposedLeaseID, opts) + resp, err := c.containerClient.ChangeLease(ctx, proposedLeaseID, opts) + if err != nil { + return resp, exported.ConvertToDFSError(err) + } + c.leaseID = &proposedLeaseID + return resp, nil } // RenewLease renews the filesystem's previously-acquired lease. // For more information, see https://docs.microsoft.com/rest/api/storageservices/lease-blob. func (c *FilesystemClient) RenewLease(ctx context.Context, o *FilesystemRenewOptions) (FilesystemRenewResponse, error) { opts := o.format() - return c.containerClient.RenewLease(ctx, opts) + resp, err := c.containerClient.RenewLease(ctx, opts) + return resp, exported.ConvertToDFSError(err) } // ReleaseLease releases the filesystem's previously-acquired lease. func (c *FilesystemClient) ReleaseLease(ctx context.Context, o *FilesystemReleaseOptions) (FilesystemReleaseResponse, error) { opts := o.format() - return c.containerClient.ReleaseLease(ctx, opts) + resp, err := c.containerClient.ReleaseLease(ctx, opts) + return resp, exported.ConvertToDFSError(err) } diff --git a/sdk/storage/azdatalake/lease/client_test.go b/sdk/storage/azdatalake/lease/client_test.go new file mode 100644 index 000000000000..51f2183ea718 --- /dev/null +++ b/sdk/storage/azdatalake/lease/client_test.go @@ -0,0 +1,560 @@ +//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 lease_test + +import ( + "context" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/file" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/filesystem" + "testing" + + "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/internal/testcommon" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/lease" + "github.com/stretchr/testify/require" + "github.com/stretchr/testify/suite" +) + +func Test(t *testing.T) { + recordMode := recording.GetRecordMode() + t.Logf("Running lease Tests in %s mode\n", recordMode) + if recordMode == recording.LiveMode { + suite.Run(t, &LeaseRecordedTestsSuite{}) + suite.Run(t, &LeaseUnrecordedTestsSuite{}) + } else if recordMode == recording.PlaybackMode { + suite.Run(t, &LeaseRecordedTestsSuite{}) + } else if recordMode == recording.RecordingMode { + suite.Run(t, &LeaseRecordedTestsSuite{}) + } +} + +func (s *LeaseRecordedTestsSuite) BeforeTest(suite string, test string) { + testcommon.BeforeTest(s.T(), suite, test) +} + +func (s *LeaseRecordedTestsSuite) AfterTest(suite string, test string) { + testcommon.AfterTest(s.T(), suite, test) +} + +func (s *LeaseUnrecordedTestsSuite) BeforeTest(suite string, test string) { + +} + +func (s *LeaseUnrecordedTestsSuite) AfterTest(suite string, test string) { + +} + +type LeaseRecordedTestsSuite struct { + suite.Suite +} + +type LeaseUnrecordedTestsSuite struct { + suite.Suite +} + +// var headersToIgnoreForLease = []string {"X-Ms-Proposed-Lease-Id", "X-Ms-Lease-Id"} +var proposedLeaseIDs = []*string{to.Ptr("c820a799-76d7-4ee2-6e15-546f19325c2c"), to.Ptr("326cc5e1-746e-4af8-4811-a50e6629a8ca")} + +func (s *LeaseRecordedTestsSuite) TestFilesystemAcquireLease() { + _require := require.New(s.T()) + testName := s.T().Name() + //ignoreHeaders(_context.recording, headersToIgnoreForLease) + + svcClient, err := testcommon.GetServiceClient(s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + filesystemName := testcommon.GenerateFilesystemName(testName) + filesystemClient := testcommon.CreateNewFilesystem(context.Background(), _require, filesystemName, svcClient) + defer testcommon.DeleteFilesystem(context.Background(), _require, filesystemClient) + + filesystemLeaseClient, _ := lease.NewFilesystemClient(filesystemClient, &lease.FilesystemClientOptions{ + LeaseID: proposedLeaseIDs[0], + }) + + ctx := context.Background() + acquireLeaseResponse, err := filesystemLeaseClient.AcquireLease(ctx, int32(60), nil) + _require.Nil(err) + _require.NotNil(acquireLeaseResponse.LeaseID) + _require.EqualValues(*acquireLeaseResponse.LeaseID, *filesystemLeaseClient.LeaseID()) + + _, err = filesystemLeaseClient.ReleaseLease(ctx, nil) + _require.Nil(err) +} + +func (s *LeaseRecordedTestsSuite) TestFilesystemDeleteFilesystemWithoutLeaseId() { + _require := require.New(s.T()) + testName := s.T().Name() + + svcClient, err := testcommon.GetServiceClient(s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + filesystemName := testcommon.GenerateFilesystemName(testName) + filesystemClient := testcommon.CreateNewFilesystem(context.Background(), _require, filesystemName, svcClient) + defer testcommon.DeleteFilesystem(context.Background(), _require, filesystemClient) + + filesystemLeaseClient, _ := lease.NewFilesystemClient(filesystemClient, &lease.FilesystemClientOptions{ + LeaseID: proposedLeaseIDs[0], + }) + + ctx := context.Background() + acquireLeaseResponse, err := filesystemLeaseClient.AcquireLease(ctx, int32(60), nil) + _require.Nil(err) + _require.NotNil(acquireLeaseResponse.LeaseID) + _require.EqualValues(*acquireLeaseResponse.LeaseID, *filesystemLeaseClient.LeaseID()) + + _, err = filesystemClient.Delete(ctx, nil) + _require.NotNil(err) + + leaseID := filesystemLeaseClient.LeaseID() + _, err = filesystemClient.Delete(ctx, &filesystem.DeleteOptions{ + AccessConditions: &filesystem.AccessConditions{ + LeaseAccessConditions: &filesystem.LeaseAccessConditions{ + LeaseID: leaseID, + }, + }, + }) + _require.Nil(err) +} + +func (s *LeaseRecordedTestsSuite) TestFilesystemReleaseLease() { + _require := require.New(s.T()) + testName := s.T().Name() + + //ignoreHeaders(_context.recording, headersToIgnoreForLease) + + svcClient, err := testcommon.GetServiceClient(s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + filesystemName := testcommon.GenerateFilesystemName(testName) + filesystemClient := testcommon.CreateNewFilesystem(context.Background(), _require, filesystemName, svcClient) + defer testcommon.DeleteFilesystem(context.Background(), _require, filesystemClient) + + filesystemLeaseClient, _ := lease.NewFilesystemClient(filesystemClient, &lease.FilesystemClientOptions{ + LeaseID: proposedLeaseIDs[0], + }) + + ctx := context.Background() + acquireLeaseResponse, err := filesystemLeaseClient.AcquireLease(ctx, int32(60), nil) + _require.Nil(err) + _require.NotNil(acquireLeaseResponse.LeaseID) + _require.EqualValues(*acquireLeaseResponse.LeaseID, *filesystemLeaseClient.LeaseID()) + + _, err = filesystemClient.Delete(ctx, nil) + _require.NotNil(err) + + _, err = filesystemLeaseClient.ReleaseLease(ctx, nil) + _require.Nil(err) + + _, err = filesystemClient.Delete(ctx, nil) + _require.Nil(err) +} + +func (s *LeaseRecordedTestsSuite) TestFilesystemRenewLease() { + _require := require.New(s.T()) + testName := s.T().Name() + + //ignoreHeaders(_context.recording, headersToIgnoreForLease) + + svcClient, err := testcommon.GetServiceClient(s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + filesystemName := testcommon.GenerateFilesystemName(testName) + filesystemClient := testcommon.CreateNewFilesystem(context.Background(), _require, filesystemName, svcClient) + defer testcommon.DeleteFilesystem(context.Background(), _require, filesystemClient) + + filesystemLeaseClient, _ := lease.NewFilesystemClient(filesystemClient, &lease.FilesystemClientOptions{ + LeaseID: proposedLeaseIDs[0], + }) + + ctx := context.Background() + acquireLeaseResponse, err := filesystemLeaseClient.AcquireLease(ctx, int32(15), nil) + _require.Nil(err) + _require.NotNil(acquireLeaseResponse.LeaseID) + _require.EqualValues(*acquireLeaseResponse.LeaseID, *filesystemLeaseClient.LeaseID()) + + _, err = filesystemLeaseClient.RenewLease(ctx, nil) + _require.Nil(err) + + _, err = filesystemLeaseClient.ReleaseLease(ctx, nil) + _require.Nil(err) +} + +func (s *LeaseRecordedTestsSuite) TestFilesystemChangeLease() { + _require := require.New(s.T()) + testName := s.T().Name() + + //ignoreHeaders(_context.recording, headersToIgnoreForLease) + + svcClient, err := testcommon.GetServiceClient(s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + fsName := testcommon.GenerateFilesystemName(testName) + fsClient := testcommon.CreateNewFilesystem(context.Background(), _require, fsName, svcClient) + defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + + fsLeaseClient, _ := lease.NewFilesystemClient(fsClient, &lease.FilesystemClientOptions{ + LeaseID: proposedLeaseIDs[0], + }) + + ctx := context.Background() + acquireLeaseResponse, err := fsLeaseClient.AcquireLease(ctx, int32(15), nil) + _require.Nil(err) + _require.NotNil(acquireLeaseResponse.LeaseID) + _require.EqualValues(*acquireLeaseResponse.LeaseID, *fsLeaseClient.LeaseID()) + + changeLeaseResp, err := fsLeaseClient.ChangeLease(ctx, *proposedLeaseIDs[1], nil) + _require.Nil(err) + _require.EqualValues(changeLeaseResp.LeaseID, proposedLeaseIDs[1]) + _require.EqualValues(fsLeaseClient.LeaseID(), proposedLeaseIDs[1]) + + _, err = fsLeaseClient.RenewLease(ctx, nil) + _require.Nil(err) + + _, err = fsLeaseClient.ReleaseLease(ctx, nil) + _require.Nil(err) +} + +func (s *LeaseRecordedTestsSuite) TestFileAcquireLease() { + _require := require.New(s.T()) + testName := s.T().Name() + + //ignoreHeaders(_context.recording, headersToIgnoreForLease) + + svcClient, err := testcommon.GetServiceClient(s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + filesystemName := testcommon.GenerateFilesystemName(testName) + filesystemClient := testcommon.CreateNewFilesystem(context.Background(), _require, filesystemName, svcClient) + defer testcommon.DeleteFilesystem(context.Background(), _require, filesystemClient) + + fileName := testcommon.GenerateFileName(testName) + fileClient := testcommon.CreateNewFile(context.Background(), _require, fileName, filesystemClient) + fileLeaseClient, err := lease.NewPathClient(fileClient, &lease.PathClientOptions{ + LeaseID: proposedLeaseIDs[0], + }) + _require.NoError(err) + + ctx := context.Background() + acquireLeaseResponse, err := fileLeaseClient.AcquireLease(ctx, int32(60), nil) + _require.Nil(err) + _require.NotNil(acquireLeaseResponse.LeaseID) + _require.EqualValues(acquireLeaseResponse.LeaseID, fileLeaseClient.LeaseID()) + + _, err = fileLeaseClient.ReleaseLease(ctx, nil) + _require.Nil(err) +} + +func (s *LeaseRecordedTestsSuite) TestDeleteFileWithoutLeaseId() { + _require := require.New(s.T()) + testName := s.T().Name() + + //ignoreHeaders(_context.recording, headersToIgnoreForLease) + + svcClient, err := testcommon.GetServiceClient(s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + filesystemName := testcommon.GenerateFilesystemName(testName) + filesystemClient := testcommon.CreateNewFilesystem(context.Background(), _require, filesystemName, svcClient) + defer testcommon.DeleteFilesystem(context.Background(), _require, filesystemClient) + + fileName := testcommon.GenerateFileName(testName) + fileClient := testcommon.CreateNewFile(context.Background(), _require, fileName, filesystemClient) + fileLeaseClient, err := lease.NewPathClient(fileClient, &lease.PathClientOptions{ + LeaseID: proposedLeaseIDs[0], + }) + _require.NoError(err) + + ctx := context.Background() + acquireLeaseResponse, err := fileLeaseClient.AcquireLease(ctx, int32(60), nil) + _require.Nil(err) + _require.NotNil(acquireLeaseResponse.LeaseID) + _require.EqualValues(acquireLeaseResponse.LeaseID, fileLeaseClient.LeaseID()) + + _, err = fileClient.Delete(ctx, nil) + _require.NotNil(err) + + leaseID := fileLeaseClient.LeaseID() + _, err = fileClient.Delete(ctx, &file.DeleteOptions{ + AccessConditions: &file.AccessConditions{ + LeaseAccessConditions: &file.LeaseAccessConditions{ + LeaseID: leaseID, + }, + }, + }) + _require.Nil(err) +} + +func (s *LeaseRecordedTestsSuite) TestFileReleaseLease() { + _require := require.New(s.T()) + testName := s.T().Name() + + //ignoreHeaders(_context.recording, headersToIgnoreForLease) + + svcClient, err := testcommon.GetServiceClient(s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + filesystemName := testcommon.GenerateFilesystemName(testName) + filesystemClient := testcommon.CreateNewFilesystem(context.Background(), _require, filesystemName, svcClient) + defer testcommon.DeleteFilesystem(context.Background(), _require, filesystemClient) + + fileName := testcommon.GenerateFileName(testName) + fileClient := testcommon.CreateNewFile(context.Background(), _require, fileName, filesystemClient) + fileLeaseClient, _ := lease.NewPathClient(fileClient, &lease.PathClientOptions{ + LeaseID: proposedLeaseIDs[0], + }) + + ctx := context.Background() + acquireLeaseResponse, err := fileLeaseClient.AcquireLease(ctx, int32(60), nil) + _require.Nil(err) + _require.NotNil(acquireLeaseResponse.LeaseID) + _require.EqualValues(acquireLeaseResponse.LeaseID, fileLeaseClient.LeaseID()) + + _, err = fileClient.Delete(ctx, nil) + _require.NotNil(err) + + _, err = fileLeaseClient.ReleaseLease(ctx, nil) + _require.Nil(err) + + _, err = fileClient.Delete(ctx, nil) + _require.Nil(err) +} + +func (s *LeaseRecordedTestsSuite) TestFileRenewLease() { + _require := require.New(s.T()) + testName := s.T().Name() + svcClient, err := testcommon.GetServiceClient(s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + filesystemName := testcommon.GenerateFilesystemName(testName) + filesystemClient := testcommon.CreateNewFilesystem(context.Background(), _require, filesystemName, svcClient) + defer testcommon.DeleteFilesystem(context.Background(), _require, filesystemClient) + + fileName := testcommon.GenerateFileName(testName) + fileClient := testcommon.CreateNewFile(context.Background(), _require, fileName, filesystemClient) + fileLeaseClient, _ := lease.NewPathClient(fileClient, &lease.PathClientOptions{ + LeaseID: proposedLeaseIDs[0], + }) + + ctx := context.Background() + acquireLeaseResponse, err := fileLeaseClient.AcquireLease(ctx, int32(15), nil) + _require.Nil(err) + _require.NotNil(acquireLeaseResponse.LeaseID) + _require.EqualValues(acquireLeaseResponse.LeaseID, fileLeaseClient.LeaseID()) + + _, err = fileLeaseClient.RenewLease(ctx, nil) + _require.Nil(err) + + _, err = fileLeaseClient.ReleaseLease(ctx, nil) + _require.Nil(err) +} + +func (s *LeaseRecordedTestsSuite) TestFileChangeLease() { + _require := require.New(s.T()) + testName := s.T().Name() + + //ignoreHeaders(_context.recording, headersToIgnoreForLease) + + svcClient, err := testcommon.GetServiceClient(s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + filesystemName := testcommon.GenerateFilesystemName(testName) + filesystemClient := testcommon.CreateNewFilesystem(context.Background(), _require, filesystemName, svcClient) + defer testcommon.DeleteFilesystem(context.Background(), _require, filesystemClient) + + fileName := testcommon.GenerateFileName(testName) + fileClient := testcommon.CreateNewFile(context.Background(), _require, fileName, filesystemClient) + fileLeaseClient, _ := lease.NewPathClient(fileClient, &lease.PathClientOptions{ + LeaseID: proposedLeaseIDs[0], + }) + + ctx := context.Background() + acquireLeaseResponse, err := fileLeaseClient.AcquireLease(ctx, int32(15), nil) + _require.Nil(err) + _require.NotNil(acquireLeaseResponse.LeaseID) + _require.Equal(*acquireLeaseResponse.LeaseID, *proposedLeaseIDs[0]) + + changeLeaseResp, err := fileLeaseClient.ChangeLease(ctx, *proposedLeaseIDs[1], nil) + _require.Nil(err) + _require.Equal(*changeLeaseResp.LeaseID, *proposedLeaseIDs[1]) + + _, err = fileLeaseClient.RenewLease(ctx, nil) + _require.Nil(err) + + _, err = fileLeaseClient.ReleaseLease(ctx, nil) + _require.Nil(err) +} + +func (s *LeaseRecordedTestsSuite) TestDirAcquireLease() { + _require := require.New(s.T()) + testName := s.T().Name() + + //ignoreHeaders(_context.recording, headersToIgnoreForLease) + + svcClient, err := testcommon.GetServiceClient(s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + filesystemName := testcommon.GenerateFilesystemName(testName) + filesystemClient := testcommon.CreateNewFilesystem(context.Background(), _require, filesystemName, svcClient) + defer testcommon.DeleteFilesystem(context.Background(), _require, filesystemClient) + + dirName := testcommon.GenerateDirName(testName) + dirClient := testcommon.CreateNewDir(context.Background(), _require, dirName, filesystemClient) + dirLeaseClient, err := lease.NewPathClient(dirClient, &lease.PathClientOptions{ + LeaseID: proposedLeaseIDs[0], + }) + _require.NoError(err) + + ctx := context.Background() + acquireLeaseResponse, err := dirLeaseClient.AcquireLease(ctx, int32(60), nil) + _require.Nil(err) + _require.NotNil(acquireLeaseResponse.LeaseID) + _require.EqualValues(acquireLeaseResponse.LeaseID, dirLeaseClient.LeaseID()) + + _, err = dirLeaseClient.ReleaseLease(ctx, nil) + _require.Nil(err) +} + +func (s *LeaseRecordedTestsSuite) TestDeleteDirWithoutLeaseId() { + _require := require.New(s.T()) + testName := s.T().Name() + + //ignoreHeaders(_context.recording, headersToIgnoreForLease) + + svcClient, err := testcommon.GetServiceClient(s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + filesystemName := testcommon.GenerateFilesystemName(testName) + filesystemClient := testcommon.CreateNewFilesystem(context.Background(), _require, filesystemName, svcClient) + defer testcommon.DeleteFilesystem(context.Background(), _require, filesystemClient) + + dirName := testcommon.GenerateDirName(testName) + dirClient := testcommon.CreateNewDir(context.Background(), _require, dirName, filesystemClient) + dirLeaseClient, err := lease.NewPathClient(dirClient, &lease.PathClientOptions{ + LeaseID: proposedLeaseIDs[0], + }) + _require.NoError(err) + + ctx := context.Background() + acquireLeaseResponse, err := dirLeaseClient.AcquireLease(ctx, int32(60), nil) + _require.Nil(err) + _require.NotNil(acquireLeaseResponse.LeaseID) + _require.EqualValues(acquireLeaseResponse.LeaseID, dirLeaseClient.LeaseID()) + + _, err = dirClient.Delete(ctx, nil) + _require.NotNil(err) + + leaseID := dirLeaseClient.LeaseID() + _, err = dirClient.Delete(ctx, &file.DeleteOptions{ + AccessConditions: &file.AccessConditions{ + LeaseAccessConditions: &file.LeaseAccessConditions{ + LeaseID: leaseID, + }, + }, + }) + _require.Nil(err) +} + +func (s *LeaseRecordedTestsSuite) TestDirReleaseLease() { + _require := require.New(s.T()) + testName := s.T().Name() + + //ignoreHeaders(_context.recording, headersToIgnoreForLease) + + svcClient, err := testcommon.GetServiceClient(s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + filesystemName := testcommon.GenerateFilesystemName(testName) + filesystemClient := testcommon.CreateNewFilesystem(context.Background(), _require, filesystemName, svcClient) + defer testcommon.DeleteFilesystem(context.Background(), _require, filesystemClient) + + DirName := testcommon.GenerateDirName(testName) + DirClient := testcommon.CreateNewDir(context.Background(), _require, DirName, filesystemClient) + DirLeaseClient, _ := lease.NewPathClient(DirClient, &lease.PathClientOptions{ + LeaseID: proposedLeaseIDs[0], + }) + + ctx := context.Background() + acquireLeaseResponse, err := DirLeaseClient.AcquireLease(ctx, int32(60), nil) + _require.Nil(err) + _require.NotNil(acquireLeaseResponse.LeaseID) + _require.EqualValues(acquireLeaseResponse.LeaseID, DirLeaseClient.LeaseID()) + + _, err = DirClient.Delete(ctx, nil) + _require.NotNil(err) + + _, err = DirLeaseClient.ReleaseLease(ctx, nil) + _require.Nil(err) + + _, err = DirClient.Delete(ctx, nil) + _require.Nil(err) +} + +func (s *LeaseRecordedTestsSuite) TestDirRenewLease() { + _require := require.New(s.T()) + testName := s.T().Name() + svcClient, err := testcommon.GetServiceClient(s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + filesystemName := testcommon.GenerateFilesystemName(testName) + filesystemClient := testcommon.CreateNewFilesystem(context.Background(), _require, filesystemName, svcClient) + defer testcommon.DeleteFilesystem(context.Background(), _require, filesystemClient) + + dirName := testcommon.GenerateDirName(testName) + dirClient := testcommon.CreateNewDir(context.Background(), _require, dirName, filesystemClient) + dirLeaseClient, _ := lease.NewPathClient(dirClient, &lease.PathClientOptions{ + LeaseID: proposedLeaseIDs[0], + }) + + ctx := context.Background() + acquireLeaseResponse, err := dirLeaseClient.AcquireLease(ctx, int32(15), nil) + _require.Nil(err) + _require.NotNil(acquireLeaseResponse.LeaseID) + _require.EqualValues(acquireLeaseResponse.LeaseID, dirLeaseClient.LeaseID()) + + _, err = dirLeaseClient.RenewLease(ctx, nil) + _require.Nil(err) + + _, err = dirLeaseClient.ReleaseLease(ctx, nil) + _require.Nil(err) +} + +func (s *LeaseRecordedTestsSuite) TestDirChangeLease() { + _require := require.New(s.T()) + testName := s.T().Name() + + //ignoreHeaders(_context.recording, headersToIgnoreForLease) + + svcClient, err := testcommon.GetServiceClient(s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + filesystemName := testcommon.GenerateFilesystemName(testName) + filesystemClient := testcommon.CreateNewFilesystem(context.Background(), _require, filesystemName, svcClient) + defer testcommon.DeleteFilesystem(context.Background(), _require, filesystemClient) + + dirName := testcommon.GenerateDirName(testName) + dirClient := testcommon.CreateNewDir(context.Background(), _require, dirName, filesystemClient) + dirLeaseClient, _ := lease.NewPathClient(dirClient, &lease.PathClientOptions{ + LeaseID: proposedLeaseIDs[0], + }) + + ctx := context.Background() + acquireLeaseResponse, err := dirLeaseClient.AcquireLease(ctx, int32(15), nil) + _require.Nil(err) + _require.NotNil(acquireLeaseResponse.LeaseID) + _require.Equal(*acquireLeaseResponse.LeaseID, *proposedLeaseIDs[0]) + + changeLeaseResp, err := dirLeaseClient.ChangeLease(ctx, *proposedLeaseIDs[1], nil) + _require.Nil(err) + _require.Equal(*changeLeaseResp.LeaseID, *proposedLeaseIDs[1]) + + _, err = dirLeaseClient.RenewLease(ctx, nil) + _require.Nil(err) + + _, err = dirLeaseClient.ReleaseLease(ctx, nil) + _require.Nil(err) +} diff --git a/sdk/storage/azdatalake/lease/models.go b/sdk/storage/azdatalake/lease/models.go index c09d30a21b40..ce552403c698 100644 --- a/sdk/storage/azdatalake/lease/models.go +++ b/sdk/storage/azdatalake/lease/models.go @@ -18,6 +18,9 @@ type FilesystemAcquireOptions struct { } func (o *FilesystemAcquireOptions) format() *lease.ContainerAcquireOptions { + if o == nil || o.ModifiedAccessConditions == nil { + return nil + } return &lease.ContainerAcquireOptions{ ModifiedAccessConditions: &blob.ModifiedAccessConditions{ IfModifiedSince: o.ModifiedAccessConditions.IfModifiedSince, @@ -35,6 +38,14 @@ type FilesystemBreakOptions struct { } func (o *FilesystemBreakOptions) format() *lease.ContainerBreakOptions { + opts := &lease.ContainerBreakOptions{} + if o == nil { + return opts + } + if o.ModifiedAccessConditions == nil { + opts.BreakPeriod = o.BreakPeriod + return opts + } return &lease.ContainerBreakOptions{ BreakPeriod: o.BreakPeriod, ModifiedAccessConditions: &blob.ModifiedAccessConditions{ @@ -52,6 +63,9 @@ type FilesystemChangeOptions struct { } func (o *FilesystemChangeOptions) format() *lease.ContainerChangeOptions { + if o == nil || o.ModifiedAccessConditions == nil { + return nil + } return &lease.ContainerChangeOptions{ ModifiedAccessConditions: &blob.ModifiedAccessConditions{ IfModifiedSince: o.ModifiedAccessConditions.IfModifiedSince, @@ -67,6 +81,9 @@ type FilesystemReleaseOptions struct { } func (o *FilesystemReleaseOptions) format() *lease.ContainerReleaseOptions { + if o == nil || o.ModifiedAccessConditions == nil { + return nil + } return &lease.ContainerReleaseOptions{ ModifiedAccessConditions: &blob.ModifiedAccessConditions{ IfModifiedSince: o.ModifiedAccessConditions.IfModifiedSince, @@ -82,6 +99,9 @@ type FilesystemRenewOptions struct { } func (o *FilesystemRenewOptions) format() *lease.ContainerRenewOptions { + if o == nil || o.ModifiedAccessConditions == nil { + return nil + } return &lease.ContainerRenewOptions{ ModifiedAccessConditions: &blob.ModifiedAccessConditions{ IfModifiedSince: o.ModifiedAccessConditions.IfModifiedSince, @@ -98,6 +118,9 @@ type PathAcquireOptions struct { } func (o *PathAcquireOptions) format() *lease.BlobAcquireOptions { + if o == nil || o.ModifiedAccessConditions == nil { + return nil + } return &lease.BlobAcquireOptions{ ModifiedAccessConditions: &blob.ModifiedAccessConditions{ IfModifiedSince: o.ModifiedAccessConditions.IfModifiedSince, @@ -115,6 +138,14 @@ type PathBreakOptions struct { } func (o *PathBreakOptions) format() *lease.BlobBreakOptions { + opts := &lease.BlobBreakOptions{} + if o == nil { + return opts + } + if o.ModifiedAccessConditions == nil { + opts.BreakPeriod = o.BreakPeriod + return opts + } return &lease.BlobBreakOptions{ BreakPeriod: o.BreakPeriod, ModifiedAccessConditions: &blob.ModifiedAccessConditions{ @@ -132,6 +163,9 @@ type PathChangeOptions struct { } func (o *PathChangeOptions) format() *lease.BlobChangeOptions { + if o == nil || o.ModifiedAccessConditions == nil { + return nil + } return &lease.BlobChangeOptions{ ModifiedAccessConditions: &blob.ModifiedAccessConditions{ IfModifiedSince: o.ModifiedAccessConditions.IfModifiedSince, @@ -147,6 +181,9 @@ type PathReleaseOptions struct { } func (o *PathReleaseOptions) format() *lease.BlobReleaseOptions { + if o == nil || o.ModifiedAccessConditions == nil { + return nil + } return &lease.BlobReleaseOptions{ ModifiedAccessConditions: &blob.ModifiedAccessConditions{ IfModifiedSince: o.ModifiedAccessConditions.IfModifiedSince, @@ -162,6 +199,9 @@ type PathRenewOptions struct { } func (o *PathRenewOptions) format() *lease.BlobRenewOptions { + if o == nil || o.ModifiedAccessConditions == nil { + return nil + } return &lease.BlobRenewOptions{ ModifiedAccessConditions: &blob.ModifiedAccessConditions{ IfModifiedSince: o.ModifiedAccessConditions.IfModifiedSince, diff --git a/sdk/storage/azdatalake/lease/path_client.go b/sdk/storage/azdatalake/lease/path_client.go index ec7aa846c47e..97e785571c05 100644 --- a/sdk/storage/azdatalake/lease/path_client.go +++ b/sdk/storage/azdatalake/lease/path_client.go @@ -8,9 +8,14 @@ package lease import ( "context" + "fmt" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/blockblob" "github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/lease" "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/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" ) // PathClient provides lease functionality for the underlying path client. @@ -20,17 +25,29 @@ type PathClient struct { } // PathClientOptions contains the optional values when creating a PathClient. -type PathClientOptions struct { - // LeaseID contains a caller-provided lease ID. - LeaseID *string -} +type PathClientOptions = lease.BlobClientOptions // NewPathClient creates a path lease client for the provided path client. // - client - an instance of a path client // - options - client options; pass nil to accept the default values func NewPathClient[T directory.Client | file.Client](client *T, options *PathClientOptions) (*PathClient, error) { - // TODO: set up blob lease client - return nil, nil + var blobClient *blockblob.Client + switch t := any(client).(type) { + case *directory.Client: + _, _, blobClient = base.InnerClients((*base.CompositeClient[generated.PathClient, generated.PathClient, blockblob.Client])(t)) + case *file.Client: + _, _, blobClient = base.InnerClients((*base.CompositeClient[generated.PathClient, generated.PathClient, blockblob.Client])(t)) + default: + return nil, fmt.Errorf("unhandled client type %T", client) + } + blobLeaseClient, err := lease.NewBlobClient(blobClient, options) + if err != nil { + return nil, exported.ConvertToDFSError(err) + } + return &PathClient{ + blobClient: blobLeaseClient, + leaseID: blobLeaseClient.LeaseID(), + }, nil } // LeaseID returns leaseID of the client. @@ -43,32 +60,41 @@ func (c *PathClient) LeaseID() *string { // For more information, see https://docs.microsoft.com/rest/api/storageservices/lease-blob. func (c *PathClient) AcquireLease(ctx context.Context, duration int32, o *PathAcquireOptions) (PathAcquireResponse, error) { opts := o.format() - return c.blobClient.AcquireLease(ctx, duration, opts) + resp, err := c.blobClient.AcquireLease(ctx, duration, opts) + return resp, exported.ConvertToDFSError(err) } // BreakLease breaks the path's previously-acquired lease. func (c *PathClient) BreakLease(ctx context.Context, o *PathBreakOptions) (PathBreakResponse, error) { opts := o.format() - return c.blobClient.BreakLease(ctx, opts) + resp, err := c.blobClient.BreakLease(ctx, opts) + return resp, exported.ConvertToDFSError(err) } // ChangeLease changes the path's lease ID. // For more information, see https://docs.microsoft.com/rest/api/storageservices/lease-blob. func (c *PathClient) ChangeLease(ctx context.Context, proposedID string, o *PathChangeOptions) (PathChangeResponse, error) { opts := o.format() - return c.blobClient.ChangeLease(ctx, proposedID, opts) + resp, err := c.blobClient.ChangeLease(ctx, proposedID, opts) + if err != nil { + return resp, exported.ConvertToDFSError(err) + } + c.leaseID = &proposedID + return resp, nil } // RenewLease renews the path's previously-acquired lease. // For more information, see https://docs.microsoft.com/rest/api/storageservices/lease-blob. func (c *PathClient) RenewLease(ctx context.Context, o *PathRenewOptions) (PathRenewResponse, error) { opts := o.format() - return c.blobClient.RenewLease(ctx, opts) + resp, err := c.blobClient.RenewLease(ctx, opts) + return resp, exported.ConvertToDFSError(err) } // ReleaseLease releases the path's previously-acquired lease. // For more information, see https://docs.microsoft.com/rest/api/storageservices/lease-blob. func (c *PathClient) ReleaseLease(ctx context.Context, o *PathReleaseOptions) (PathReleaseResponse, error) { opts := o.format() - return c.blobClient.ReleaseLease(ctx, opts) + resp, err := c.blobClient.ReleaseLease(ctx, opts) + return resp, exported.ConvertToDFSError(err) } diff --git a/sdk/storage/azdatalake/service/client.go b/sdk/storage/azdatalake/service/client.go index 33e96821f3bd..9a31c3f6a8ab 100644 --- a/sdk/storage/azdatalake/service/client.go +++ b/sdk/storage/azdatalake/service/client.go @@ -147,7 +147,7 @@ func (s *Client) getClientOptions() *base.ClientOptions { // The new filesystem.Client uses the same request policy pipeline as the Client. func (s *Client) NewFilesystemClient(filesystemName string) *filesystem.Client { filesystemURL := runtime.JoinPaths(s.generatedServiceClientWithDFS().Endpoint(), filesystemName) - filesystemURL, containerURL := shared.GetURLs(filesystemURL) + containerURL, filesystemURL := shared.GetURLs(filesystemURL) return (*filesystem.Client)(base.NewFilesystemClient(filesystemURL, containerURL, s.serviceClient().NewContainerClient(filesystemName), s.generatedServiceClientWithDFS().InternalClient().WithClientName(shared.FilesystemClient), s.sharedKey(), s.identityCredential(), s.getClientOptions())) } @@ -162,7 +162,7 @@ func (s *Client) GetUserDelegationCredential(ctx context.Context, info KeyInfo, getUserDelegationKeyOptions := o.format() udk, err := s.generatedServiceClientWithBlob().GetUserDelegationKey(ctx, info, getUserDelegationKeyOptions) if err != nil { - return nil, err + return nil, exported.ConvertToDFSError(err) } return exported.NewUserDelegationCredential(strings.Split(url.Host, ".")[0], udk.UserDelegationKey), nil From 8fd00224af9befd2904d787e3676c195cdcca84b Mon Sep 17 00:00:00 2001 From: Tamer Sherif <69483382+tasherif-msft@users.noreply.github.com> Date: Wed, 9 Aug 2023 18:06:57 -0700 Subject: [PATCH 13/16] [AzDatalake] Pipelines + cleanup (#21298) * Enable gocritic during linting (#20715) Enabled gocritic's evalOrder to catch dependencies on undefined behavior on return statements. Updated to latest version of golangci-lint. Fixed issue in azblob flagged by latest linter. * Cosmos DB: Enable merge support (#20716) * Adding header and value * Wiring and tests * format * Fixing value * change log * [azservicebus, azeventhubs] Stress test and logging improvement (#20710) Logging improvements: * Updating the logging to print more tracing information (per-link) in prep for the bigger release coming up. * Trimming out some of the verbose logging, seeing if I can get it a bit more reasonable. Stress tests: * Add a timestamp to the log name we generate and also default to append, not overwrite. * Use 0.5 cores, 0.5GB as our baseline. Some pods use more and I'll tune them more later. * update proxy version (#20712) Co-authored-by: Scott Beddall * Return an error when you try to send a message that's too large. (#20721) This now works just like the message batch - you'll get an ErrMessageTooLarge if you attempt to send a message that's too large for the link's configured size. NOTE: there's a patch to `internal/go-amqp/Sender.go` to match what's in go-amqp's main so it returns a programmatically useful error when the message is too large. Fixes #20647 * Changes in test that is failing in pipeline (#20693) * [azservicebus, azeventhubs] Treat 'entity full' as a fatal error (#20722) When the remote entity is full we get a resource-limit-exceeded condition. This isn't something we should keep retrying on and it's best to just abort and let the user know immediately, rather than hoping it might eventually clear out. This affected both Event Hubs and Service Bus. Fixes #20647 * [azservicebus/azeventhubs] Redirect stderr and stdout to tee (#20726) * Update changelog with latest features (#20730) * Update changelog with latest features Prepare for upcoming release. * bump minor version * pass along the artifact name so we can override it later (#20732) Co-authored-by: scbedd <45376673+scbedd@users.noreply.github.com> * [azeventhubs] Fixing checkpoint store race condition (#20727) The checkpoint store wasn't guarding against multiple owners claiming for the first time - fixing this by using IfNoneMatch Fixes #20717 * Fix azidentity troubleshooting guide link (#20736) * [Release] sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/0.1.0 (#20437) * [Release] sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/0.1.0 generation from spec commit: 85fb4ac6f8bfefd179e6c2632976a154b5c9ff04 * client factory * fix * fix * update * add sdk/resourcemanager/postgresql/armpostgresql live test (#20685) * add sdk/resourcemanager/postgresql/armpostgresql live test * update assets.json * set subscriptionId default value * format * add sdk/resourcemanager/eventhub/armeventhub live test (#20686) * add sdk/resourcemanager/eventhub/armeventhub live test * update assets * add sdk/resourcemanager/compute/armcompute live test (#20048) * add sdk/resourcemanager/compute/armcompute live test * skus filter * fix subscriptionId default value * fix * gofmt * update recording * sdk/resourcemanager/network/armnetwork live test (#20331) * sdk/resourcemanager/network/armnetwork live test * update subscriptionId default value * update recording * add sdk/resourcemanager/cosmos/armcosmos live test (#20705) * add sdk/resourcemanager/cosmos/armcosmos live test * update assets.json * update assets.json * update assets.json * update assets.json * Increment package version after release of azcore (#20740) * [azeventhubs] Improperly resetting etag in the checkpoint store (#20737) We shouldn't be resetting the etag to nil - it's what we use to enforce a "single winner" when doing ownership claims. The bug here was two-fold: I had bad logic in my previous claim ownership, which I fixed in a previous PR, but we need to reflect that same constraint properly in our in-memory checkpoint store for these tests. * Eng workflows sync and branch cleanup additions (#20743) Co-authored-by: James Suplizio * [azeventhubs] Latest start position can also be inclusive (ie, get the latest message) (#20744) * Update GitHubEventProcessor version and remove pull_request_review procesing (#20751) Co-authored-by: James Suplizio * Rename DisableAuthorityValidationAndInstanceDiscovery (#20746) * fix (#20707) * AzFile (#20739) * azfile: Fixing connection string parsing logic (#20798) * Fixing connection string parse logic * Update README * [azadmin] fix flaky test (#20758) * fix flaky test * charles suggestion * Prepare azidentity v1.3.0 for release (#20756) * Fix broken podman link (#20801) Co-authored-by: Wes Haggard * [azquery] update doc comments (#20755) * update doc comments * update statistics and visualization generation * prep-for-release * Fixed contribution section (#20752) Co-authored-by: Bob Tabor * [azeventhubs,azservicebus] Some API cleanup, renames (#20754) * Adding options to UpdateCheckpoint(), just for future potential expansion * Make Offset an int64, not a *int64 (it's not optional, it'll always come back with ReceivedEvents) * Adding more logging into the checkpoint store. * Point all imports at the production go-amqp * Add supporting features to enable distributed tracing (#20301) (#20708) * Add supporting features to enable distributed tracing This includes new internal pipeline policies and other supporting types. See the changelog for a full description. Added some missing doc comments. * fix linter issue * add net.peer.name trace attribute sequence custom HTTP header policy before logging policy. sequence logging policy after HTTP trace policy. keep body download policy at the end. * add span for iterating over pages * Restore ARM CAE support for azcore beta (#20657) This reverts commit 902097226ff3fe2fc6c3e7fc50d3478350253614. * Upgrade to stable azcore (#20808) * Increment package version after release of data/azcosmos (#20807) * Updating changelog (#20810) * Add fake package to azcore (#20711) * Add fake package to azcore This is the supporting infrastructure for the generated SDK fakes. * fix doc comment * Updating CHANGELOG.md (#20809) * changelog (#20811) * Increment package version after release of storage/azfile (#20813) * Update changelog (azblob) (#20815) * Updating CHANGELOG.md * Update the changelog with correct version * [azquery] migration guide (#20742) * migration guide * Charles feedback * Richard feedback --------- Co-authored-by: Charles Lowell <10964656+chlowell@users.noreply.github.com> * Increment package version after release of monitor/azquery (#20820) * [keyvault] prep for release (#20819) * prep for release * perf tests * update date * ci pipeline * code cov * test resources file * fix ci * ci fix * ci fix * ci fix * ci * generated blobs * cleanup * cleanup * fix sas * cleanup * cleanup * cleanup * added tests for recursive acls * added one more tests for dir * added more tests * added more tests * tests * tests * added more tests for fs and fixed some linting issues * cleanup --------- Co-authored-by: Joel Hendrix Co-authored-by: Matias Quaranta Co-authored-by: Richard Park <51494936+richardpark-msft@users.noreply.github.com> Co-authored-by: Azure SDK Bot <53356347+azure-sdk@users.noreply.github.com> Co-authored-by: Scott Beddall Co-authored-by: siminsavani-msft <77068571+siminsavani-msft@users.noreply.github.com> Co-authored-by: scbedd <45376673+scbedd@users.noreply.github.com> Co-authored-by: Charles Lowell <10964656+chlowell@users.noreply.github.com> Co-authored-by: Peng Jiahui <46921893+Alancere@users.noreply.github.com> Co-authored-by: James Suplizio Co-authored-by: Sourav Gupta <98318303+souravgupta-msft@users.noreply.github.com> Co-authored-by: gracewilcox <43627800+gracewilcox@users.noreply.github.com> Co-authored-by: Wes Haggard Co-authored-by: Bob Tabor Co-authored-by: Bob Tabor --- eng/config.json | 4 + sdk/storage/azdatalake/LICENSE.txt | 21 + sdk/storage/azdatalake/assets.json | 2 +- sdk/storage/azdatalake/ci.yml | 28 + sdk/storage/azdatalake/directory/client.go | 128 +- .../azdatalake/directory/client_test.go | 466 ++- sdk/storage/azdatalake/directory/models.go | 43 +- sdk/storage/azdatalake/directory/responses.go | 28 +- sdk/storage/azdatalake/file/client.go | 34 +- sdk/storage/azdatalake/file/client_test.go | 1300 ++++++-- sdk/storage/azdatalake/file/constants.go | 38 + sdk/storage/azdatalake/file/models.go | 33 +- sdk/storage/azdatalake/file/responses.go | 36 +- sdk/storage/azdatalake/filesystem/client.go | 19 +- .../azdatalake/filesystem/client_test.go | 588 +++- .../azdatalake/filesystem/constants.go | 42 +- sdk/storage/azdatalake/filesystem/models.go | 60 +- .../azdatalake/filesystem/responses.go | 43 +- .../azdatalake/internal/base/clients.go | 13 +- .../internal/exported/access_conditions.go | 6 + .../internal/exported/set_expiry.go | 20 +- .../exported/user_delegation_credential.go | 4 +- .../azdatalake/internal/generated/autorest.md | 33 + .../internal/generated/user_delegation_key.go | 144 - .../generated/zz_filesystem_client.go | 10 +- .../internal/generated/zz_models.go | 32 +- .../internal/generated/zz_models_serde.go | 30 +- .../internal/generated/zz_response_types.go | 6 +- .../internal/generated_blob/autorest.md | 480 +++ .../internal/generated_blob/blob_client.go | 44 + .../internal/generated_blob/build.go | 10 + .../generated_blob/container_client.go | 30 + .../internal/generated_blob/models.go | 65 + .../internal/generated_blob/service_client.go | 30 + .../generated_blob/zz_appendblob_client.go | 651 ++++ .../internal/generated_blob/zz_blob_client.go | 2874 +++++++++++++++++ .../generated_blob/zz_blockblob_client.go | 970 ++++++ .../internal/generated_blob/zz_constants.go | 714 ++++ .../generated_blob/zz_container_client.go | 1473 +++++++++ .../internal/generated_blob/zz_models.go | 1733 ++++++++++ .../generated_blob/zz_models_serde.go | 473 +++ .../generated_blob/zz_pageblob_client.go | 1289 ++++++++ .../generated_blob/zz_response_types.go | 1972 +++++++++++ .../generated_blob/zz_service_client.go | 557 ++++ .../generated_blob/zz_time_rfc1123.go | 43 + .../generated_blob/zz_time_rfc3339.go | 59 + .../internal/generated_blob/zz_xml_helper.go | 41 + .../azdatalake/internal/path/constants.go | 38 + .../azdatalake/internal/path/models.go | 8 +- .../azdatalake/internal/path/responses.go | 21 +- .../internal/testcommon/clients_auth.go | 7 + .../azdatalake/internal/testcommon/common.go | 6 + sdk/storage/azdatalake/lease/path_client.go | 5 +- sdk/storage/azdatalake/sas/service_test.go | 54 +- sdk/storage/azdatalake/sas/url_parts_test.go | 6 +- sdk/storage/azdatalake/service/client.go | 69 +- sdk/storage/azdatalake/service/client_test.go | 26 +- sdk/storage/azdatalake/service/constants.go | 57 + sdk/storage/azdatalake/service/models.go | 118 +- sdk/storage/azdatalake/service/responses.go | 100 +- sdk/storage/azdatalake/test-resources.json | 579 ++++ 61 files changed, 16885 insertions(+), 928 deletions(-) create mode 100644 sdk/storage/azdatalake/LICENSE.txt create mode 100644 sdk/storage/azdatalake/ci.yml delete mode 100644 sdk/storage/azdatalake/internal/generated/user_delegation_key.go create mode 100644 sdk/storage/azdatalake/internal/generated_blob/autorest.md create mode 100644 sdk/storage/azdatalake/internal/generated_blob/blob_client.go create mode 100644 sdk/storage/azdatalake/internal/generated_blob/build.go create mode 100644 sdk/storage/azdatalake/internal/generated_blob/container_client.go create mode 100644 sdk/storage/azdatalake/internal/generated_blob/models.go create mode 100644 sdk/storage/azdatalake/internal/generated_blob/service_client.go create mode 100644 sdk/storage/azdatalake/internal/generated_blob/zz_appendblob_client.go create mode 100644 sdk/storage/azdatalake/internal/generated_blob/zz_blob_client.go create mode 100644 sdk/storage/azdatalake/internal/generated_blob/zz_blockblob_client.go create mode 100644 sdk/storage/azdatalake/internal/generated_blob/zz_constants.go create mode 100644 sdk/storage/azdatalake/internal/generated_blob/zz_container_client.go create mode 100644 sdk/storage/azdatalake/internal/generated_blob/zz_models.go create mode 100644 sdk/storage/azdatalake/internal/generated_blob/zz_models_serde.go create mode 100644 sdk/storage/azdatalake/internal/generated_blob/zz_pageblob_client.go create mode 100644 sdk/storage/azdatalake/internal/generated_blob/zz_response_types.go create mode 100644 sdk/storage/azdatalake/internal/generated_blob/zz_service_client.go create mode 100644 sdk/storage/azdatalake/internal/generated_blob/zz_time_rfc1123.go create mode 100644 sdk/storage/azdatalake/internal/generated_blob/zz_time_rfc3339.go create mode 100644 sdk/storage/azdatalake/internal/generated_blob/zz_xml_helper.go create mode 100644 sdk/storage/azdatalake/service/constants.go create mode 100644 sdk/storage/azdatalake/test-resources.json diff --git a/eng/config.json b/eng/config.json index 09645b7b7bd1..39a8588ebe8b 100644 --- a/eng/config.json +++ b/eng/config.json @@ -28,6 +28,10 @@ "Name": "azqueue", "CoverageGoal": 0.60 }, + { + "Name": "azdatalake", + "CoverageGoal": 0.60 + }, { "Name": "azfile", "CoverageGoal": 0.75 diff --git a/sdk/storage/azdatalake/LICENSE.txt b/sdk/storage/azdatalake/LICENSE.txt new file mode 100644 index 000000000000..d1ca00f20a89 --- /dev/null +++ b/sdk/storage/azdatalake/LICENSE.txt @@ -0,0 +1,21 @@ + MIT License + + Copyright (c) Microsoft Corporation. All rights reserved. + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE \ No newline at end of file diff --git a/sdk/storage/azdatalake/assets.json b/sdk/storage/azdatalake/assets.json index 89fb3cdc8b61..3ec59c60cd99 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_78f150eb1d" + "Tag": "go/storage/azdatalake_ec80a91bf3" } \ No newline at end of file diff --git a/sdk/storage/azdatalake/ci.yml b/sdk/storage/azdatalake/ci.yml new file mode 100644 index 000000000000..612cde201ffa --- /dev/null +++ b/sdk/storage/azdatalake/ci.yml @@ -0,0 +1,28 @@ +trigger: + branches: + include: + - main + - feature/* + - hotfix/* + - release/* + paths: + include: + - sdk/storage/azdatalake + +pr: + branches: + include: + - main + - feature/* + - hotfix/* + - release/* + paths: + include: + - sdk/storage/azdatalake + + +stages: + - template: /eng/pipelines/templates/jobs/archetype-sdk-client.yml + parameters: + ServiceDirectory: 'storage/azdatalake' + RunLiveTests: true \ No newline at end of file diff --git a/sdk/storage/azdatalake/directory/client.go b/sdk/storage/azdatalake/directory/client.go index da7982ab0b62..dc7a6d0e63b6 100644 --- a/sdk/storage/azdatalake/directory/client.go +++ b/sdk/storage/azdatalake/directory/client.go @@ -11,11 +11,14 @@ import ( "github.com/Azure/azure-sdk-for-go/sdk/azcore" "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/azcore/to" "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/file" "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/generated_blob" "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" @@ -29,7 +32,7 @@ import ( type ClientOptions base.ClientOptions // Client represents a URL to the Azure Datalake Storage service. -type Client base.CompositeClient[generated.PathClient, generated.PathClient, blockblob.Client] +type Client base.CompositeClient[generated.PathClient, generated_blob.BlobClient, blockblob.Client] // NewClient creates an instance of Client with the specified values. // - directoryURL - the URL of the directory e.g. https://.dfs.core.windows.net/fs/dir @@ -128,12 +131,15 @@ func NewClientWithSharedKeyCredential(directoryURL string, cred *SharedKeyCreden // NewClientFromConnectionString creates an instance of Client with the specified values. // - connectionString - a connection string for the desired storage account // - options - client options; pass nil to accept the default values -func NewClientFromConnectionString(connectionString string, options *ClientOptions) (*Client, error) { +func NewClientFromConnectionString(connectionString string, dirPath, fsName string, options *ClientOptions) (*Client, error) { parsed, err := shared.ParseConnectionString(connectionString) if err != nil { return nil, err } + dirPath = strings.ReplaceAll(dirPath, "\\", "/") + parsed.ServiceURL = runtime.JoinPaths(parsed.ServiceURL, fsName, dirPath) + if parsed.AccountKey != "" && parsed.AccountName != "" { credential, err := exported.NewSharedKeyCredential(parsed.AccountName, parsed.AccountKey) if err != nil { @@ -146,31 +152,30 @@ func NewClientFromConnectionString(connectionString string, options *ClientOptio } func (d *Client) generatedDirClientWithDFS() *generated.PathClient { - //base.SharedKeyComposite((*base.CompositeClient[generated.BlobClient, generated.BlockBlobClient])(bb)) - dirClientWithDFS, _, _ := base.InnerClients((*base.CompositeClient[generated.PathClient, generated.PathClient, blockblob.Client])(d)) + dirClientWithDFS, _, _ := base.InnerClients((*base.CompositeClient[generated.PathClient, generated_blob.BlobClient, blockblob.Client])(d)) return dirClientWithDFS } -func (d *Client) generatedDirClientWithBlob() *generated.PathClient { - _, dirClientWithBlob, _ := base.InnerClients((*base.CompositeClient[generated.PathClient, generated.PathClient, blockblob.Client])(d)) +func (d *Client) generatedDirClientWithBlob() *generated_blob.BlobClient { + _, dirClientWithBlob, _ := base.InnerClients((*base.CompositeClient[generated.PathClient, generated_blob.BlobClient, blockblob.Client])(d)) return dirClientWithBlob } func (d *Client) blobClient() *blockblob.Client { - _, _, blobClient := base.InnerClients((*base.CompositeClient[generated.PathClient, generated.PathClient, blockblob.Client])(d)) + _, _, blobClient := base.InnerClients((*base.CompositeClient[generated.PathClient, generated_blob.BlobClient, blockblob.Client])(d)) return blobClient } func (d *Client) getClientOptions() *base.ClientOptions { - return base.GetCompositeClientOptions((*base.CompositeClient[generated.PathClient, generated.PathClient, blockblob.Client])(d)) + return base.GetCompositeClientOptions((*base.CompositeClient[generated.PathClient, generated_blob.BlobClient, blockblob.Client])(d)) } func (d *Client) sharedKey() *exported.SharedKeyCredential { - return base.SharedKeyComposite((*base.CompositeClient[generated.PathClient, generated.PathClient, blockblob.Client])(d)) + return base.SharedKeyComposite((*base.CompositeClient[generated.PathClient, generated_blob.BlobClient, blockblob.Client])(d)) } func (d *Client) identityCredential() *azcore.TokenCredential { - return base.IdentityCredentialComposite((*base.CompositeClient[generated.PathClient, generated.PathClient, blockblob.Client])(d)) + return base.IdentityCredentialComposite((*base.CompositeClient[generated.PathClient, generated_blob.BlobClient, blockblob.Client])(d)) } // DFSURL returns the URL endpoint used by the Client object. @@ -183,7 +188,27 @@ func (d *Client) BlobURL() string { return d.generatedDirClientWithBlob().Endpoint() } -//TODO: create method to get file client - this will require block blob to have a method to get another block blob +// NewFileClient creates a new file.Client object by concatenating fileName to the end of this Client's URL. +// The new file.Client uses the same request policy pipeline as the Client. +func (d *Client) NewFileClient(fileName string) (*file.Client, error) { + fileName = url.PathEscape(fileName) + fileURL := runtime.JoinPaths(d.DFSURL(), fileName) + newBlobURL, fileURL := shared.GetURLs(fileURL) + 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 nil, exported.ConvertToDFSError(err) + } + return (*file.Client)(base.NewPathClient(fileURL, newBlobURL, newBlobClient, d.generatedDirClientWithDFS().InternalClient().WithClientName(shared.FileClient), d.sharedKey(), d.identityCredential(), d.getClientOptions())), nil +} // Create creates a new directory (dfs1). func (d *Client) Create(ctx context.Context, options *CreateOptions) (CreateResponse, error) { @@ -260,12 +285,12 @@ func (d *Client) SetAccessControl(ctx context.Context, options *SetAccessControl return resp, err } -func (d *Client) setAccessControlHelper(mode generated.PathSetAccessControlRecursiveMode, listOptions *generated.PathClientSetAccessControlRecursiveOptions) *runtime.Pager[SetAccessControlRecursiveResponse] { - return runtime.NewPager(runtime.PagingHandler[SetAccessControlRecursiveResponse]{ - More: func(page SetAccessControlRecursiveResponse) bool { +func (d *Client) setAccessControlPager(mode generated.PathSetAccessControlRecursiveMode, listOptions *generated.PathClientSetAccessControlRecursiveOptions) *runtime.Pager[generated.PathClientSetAccessControlRecursiveResponse] { + return runtime.NewPager(runtime.PagingHandler[generated.PathClientSetAccessControlRecursiveResponse]{ + More: func(page generated.PathClientSetAccessControlRecursiveResponse) bool { return page.Continuation != nil && len(*page.Continuation) > 0 }, - Fetcher: func(ctx context.Context, page *SetAccessControlRecursiveResponse) (SetAccessControlRecursiveResponse, error) { + Fetcher: func(ctx context.Context, page *generated.PathClientSetAccessControlRecursiveResponse) (generated.PathClientSetAccessControlRecursiveResponse, error) { var req *policy.Request var err error if page == nil { @@ -277,15 +302,15 @@ func (d *Client) setAccessControlHelper(mode generated.PathSetAccessControlRecur err = exported.ConvertToDFSError(err) } if err != nil { - return SetAccessControlRecursiveResponse{}, err + return generated.PathClientSetAccessControlRecursiveResponse{}, err } resp, err := d.generatedDirClientWithDFS().InternalClient().Pipeline().Do(req) err = exported.ConvertToDFSError(err) if err != nil { - return SetAccessControlRecursiveResponse{}, err + return generated.PathClientSetAccessControlRecursiveResponse{}, err } if !runtime.HasStatusCode(resp, http.StatusOK) { - return SetAccessControlRecursiveResponse{}, runtime.NewResponseError(resp) + return generated.PathClientSetAccessControlRecursiveResponse{}, runtime.NewResponseError(resp) } newResp, err := d.generatedDirClientWithDFS().SetAccessControlRecursiveHandleResponse(resp) return newResp, exported.ConvertToDFSError(err) @@ -294,22 +319,61 @@ func (d *Client) setAccessControlHelper(mode generated.PathSetAccessControlRecur } -// NewSetAccessControlRecursivePager sets the owner, owning group, and permissions for a directory (dfs1). -func (d *Client) NewSetAccessControlRecursivePager(ACL string, options *SetAccessControlRecursiveOptions) *runtime.Pager[SetAccessControlRecursiveResponse] { +func (d *Client) setAccessControlRecursiveHelper(mode generated.PathSetAccessControlRecursiveMode, listOptions *generated.PathClientSetAccessControlRecursiveOptions, options *SetAccessControlRecursiveOptions) (SetAccessControlRecursiveResponse, error) { + pager := d.setAccessControlPager(mode, listOptions) + counter := *options.MaxBatches + continueOnFailure := listOptions.ForceFlag + totalSuccessfulDirs := int32(0) + totalSuccessfulFiles := int32(0) + totalFailureCount := int32(0) + finalResponse := SetAccessControlRecursiveResponse{ + DirectoriesSuccessful: &totalSuccessfulDirs, + FilesSuccessful: &totalSuccessfulFiles, + FailureCount: &totalFailureCount, + FailedEntries: []*ACLFailedEntry{}, + } + for pager.More() && counter != 0 { + resp, err := pager.NextPage(context.Background()) + if err != nil { + return finalResponse, exported.ConvertToDFSError(err) + } + finalResponse.DirectoriesSuccessful = to.Ptr(*finalResponse.DirectoriesSuccessful + *resp.DirectoriesSuccessful) + finalResponse.FilesSuccessful = to.Ptr(*finalResponse.FilesSuccessful + *resp.FilesSuccessful) + finalResponse.FailureCount = to.Ptr(*finalResponse.FailureCount + *resp.FailureCount) + finalResponse.FailedEntries = append(finalResponse.FailedEntries, resp.FailedEntries...) + counter = counter - 1 + if !*continueOnFailure && *resp.FailureCount > 0 { + return finalResponse, exported.ConvertToDFSError(err) + } + } + return finalResponse, nil +} + +// SetAccessControlRecursive sets the owner, owning group, and permissions for a directory (dfs1). +func (d *Client) SetAccessControlRecursive(ACL string, options *SetAccessControlRecursiveOptions) (SetAccessControlRecursiveResponse, error) { + if options == nil { + options = &SetAccessControlRecursiveOptions{} + } mode, listOptions := options.format(ACL, "set") - return d.setAccessControlHelper(mode, listOptions) + return d.setAccessControlRecursiveHelper(mode, listOptions, options) } -// NewUpdateAccessControlRecursivePager updates the owner, owning group, and permissions for a directory (dfs1). -func (d *Client) NewUpdateAccessControlRecursivePager(ACL string, options *UpdateAccessControlRecursiveOptions) *runtime.Pager[UpdateAccessControlRecursiveResponse] { +// UpdateAccessControlRecursive updates the owner, owning group, and permissions for a directory (dfs1). +func (d *Client) UpdateAccessControlRecursive(ACL string, options *UpdateAccessControlRecursiveOptions) (SetAccessControlRecursiveResponse, error) { + if options == nil { + options = &UpdateAccessControlRecursiveOptions{} + } mode, listOptions := options.format(ACL, "modify") - return d.setAccessControlHelper(mode, listOptions) + return d.setAccessControlRecursiveHelper(mode, listOptions, options) } -// NewRemoveAccessControlRecursivePager removes the owner, owning group, and permissions for a directory (dfs1). -func (d *Client) NewRemoveAccessControlRecursivePager(ACL string, options *RemoveAccessControlRecursiveOptions) *runtime.Pager[RemoveAccessControlRecursiveResponse] { +// RemoveAccessControlRecursive removes the owner, owning group, and permissions for a directory (dfs1). +func (d *Client) RemoveAccessControlRecursive(ACL string, options *RemoveAccessControlRecursiveOptions) (SetAccessControlRecursiveResponse, error) { + if options == nil { + options = &RemoveAccessControlRecursiveOptions{} + } mode, listOptions := options.format(ACL, "remove") - return d.setAccessControlHelper(mode, listOptions) + return d.setAccessControlRecursiveHelper(mode, listOptions, options) } // GetAccessControl gets the owner, owning group, and permissions for a directory (dfs1). @@ -340,12 +404,12 @@ func (d *Client) SetHTTPHeaders(ctx context.Context, httpHeaders HTTPHeaders, op // 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 { +func (d *Client) GetSASURL(permissions sas.DirectoryPermissions, expiry time.Time, o *GetSASURLOptions) (string, error) { + if d.sharedKey() == nil { return "", datalakeerror.MissingSharedKeyCredential } - urlParts, err := sas.ParseURL(f.BlobURL()) + urlParts, err := sas.ParseURL(d.BlobURL()) err = exported.ConvertToDFSError(err) if err != nil { return "", err @@ -360,14 +424,14 @@ func (f *Client) GetSASURL(permissions sas.DirectoryPermissions, expiry time.Tim Permissions: permissions.String(), StartTime: st, ExpiryTime: expiry.UTC(), - }.SignWithSharedKey(f.sharedKey()) + }.SignWithSharedKey(d.sharedKey()) err = exported.ConvertToDFSError(err) if err != nil { return "", err } - endpoint := f.BlobURL() + "?" + qps.Encode() + endpoint := d.BlobURL() + "?" + qps.Encode() return endpoint, nil } diff --git a/sdk/storage/azdatalake/directory/client_test.go b/sdk/storage/azdatalake/directory/client_test.go index 2a11a11d0751..f9b0ea71f857 100644 --- a/sdk/storage/azdatalake/directory/client_test.go +++ b/sdk/storage/azdatalake/directory/client_test.go @@ -59,6 +59,59 @@ type UnrecordedTestSuite struct { suite.Suite } +func (s *UnrecordedTestSuite) TestCreateDirAndDeleteWithConnectionString() { + + _require := require.New(s.T()) + testName := s.T().Name() + + connectionString, _ := testcommon.GetGenericConnectionString(testcommon.TestAccountDatalake) + + 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 := directory.NewClientFromConnectionString(*connectionString, dirName, filesystemName, 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) TestBlobURLAndDFSURL() { + _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) + + _require.Contains(dirClient.DFSURL(), ".dfs.core.windows.net/"+filesystemName+"/"+dirName) + _require.Contains(dirClient.BlobURL(), ".blob.core.windows.net/"+filesystemName+"/"+dirName) +} + func (s *RecordedTestSuite) TestCreateDirAndDelete() { _require := require.New(s.T()) testName := s.T().Name() @@ -82,6 +135,36 @@ func (s *RecordedTestSuite) TestCreateDirAndDelete() { _require.NotNil(resp) } +func (s *RecordedTestSuite) TestGetAndCreateFileClient() { + _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) + + fileClient, err := dirClient.NewFileClient(testcommon.GenerateFileName(testName)) + _require.Nil(err) + _require.NotNil(fileClient) + + _, err = fileClient.Create(context.Background(), nil) + _require.Nil(err) +} + func (s *RecordedTestSuite) TestCreateDirWithNilAccessConditions() { _require := require.New(s.T()) testName := s.T().Name() @@ -224,7 +307,7 @@ func (s *RecordedTestSuite) TestCreateDirIfUnmodifiedSinceTrue() { _require.NotNil(resp) } -func (s *RecordedTestSuite) TestCreateFileIfUnmodifiedSinceFalse() { +func (s *RecordedTestSuite) TestCreateDirIfUnmodifiedSinceFalse() { _require := require.New(s.T()) testName := s.T().Name() @@ -262,7 +345,7 @@ func (s *RecordedTestSuite) TestCreateFileIfUnmodifiedSinceFalse() { testcommon.ValidateErrorCode(_require, err, datalakeerror.ConditionNotMet) } -func (s *RecordedTestSuite) TestCreateFileIfETagMatch() { +func (s *RecordedTestSuite) TestCreateDirIfETagMatch() { _require := require.New(s.T()) testName := s.T().Name() @@ -299,7 +382,7 @@ func (s *RecordedTestSuite) TestCreateFileIfETagMatch() { _require.NotNil(resp) } -func (s *RecordedTestSuite) TestCreateFileIfETagMatchFalse() { +func (s *RecordedTestSuite) TestCreateDirIfETagMatchFalse() { _require := require.New(s.T()) testName := s.T().Name() @@ -337,7 +420,7 @@ func (s *RecordedTestSuite) TestCreateFileIfETagMatchFalse() { testcommon.ValidateErrorCode(_require, err, datalakeerror.ConditionNotMet) } -func (s *RecordedTestSuite) TestCreateFileWithMetadataNotNil() { +func (s *RecordedTestSuite) TestCreateDirWithMetadataNotNil() { _require := require.New(s.T()) testName := s.T().Name() @@ -364,7 +447,7 @@ func (s *RecordedTestSuite) TestCreateFileWithMetadataNotNil() { _require.NotNil(resp) } -func (s *RecordedTestSuite) TestCreateFileWithEmptyMetadata() { +func (s *RecordedTestSuite) TestCreateDirWithEmptyMetadata() { _require := require.New(s.T()) testName := s.T().Name() @@ -391,7 +474,7 @@ func (s *RecordedTestSuite) TestCreateFileWithEmptyMetadata() { _require.NotNil(resp) } -func (s *RecordedTestSuite) TestCreateFileWithNilHTTPHeaders() { +func (s *RecordedTestSuite) TestCreateDirWithNilHTTPHeaders() { _require := require.New(s.T()) testName := s.T().Name() @@ -418,7 +501,7 @@ func (s *RecordedTestSuite) TestCreateFileWithNilHTTPHeaders() { _require.NotNil(resp) } -func (s *RecordedTestSuite) TestCreateFileWithHTTPHeaders() { +func (s *RecordedTestSuite) TestCreateDirWithHTTPHeaders() { _require := require.New(s.T()) testName := s.T().Name() @@ -785,7 +868,7 @@ func (s *RecordedTestSuite) TestDeleteDirIfETagMatchFalse() { testcommon.ValidateErrorCode(_require, err, datalakeerror.ConditionNotMet) } -func (s *RecordedTestSuite) TestSetAccessControlNil() { +func (s *RecordedTestSuite) TestDirSetAccessControlNil() { _require := require.New(s.T()) testName := s.T().Name() @@ -812,7 +895,7 @@ func (s *RecordedTestSuite) TestSetAccessControlNil() { } // TODO: write test that fails if you provide permissions and acls -func (s *RecordedTestSuite) TestSetAccessControl() { +func (s *RecordedTestSuite) TestDirSetAccessControl() { _require := require.New(s.T()) testName := s.T().Name() @@ -845,7 +928,7 @@ func (s *RecordedTestSuite) TestSetAccessControl() { _require.Nil(err) } -func (s *RecordedTestSuite) TestSetAccessControlWithNilAccessConditions() { +func (s *RecordedTestSuite) TestDirSetAccessControlWithNilAccessConditions() { _require := require.New(s.T()) testName := s.T().Name() @@ -879,7 +962,7 @@ func (s *RecordedTestSuite) TestSetAccessControlWithNilAccessConditions() { _require.Nil(err) } -func (s *RecordedTestSuite) TestSetAccessControlIfModifiedSinceTrue() { +func (s *RecordedTestSuite) TestDirSetAccessControlIfModifiedSinceTrue() { _require := require.New(s.T()) testName := s.T().Name() @@ -918,7 +1001,7 @@ func (s *RecordedTestSuite) TestSetAccessControlIfModifiedSinceTrue() { _require.Nil(err) } -func (s *RecordedTestSuite) TestSetAccessControlIfModifiedSinceFalse() { +func (s *RecordedTestSuite) TestDirSetAccessControlIfModifiedSinceFalse() { _require := require.New(s.T()) testName := s.T().Name() @@ -958,7 +1041,7 @@ func (s *RecordedTestSuite) TestSetAccessControlIfModifiedSinceFalse() { testcommon.ValidateErrorCode(_require, err, datalakeerror.ConditionNotMet) } -func (s *RecordedTestSuite) TestSetAccessControlIfUnmodifiedSinceTrue() { +func (s *RecordedTestSuite) TestDirSetAccessControlIfUnmodifiedSinceTrue() { _require := require.New(s.T()) testName := s.T().Name() @@ -996,7 +1079,7 @@ func (s *RecordedTestSuite) TestSetAccessControlIfUnmodifiedSinceTrue() { _require.Nil(err) } -func (s *RecordedTestSuite) TestSetAccessControlIfUnmodifiedSinceFalse() { +func (s *RecordedTestSuite) TestDirSetAccessControlIfUnmodifiedSinceFalse() { _require := require.New(s.T()) testName := s.T().Name() @@ -1038,7 +1121,7 @@ func (s *RecordedTestSuite) TestSetAccessControlIfUnmodifiedSinceFalse() { testcommon.ValidateErrorCode(_require, err, datalakeerror.ConditionNotMet) } -func (s *RecordedTestSuite) TestSetAccessControlIfETagMatch() { +func (s *RecordedTestSuite) TestDirSetAccessControlIfETagMatch() { _require := require.New(s.T()) testName := s.T().Name() @@ -1077,7 +1160,7 @@ func (s *RecordedTestSuite) TestSetAccessControlIfETagMatch() { _require.Nil(err) } -func (s *RecordedTestSuite) TestSetAccessControlIfETagMatchFalse() { +func (s *RecordedTestSuite) TestDirSetAccessControlIfETagMatchFalse() { _require := require.New(s.T()) testName := s.T().Name() @@ -1116,7 +1199,7 @@ func (s *RecordedTestSuite) TestSetAccessControlIfETagMatchFalse() { testcommon.ValidateErrorCode(_require, err, datalakeerror.ConditionNotMet) } -func (s *RecordedTestSuite) TestGetAccessControl() { +func (s *RecordedTestSuite) TestDirGetAccessControl() { _require := require.New(s.T()) testName := s.T().Name() @@ -1145,7 +1228,7 @@ func (s *RecordedTestSuite) TestGetAccessControl() { _require.Equal(acl, *getACLResp.ACL) } -func (s *RecordedTestSuite) TestGetAccessControlWithSAS() { +func (s *UnrecordedTestSuite) TestDirGetAccessControlWithSAS() { _require := require.New(s.T()) testName := s.T().Name() @@ -1189,7 +1272,7 @@ func (s *RecordedTestSuite) TestGetAccessControlWithSAS() { _require.Equal(acl, *getACLResp.ACL) } -func (s *RecordedTestSuite) TestDeleteWithSAS() { +func (s *UnrecordedTestSuite) TestDeleteWithSAS() { _require := require.New(s.T()) testName := s.T().Name() @@ -1228,7 +1311,7 @@ func (s *RecordedTestSuite) TestDeleteWithSAS() { _require.Nil(err) } -func (s *RecordedTestSuite) TestGetAccessControlWithNilAccessConditions() { +func (s *RecordedTestSuite) TestDirGetAccessControlWithNilAccessConditions() { _require := require.New(s.T()) testName := s.T().Name() @@ -1261,7 +1344,7 @@ func (s *RecordedTestSuite) TestGetAccessControlWithNilAccessConditions() { _require.Equal(acl, *getACLResp.ACL) } -func (s *RecordedTestSuite) TestGetAccessControlIfModifiedSinceTrue() { +func (s *RecordedTestSuite) TestDirGetAccessControlIfModifiedSinceTrue() { _require := require.New(s.T()) testName := s.T().Name() @@ -1299,7 +1382,7 @@ func (s *RecordedTestSuite) TestGetAccessControlIfModifiedSinceTrue() { _require.Equal(acl, *getACLResp.ACL) } -func (s *RecordedTestSuite) TestGetAccessControlIfModifiedSinceFalse() { +func (s *RecordedTestSuite) TestDirGetAccessControlIfModifiedSinceFalse() { _require := require.New(s.T()) testName := s.T().Name() @@ -1337,7 +1420,7 @@ func (s *RecordedTestSuite) TestGetAccessControlIfModifiedSinceFalse() { testcommon.ValidateErrorCode(_require, err, datalakeerror.ConditionNotMet) } -func (s *RecordedTestSuite) TestGetAccessControlIfUnmodifiedSinceTrue() { +func (s *RecordedTestSuite) TestDirGetAccessControlIfUnmodifiedSinceTrue() { _require := require.New(s.T()) testName := s.T().Name() @@ -1374,7 +1457,7 @@ func (s *RecordedTestSuite) TestGetAccessControlIfUnmodifiedSinceTrue() { _require.Equal(acl, *getACLResp.ACL) } -func (s *RecordedTestSuite) TestGetAccessControlIfUnmodifiedSinceFalse() { +func (s *RecordedTestSuite) TestDirGetAccessControlIfUnmodifiedSinceFalse() { _require := require.New(s.T()) testName := s.T().Name() @@ -1414,7 +1497,7 @@ func (s *RecordedTestSuite) TestGetAccessControlIfUnmodifiedSinceFalse() { testcommon.ValidateErrorCode(_require, err, datalakeerror.ConditionNotMet) } -func (s *RecordedTestSuite) TestGetAccessControlIfETagMatch() { +func (s *RecordedTestSuite) TestDirGetAccessControlIfETagMatch() { _require := require.New(s.T()) testName := s.T().Name() @@ -1452,7 +1535,7 @@ func (s *RecordedTestSuite) TestGetAccessControlIfETagMatch() { _require.Equal(acl, *getACLResp.ACL) } -func (s *RecordedTestSuite) TestGetAccessControlIfETagMatchFalse() { +func (s *RecordedTestSuite) TestDirGetAccessControlIfETagMatchFalse() { _require := require.New(s.T()) testName := s.T().Name() @@ -1491,7 +1574,263 @@ func (s *RecordedTestSuite) TestGetAccessControlIfETagMatchFalse() { ///===================================================================== -func (s *RecordedTestSuite) TestUpdateAccessControlRecursive() { +func (s *RecordedTestSuite) TestDirSetAccessControlRecursive() { + _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) + + _, 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.SetAccessControlRecursive(acl, nil) + _require.Nil(err) + + _require.Equal(resp1.DirectoriesSuccessful, to.Ptr(int32(1))) + _require.Equal(resp1.FilesSuccessful, to.Ptr(int32(0))) + _require.Equal(resp1.FailureCount, to.Ptr(int32(0))) + + getACLResp, err := dirClient.GetAccessControl(context.Background(), nil) + _require.Nil(err) + _require.Equal(acl, *getACLResp.ACL) +} + +func (s *RecordedTestSuite) TestDirSetAccessControlRecursiveWithBadContinuation() { + _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) + + _, 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.SetAccessControlRecursiveOptions{Marker: to.Ptr("garbage")} + resp1, err := dirClient.SetAccessControlRecursive(acl, opts) + _require.Nil(err) + + _require.Equal(resp1.DirectoriesSuccessful, to.Ptr(int32(0))) + _require.Equal(resp1.FilesSuccessful, to.Ptr(int32(0))) + _require.Equal(resp1.FailureCount, to.Ptr(int32(0))) +} + +func (s *RecordedTestSuite) TestDirSetAccessControlRecursiveWithEmptyOpts() { + _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) + + _, 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.SetAccessControlRecursiveOptions{} + resp1, err := dirClient.SetAccessControlRecursive(acl, opts) + _require.Nil(err) + + _require.Equal(resp1.DirectoriesSuccessful, to.Ptr(int32(1))) + _require.Equal(resp1.FilesSuccessful, to.Ptr(int32(0))) + _require.Equal(resp1.FailureCount, to.Ptr(int32(0))) + + getACLResp, err := dirClient.GetAccessControl(context.Background(), nil) + _require.Nil(err) + _require.Equal(acl, *getACLResp.ACL) +} + +func (s *RecordedTestSuite) TestDirSetAccessControlRecursiveWithMaxResults() { + _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) + + _, 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.Create(context.Background(), nil) + _require.Nil(err) + _require.NotNil(resp1) + + fileClient, err := dirClient.NewFileClient(testcommon.GenerateFileName(testName)) + _require.Nil(err) + _require.NotNil(fileClient) + + _, err = fileClient.Create(context.Background(), nil) + _require.Nil(err) + + fileClient1, err := dirClient.NewFileClient(testcommon.GenerateFileName(testName + "1")) + _require.Nil(err) + _require.NotNil(fileClient1) + + _, err = fileClient1.Create(context.Background(), nil) + _require.Nil(err) + + opts := &directory.SetAccessControlRecursiveOptions{BatchSize: to.Ptr(int32(2)), MaxBatches: to.Ptr(int32(1)), ContinueOnFailure: to.Ptr(true), Marker: nil} + resp2, err := dirClient.SetAccessControlRecursive(acl, opts) + _require.Nil(err) + + // we expect only one file to have been updated not both since our batch size is 2 and max batches is 1 + _require.Equal(resp2.DirectoriesSuccessful, to.Ptr(int32(1))) + _require.Equal(resp2.FilesSuccessful, to.Ptr(int32(1))) + _require.Equal(resp2.FailureCount, to.Ptr(int32(0))) + + getACLResp, err := dirClient.GetAccessControl(context.Background(), nil) + _require.Nil(err) + _require.Equal(acl, *getACLResp.ACL) +} + +func (s *RecordedTestSuite) TestDirSetAccessControlRecursiveWithMaxResults2() { + _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) + + _, 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.Create(context.Background(), nil) + _require.Nil(err) + _require.NotNil(resp1) + + fileClient, err := dirClient.NewFileClient(testcommon.GenerateFileName(testName)) + _require.Nil(err) + _require.NotNil(fileClient) + + _, err = fileClient.Create(context.Background(), nil) + _require.Nil(err) + + fileClient1, err := dirClient.NewFileClient(testcommon.GenerateFileName(testName + "1")) + _require.Nil(err) + _require.NotNil(fileClient1) + + _, err = fileClient1.Create(context.Background(), nil) + _require.Nil(err) + + opts := &directory.SetAccessControlRecursiveOptions{ContinueOnFailure: to.Ptr(true), Marker: nil} + resp2, err := dirClient.SetAccessControlRecursive(acl, opts) + _require.Nil(err) + + // we expect only one file to have been updated not both since our batch size is 2 and max batches is 1 + _require.Equal(resp2.DirectoriesSuccessful, to.Ptr(int32(1))) + _require.Equal(resp2.FilesSuccessful, to.Ptr(int32(2))) + _require.Equal(resp2.FailureCount, to.Ptr(int32(0))) + + getACLResp, err := dirClient.GetAccessControl(context.Background(), nil) + _require.Nil(err) + _require.Equal(acl, *getACLResp.ACL) +} + +func (s *RecordedTestSuite) TestDirSetAccessControlRecursiveWithMaxResults3() { + _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) + + _, 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.Create(context.Background(), nil) + _require.Nil(err) + _require.NotNil(resp1) + + fileClient, err := dirClient.NewFileClient(testcommon.GenerateFileName(testName)) + _require.Nil(err) + _require.NotNil(fileClient) + + _, err = fileClient.Create(context.Background(), nil) + _require.Nil(err) + + fileClient1, err := dirClient.NewFileClient(testcommon.GenerateFileName(testName + "1")) + _require.Nil(err) + _require.NotNil(fileClient1) + + _, err = fileClient1.Create(context.Background(), nil) + _require.Nil(err) + + opts := &directory.SetAccessControlRecursiveOptions{BatchSize: to.Ptr(int32(1)), ContinueOnFailure: to.Ptr(true), Marker: nil} + resp2, err := dirClient.SetAccessControlRecursive(acl, opts) + _require.Nil(err) + + // we expect only one file to have been updated not both since our batch size is 2 and max batches is 1 + _require.Equal(resp2.DirectoriesSuccessful, to.Ptr(int32(1))) + _require.Equal(resp2.FilesSuccessful, to.Ptr(int32(2))) + _require.Equal(resp2.FailureCount, to.Ptr(int32(0))) + + getACLResp, err := dirClient.GetAccessControl(context.Background(), nil) + _require.Nil(err) + _require.Equal(acl, *getACLResp.ACL) +} + +func (s *RecordedTestSuite) TestDirUpdateAccessControlRecursive() { _require := require.New(s.T()) testName := s.T().Name() @@ -1516,19 +1855,17 @@ func (s *RecordedTestSuite) TestUpdateAccessControlRecursive() { _require.Nil(err) _require.NotNil(resp) - pager := dirClient.NewUpdateAccessControlRecursivePager(acl1, nil) + resp1, err := dirClient.UpdateAccessControlRecursive(acl1, nil) + _require.Nil(err) + _require.Equal(resp1.DirectoriesSuccessful, to.Ptr(int32(1))) + + resp2, err := dirClient.GetAccessControl(context.Background(), nil) + _require.Nil(err) + _require.Equal(acl1, *resp2.ACL) - 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() { +func (s *RecordedTestSuite) TestDirRemoveAccessControlRecursive() { _require := require.New(s.T()) testName := s.T().Name() @@ -1551,19 +1888,12 @@ func (s *RecordedTestSuite) TestRemoveAccessControlRecursive() { _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 - } - } + resp1, err := dirClient.RemoveAccessControlRecursive(acl, nil) + _require.Nil(err) + _require.Equal(resp1.DirectoriesSuccessful, to.Ptr(int32(1))) } -func (s *RecordedTestSuite) TestSetMetadataNil() { +func (s *RecordedTestSuite) TestDirSetMetadataNil() { _require := require.New(s.T()) testName := s.T().Name() @@ -1589,7 +1919,7 @@ func (s *RecordedTestSuite) TestSetMetadataNil() { _require.Nil(err) } -func (s *RecordedTestSuite) TestSetMetadataWithEmptyOpts() { +func (s *RecordedTestSuite) TestDirSetMetadataWithEmptyOpts() { _require := require.New(s.T()) testName := s.T().Name() @@ -1618,7 +1948,7 @@ func (s *RecordedTestSuite) TestSetMetadataWithEmptyOpts() { _require.Nil(err) } -func (s *RecordedTestSuite) TestSetMetadataWithBasicMetadata() { +func (s *RecordedTestSuite) TestDirSetMetadataWithBasicMetadata() { _require := require.New(s.T()) testName := s.T().Name() @@ -1647,7 +1977,7 @@ func (s *RecordedTestSuite) TestSetMetadataWithBasicMetadata() { _require.Nil(err) } -func (s *RecordedTestSuite) TestSetMetadataWithAccessConditions() { +func (s *RecordedTestSuite) TestDirSetMetadataWithAccessConditions() { _require := require.New(s.T()) testName := s.T().Name() @@ -1689,7 +2019,7 @@ func validatePropertiesSet(_require *require.Assertions, dirClient *directory.Cl _require.Equal(*resp.ContentDisposition, disposition) } -func (s *RecordedTestSuite) TestSetHTTPHeaders() { +func (s *RecordedTestSuite) TestDirSetHTTPHeaders() { _require := require.New(s.T()) testName := s.T().Name() @@ -1714,7 +2044,7 @@ func (s *RecordedTestSuite) TestSetHTTPHeaders() { validatePropertiesSet(_require, dirClient, *testcommon.BasicHeaders.ContentDisposition) } -func (s *RecordedTestSuite) TestSetHTTPHeadersWithNilAccessConditions() { +func (s *RecordedTestSuite) TestDirSetHTTPHeadersWithNilAccessConditions() { _require := require.New(s.T()) testName := s.T().Name() @@ -1743,7 +2073,7 @@ func (s *RecordedTestSuite) TestSetHTTPHeadersWithNilAccessConditions() { validatePropertiesSet(_require, dirClient, *testcommon.BasicHeaders.ContentDisposition) } -func (s *RecordedTestSuite) TestSetHTTPHeadersIfModifiedSinceTrue() { +func (s *RecordedTestSuite) TestDirSetHTTPHeadersIfModifiedSinceTrue() { _require := require.New(s.T()) testName := s.T().Name() @@ -1777,7 +2107,7 @@ func (s *RecordedTestSuite) TestSetHTTPHeadersIfModifiedSinceTrue() { validatePropertiesSet(_require, dirClient, *testcommon.BasicHeaders.ContentDisposition) } -func (s *RecordedTestSuite) TestSetHTTPHeadersIfModifiedSinceFalse() { +func (s *RecordedTestSuite) TestDirSetHTTPHeadersIfModifiedSinceFalse() { _require := require.New(s.T()) testName := s.T().Name() @@ -1811,7 +2141,7 @@ func (s *RecordedTestSuite) TestSetHTTPHeadersIfModifiedSinceFalse() { testcommon.ValidateErrorCode(_require, err, datalakeerror.ConditionNotMet) } -func (s *RecordedTestSuite) TestSetHTTPHeadersIfUnmodifiedSinceTrue() { +func (s *RecordedTestSuite) TestDirSetHTTPHeadersIfUnmodifiedSinceTrue() { _require := require.New(s.T()) testName := s.T().Name() @@ -1845,7 +2175,7 @@ func (s *RecordedTestSuite) TestSetHTTPHeadersIfUnmodifiedSinceTrue() { validatePropertiesSet(_require, dirClient, *testcommon.BasicHeaders.ContentDisposition) } -func (s *RecordedTestSuite) TestSetHTTPHeadersIfUnmodifiedSinceFalse() { +func (s *RecordedTestSuite) TestDirSetHTTPHeadersIfUnmodifiedSinceFalse() { _require := require.New(s.T()) testName := s.T().Name() @@ -1879,7 +2209,7 @@ func (s *RecordedTestSuite) TestSetHTTPHeadersIfUnmodifiedSinceFalse() { testcommon.ValidateErrorCode(_require, err, datalakeerror.ConditionNotMet) } -func (s *RecordedTestSuite) TestSetHTTPHeadersIfETagMatch() { +func (s *RecordedTestSuite) TestDirSetHTTPHeadersIfETagMatch() { _require := require.New(s.T()) testName := s.T().Name() @@ -1912,7 +2242,7 @@ func (s *RecordedTestSuite) TestSetHTTPHeadersIfETagMatch() { validatePropertiesSet(_require, dirClient, *testcommon.BasicHeaders.ContentDisposition) } -func (s *RecordedTestSuite) TestSetHTTPHeadersIfETagMatchFalse() { +func (s *RecordedTestSuite) TestDirSetHTTPHeadersIfETagMatchFalse() { _require := require.New(s.T()) testName := s.T().Name() @@ -1946,7 +2276,7 @@ func (s *RecordedTestSuite) TestSetHTTPHeadersIfETagMatchFalse() { testcommon.ValidateErrorCode(_require, err, datalakeerror.ConditionNotMet) } -func (s *RecordedTestSuite) TestRenameNoOptions() { +func (s *RecordedTestSuite) TestDirRenameNoOptions() { _require := require.New(s.T()) testName := s.T().Name() @@ -1972,7 +2302,7 @@ func (s *RecordedTestSuite) TestRenameNoOptions() { _require.Contains(resp1.NewDirectoryClient.DFSURL(), "newName") } -func (s *RecordedTestSuite) TestRenameFileWithNilAccessConditions() { +func (s *RecordedTestSuite) TestRenameDirWithNilAccessConditions() { _require := require.New(s.T()) testName := s.T().Name() @@ -2002,7 +2332,7 @@ func (s *RecordedTestSuite) TestRenameFileWithNilAccessConditions() { _require.Contains(resp1.NewDirectoryClient.DFSURL(), "newName") } -func (s *RecordedTestSuite) TestRenameFileIfModifiedSinceTrue() { +func (s *RecordedTestSuite) TestRenameDirIfModifiedSinceTrue() { _require := require.New(s.T()) testName := s.T().Name() @@ -2037,7 +2367,7 @@ func (s *RecordedTestSuite) TestRenameFileIfModifiedSinceTrue() { _require.Contains(resp1.NewDirectoryClient.DFSURL(), "newName") } -func (s *RecordedTestSuite) TestRenameFileIfModifiedSinceFalse() { +func (s *RecordedTestSuite) TestRenameDirIfModifiedSinceFalse() { _require := require.New(s.T()) testName := s.T().Name() @@ -2072,7 +2402,7 @@ func (s *RecordedTestSuite) TestRenameFileIfModifiedSinceFalse() { testcommon.ValidateErrorCode(_require, err, datalakeerror.SourceConditionNotMet) } -func (s *RecordedTestSuite) TestRenameFileIfUnmodifiedSinceTrue() { +func (s *RecordedTestSuite) TestRenameDirIfUnmodifiedSinceTrue() { _require := require.New(s.T()) testName := s.T().Name() @@ -2103,11 +2433,12 @@ func (s *RecordedTestSuite) TestRenameFileIfUnmodifiedSinceTrue() { } resp1, err := dirClient.Rename(context.Background(), "newName", renameFileOpts) + _require.Nil(err) _require.NotNil(resp1) _require.Contains(resp1.NewDirectoryClient.DFSURL(), "newName") } -func (s *RecordedTestSuite) TestRenameFileIfUnmodifiedSinceFalse() { +func (s *RecordedTestSuite) TestRenameDirIfUnmodifiedSinceFalse() { _require := require.New(s.T()) testName := s.T().Name() @@ -2142,7 +2473,7 @@ func (s *RecordedTestSuite) TestRenameFileIfUnmodifiedSinceFalse() { testcommon.ValidateErrorCode(_require, err, datalakeerror.SourceConditionNotMet) } -func (s *RecordedTestSuite) TestRenameFileIfETagMatch() { +func (s *RecordedTestSuite) TestRenameDirIfETagMatch() { _require := require.New(s.T()) testName := s.T().Name() @@ -2173,11 +2504,12 @@ func (s *RecordedTestSuite) TestRenameFileIfETagMatch() { } resp1, err := dirClient.Rename(context.Background(), "newName", renameFileOpts) + _require.Nil(err) _require.NotNil(resp1) _require.Contains(resp1.NewDirectoryClient.DFSURL(), "newName") } -func (s *RecordedTestSuite) TestRenameFileIfETagMatchFalse() { +func (s *RecordedTestSuite) TestRenameDirIfETagMatchFalse() { _require := require.New(s.T()) testName := s.T().Name() diff --git a/sdk/storage/azdatalake/directory/models.go b/sdk/storage/azdatalake/directory/models.go index 517fdf0cda44..9e3016c05322 100644 --- a/sdk/storage/azdatalake/directory/models.go +++ b/sdk/storage/azdatalake/directory/models.go @@ -7,6 +7,7 @@ package directory import ( + "github.com/Azure/azure-sdk-for-go/sdk/azcore/to" "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" @@ -73,17 +74,14 @@ 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 = path.DeleteOptions - -// 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 +// SetAccessControlRecursiveOptions contains the optional parameters when calling the SetAccessControlRecursive operation. type accessControlRecursiveOptions struct { - MaxResults *int32 + // Max batch size is 2000 paths + BatchSize *int32 + // Number of recursive calls to be made to set access control + 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. @@ -91,30 +89,42 @@ type accessControlRecursiveOptions struct { } func (o *accessControlRecursiveOptions) format(ACL, mode string) (generated.PathSetAccessControlRecursiveMode, *generated.PathClientSetAccessControlRecursiveOptions) { + defaultMaxBatches := to.Ptr(int32(-1)) + defaultForceFlag := to.Ptr(false) opts := &generated.PathClientSetAccessControlRecursiveOptions{ ACL: &ACL, } newMode := generated.PathSetAccessControlRecursiveMode(mode) - if o == nil { - return newMode, opts + if o.ContinueOnFailure == nil { + opts.ForceFlag = defaultForceFlag + } else { + opts.ForceFlag = o.ContinueOnFailure } - opts.ForceFlag = o.ContinueOnFailure opts.Continuation = o.Marker - opts.MaxRecords = o.MaxResults + opts.MaxRecords = o.BatchSize + if o.MaxBatches == nil { + o.MaxBatches = defaultMaxBatches + } return newMode, opts } -// SetAccessControlRecursiveOptions contains the optional parameters when calling the UpdateAccessControlRecursive operation. TODO: Design formatter +// SetAccessControlRecursiveOptions contains the optional parameters when calling the UpdateAccessControlRecursive operation. type SetAccessControlRecursiveOptions = accessControlRecursiveOptions -// UpdateAccessControlRecursiveOptions contains the optional parameters when calling the UpdateAccessControlRecursive operation. TODO: Design formatter +// UpdateAccessControlRecursiveOptions contains the optional parameters when calling the UpdateAccessControlRecursive operation. type UpdateAccessControlRecursiveOptions = accessControlRecursiveOptions -// RemoveAccessControlRecursiveOptions contains the optional parameters when calling the RemoveAccessControlRecursive operation. TODO: Design formatter +// RemoveAccessControlRecursiveOptions contains the optional parameters when calling the RemoveAccessControlRecursive operation. type RemoveAccessControlRecursiveOptions = accessControlRecursiveOptions // ================================= 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 @@ -159,3 +169,6 @@ type SourceModifiedAccessConditions = path.SourceModifiedAccessConditions // CPKScopeInfo contains a group of parameters for the PathClient.SetMetadata method. type CPKScopeInfo path.CPKScopeInfo + +// ACLFailedEntry contains the failed ACL entry (response model). +type ACLFailedEntry = path.ACLFailedEntry diff --git a/sdk/storage/azdatalake/directory/responses.go b/sdk/storage/azdatalake/directory/responses.go index dc2ad337ddb9..ce5a222f298b 100644 --- a/sdk/storage/azdatalake/directory/responses.go +++ b/sdk/storage/azdatalake/directory/responses.go @@ -7,30 +7,30 @@ package directory import ( - "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/internal/generated" "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/internal/path" ) -// CreateResponse contains the response fields for the Create operation. -type CreateResponse = generated.PathClientCreateResponse - -// DeleteResponse contains the response fields for the Delete operation. -type DeleteResponse = generated.PathClientDeleteResponse - // RenameResponse contains the response fields for the Create operation. type RenameResponse struct { - Response generated.PathClientCreateResponse + Response CreateResponse NewDirectoryClient *Client } +type setAccessControlRecursiveResponse struct { + DirectoriesSuccessful *int32 + FailureCount *int32 + FilesSuccessful *int32 + FailedEntries []*ACLFailedEntry +} + // SetAccessControlRecursiveResponse contains the response fields for the SetAccessControlRecursive operation. -type SetAccessControlRecursiveResponse = generated.PathClientSetAccessControlRecursiveResponse +type SetAccessControlRecursiveResponse = setAccessControlRecursiveResponse // UpdateAccessControlRecursiveResponse contains the response fields for the UpdateAccessControlRecursive operation. -type UpdateAccessControlRecursiveResponse = generated.PathClientSetAccessControlRecursiveResponse +type UpdateAccessControlRecursiveResponse = setAccessControlRecursiveResponse // RemoveAccessControlRecursiveResponse contains the response fields for the RemoveAccessControlRecursive operation. -type RemoveAccessControlRecursiveResponse = generated.PathClientSetAccessControlRecursiveResponse +type RemoveAccessControlRecursiveResponse = setAccessControlRecursiveResponse // ========================================== path imports =========================================================== @@ -48,3 +48,9 @@ type GetPropertiesResponse = path.GetPropertiesResponse // SetMetadataResponse contains the response fields for the SetMetadata operation. type SetMetadataResponse = path.SetMetadataResponse + +// CreateResponse contains the response fields for the Create operation. +type CreateResponse = path.CreateResponse + +// DeleteResponse contains the response fields for the Delete operation. +type DeleteResponse = path.DeleteResponse diff --git a/sdk/storage/azdatalake/file/client.go b/sdk/storage/azdatalake/file/client.go index ca83eeecf698..101f580e06e7 100644 --- a/sdk/storage/azdatalake/file/client.go +++ b/sdk/storage/azdatalake/file/client.go @@ -21,6 +21,7 @@ import ( "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/generated_blob" "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" @@ -37,7 +38,7 @@ import ( type ClientOptions base.ClientOptions // Client represents a URL to the Azure Datalake Storage service. -type Client base.CompositeClient[generated.PathClient, generated.PathClient, blockblob.Client] +type Client base.CompositeClient[generated.PathClient, generated_blob.BlobClient, blockblob.Client] // NewClient creates an instance of Client with the specified values. // - fileURL - the URL of the blob e.g. https://.dfs.core.windows.net/fs/file.txt @@ -135,12 +136,15 @@ func NewClientWithSharedKeyCredential(fileURL string, cred *SharedKeyCredential, // NewClientFromConnectionString creates an instance of Client with the specified values. // - connectionString - a connection string for the desired storage account // - options - client options; pass nil to accept the default values -func NewClientFromConnectionString(connectionString string, options *ClientOptions) (*Client, error) { +func NewClientFromConnectionString(connectionString string, filePath, fsName string, options *ClientOptions) (*Client, error) { parsed, err := shared.ParseConnectionString(connectionString) if err != nil { return nil, err } + filePath = strings.ReplaceAll(filePath, "\\", "/") + parsed.ServiceURL = runtime.JoinPaths(parsed.ServiceURL, fsName, filePath) + if parsed.AccountKey != "" && parsed.AccountName != "" { credential, err := exported.NewSharedKeyCredential(parsed.AccountName, parsed.AccountKey) if err != nil { @@ -154,30 +158,30 @@ func NewClientFromConnectionString(connectionString string, options *ClientOptio func (f *Client) generatedFileClientWithDFS() *generated.PathClient { //base.SharedKeyComposite((*base.CompositeClient[generated.BlobClient, generated.BlockBlobClient])(bb)) - dirClientWithDFS, _, _ := base.InnerClients((*base.CompositeClient[generated.PathClient, generated.PathClient, blockblob.Client])(f)) + dirClientWithDFS, _, _ := base.InnerClients((*base.CompositeClient[generated.PathClient, generated_blob.BlobClient, blockblob.Client])(f)) return dirClientWithDFS } -func (f *Client) generatedFileClientWithBlob() *generated.PathClient { - _, dirClientWithBlob, _ := base.InnerClients((*base.CompositeClient[generated.PathClient, generated.PathClient, blockblob.Client])(f)) +func (f *Client) generatedFileClientWithBlob() *generated_blob.BlobClient { + _, dirClientWithBlob, _ := base.InnerClients((*base.CompositeClient[generated.PathClient, generated_blob.BlobClient, blockblob.Client])(f)) return dirClientWithBlob } func (f *Client) blobClient() *blockblob.Client { - _, _, blobClient := base.InnerClients((*base.CompositeClient[generated.PathClient, generated.PathClient, blockblob.Client])(f)) + _, _, blobClient := base.InnerClients((*base.CompositeClient[generated.PathClient, generated_blob.BlobClient, blockblob.Client])(f)) return blobClient } func (f *Client) sharedKey() *exported.SharedKeyCredential { - return base.SharedKeyComposite((*base.CompositeClient[generated.PathClient, generated.PathClient, blockblob.Client])(f)) + return base.SharedKeyComposite((*base.CompositeClient[generated.PathClient, generated_blob.BlobClient, blockblob.Client])(f)) } func (f *Client) identityCredential() *azcore.TokenCredential { - return base.IdentityCredentialComposite((*base.CompositeClient[generated.PathClient, generated.PathClient, blockblob.Client])(f)) + return base.IdentityCredentialComposite((*base.CompositeClient[generated.PathClient, generated_blob.BlobClient, blockblob.Client])(f)) } func (f *Client) getClientOptions() *base.ClientOptions { - return base.GetCompositeClientOptions((*base.CompositeClient[generated.PathClient, generated.PathClient, blockblob.Client])(f)) + return base.GetCompositeClientOptions((*base.CompositeClient[generated.PathClient, generated_blob.BlobClient, blockblob.Client])(f)) } // DFSURL returns the URL endpoint used by the Client object. @@ -350,12 +354,18 @@ func (f *Client) GetSASURL(permissions sas.FilePermissions, expiry time.Time, o } func (f *Client) AppendData(ctx context.Context, offset int64, body io.ReadSeekCloser, options *AppendDataOptions) (AppendDataResponse, error) { - appendDataOptions, leaseAccessConditions, httpsHeaders, cpkInfo, err := options.format(offset, body) + appendDataOptions, leaseAccessConditions, cpkInfo, err := options.format(offset, body) if err != nil { return AppendDataResponse{}, err } - - resp, err := f.generatedFileClientWithDFS().AppendData(ctx, body, appendDataOptions, httpsHeaders, leaseAccessConditions, cpkInfo) + resp, err := f.generatedFileClientWithDFS().AppendData(ctx, body, appendDataOptions, nil, leaseAccessConditions, cpkInfo) + // TODO: check and uncomment this + //if err != nil { + // _, err1 := body.Seek(0, io.SeekStart) + // if err1 != nil { + // return AppendDataResponse{}, err1 + // } + //} return resp, exported.ConvertToDFSError(err) } diff --git a/sdk/storage/azdatalake/file/client_test.go b/sdk/storage/azdatalake/file/client_test.go index 09e50c55615c..a05807217188 100644 --- a/sdk/storage/azdatalake/file/client_test.go +++ b/sdk/storage/azdatalake/file/client_test.go @@ -69,11 +69,38 @@ type UnrecordedTestSuite struct { suite.Suite } -func validateFileDeleted(_require *require.Assertions, fileClient *file.Client) { - _, err := fileClient.GetAccessControl(context.Background(), nil) - _require.NotNil(err) +//func validateFileDeleted(_require *require.Assertions, fileClient *file.Client) { +// _, err := fileClient.GetAccessControl(context.Background(), nil) +// _require.NotNil(err) +// +// testcommon.ValidateErrorCode(_require, err, datalakeerror.PathNotFound) +//} - testcommon.ValidateErrorCode(_require, err, datalakeerror.PathNotFound) +func (s *UnrecordedTestSuite) TestCreateFileAndDeleteWithConnectionString() { + + _require := require.New(s.T()) + testName := s.T().Name() + + connectionString, _ := testcommon.GetGenericConnectionString(testcommon.TestAccountDatalake) + + 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) + + fileName := testcommon.GenerateDirName(testName) + fileClient, err := file.NewClientFromConnectionString(*connectionString, fileName, filesystemName, nil) + + _require.NoError(err) + + defer testcommon.DeleteFile(context.Background(), _require, fileClient) + + resp, err := fileClient.Create(context.Background(), nil) + _require.Nil(err) + _require.NotNil(resp) } func (s *RecordedTestSuite) TestCreateFileAndDelete() { @@ -435,34 +462,7 @@ func (s *RecordedTestSuite) TestCreateFileWithNilHTTPHeaders() { _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) - - createFileOpts := &file.CreateOptions{ - HTTPHeaders: &testcommon.BasicHeaders, - } - - _, err = fsClient.Create(context.Background(), nil) - _require.Nil(err) - - fileName := testcommon.GenerateFileName(testName) - fClient, err := testcommon.GetFileClient(filesystemName, fileName, s.T(), testcommon.TestAccountDatalake, nil) - _require.NoError(err) - - defer testcommon.DeleteFile(context.Background(), _require, fClient) - - resp, err := fClient.Create(context.Background(), createFileOpts) - _require.Nil(err) - _require.NotNil(resp) -} - -func (s *RecordedTestSuite) TestCreateFileWithExpiryAbsolute() { +func (s *UnrecordedTestSuite) TestCreateFileWithExpiryAbsolute() { _require := require.New(s.T()) testName := s.T().Name() @@ -899,7 +899,7 @@ func (s *RecordedTestSuite) TestDeleteFileIfETagMatchFalse() { testcommon.ValidateErrorCode(_require, err, datalakeerror.ConditionNotMet) } -func (s *RecordedTestSuite) TestSetAccessControlNil() { +func (s *RecordedTestSuite) TestFileSetAccessControlNil() { _require := require.New(s.T()) testName := s.T().Name() @@ -926,7 +926,7 @@ func (s *RecordedTestSuite) TestSetAccessControlNil() { } // TODO: write test that fails if you provide permissions and acls -func (s *RecordedTestSuite) TestSetAccessControl() { +func (s *RecordedTestSuite) TestFileSetAccessControl() { _require := require.New(s.T()) testName := s.T().Name() @@ -959,7 +959,7 @@ func (s *RecordedTestSuite) TestSetAccessControl() { _require.Nil(err) } -func (s *RecordedTestSuite) TestSetAccessControlWithNilAccessConditions() { +func (s *RecordedTestSuite) TestFileSetAccessControlWithNilAccessConditions() { _require := require.New(s.T()) testName := s.T().Name() @@ -993,7 +993,7 @@ func (s *RecordedTestSuite) TestSetAccessControlWithNilAccessConditions() { _require.Nil(err) } -func (s *RecordedTestSuite) TestSetAccessControlIfModifiedSinceTrue() { +func (s *RecordedTestSuite) TestFileSetAccessControlIfModifiedSinceTrue() { _require := require.New(s.T()) testName := s.T().Name() @@ -1032,7 +1032,7 @@ func (s *RecordedTestSuite) TestSetAccessControlIfModifiedSinceTrue() { _require.Nil(err) } -func (s *RecordedTestSuite) TestSetAccessControlIfModifiedSinceFalse() { +func (s *RecordedTestSuite) TestFileSetAccessControlIfModifiedSinceFalse() { _require := require.New(s.T()) testName := s.T().Name() @@ -1072,7 +1072,7 @@ func (s *RecordedTestSuite) TestSetAccessControlIfModifiedSinceFalse() { testcommon.ValidateErrorCode(_require, err, datalakeerror.ConditionNotMet) } -func (s *RecordedTestSuite) TestSetAccessControlIfUnmodifiedSinceTrue() { +func (s *RecordedTestSuite) TestFileSetAccessControlIfUnmodifiedSinceTrue() { _require := require.New(s.T()) testName := s.T().Name() @@ -1110,7 +1110,7 @@ func (s *RecordedTestSuite) TestSetAccessControlIfUnmodifiedSinceTrue() { _require.Nil(err) } -func (s *RecordedTestSuite) TestSetAccessControlIfUnmodifiedSinceFalse() { +func (s *RecordedTestSuite) TestFileSetAccessControlIfUnmodifiedSinceFalse() { _require := require.New(s.T()) testName := s.T().Name() @@ -1152,7 +1152,7 @@ func (s *RecordedTestSuite) TestSetAccessControlIfUnmodifiedSinceFalse() { testcommon.ValidateErrorCode(_require, err, datalakeerror.ConditionNotMet) } -func (s *RecordedTestSuite) TestSetAccessControlIfETagMatch() { +func (s *RecordedTestSuite) TestFileSetAccessControlIfETagMatch() { _require := require.New(s.T()) testName := s.T().Name() @@ -1191,7 +1191,7 @@ func (s *RecordedTestSuite) TestSetAccessControlIfETagMatch() { _require.Nil(err) } -func (s *RecordedTestSuite) TestSetAccessControlIfETagMatchFalse() { +func (s *RecordedTestSuite) TestFileSetAccessControlIfETagMatchFalse() { _require := require.New(s.T()) testName := s.T().Name() @@ -1230,7 +1230,7 @@ func (s *RecordedTestSuite) TestSetAccessControlIfETagMatchFalse() { testcommon.ValidateErrorCode(_require, err, datalakeerror.ConditionNotMet) } -func (s *RecordedTestSuite) TestGetAccessControl() { +func (s *RecordedTestSuite) TestFileGetAccessControl() { _require := require.New(s.T()) testName := s.T().Name() @@ -1259,7 +1259,7 @@ func (s *RecordedTestSuite) TestGetAccessControl() { _require.Equal(acl, *getACLResp.ACL) } -func (s *RecordedTestSuite) TestGetAccessControlWithSAS() { +func (s *UnrecordedTestSuite) TestFileGetAccessControlWithSAS() { _require := require.New(s.T()) testName := s.T().Name() @@ -1303,7 +1303,7 @@ func (s *RecordedTestSuite) TestGetAccessControlWithSAS() { _require.Equal(acl, *getACLResp.ACL) } -func (s *RecordedTestSuite) TestDeleteWithSAS() { +func (s *UnrecordedTestSuite) TestFileDeleteWithSAS() { _require := require.New(s.T()) testName := s.T().Name() @@ -1342,7 +1342,7 @@ func (s *RecordedTestSuite) TestDeleteWithSAS() { _require.Nil(err) } -func (s *RecordedTestSuite) TestGetAccessControlWithNilAccessConditions() { +func (s *RecordedTestSuite) TestFileGetAccessControlWithNilAccessConditions() { _require := require.New(s.T()) testName := s.T().Name() @@ -1375,7 +1375,7 @@ func (s *RecordedTestSuite) TestGetAccessControlWithNilAccessConditions() { _require.Equal(acl, *getACLResp.ACL) } -func (s *RecordedTestSuite) TestGetAccessControlIfModifiedSinceTrue() { +func (s *RecordedTestSuite) TestFileGetAccessControlIfModifiedSinceTrue() { _require := require.New(s.T()) testName := s.T().Name() @@ -1413,7 +1413,7 @@ func (s *RecordedTestSuite) TestGetAccessControlIfModifiedSinceTrue() { _require.Equal(acl, *getACLResp.ACL) } -func (s *RecordedTestSuite) TestGetAccessControlIfModifiedSinceFalse() { +func (s *RecordedTestSuite) TestFileGetAccessControlIfModifiedSinceFalse() { _require := require.New(s.T()) testName := s.T().Name() @@ -1451,7 +1451,7 @@ func (s *RecordedTestSuite) TestGetAccessControlIfModifiedSinceFalse() { testcommon.ValidateErrorCode(_require, err, datalakeerror.ConditionNotMet) } -func (s *RecordedTestSuite) TestGetAccessControlIfUnmodifiedSinceTrue() { +func (s *RecordedTestSuite) TestFileGetAccessControlIfUnmodifiedSinceTrue() { _require := require.New(s.T()) testName := s.T().Name() @@ -1488,7 +1488,7 @@ func (s *RecordedTestSuite) TestGetAccessControlIfUnmodifiedSinceTrue() { _require.Equal(acl, *getACLResp.ACL) } -func (s *RecordedTestSuite) TestGetAccessControlIfUnmodifiedSinceFalse() { +func (s *RecordedTestSuite) TestFileGetAccessControlIfUnmodifiedSinceFalse() { _require := require.New(s.T()) testName := s.T().Name() @@ -1528,7 +1528,7 @@ func (s *RecordedTestSuite) TestGetAccessControlIfUnmodifiedSinceFalse() { testcommon.ValidateErrorCode(_require, err, datalakeerror.ConditionNotMet) } -func (s *RecordedTestSuite) TestGetAccessControlIfETagMatch() { +func (s *RecordedTestSuite) TestFileGetAccessControlIfETagMatch() { _require := require.New(s.T()) testName := s.T().Name() @@ -1566,7 +1566,7 @@ func (s *RecordedTestSuite) TestGetAccessControlIfETagMatch() { _require.Equal(acl, *getACLResp.ACL) } -func (s *RecordedTestSuite) TestGetAccessControlIfETagMatchFalse() { +func (s *RecordedTestSuite) TestFileGetAccessControlIfETagMatchFalse() { _require := require.New(s.T()) testName := s.T().Name() @@ -1603,7 +1603,7 @@ func (s *RecordedTestSuite) TestGetAccessControlIfETagMatchFalse() { testcommon.ValidateErrorCode(_require, err, datalakeerror.ConditionNotMet) } -func (s *RecordedTestSuite) TestUpdateAccessControl() { +func (s *RecordedTestSuite) TestFileUpdateAccessControl() { _require := require.New(s.T()) testName := s.T().Name() @@ -1636,7 +1636,7 @@ func (s *RecordedTestSuite) TestUpdateAccessControl() { _require.Equal(acl1, *getACLResp.ACL) } -func (s *RecordedTestSuite) TestRemoveAccessControl() { +func (s *RecordedTestSuite) TestFileRemoveAccessControl() { _require := require.New(s.T()) testName := s.T().Name() @@ -1663,7 +1663,7 @@ func (s *RecordedTestSuite) TestRemoveAccessControl() { _require.Nil(err) } -func (s *RecordedTestSuite) TestSetMetadataNil() { +func (s *RecordedTestSuite) TestFileSetMetadataNil() { _require := require.New(s.T()) testName := s.T().Name() @@ -1689,7 +1689,7 @@ func (s *RecordedTestSuite) TestSetMetadataNil() { _require.Nil(err) } -func (s *RecordedTestSuite) TestSetMetadataWithEmptyOpts() { +func (s *RecordedTestSuite) TestFileSetMetadataWithEmptyOpts() { _require := require.New(s.T()) testName := s.T().Name() @@ -1718,7 +1718,7 @@ func (s *RecordedTestSuite) TestSetMetadataWithEmptyOpts() { _require.Nil(err) } -func (s *RecordedTestSuite) TestSetMetadataWithBasicMetadata() { +func (s *RecordedTestSuite) TestFileSetMetadataWithBasicMetadata() { _require := require.New(s.T()) testName := s.T().Name() @@ -1747,7 +1747,7 @@ func (s *RecordedTestSuite) TestSetMetadataWithBasicMetadata() { _require.Nil(err) } -func (s *RecordedTestSuite) TestSetMetadataWithAccessConditions() { +func (s *RecordedTestSuite) TestFileSetMetadataWithAccessConditions() { _require := require.New(s.T()) testName := s.T().Name() @@ -1789,7 +1789,7 @@ func validatePropertiesSet(_require *require.Assertions, fileClient *file.Client _require.Equal(*resp.ContentDisposition, disposition) } -func (s *RecordedTestSuite) TestSetHTTPHeaders() { +func (s *RecordedTestSuite) TestFileSetHTTPHeaders() { _require := require.New(s.T()) testName := s.T().Name() @@ -1814,7 +1814,7 @@ func (s *RecordedTestSuite) TestSetHTTPHeaders() { validatePropertiesSet(_require, fClient, *testcommon.BasicHeaders.ContentDisposition) } -func (s *RecordedTestSuite) TestSetHTTPHeadersWithNilAccessConditions() { +func (s *RecordedTestSuite) TestFileSetHTTPHeadersWithNilAccessConditions() { _require := require.New(s.T()) testName := s.T().Name() @@ -1843,7 +1843,7 @@ func (s *RecordedTestSuite) TestSetHTTPHeadersWithNilAccessConditions() { validatePropertiesSet(_require, fClient, *testcommon.BasicHeaders.ContentDisposition) } -func (s *RecordedTestSuite) TestSetHTTPHeadersIfModifiedSinceTrue() { +func (s *RecordedTestSuite) TestFileSetHTTPHeadersIfModifiedSinceTrue() { _require := require.New(s.T()) testName := s.T().Name() @@ -1877,7 +1877,7 @@ func (s *RecordedTestSuite) TestSetHTTPHeadersIfModifiedSinceTrue() { validatePropertiesSet(_require, fClient, *testcommon.BasicHeaders.ContentDisposition) } -func (s *RecordedTestSuite) TestSetHTTPHeadersIfModifiedSinceFalse() { +func (s *RecordedTestSuite) TestFileSetHTTPHeadersIfModifiedSinceFalse() { _require := require.New(s.T()) testName := s.T().Name() @@ -1911,7 +1911,7 @@ func (s *RecordedTestSuite) TestSetHTTPHeadersIfModifiedSinceFalse() { testcommon.ValidateErrorCode(_require, err, datalakeerror.ConditionNotMet) } -func (s *RecordedTestSuite) TestSetHTTPHeadersIfUnmodifiedSinceTrue() { +func (s *RecordedTestSuite) TestFileSetHTTPHeadersIfUnmodifiedSinceTrue() { _require := require.New(s.T()) testName := s.T().Name() @@ -1945,7 +1945,7 @@ func (s *RecordedTestSuite) TestSetHTTPHeadersIfUnmodifiedSinceTrue() { validatePropertiesSet(_require, fClient, *testcommon.BasicHeaders.ContentDisposition) } -func (s *RecordedTestSuite) TestSetHTTPHeadersIfUnmodifiedSinceFalse() { +func (s *RecordedTestSuite) TestFileSetHTTPHeadersIfUnmodifiedSinceFalse() { _require := require.New(s.T()) testName := s.T().Name() @@ -1979,7 +1979,7 @@ func (s *RecordedTestSuite) TestSetHTTPHeadersIfUnmodifiedSinceFalse() { testcommon.ValidateErrorCode(_require, err, datalakeerror.ConditionNotMet) } -func (s *RecordedTestSuite) TestSetHTTPHeadersIfETagMatch() { +func (s *RecordedTestSuite) TestFileSetHTTPHeadersIfETagMatch() { _require := require.New(s.T()) testName := s.T().Name() @@ -2012,7 +2012,7 @@ func (s *RecordedTestSuite) TestSetHTTPHeadersIfETagMatch() { validatePropertiesSet(_require, fClient, *testcommon.BasicHeaders.ContentDisposition) } -func (s *RecordedTestSuite) TestSetHTTPHeadersIfETagMatchFalse() { +func (s *RecordedTestSuite) TestFileSetHTTPHeadersIfETagMatchFalse() { _require := require.New(s.T()) testName := s.T().Name() @@ -2203,6 +2203,7 @@ func (s *RecordedTestSuite) TestRenameFileIfUnmodifiedSinceTrue() { } resp1, err := fClient.Rename(context.Background(), "newName", renameFileOpts) + _require.Nil(err) _require.NotNil(resp1) _require.Contains(resp1.NewFileClient.DFSURL(), "newName") } @@ -2273,6 +2274,7 @@ func (s *RecordedTestSuite) TestRenameFileIfETagMatch() { } resp1, err := fClient.Rename(context.Background(), "newName", renameFileOpts) + _require.Nil(err) _require.NotNil(resp1) _require.Contains(resp1.NewFileClient.DFSURL(), "newName") } @@ -2312,7 +2314,7 @@ func (s *RecordedTestSuite) TestRenameFileIfETagMatchFalse() { testcommon.ValidateErrorCode(_require, err, datalakeerror.SourceConditionNotMet) } -func (s *RecordedTestSuite) TestFileUploadDownloadStream() { +func (s *UnrecordedTestSuite) TestFileUploadDownloadStream() { _require := require.New(s.T()) testName := s.T().Name() @@ -2383,9 +2385,7 @@ func (s *RecordedTestSuite) TestFileUploadDownloadSmallStream() { _require.Nil(err) _require.NotNil(resp) - content := make([]byte, fileSize) - _, err = rand.Read(content) - _require.NoError(err) + _, content := testcommon.GenerateData(int(fileSize)) md5Value := md5.Sum(content) contentMD5 := md5Value[:] @@ -2395,10 +2395,6 @@ func (s *RecordedTestSuite) TestFileUploadDownloadSmallStream() { }) _require.NoError(err) - gResp2, err := fClient.GetProperties(context.Background(), nil) - _require.NoError(err) - _require.Equal(*gResp2.ContentLength, fileSize) - dResp, err := fClient.DownloadStream(context.Background(), nil) _require.NoError(err) @@ -2409,6 +2405,10 @@ func (s *RecordedTestSuite) TestFileUploadDownloadSmallStream() { downloadedContentMD5 := downloadedMD5Value[:] _require.EqualValues(downloadedContentMD5, contentMD5) + + gResp2, err := fClient.GetProperties(context.Background(), nil) + _require.NoError(err) + _require.Equal(*gResp2.ContentLength, fileSize) } func (s *RecordedTestSuite) TestFileUploadTinyStream() { @@ -2432,9 +2432,7 @@ func (s *RecordedTestSuite) TestFileUploadTinyStream() { _require.Nil(err) _require.NotNil(resp) - content := make([]byte, fileSize) - _, err = rand.Read(content) - _require.NoError(err) + _, content := testcommon.GenerateData(int(fileSize)) md5Value := md5.Sum(content) contentMD5 := md5Value[:] @@ -2460,7 +2458,7 @@ func (s *RecordedTestSuite) TestFileUploadTinyStream() { _require.EqualValues(downloadedContentMD5, contentMD5) } -func (s *RecordedTestSuite) TestFileUploadFile() { +func (s *UnrecordedTestSuite) TestFileUploadFile() { _require := require.New(s.T()) testName := s.T().Name() @@ -2550,8 +2548,7 @@ func (s *RecordedTestSuite) TestSmallFileUploadFile() { _require.NotNil(resp) // create local file - content := make([]byte, fileSize) - _, err = rand.Read(content) + _, content := testcommon.GenerateData(int(fileSize)) _require.NoError(err) err = os.WriteFile("testFile", content, 0644) _require.NoError(err) @@ -2618,8 +2615,7 @@ func (s *RecordedTestSuite) TestTinyFileUploadFile() { _require.NotNil(resp) // create local file - content := make([]byte, fileSize) - _, err = rand.Read(content) + _, content := testcommon.GenerateData(int(fileSize)) _require.NoError(err) err = os.WriteFile("testFile", content, 0644) _require.NoError(err) @@ -2663,7 +2659,7 @@ func (s *RecordedTestSuite) TestTinyFileUploadFile() { _require.EqualValues(downloadedContentMD5, contentMD5) } -func (s *RecordedTestSuite) TestFileUploadBuffer() { +func (s *UnrecordedTestSuite) TestFileUploadBuffer() { _require := require.New(s.T()) testName := s.T().Name() @@ -2732,9 +2728,7 @@ func (s *RecordedTestSuite) TestFileUploadSmallBuffer() { _require.Nil(err) _require.NotNil(resp) - content := make([]byte, fileSize) - _, err = rand.Read(content) - _require.NoError(err) + _, content := testcommon.GenerateData(int(fileSize)) md5Value := md5.Sum(content) contentMD5 := md5Value[:] @@ -2794,7 +2788,7 @@ func (s *RecordedTestSuite) TestFileAppendAndFlushData() { _require.Equal(*gResp2.ContentLength, int64(contentSize)) } -func (s *RecordedTestSuite) TestFileAppendAndFlushDataWithValidation() { +func (s *UnrecordedTestSuite) TestFileAppendAndFlushDataWithValidation() { _require := require.New(s.T()) testName := s.T().Name() @@ -2838,7 +2832,7 @@ func (s *RecordedTestSuite) TestFileAppendAndFlushDataWithValidation() { _require.Equal(*gResp2.ContentLength, int64(contentSize)) } -func (s *RecordedTestSuite) TestFileDownloadFile() { +func (s *RecordedTestSuite) TestFileAppendAndFlushDataWithEmptyOpts() { _require := require.New(s.T()) testName := s.T().Name() @@ -2850,59 +2844,33 @@ func (s *RecordedTestSuite) TestFileDownloadFile() { _, err = fsClient.Create(context.Background(), nil) _require.Nil(err) - var fileSize int64 = 100 * 1024 * 1024 - fileName := testcommon.GenerateFileName(testName) - fClient, err := testcommon.GetFileClient(filesystemName, fileName, s.T(), testcommon.TestAccountDatalake, nil) + srcFileName := "src" + testcommon.GenerateFileName(testName) + + srcFClient, err := testcommon.GetFileClient(filesystemName, srcFileName, s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) - resp, err := fClient.Create(context.Background(), nil) + resp, err := srcFClient.Create(context.Background(), nil) _require.Nil(err) _require.NotNil(resp) - content := make([]byte, fileSize) - _, err = rand.Read(content) - _require.NoError(err) - md5Value := md5.Sum(content) - contentMD5 := md5Value[:] - - err = fClient.UploadBuffer(context.Background(), content, &file.UploadBufferOptions{ - Concurrency: 5, - ChunkSize: 4 * 1024 * 1024, - }) - _require.NoError(err) + contentSize := 1024 * 8 // 8KB + rsc, _ := testcommon.GenerateData(contentSize) - destFileName := "BigFile-downloaded.bin" - destFile, err := os.Create(destFileName) - _require.NoError(err) - defer func(name string) { - err = os.Remove(name) - _require.NoError(err) - }(destFileName) - defer func(destFile *os.File) { - err = destFile.Close() - _require.NoError(err) - }(destFile) + opts := &file.AppendDataOptions{} + opts1 := &file.FlushDataOptions{} - cnt, err := fClient.DownloadFile(context.Background(), destFile, &file.DownloadFileOptions{ - ChunkSize: 10 * 1024 * 1024, - Concurrency: 5, - }) + _, err = srcFClient.AppendData(context.Background(), 0, rsc, opts) _require.NoError(err) - _require.Equal(cnt, fileSize) - hash := md5.New() - _, err = io.Copy(hash, destFile) + _, err = srcFClient.FlushData(context.Background(), int64(contentSize), opts1) _require.NoError(err) - downloadedContentMD5 := hash.Sum(nil) - - _require.EqualValues(downloadedContentMD5, contentMD5) - gResp2, err := fClient.GetProperties(context.Background(), nil) + gResp2, err := srcFClient.GetProperties(context.Background(), nil) _require.NoError(err) - _require.Equal(*gResp2.ContentLength, fileSize) + _require.Equal(*gResp2.ContentLength, int64(contentSize)) } -func (s *RecordedTestSuite) TestFileUploadDownloadSmallFile() { +func (s *RecordedTestSuite) TestFileAppendAndFlushDataWithLeasedFile() { _require := require.New(s.T()) testName := s.T().Name() @@ -2914,74 +2882,50 @@ func (s *RecordedTestSuite) TestFileUploadDownloadSmallFile() { _, err = fsClient.Create(context.Background(), nil) _require.Nil(err) - var fileSize int64 = 10 * 1024 - fileName := testcommon.GenerateFileName(testName) - fClient, err := testcommon.GetFileClient(filesystemName, fileName, s.T(), testcommon.TestAccountDatalake, nil) + srcFileName := "src" + testcommon.GenerateFileName(testName) + + srcFClient, err := testcommon.GetFileClient(filesystemName, srcFileName, s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) - resp, err := fClient.Create(context.Background(), nil) + createFileOpts := &file.CreateOptions{ + ProposedLeaseID: proposedLeaseIDs[0], + LeaseDuration: to.Ptr(int64(15)), + } + resp, err := srcFClient.Create(context.Background(), createFileOpts) _require.Nil(err) _require.NotNil(resp) - // create local file - _, content := testcommon.GenerateData(int(fileSize)) - srcFileName := "testFileUpload" - err = os.WriteFile(srcFileName, content, 0644) - _require.NoError(err) - defer func() { - err = os.Remove(srcFileName) - _require.NoError(err) - }() - fh, err := os.Open(srcFileName) - _require.NoError(err) - defer func(fh *os.File) { - err := fh.Close() - _require.NoError(err) - }(fh) + contentSize := 1024 * 8 // 8KB + rsc, _ := testcommon.GenerateData(contentSize) - srcHash := md5.New() - _, err = io.Copy(srcHash, fh) - _require.NoError(err) - contentMD5 := srcHash.Sum(nil) + opts := &file.AppendDataOptions{LeaseAccessConditions: &file.LeaseAccessConditions{ + LeaseID: proposedLeaseIDs[0], + }} - err = fClient.UploadFile(context.Background(), fh, &file.UploadFileOptions{ - Concurrency: 5, - ChunkSize: 2 * 1024, - }) - _require.NoError(err) + _, err = srcFClient.AppendData(context.Background(), 0, rsc, nil) + _require.NotNil(err) - destFileName := "SmallFile-downloaded.bin" - destFile, err := os.Create(destFileName) + _, err = rsc.Seek(0, io.SeekStart) _require.NoError(err) - defer func(name string) { - err = os.Remove(name) - _require.NoError(err) - }(destFileName) - defer func(destFile *os.File) { - err = destFile.Close() - _require.NoError(err) - }(destFile) - cnt, err := fClient.DownloadFile(context.Background(), destFile, &file.DownloadFileOptions{ - ChunkSize: 2 * 1024, - Concurrency: 5, - }) - _require.NoError(err) - _require.Equal(cnt, fileSize) + _, err = srcFClient.AppendData(context.Background(), 0, rsc, opts) + _require.Nil(err) - destHash := md5.New() - _, err = io.Copy(destHash, destFile) + opts1 := &file.FlushDataOptions{AccessConditions: &file.AccessConditions{LeaseAccessConditions: &file.LeaseAccessConditions{ + LeaseID: proposedLeaseIDs[0], + }}} + _, err = srcFClient.FlushData(context.Background(), int64(contentSize), opts1) _require.NoError(err) - downloadedContentMD5 := destHash.Sum(nil) - _require.EqualValues(downloadedContentMD5, contentMD5) - - gResp2, err := fClient.GetProperties(context.Background(), nil) + gResp2, err := srcFClient.GetProperties(context.Background(), &file.GetPropertiesOptions{ + AccessConditions: &file.AccessConditions{LeaseAccessConditions: &file.LeaseAccessConditions{ + LeaseID: proposedLeaseIDs[0], + }}}) _require.NoError(err) - _require.Equal(*gResp2.ContentLength, fileSize) + _require.Equal(*gResp2.ContentLength, int64(contentSize)) } -func (s *RecordedTestSuite) TestFileUploadDownloadWithProgress() { +func (s *RecordedTestSuite) TestFileAppendAndFlushAndDownloadDataWithLeasedFile() { _require := require.New(s.T()) testName := s.T().Name() @@ -2993,56 +2937,57 @@ func (s *RecordedTestSuite) TestFileUploadDownloadWithProgress() { _, err = fsClient.Create(context.Background(), nil) _require.Nil(err) - var fileSize int64 = 10 * 1024 - fileName := testcommon.GenerateFileName(testName) - fClient, err := testcommon.GetFileClient(filesystemName, fileName, s.T(), testcommon.TestAccountDatalake, nil) + srcFileName := "src" + testcommon.GenerateFileName(testName) + + srcFClient, err := testcommon.GetFileClient(filesystemName, srcFileName, s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) - resp, err := fClient.Create(context.Background(), nil) + createFileOpts := &file.CreateOptions{ + ProposedLeaseID: proposedLeaseIDs[0], + LeaseDuration: to.Ptr(int64(15)), + } + resp, err := srcFClient.Create(context.Background(), createFileOpts) _require.Nil(err) _require.NotNil(resp) - _, content := testcommon.GenerateData(int(fileSize)) - md5Value := md5.Sum(content) - contentMD5 := md5Value[:] + contentSize := 1024 * 8 // 8KB + rsc, _ := testcommon.GenerateData(contentSize) - bytesUploaded := int64(0) - err = fClient.UploadBuffer(context.Background(), content, &file.UploadBufferOptions{ - Concurrency: 5, - ChunkSize: 2 * 1024, - Progress: func(bytesTransferred int64) { - _require.GreaterOrEqual(bytesTransferred, bytesUploaded) - bytesUploaded = bytesTransferred - }, - }) - _require.NoError(err) - _require.Equal(bytesUploaded, fileSize) + opts := &file.AppendDataOptions{LeaseAccessConditions: &file.LeaseAccessConditions{ + LeaseID: proposedLeaseIDs[0], + }} - destBuffer := make([]byte, fileSize) - bytesDownloaded := int64(0) - cnt, err := fClient.DownloadBuffer(context.Background(), destBuffer, &file.DownloadBufferOptions{ - ChunkSize: 2 * 1024, - Concurrency: 5, - Progress: func(bytesTransferred int64) { - _require.GreaterOrEqual(bytesTransferred, bytesDownloaded) - bytesDownloaded = bytesTransferred - }, - }) - _require.NoError(err) - _require.Equal(cnt, fileSize) - _require.Equal(bytesDownloaded, fileSize) + _, err = srcFClient.AppendData(context.Background(), 0, rsc, opts) + _require.Nil(err) - downloadedMD5Value := md5.Sum(destBuffer) - downloadedContentMD5 := downloadedMD5Value[:] + _, err = rsc.Seek(0, io.SeekStart) - _require.EqualValues(downloadedContentMD5, contentMD5) + _, err = srcFClient.AppendData(context.Background(), int64(contentSize), rsc, opts) + _require.Nil(err) - gResp2, err := fClient.GetProperties(context.Background(), nil) + opts1 := &file.FlushDataOptions{AccessConditions: &file.AccessConditions{LeaseAccessConditions: &file.LeaseAccessConditions{ + LeaseID: proposedLeaseIDs[0], + }}} + _, err = srcFClient.FlushData(context.Background(), int64(contentSize)*2, opts1) _require.NoError(err) - _require.Equal(*gResp2.ContentLength, fileSize) + + gResp2, err := srcFClient.GetProperties(context.Background(), &file.GetPropertiesOptions{ + AccessConditions: &file.AccessConditions{LeaseAccessConditions: &file.LeaseAccessConditions{ + LeaseID: proposedLeaseIDs[0], + }}}) + _require.NoError(err) + _require.Equal(*gResp2.ContentLength, int64(contentSize)*2) + + destBuffer := make([]byte, contentSize*2) + cnt, err := srcFClient.DownloadBuffer(context.Background(), destBuffer, &file.DownloadBufferOptions{ + ChunkSize: 8 * 1024, + Concurrency: 5, + }) + _require.NoError(err) + _require.Equal(cnt, int64(contentSize*2)) } -func (s *RecordedTestSuite) TestFileDownloadBuffer() { +func (s *RecordedTestSuite) TestAppendAndFlushFileWithHTTPHeaders() { _require := require.New(s.T()) testName := s.T().Name() @@ -3054,20 +2999,816 @@ func (s *RecordedTestSuite) TestFileDownloadBuffer() { _, err = fsClient.Create(context.Background(), nil) _require.Nil(err) - var fileSize int64 = 100 * 1024 * 1024 - fileName := testcommon.GenerateFileName(testName) - fClient, err := testcommon.GetFileClient(filesystemName, fileName, s.T(), testcommon.TestAccountDatalake, nil) + srcFileName := "src" + testcommon.GenerateFileName(testName) + + srcFClient, err := testcommon.GetFileClient(filesystemName, srcFileName, s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) - resp, err := fClient.Create(context.Background(), nil) + resp, err := srcFClient.Create(context.Background(), nil) _require.Nil(err) _require.NotNil(resp) - content := make([]byte, fileSize) - _, err = rand.Read(content) + contentSize := 1024 * 8 // 8KB + rsc, _ := testcommon.GenerateData(contentSize) + + opts := &file.FlushDataOptions{HTTPHeaders: &testcommon.BasicHeaders} + + _, err = srcFClient.AppendData(context.Background(), 0, rsc, nil) _require.NoError(err) - md5Value := md5.Sum(content) - contentMD5 := md5Value[:] + + _, err = srcFClient.FlushData(context.Background(), int64(contentSize), opts) + _require.NoError(err) + + gResp2, err := srcFClient.GetProperties(context.Background(), nil) + _require.NoError(err) + _require.Equal(*gResp2.ContentLength, int64(contentSize)) + validatePropertiesSet(_require, srcFClient, *testcommon.BasicHeaders.ContentDisposition) +} + +func (s *RecordedTestSuite) TestFlushWithNilAccessConditions() { + _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) + + srcFileName := "src" + testcommon.GenerateFileName(testName) + + srcFClient, err := testcommon.GetFileClient(filesystemName, srcFileName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + resp, err := srcFClient.Create(context.Background(), nil) + _require.Nil(err) + _require.NotNil(resp) + + contentSize := 1024 * 8 // 8KB + rsc, _ := testcommon.GenerateData(contentSize) + + _, err = srcFClient.AppendData(context.Background(), 0, rsc, nil) + _require.NoError(err) + + opts := &file.FlushDataOptions{ + AccessConditions: nil, + } + _, err = srcFClient.FlushData(context.Background(), int64(contentSize), opts) + _require.NoError(err) + + gResp2, err := srcFClient.GetProperties(context.Background(), nil) + _require.NoError(err) + _require.Equal(*gResp2.ContentLength, int64(contentSize)) +} + +func (s *RecordedTestSuite) TestFlushWithEmptyAccessConditions() { + _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) + + srcFileName := "src" + testcommon.GenerateFileName(testName) + + srcFClient, err := testcommon.GetFileClient(filesystemName, srcFileName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + resp, err := srcFClient.Create(context.Background(), nil) + _require.Nil(err) + _require.NotNil(resp) + + contentSize := 1024 * 8 // 8KB + rsc, _ := testcommon.GenerateData(contentSize) + + _, err = srcFClient.AppendData(context.Background(), 0, rsc, nil) + _require.NoError(err) + + opts := &file.FlushDataOptions{ + AccessConditions: &file.AccessConditions{}, + } + _, err = srcFClient.FlushData(context.Background(), int64(contentSize), opts) + _require.NoError(err) + + gResp2, err := srcFClient.GetProperties(context.Background(), nil) + _require.NoError(err) + _require.Equal(*gResp2.ContentLength, int64(contentSize)) +} + +// ========================================== + +func (s *RecordedTestSuite) TestFlushIfModifiedSinceTrue() { + _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) + + srcFileName := "src" + testcommon.GenerateFileName(testName) + + srcFClient, err := testcommon.GetFileClient(filesystemName, srcFileName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + resp, err := srcFClient.Create(context.Background(), nil) + _require.Nil(err) + _require.NotNil(resp) + + contentSize := 1024 * 8 // 8KB + rsc, _ := testcommon.GenerateData(contentSize) + + _, err = srcFClient.AppendData(context.Background(), 0, rsc, nil) + _require.NoError(err) + currentTime := testcommon.GetRelativeTimeFromAnchor(resp.Date, -10) + + opts := &file.FlushDataOptions{ + AccessConditions: &file.AccessConditions{ + ModifiedAccessConditions: &file.ModifiedAccessConditions{ + IfModifiedSince: ¤tTime, + }, + }, + } + _, err = srcFClient.FlushData(context.Background(), int64(contentSize), opts) + _require.NoError(err) + + gResp2, err := srcFClient.GetProperties(context.Background(), nil) + _require.NoError(err) + _require.Equal(*gResp2.ContentLength, int64(contentSize)) +} + +func (s *RecordedTestSuite) TestFlushIfModifiedSinceFalse() { + _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) + + srcFileName := "src" + testcommon.GenerateFileName(testName) + + srcFClient, err := testcommon.GetFileClient(filesystemName, srcFileName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + resp, err := srcFClient.Create(context.Background(), nil) + _require.Nil(err) + _require.NotNil(resp) + + contentSize := 1024 * 8 // 8KB + rsc, _ := testcommon.GenerateData(contentSize) + + _, err = srcFClient.AppendData(context.Background(), 0, rsc, nil) + _require.NoError(err) + + currentTime := testcommon.GetRelativeTimeFromAnchor(resp.Date, 10) + + opts := &file.FlushDataOptions{ + AccessConditions: &file.AccessConditions{ + ModifiedAccessConditions: &file.ModifiedAccessConditions{ + IfModifiedSince: ¤tTime, + }, + }, + } + _, err = srcFClient.FlushData(context.Background(), int64(contentSize), opts) + _require.NotNil(err) +} + +func (s *RecordedTestSuite) TestFlushIfUnmodifiedSinceTrue() { + _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) + + srcFileName := "src" + testcommon.GenerateFileName(testName) + + srcFClient, err := testcommon.GetFileClient(filesystemName, srcFileName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + resp, err := srcFClient.Create(context.Background(), nil) + _require.Nil(err) + _require.NotNil(resp) + + contentSize := 1024 * 8 // 8KB + rsc, _ := testcommon.GenerateData(contentSize) + + _, err = srcFClient.AppendData(context.Background(), 0, rsc, nil) + _require.NoError(err) + + currentTime := testcommon.GetRelativeTimeFromAnchor(resp.Date, 10) + + opts := &file.FlushDataOptions{ + AccessConditions: &file.AccessConditions{ + ModifiedAccessConditions: &file.ModifiedAccessConditions{ + IfUnmodifiedSince: ¤tTime, + }, + }, + } + _, err = srcFClient.FlushData(context.Background(), int64(contentSize), opts) + _require.NoError(err) + + gResp2, err := srcFClient.GetProperties(context.Background(), nil) + _require.NoError(err) + _require.Equal(*gResp2.ContentLength, int64(contentSize)) +} + +func (s *RecordedTestSuite) TestFlushIfUnmodifiedSinceFalse() { + _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) + + srcFileName := "src" + testcommon.GenerateFileName(testName) + + srcFClient, err := testcommon.GetFileClient(filesystemName, srcFileName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + resp, err := srcFClient.Create(context.Background(), nil) + _require.Nil(err) + _require.NotNil(resp) + + contentSize := 1024 * 8 // 8KB + rsc, _ := testcommon.GenerateData(contentSize) + + _, err = srcFClient.AppendData(context.Background(), 0, rsc, nil) + _require.NoError(err) + + currentTime := testcommon.GetRelativeTimeFromAnchor(resp.Date, -10) + + opts := &file.FlushDataOptions{ + AccessConditions: &file.AccessConditions{ + ModifiedAccessConditions: &file.ModifiedAccessConditions{ + IfUnmodifiedSince: ¤tTime, + }, + }, + } + _, err = srcFClient.FlushData(context.Background(), int64(contentSize), opts) + _require.NotNil(err) +} + +func (s *RecordedTestSuite) TestFlushIfEtagMatch() { + _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) + + srcFileName := "src" + testcommon.GenerateFileName(testName) + + srcFClient, err := testcommon.GetFileClient(filesystemName, srcFileName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + resp, err := srcFClient.Create(context.Background(), nil) + _require.Nil(err) + _require.NotNil(resp) + + contentSize := 1024 * 8 // 8KB + rsc, _ := testcommon.GenerateData(contentSize) + + resp1, err := srcFClient.AppendData(context.Background(), 0, rsc, nil) + _require.NoError(err) + etag := resp1.ETag + + opts := &file.FlushDataOptions{ + AccessConditions: &file.AccessConditions{ + ModifiedAccessConditions: &file.ModifiedAccessConditions{ + IfMatch: etag, + }, + }, + } + _, err = srcFClient.FlushData(context.Background(), int64(contentSize), opts) + _require.NoError(err) + + gResp2, err := srcFClient.GetProperties(context.Background(), nil) + _require.NoError(err) + _require.Equal(*gResp2.ContentLength, int64(contentSize)) +} + +func (s *RecordedTestSuite) TestFlushIfEtagMatchFalse() { + _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) + + srcFileName := "src" + testcommon.GenerateFileName(testName) + + srcFClient, err := testcommon.GetFileClient(filesystemName, srcFileName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + resp, err := srcFClient.Create(context.Background(), nil) + _require.Nil(err) + _require.NotNil(resp) + + contentSize := 1024 * 8 // 8KB + rsc, _ := testcommon.GenerateData(contentSize) + + resp1, err := srcFClient.AppendData(context.Background(), 0, rsc, nil) + _require.NoError(err) + etag := resp1.ETag + + opts := &file.FlushDataOptions{ + AccessConditions: &file.AccessConditions{ + ModifiedAccessConditions: &file.ModifiedAccessConditions{ + IfNoneMatch: etag, + }, + }, + } + _, err = srcFClient.FlushData(context.Background(), int64(contentSize), opts) + _require.NoError(err) + + gResp2, err := srcFClient.GetProperties(context.Background(), nil) + _require.NoError(err) + _require.Equal(*gResp2.ContentLength, int64(contentSize)) +} + +// TODO: test retain uncommitted data + +func (s *UnrecordedTestSuite) TestFileDownloadFile() { + _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) + + var fileSize int64 = 100 * 1024 * 1024 + fileName := testcommon.GenerateFileName(testName) + fClient, err := testcommon.GetFileClient(filesystemName, fileName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + resp, err := fClient.Create(context.Background(), nil) + _require.Nil(err) + _require.NotNil(resp) + + content := make([]byte, fileSize) + _, err = rand.Read(content) + _require.NoError(err) + md5Value := md5.Sum(content) + contentMD5 := md5Value[:] + + err = fClient.UploadBuffer(context.Background(), content, &file.UploadBufferOptions{ + Concurrency: 5, + ChunkSize: 4 * 1024 * 1024, + }) + _require.NoError(err) + + destFileName := "BigFile-downloaded.bin" + destFile, err := os.Create(destFileName) + _require.NoError(err) + defer func(name string) { + err = os.Remove(name) + _require.NoError(err) + }(destFileName) + defer func(destFile *os.File) { + err = destFile.Close() + _require.NoError(err) + }(destFile) + + cnt, err := fClient.DownloadFile(context.Background(), destFile, &file.DownloadFileOptions{ + ChunkSize: 10 * 1024 * 1024, + Concurrency: 5, + }) + _require.NoError(err) + _require.Equal(cnt, fileSize) + + hash := md5.New() + _, err = io.Copy(hash, destFile) + _require.NoError(err) + downloadedContentMD5 := hash.Sum(nil) + + _require.EqualValues(downloadedContentMD5, contentMD5) + + gResp2, err := fClient.GetProperties(context.Background(), nil) + _require.NoError(err) + _require.Equal(*gResp2.ContentLength, fileSize) +} + +func (s *RecordedTestSuite) TestFileUploadDownloadSmallFile() { + _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) + + var fileSize int64 = 10 * 1024 + fileName := testcommon.GenerateFileName(testName) + fClient, err := testcommon.GetFileClient(filesystemName, fileName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + resp, err := fClient.Create(context.Background(), nil) + _require.Nil(err) + _require.NotNil(resp) + + // create local file + _, content := testcommon.GenerateData(int(fileSize)) + srcFileName := "testFileUpload" + err = os.WriteFile(srcFileName, content, 0644) + _require.NoError(err) + defer func() { + err = os.Remove(srcFileName) + _require.NoError(err) + }() + fh, err := os.Open(srcFileName) + _require.NoError(err) + defer func(fh *os.File) { + err := fh.Close() + _require.NoError(err) + }(fh) + + srcHash := md5.New() + _, err = io.Copy(srcHash, fh) + _require.NoError(err) + contentMD5 := srcHash.Sum(nil) + + err = fClient.UploadFile(context.Background(), fh, &file.UploadFileOptions{ + Concurrency: 5, + ChunkSize: 2 * 1024, + }) + _require.NoError(err) + + destFileName := "SmallFile-downloaded.bin" + destFile, err := os.Create(destFileName) + _require.NoError(err) + defer func(name string) { + err = os.Remove(name) + _require.NoError(err) + }(destFileName) + defer func(destFile *os.File) { + err = destFile.Close() + _require.NoError(err) + }(destFile) + + cnt, err := fClient.DownloadFile(context.Background(), destFile, &file.DownloadFileOptions{ + ChunkSize: 2 * 1024, + Concurrency: 5, + }) + _require.NoError(err) + _require.Equal(cnt, fileSize) + + destHash := md5.New() + _, err = io.Copy(destHash, destFile) + _require.NoError(err) + downloadedContentMD5 := destHash.Sum(nil) + + _require.EqualValues(downloadedContentMD5, contentMD5) + + gResp2, err := fClient.GetProperties(context.Background(), nil) + _require.NoError(err) + _require.Equal(*gResp2.ContentLength, fileSize) +} + +func (s *RecordedTestSuite) TestFileUploadDownloadSmallFileWithRange() { + _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) + + var fileSize int64 = 10 * 1024 + fileName := testcommon.GenerateFileName(testName) + fClient, err := testcommon.GetFileClient(filesystemName, fileName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + resp, err := fClient.Create(context.Background(), nil) + _require.Nil(err) + _require.NotNil(resp) + + // create local file + _, content := testcommon.GenerateData(int(fileSize)) + srcFileName := "testFileUpload" + err = os.WriteFile(srcFileName, content, 0644) + _require.NoError(err) + defer func() { + err = os.Remove(srcFileName) + _require.NoError(err) + }() + fh, err := os.Open(srcFileName) + _require.NoError(err) + defer func(fh *os.File) { + err := fh.Close() + _require.NoError(err) + }(fh) + + srcHash := md5.New() + _, err = io.Copy(srcHash, fh) + _require.NoError(err) + contentMD5 := srcHash.Sum(nil) + + err = fClient.UploadFile(context.Background(), fh, &file.UploadFileOptions{ + Concurrency: 5, + ChunkSize: 2 * 1024, + }) + _require.NoError(err) + + destFileName := "SmallFile-downloaded.bin" + destFile, err := os.Create(destFileName) + _require.NoError(err) + defer func(name string) { + err = os.Remove(name) + _require.NoError(err) + }(destFileName) + defer func(destFile *os.File) { + err = destFile.Close() + _require.NoError(err) + }(destFile) + + cnt, err := fClient.DownloadFile(context.Background(), destFile, &file.DownloadFileOptions{ + ChunkSize: 2 * 1024, + Concurrency: 5, + Range: &file.HTTPRange{ + Offset: 0, + Count: 10 * 1024, + }, + }) + _require.NoError(err) + _require.Equal(cnt, fileSize) + + destHash := md5.New() + _, err = io.Copy(destHash, destFile) + _require.NoError(err) + downloadedContentMD5 := destHash.Sum(nil) + + _require.EqualValues(downloadedContentMD5, contentMD5) + + gResp2, err := fClient.GetProperties(context.Background(), nil) + _require.NoError(err) + _require.Equal(*gResp2.ContentLength, fileSize) +} + +func (s *RecordedTestSuite) TestFileUploadDownloadSmallFileWithAccessConditions() { + _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) + + var fileSize int64 = 10 * 1024 + fileName := testcommon.GenerateFileName(testName) + fClient, err := testcommon.GetFileClient(filesystemName, fileName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + resp, err := fClient.Create(context.Background(), nil) + _require.Nil(err) + _require.NotNil(resp) + currentTime := testcommon.GetRelativeTimeFromAnchor(resp.Date, -10) + + // create local file + _, content := testcommon.GenerateData(int(fileSize)) + srcFileName := "testFileUpload" + err = os.WriteFile(srcFileName, content, 0644) + _require.NoError(err) + defer func() { + err = os.Remove(srcFileName) + _require.NoError(err) + }() + fh, err := os.Open(srcFileName) + _require.NoError(err) + defer func(fh *os.File) { + err := fh.Close() + _require.NoError(err) + }(fh) + + srcHash := md5.New() + _, err = io.Copy(srcHash, fh) + _require.NoError(err) + contentMD5 := srcHash.Sum(nil) + + err = fClient.UploadFile(context.Background(), fh, &file.UploadFileOptions{ + Concurrency: 5, + ChunkSize: 2 * 1024, + }) + _require.NoError(err) + + destFileName := "SmallFile-downloaded.bin" + destFile, err := os.Create(destFileName) + _require.NoError(err) + defer func(name string) { + err = os.Remove(name) + _require.NoError(err) + }(destFileName) + defer func(destFile *os.File) { + err = destFile.Close() + _require.NoError(err) + }(destFile) + + cnt, err := fClient.DownloadFile(context.Background(), destFile, &file.DownloadFileOptions{ + ChunkSize: 2 * 1024, + Concurrency: 5, + Range: &file.HTTPRange{ + Offset: 0, + Count: 10 * 1024, + }, + AccessConditions: &file.AccessConditions{ + ModifiedAccessConditions: &file.ModifiedAccessConditions{ + IfModifiedSince: ¤tTime, + }, + }, + }) + _require.NoError(err) + _require.Equal(cnt, fileSize) + + destHash := md5.New() + _, err = io.Copy(destHash, destFile) + _require.NoError(err) + downloadedContentMD5 := destHash.Sum(nil) + + _require.EqualValues(downloadedContentMD5, contentMD5) + + gResp2, err := fClient.GetProperties(context.Background(), nil) + _require.NoError(err) + _require.Equal(*gResp2.ContentLength, fileSize) +} + +func (s *RecordedTestSuite) TestFileUploadDownloadWithProgress() { + _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) + + var fileSize int64 = 10 * 1024 + fileName := testcommon.GenerateFileName(testName) + fClient, err := testcommon.GetFileClient(filesystemName, fileName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + resp, err := fClient.Create(context.Background(), nil) + _require.Nil(err) + _require.NotNil(resp) + + _, content := testcommon.GenerateData(int(fileSize)) + md5Value := md5.Sum(content) + contentMD5 := md5Value[:] + + bytesUploaded := int64(0) + err = fClient.UploadBuffer(context.Background(), content, &file.UploadBufferOptions{ + Concurrency: 5, + ChunkSize: 2 * 1024, + Progress: func(bytesTransferred int64) { + _require.GreaterOrEqual(bytesTransferred, bytesUploaded) + bytesUploaded = bytesTransferred + }, + }) + _require.NoError(err) + _require.Equal(bytesUploaded, fileSize) + + destBuffer := make([]byte, fileSize) + bytesDownloaded := int64(0) + cnt, err := fClient.DownloadBuffer(context.Background(), destBuffer, &file.DownloadBufferOptions{ + ChunkSize: 2 * 1024, + Concurrency: 5, + Progress: func(bytesTransferred int64) { + _require.GreaterOrEqual(bytesTransferred, bytesDownloaded) + bytesDownloaded = bytesTransferred + }, + }) + _require.NoError(err) + _require.Equal(cnt, fileSize) + _require.Equal(bytesDownloaded, fileSize) + + downloadedMD5Value := md5.Sum(destBuffer) + downloadedContentMD5 := downloadedMD5Value[:] + + _require.EqualValues(downloadedContentMD5, contentMD5) + + gResp2, err := fClient.GetProperties(context.Background(), nil) + _require.NoError(err) + _require.Equal(*gResp2.ContentLength, fileSize) +} + +func (s *UnrecordedTestSuite) TestFileDownloadBuffer() { + _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) + + var fileSize int64 = 100 * 1024 * 1024 + fileName := testcommon.GenerateFileName(testName) + fClient, err := testcommon.GetFileClient(filesystemName, fileName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + resp, err := fClient.Create(context.Background(), nil) + _require.Nil(err) + _require.NotNil(resp) + + content := make([]byte, fileSize) + _, err = rand.Read(content) + _require.NoError(err) + md5Value := md5.Sum(content) + contentMD5 := md5Value[:] + + err = fClient.UploadBuffer(context.Background(), content, &file.UploadBufferOptions{ + Concurrency: 5, + ChunkSize: 4 * 1024 * 1024, + }) + _require.NoError(err) + + destBuffer := make([]byte, fileSize) + cnt, err := fClient.DownloadBuffer(context.Background(), destBuffer, &file.DownloadBufferOptions{ + ChunkSize: 10 * 1024 * 1024, + Concurrency: 5, + }) + _require.NoError(err) + _require.Equal(cnt, fileSize) + + downloadedMD5Value := md5.Sum(destBuffer) + downloadedContentMD5 := downloadedMD5Value[:] + + _require.EqualValues(downloadedContentMD5, contentMD5) + + gResp2, err := fClient.GetProperties(context.Background(), nil) + _require.NoError(err) + _require.Equal(*gResp2.ContentLength, fileSize) +} + +func (s *RecordedTestSuite) TestFileDownloadSmallBuffer() { + _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) + + var fileSize int64 = 10 * 1024 + fileName := testcommon.GenerateFileName(testName) + fClient, err := testcommon.GetFileClient(filesystemName, fileName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + resp, err := fClient.Create(context.Background(), nil) + _require.Nil(err) + _require.NotNil(resp) + + _, content := testcommon.GenerateData(int(fileSize)) + md5Value := md5.Sum(content) + contentMD5 := md5Value[:] err = fClient.UploadBuffer(context.Background(), content, &file.UploadBufferOptions{ Concurrency: 5, @@ -3093,4 +3834,117 @@ func (s *RecordedTestSuite) TestFileDownloadBuffer() { _require.Equal(*gResp2.ContentLength, fileSize) } +func (s *RecordedTestSuite) TestFileDownloadSmallBufferWithHTTPRange() { + _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) + + var fileSize int64 = 10 * 1024 + fileName := testcommon.GenerateFileName(testName) + fClient, err := testcommon.GetFileClient(filesystemName, fileName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + resp, err := fClient.Create(context.Background(), nil) + _require.Nil(err) + _require.NotNil(resp) + + _, content := testcommon.GenerateData(int(fileSize)) + md5Value := md5.Sum(content[0 : fileSize/2]) + contentMD5 := md5Value[:] + + err = fClient.UploadBuffer(context.Background(), content, &file.UploadBufferOptions{ + Concurrency: 5, + ChunkSize: 4 * 1024 * 1024, + }) + _require.NoError(err) + + destBuffer := make([]byte, fileSize/2) + cnt, err := fClient.DownloadBuffer(context.Background(), destBuffer, &file.DownloadBufferOptions{ + ChunkSize: 10 * 1024 * 1024, + Concurrency: 5, + Range: &file.HTTPRange{ + Offset: 0, + Count: 5 * 1024, + }, + }) + _require.NoError(err) + _require.Equal(cnt, fileSize/2) + + downloadedMD5Value := md5.Sum(destBuffer) + downloadedContentMD5 := downloadedMD5Value[:] + + _require.EqualValues(downloadedContentMD5, contentMD5) + + gResp2, err := fClient.GetProperties(context.Background(), nil) + _require.NoError(err) + _require.Equal(*gResp2.ContentLength, fileSize) +} + +func (s *RecordedTestSuite) TestFileDownloadSmallBufferWithAccessConditions() { + _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) + + var fileSize int64 = 10 * 1024 + fileName := testcommon.GenerateFileName(testName) + fClient, err := testcommon.GetFileClient(filesystemName, fileName, s.T(), testcommon.TestAccountDatalake, nil) + _require.NoError(err) + + resp, err := fClient.Create(context.Background(), nil) + _require.Nil(err) + _require.NotNil(resp) + + _, content := testcommon.GenerateData(int(fileSize)) + md5Value := md5.Sum(content[0 : fileSize/2]) + contentMD5 := md5Value[:] + + err = fClient.UploadBuffer(context.Background(), content, &file.UploadBufferOptions{ + Concurrency: 5, + ChunkSize: 4 * 1024 * 1024, + }) + _require.NoError(err) + + currentTime := testcommon.GetRelativeTimeFromAnchor(resp.Date, -10) + + destBuffer := make([]byte, fileSize/2) + cnt, err := fClient.DownloadBuffer(context.Background(), destBuffer, &file.DownloadBufferOptions{ + ChunkSize: 10 * 1024 * 1024, + Concurrency: 5, + AccessConditions: &file.AccessConditions{ + ModifiedAccessConditions: &file.ModifiedAccessConditions{ + IfModifiedSince: ¤tTime, + }, + }, + Range: &file.HTTPRange{ + Offset: 0, + Count: 5 * 1024, + }, + }) + _require.NoError(err) + _require.Equal(cnt, fileSize/2) + + downloadedMD5Value := md5.Sum(destBuffer) + downloadedContentMD5 := downloadedMD5Value[:] + + _require.EqualValues(downloadedContentMD5, contentMD5) + + gResp2, err := fClient.GetProperties(context.Background(), nil) + _require.NoError(err) + _require.Equal(*gResp2.ContentLength, fileSize) +} + // TODO tests all uploads/downloads with other opts diff --git a/sdk/storage/azdatalake/file/constants.go b/sdk/storage/azdatalake/file/constants.go index 7dd13f5de226..28032750ce15 100644 --- a/sdk/storage/azdatalake/file/constants.go +++ b/sdk/storage/azdatalake/file/constants.go @@ -7,6 +7,7 @@ package file import ( + "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake" "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/internal/exported" "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/internal/path" ) @@ -48,3 +49,40 @@ type TransferValidationTypeCRC64 = exported.TransferValidationTypeCRC64 func TransferValidationTypeComputeCRC64() TransferValidationType { return exported.TransferValidationTypeComputeCRC64() } + +// StatusType defines values for StatusType +type StatusType = azdatalake.StatusType + +const ( + StatusTypeLocked StatusType = azdatalake.StatusTypeLocked + StatusTypeUnlocked StatusType = azdatalake.StatusTypeUnlocked +) + +// PossibleStatusTypeValues returns the possible values for the StatusType const type. +func PossibleStatusTypeValues() []StatusType { + return azdatalake.PossibleStatusTypeValues() +} + +// DurationType defines values for DurationType +type DurationType = azdatalake.DurationType + +const ( + DurationTypeInfinite DurationType = azdatalake.DurationTypeInfinite + DurationTypeFixed DurationType = azdatalake.DurationTypeFixed +) + +// PossibleDurationTypeValues returns the possible values for the DurationType const type. +func PossibleDurationTypeValues() []DurationType { + return azdatalake.PossibleDurationTypeValues() +} + +// StateType defines values for StateType +type StateType = azdatalake.StateType + +const ( + StateTypeAvailable StateType = azdatalake.StateTypeAvailable + StateTypeLeased StateType = azdatalake.StateTypeLeased + StateTypeExpired StateType = azdatalake.StateTypeExpired + StateTypeBreaking StateType = azdatalake.StateTypeBreaking + StateTypeBroken StateType = azdatalake.StateTypeBroken +) diff --git a/sdk/storage/azdatalake/file/models.go b/sdk/storage/azdatalake/file/models.go index 55c2a781be83..a11818377e3f 100644 --- a/sdk/storage/azdatalake/file/models.go +++ b/sdk/storage/azdatalake/file/models.go @@ -206,7 +206,7 @@ func (o *FlushDataOptions) format(offset int64) (*generated.PathClientFlushDataO } leaseAccessConditions, modifiedAccessConditions = exported.FormatPathAccessConditions(o.AccessConditions) if o.HTTPHeaders != nil { - httpHeaderOpts := generated.PathHTTPHeaders{} + httpHeaderOpts = &generated.PathHTTPHeaders{} httpHeaderOpts.ContentMD5 = o.HTTPHeaders.ContentMD5 httpHeaderOpts.ContentType = o.HTTPHeaders.ContentType httpHeaderOpts.CacheControl = o.HTTPHeaders.CacheControl @@ -214,7 +214,7 @@ func (o *FlushDataOptions) format(offset int64) (*generated.PathClientFlushDataO httpHeaderOpts.ContentEncoding = o.HTTPHeaders.ContentEncoding } if o.CPKInfo != nil { - cpkInfoOpts := generated.CPKInfo{} + cpkInfoOpts = &generated.CPKInfo{} cpkInfoOpts.EncryptionKey = o.CPKInfo.EncryptionKey cpkInfoOpts.EncryptionKeySHA256 = o.CPKInfo.EncryptionKeySHA256 cpkInfoOpts.EncryptionAlgorithm = o.CPKInfo.EncryptionAlgorithm @@ -230,24 +230,22 @@ type AppendDataOptions struct { TransactionalValidation TransferValidationType // LeaseAccessConditions contains optional parameters to access leased entity. LeaseAccessConditions *LeaseAccessConditions - // HTTPHeaders contains the optional path HTTP headers to set when the file is created. - HTTPHeaders *HTTPHeaders // CPKInfo contains optional parameters to perform encryption using customer-provided key. CPKInfo *CPKInfo } -func (o *AppendDataOptions) format(offset int64, body io.ReadSeekCloser) (*generated.PathClientAppendDataOptions, *generated.LeaseAccessConditions, *generated.PathHTTPHeaders, *generated.CPKInfo, error) { +func (o *AppendDataOptions) format(offset int64, body io.ReadSeekCloser) (*generated.PathClientAppendDataOptions, *generated.LeaseAccessConditions, *generated.CPKInfo, error) { if offset < 0 || body == nil { - return nil, nil, nil, nil, errors.New("invalid argument: offset must be >= 0 and body must not be nil") + return nil, nil, nil, errors.New("invalid argument: offset must be >= 0 and body must not be nil") } count, err := shared.ValidateSeekableStreamAt0AndGetCount(body) if err != nil { - return nil, nil, nil, nil, err + return nil, nil, nil, err } if count == 0 { - return nil, nil, nil, nil, errors.New("invalid argument: body must contain readable data whose size is > 0") + return nil, nil, nil, errors.New("invalid argument: body must contain readable data whose size is > 0") } appendDataOptions := &generated.PathClientAppendDataOptions{} @@ -261,21 +259,12 @@ func (o *AppendDataOptions) format(offset int64, body io.ReadSeekCloser) (*gener } var leaseAccessConditions *LeaseAccessConditions - var httpHeaderOpts *generated.PathHTTPHeaders var cpkInfoOpts *generated.CPKInfo if o != nil { leaseAccessConditions = o.LeaseAccessConditions - if o.HTTPHeaders != nil { - httpHeaderOpts := generated.PathHTTPHeaders{} - httpHeaderOpts.ContentMD5 = o.HTTPHeaders.ContentMD5 - httpHeaderOpts.ContentType = o.HTTPHeaders.ContentType - httpHeaderOpts.CacheControl = o.HTTPHeaders.CacheControl - httpHeaderOpts.ContentDisposition = o.HTTPHeaders.ContentDisposition - httpHeaderOpts.ContentEncoding = o.HTTPHeaders.ContentEncoding - } if o.CPKInfo != nil { - cpkInfoOpts := generated.CPKInfo{} + cpkInfoOpts = &generated.CPKInfo{} cpkInfoOpts.EncryptionKey = o.CPKInfo.EncryptionKey cpkInfoOpts.EncryptionKeySHA256 = o.CPKInfo.EncryptionKeySHA256 cpkInfoOpts.EncryptionAlgorithm = o.CPKInfo.EncryptionAlgorithm @@ -284,11 +273,11 @@ func (o *AppendDataOptions) format(offset int64, body io.ReadSeekCloser) (*gener if o != nil && o.TransactionalValidation != nil { _, err = o.TransactionalValidation.Apply(body, appendDataOptions) if err != nil { - return nil, nil, nil, nil, err + return nil, nil, nil, err } } - return appendDataOptions, leaseAccessConditions, httpHeaderOpts, cpkInfoOpts, nil + return appendDataOptions, leaseAccessConditions, cpkInfoOpts, nil } func (u *UploadStreamOptions) setDefaults() { @@ -308,7 +297,6 @@ func (u *uploadFromReaderOptions) getAppendDataOptions() *AppendDataOptions { leaseAccessConditions, _ := exported.FormatPathAccessConditions(u.AccessConditions) return &AppendDataOptions{ LeaseAccessConditions: leaseAccessConditions, - HTTPHeaders: u.HTTPHeaders, CPKInfo: u.CPKInfo, } } @@ -331,7 +319,6 @@ func (u *UploadStreamOptions) getAppendDataOptions() *AppendDataOptions { leaseAccessConditions, _ := exported.FormatPathAccessConditions(u.AccessConditions) return &AppendDataOptions{ LeaseAccessConditions: leaseAccessConditions, - HTTPHeaders: u.HTTPHeaders, CPKInfo: u.CPKInfo, } } @@ -541,7 +528,7 @@ func (e CreationExpiryTypeNever) Format() (generated.ExpiryOptions, *string) { func (e CreationExpiryTypeNever) notPubliclyImplementable() {} // ACLFailedEntry contains the failed ACL entry (response model). -type ACLFailedEntry = generated.ACLFailedEntry +type ACLFailedEntry = path.ACLFailedEntry // SetAccessControlRecursiveResponse contains part of the response data returned by the []OP_AccessControl operations. type SetAccessControlRecursiveResponse = generated.SetAccessControlRecursiveResponse diff --git a/sdk/storage/azdatalake/file/responses.go b/sdk/storage/azdatalake/file/responses.go index a518ee58f376..801c9d03b0c0 100644 --- a/sdk/storage/azdatalake/file/responses.go +++ b/sdk/storage/azdatalake/file/responses.go @@ -10,27 +10,15 @@ import ( "context" "github.com/Azure/azure-sdk-for-go/sdk/azcore" "github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/blob" - "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake" "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/internal/generated" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/internal/generated_blob" "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/internal/path" "io" "time" ) // SetExpiryResponse contains the response fields for the SetExpiry operation. -type SetExpiryResponse = generated.PathClientSetExpiryResponse - -// CreateResponse contains the response fields for the Create operation. -type CreateResponse = generated.PathClientCreateResponse - -// DeleteResponse contains the response fields for the Delete operation. -type DeleteResponse = generated.PathClientDeleteResponse - -// UpdateAccessControlResponse contains the response fields for the UpdateAccessControlRecursive operation. -type UpdateAccessControlResponse = generated.PathClientSetAccessControlRecursiveResponse - -// RemoveAccessControlResponse contains the response fields for the RemoveAccessControlRecursive operation. -type RemoveAccessControlResponse = generated.PathClientSetAccessControlRecursiveResponse +type SetExpiryResponse = generated_blob.BlobClientSetExpiryResponse // AppendDataResponse contains the response from method Client.AppendData. type AppendDataResponse = generated.PathClientAppendDataResponse @@ -40,7 +28,7 @@ type FlushDataResponse = generated.PathClientFlushDataResponse // RenameResponse contains the response fields for the Create operation. type RenameResponse struct { - Response generated.PathClientCreateResponse + Response CreateResponse NewFileClient *Client } @@ -174,13 +162,13 @@ type DownloadResponse struct { LastModified *time.Time // LeaseDuration contains the information returned from the x-ms-lease-duration header response. - LeaseDuration *azdatalake.DurationType + LeaseDuration *DurationType // LeaseState contains the information returned from the x-ms-lease-state header response. - LeaseState *azdatalake.StateType + LeaseState *StateType // LeaseStatus contains the information returned from the x-ms-lease-status header response. - LeaseStatus *azdatalake.StatusType + LeaseStatus *StatusType // LegalHold contains the information returned from the x-ms-legal-hold header response. LegalHold *bool @@ -271,3 +259,15 @@ type GetPropertiesResponse = path.GetPropertiesResponse // SetMetadataResponse contains the response fields for the SetMetadata operation. type SetMetadataResponse = path.SetMetadataResponse + +// CreateResponse contains the response fields for the Create operation. +type CreateResponse = path.CreateResponse + +// DeleteResponse contains the response fields for the Delete operation. +type DeleteResponse = path.DeleteResponse + +// UpdateAccessControlResponse contains the response fields for the UpdateAccessControlRecursive operation. +type UpdateAccessControlResponse = path.UpdateAccessControlResponse + +// RemoveAccessControlResponse contains the response fields for the RemoveAccessControlRecursive operation. +type RemoveAccessControlResponse = path.RemoveAccessControlResponse diff --git a/sdk/storage/azdatalake/filesystem/client.go b/sdk/storage/azdatalake/filesystem/client.go index 46f6c22f06bb..b42803edb8cf 100644 --- a/sdk/storage/azdatalake/filesystem/client.go +++ b/sdk/storage/azdatalake/filesystem/client.go @@ -4,6 +4,8 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. See License.txt in the project root for license information. +// FOR FS CLIENT WE STORE THE GENERATED DATALAKE LAYER WITH BLOB ENDPOINT IN ORDER TO USE DELETED PATH LISTING + package filesystem import ( @@ -22,6 +24,7 @@ import ( "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" + "strings" "time" ) @@ -125,8 +128,9 @@ func NewClientWithSharedKeyCredential(filesystemURL string, cred *SharedKeyCrede // NewClientFromConnectionString creates an instance of Client with the specified values. // - connectionString - a connection string for the desired storage account // - options - client options; pass nil to accept the default values -func NewClientFromConnectionString(connectionString string, options *ClientOptions) (*Client, error) { +func NewClientFromConnectionString(connectionString string, fsName string, options *ClientOptions) (*Client, error) { parsed, err := shared.ParseConnectionString(connectionString) + parsed.ServiceURL = runtime.JoinPaths(parsed.ServiceURL, fsName) if err != nil { return nil, err } @@ -143,7 +147,6 @@ func NewClientFromConnectionString(connectionString string, options *ClientOptio } func (fs *Client) generatedFSClientWithDFS() *generated.FileSystemClient { - //base.SharedKeyComposite((*base.CompositeClient[generated.BlobClient, generated.BlockBlobClient])(bb)) fsClientWithDFS, _, _ := base.InnerClients((*base.CompositeClient[generated.FileSystemClient, generated.FileSystemClient, container.Client])(fs)) return fsClientWithDFS } @@ -183,6 +186,7 @@ func (fs *Client) BlobURL() string { // NewDirectoryClient creates a new directory.Client object by concatenating directory path to the end of this Client's URL. // The new directory.Client uses the same request policy pipeline as the Client. func (fs *Client) NewDirectoryClient(directoryPath string) *directory.Client { + directoryPath = strings.ReplaceAll(directoryPath, "\\", "/") dirURL := runtime.JoinPaths(fs.generatedFSClientWithDFS().Endpoint(), directoryPath) blobURL, dirURL := shared.GetURLs(dirURL) return (*directory.Client)(base.NewPathClient(dirURL, blobURL, fs.containerClient().NewBlockBlobClient(directoryPath), fs.generatedFSClientWithDFS().InternalClient().WithClientName(shared.DirectoryClient), fs.sharedKey(), fs.identityCredential(), fs.getClientOptions())) @@ -191,6 +195,7 @@ func (fs *Client) NewDirectoryClient(directoryPath string) *directory.Client { // NewFileClient creates a new file.Client object by concatenating file path to the end of this Client's URL. // The new file.Client uses the same request policy pipeline as the Client. func (fs *Client) NewFileClient(filePath string) *file.Client { + filePath = strings.ReplaceAll(filePath, "\\", "/") fileURL := runtime.JoinPaths(fs.generatedFSClientWithDFS().Endpoint(), filePath) blobURL, fileURL := shared.GetURLs(fileURL) return (*file.Client)(base.NewPathClient(fileURL, blobURL, fs.containerClient().NewBlockBlobClient(filePath), fs.generatedFSClientWithDFS().InternalClient().WithClientName(shared.FileClient), fs.sharedKey(), fs.identityCredential(), fs.getClientOptions())) @@ -217,7 +222,6 @@ func (fs *Client) GetProperties(ctx context.Context, options *GetPropertiesOptio opts := options.format() newResp := GetPropertiesResponse{} resp, err := fs.containerClient().GetProperties(ctx, opts) - // TODO: find a cleaner way to not use lease from blob package formatFilesystemProperties(&newResp, &resp) err = exported.ConvertToDFSError(err) return newResp, err @@ -254,7 +258,6 @@ func (fs *Client) GetAccessPolicy(ctx context.Context, options *GetAccessPolicyO // NewListPathsPager operation returns a pager of the shares under the specified account. (dfs1) // For more information, see https://learn.microsoft.com/en-us/rest/api/storageservices/list-shares func (fs *Client) NewListPathsPager(recursive bool, options *ListPathsOptions) *runtime.Pager[ListPathsSegmentResponse] { - //TODO: look into possibility of using blob endpoint like list deleted paths is listOptions := options.format() return runtime.NewPager(runtime.PagingHandler[ListPathsSegmentResponse]{ More: func(page ListPathsSegmentResponse) bool { @@ -300,17 +303,17 @@ func (fs *Client) NewListDeletedPathsPager(options *ListDeletedPathsOptions) *ru var req *policy.Request var err error if page == nil { - req, err = fs.generatedFSClientWithDFS().ListBlobHierarchySegmentCreateRequest(ctx, &listOptions) + req, err = fs.generatedFSClientWithBlob().ListBlobHierarchySegmentCreateRequest(ctx, &listOptions) err = exported.ConvertToDFSError(err) } else { listOptions.Marker = page.NextMarker - req, err = fs.generatedFSClientWithDFS().ListBlobHierarchySegmentCreateRequest(ctx, &listOptions) + req, err = fs.generatedFSClientWithBlob().ListBlobHierarchySegmentCreateRequest(ctx, &listOptions) err = exported.ConvertToDFSError(err) } if err != nil { return ListDeletedPathsSegmentResponse{}, err } - resp, err := fs.generatedFSClientWithDFS().InternalClient().Pipeline().Do(req) + resp, err := fs.generatedFSClientWithBlob().InternalClient().Pipeline().Do(req) err = exported.ConvertToDFSError(err) if err != nil { return ListDeletedPathsSegmentResponse{}, err @@ -318,7 +321,7 @@ func (fs *Client) NewListDeletedPathsPager(options *ListDeletedPathsOptions) *ru if !runtime.HasStatusCode(resp, http.StatusOK) { return ListDeletedPathsSegmentResponse{}, runtime.NewResponseError(resp) } - newResp, err := fs.generatedFSClientWithDFS().ListBlobHierarchySegmentHandleResponse(resp) + newResp, err := fs.generatedFSClientWithBlob().ListBlobHierarchySegmentHandleResponse(resp) return newResp, exported.ConvertToDFSError(err) }, }) diff --git a/sdk/storage/azdatalake/filesystem/client_test.go b/sdk/storage/azdatalake/filesystem/client_test.go index 37df43b164fe..1cbe0105d181 100644 --- a/sdk/storage/azdatalake/filesystem/client_test.go +++ b/sdk/storage/azdatalake/filesystem/client_test.go @@ -13,6 +13,7 @@ import ( "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/datalakeerror" "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/filesystem" "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/internal/testcommon" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/lease" "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/sas" "github.com/stretchr/testify/require" "github.com/stretchr/testify/suite" @@ -435,7 +436,7 @@ func (s *RecordedTestSuite) TestFilesystemSetMetadataNonExistent() { testcommon.ValidateErrorCode(_require, err, datalakeerror.FilesystemNotFound) } -func (s *RecordedTestSuite) TestSetEmptyAccessPolicy() { +func (s *RecordedTestSuite) TestFilesystemSetEmptyAccessPolicy() { _require := require.New(s.T()) testName := s.T().Name() @@ -451,7 +452,7 @@ func (s *RecordedTestSuite) TestSetEmptyAccessPolicy() { _require.Nil(err) } -func (s *RecordedTestSuite) TestSetNilAccessPolicy() { +func (s *RecordedTestSuite) TestFilesystemSetNilAccessPolicy() { _require := require.New(s.T()) testName := s.T().Name() @@ -467,7 +468,7 @@ func (s *RecordedTestSuite) TestSetNilAccessPolicy() { _require.Nil(err) } -func (s *RecordedTestSuite) TestSetAccessPolicy() { +func (s *RecordedTestSuite) TestFilesystemSetAccessPolicy() { _require := require.New(s.T()) testName := s.T().Name() @@ -499,7 +500,7 @@ func (s *RecordedTestSuite) TestSetAccessPolicy() { _require.Nil(err) } -func (s *RecordedTestSuite) TestSetMultipleAccessPolicies() { +func (s *RecordedTestSuite) TestFilesystemSetMultipleAccessPolicies() { _require := require.New(s.T()) testName := s.T().Name() @@ -551,7 +552,7 @@ func (s *RecordedTestSuite) TestSetMultipleAccessPolicies() { _require.Len(resp.SignedIdentifiers, 3) } -func (s *RecordedTestSuite) TestSetNullAccessPolicy() { +func (s *RecordedTestSuite) TestFilesystemSetNullAccessPolicy() { _require := require.New(s.T()) testName := s.T().Name() @@ -578,6 +579,87 @@ func (s *RecordedTestSuite) TestSetNullAccessPolicy() { _require.Equal(len(resp.SignedIdentifiers), 1) } +func (s *RecordedTestSuite) TestFilesystemGetAccessPolicyWithEmptyOpts() { + _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) + + _, err = fsClient.Create(context.Background(), nil) + _require.Nil(err) + defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + + id := "null" + + signedIdentifiers := make([]*filesystem.SignedIdentifier, 0) + signedIdentifiers = append(signedIdentifiers, &filesystem.SignedIdentifier{ + ID: &id, + }) + options := filesystem.SetAccessPolicyOptions{FilesystemACL: signedIdentifiers} + _, err = fsClient.SetAccessPolicy(context.Background(), &options) + _require.Nil(err) + + opts := &filesystem.GetAccessPolicyOptions{} + + resp, err := fsClient.GetAccessPolicy(context.Background(), opts) + _require.Nil(err) + _require.Equal(len(resp.SignedIdentifiers), 1) +} + +func (s *RecordedTestSuite) TestFilesystemGetAccessPolicyOnLeasedFilesystem() { + _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) + + _, err = fsClient.Create(context.Background(), nil) + _require.Nil(err) + + var proposedLeaseIDs = []*string{to.Ptr("c820a799-76d7-4ee2-6e15-546f19325c2c"), to.Ptr("326cc5e1-746e-4af8-4811-a50e6629a8ca")} + + fsLeaseClient, err := lease.NewFilesystemClient(fsClient, &lease.FilesystemClientOptions{ + LeaseID: proposedLeaseIDs[0], + }) + _require.Nil(err) + + id := "null" + + signedIdentifiers := make([]*filesystem.SignedIdentifier, 0) + signedIdentifiers = append(signedIdentifiers, &filesystem.SignedIdentifier{ + ID: &id, + }) + options := filesystem.SetAccessPolicyOptions{FilesystemACL: signedIdentifiers} + _, err = fsClient.SetAccessPolicy(context.Background(), &options) + _require.Nil(err) + + _, err = fsLeaseClient.AcquireLease(context.Background(), int32(15), nil) + _require.Nil(err) + + opts1 := &filesystem.GetAccessPolicyOptions{ + LeaseAccessConditions: &filesystem.LeaseAccessConditions{ + LeaseID: proposedLeaseIDs[0], + }, + } + + _, err = fsClient.SetAccessPolicy(context.Background(), &options) + _require.Nil(err) + + resp, err := fsClient.GetAccessPolicy(context.Background(), opts1) + _require.Nil(err) + _require.Equal(len(resp.SignedIdentifiers), 1) + + _, err = fsClient.Delete(context.Background(), &filesystem.DeleteOptions{AccessConditions: &filesystem.AccessConditions{ + LeaseAccessConditions: &filesystem.LeaseAccessConditions{ + LeaseID: proposedLeaseIDs[0], + }, + }}) + _require.Nil(err) +} + func (s *RecordedTestSuite) TestFilesystemGetSetPermissionsMultiplePolicies() { _require := require.New(s.T()) testName := s.T().Name() @@ -1047,7 +1129,7 @@ func (s *RecordedTestSuite) TestFilesystemSetPermissionsIfUnModifiedSinceFalse() testcommon.ValidateErrorCode(_require, err, datalakeerror.ConditionNotMet) } -func (s *RecordedTestSuite) TestSetAccessPoliciesInDifferentTimeFormats() { +func (s *UnrecordedTestSuite) TestFilesystemSetAccessPoliciesInDifferentTimeFormats() { _require := require.New(s.T()) testName := s.T().Name() @@ -1112,7 +1194,7 @@ func (s *RecordedTestSuite) TestSetAccessPoliciesInDifferentTimeFormats() { _require.EqualValues(resp1.SignedIdentifiers, signedIdentifiers) } -func (s *RecordedTestSuite) TestSetAccessPolicyWithNullId() { +func (s *RecordedTestSuite) TestFilesystemSetAccessPolicyWithNullId() { _require := require.New(s.T()) testName := s.T().Name() @@ -1172,34 +1254,464 @@ func (s *UnrecordedTestSuite) TestSASFilesystemClient() { _require.Nil(err) } -// TODO: test sas on files - -//func (s *RecordedTestSuite) TestFilesystemListPaths() { -// _require := require.New(s.T()) -// //testName := s.T().Name() -// -// //filesystemName := testcommon.GenerateFilesystemName(testName) -// fsClient, err := testcommon.GetFilesystemClient("cont1", s.T(), testcommon.TestAccountDatalake, nil) -// _require.NoError(err) -// //defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) -// -// //_, err = fsClient.Create(context.Background(), nil) -// //_require.Nil(err) -// -// resp, err := fsClient.GetProperties(context.Background(), nil) -// _require.Nil(err) -// _require.NotNil(resp.ETag) -// _require.Nil(resp.Metadata) -// -// pager := fsClient.NewListPathsPager(true, nil) -// -// for pager.More() { -// _, err := pager.NextPage(context.Background()) -// _require.NotNil(err) -// if err != nil { -// break -// } -// } -//} - -// TODO: Lease tests +func (s *RecordedTestSuite) TestFilesystemListPathsWithRecursive() { + _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) + + client := fsClient.NewFileClient(testName + "file1") + _, err = client.Create(context.Background(), nil) + _require.Nil(err) + client = fsClient.NewFileClient(testName + "file2") + _, err = client.Create(context.Background(), nil) + _require.Nil(err) + dirClient := fsClient.NewDirectoryClient(testName + "dir1") + _, err = dirClient.Create(context.Background(), nil) + _require.Nil(err) + dirClient = fsClient.NewDirectoryClient(testName + "dir2") + _, err = dirClient.Create(context.Background(), nil) + _require.Nil(err) + + pager := fsClient.NewListPathsPager(true, nil) + for pager.More() { + resp, err := pager.NextPage(context.Background()) + _require.Nil(err) + _require.Equal(5, len(resp.Paths)) + if err != nil { + break + } + } +} + +func (s *RecordedTestSuite) TestFilesystemListPathsWithoutRecursive() { + _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) + + client := fsClient.NewFileClient(testName + "file1") + _, err = client.Create(context.Background(), nil) + _require.Nil(err) + client = fsClient.NewFileClient(testName + "file2") + _, err = client.Create(context.Background(), nil) + _require.Nil(err) + dirClient := fsClient.NewDirectoryClient(testName + "dir1") + _, err = dirClient.Create(context.Background(), nil) + _require.Nil(err) + dirClient = fsClient.NewDirectoryClient(testName + "dir2") + _, err = dirClient.Create(context.Background(), nil) + _require.Nil(err) + + pager := fsClient.NewListPathsPager(false, nil) + for pager.More() { + resp, err := pager.NextPage(context.Background()) + _require.Nil(err) + _require.Equal(1, len(resp.Paths)) + if err != nil { + break + } + } +} + +func (s *RecordedTestSuite) TestFilesystemListPathsWithMaxResults() { + _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) + + client := fsClient.NewFileClient(testName + "file1") + _, err = client.Create(context.Background(), nil) + _require.Nil(err) + client = fsClient.NewFileClient(testName + "file2") + _, err = client.Create(context.Background(), nil) + _require.Nil(err) + dirClient := fsClient.NewDirectoryClient(testName + "dir1") + _, err = dirClient.Create(context.Background(), nil) + _require.Nil(err) + dirClient = fsClient.NewDirectoryClient(testName + "dir2") + _, err = dirClient.Create(context.Background(), nil) + _require.Nil(err) + + opts := filesystem.ListPathsOptions{ + MaxResults: to.Ptr(int32(2)), + } + pages := 3 + count := 0 + pager := fsClient.NewListPathsPager(true, &opts) + for pager.More() { + _, err = pager.NextPage(context.Background()) + _require.Nil(err) + count += 1 + if err != nil { + break + } + } + _require.Equal(pages, count) +} + +func (s *RecordedTestSuite) TestFilesystemListPathsWithPrefix() { + _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) + + client := fsClient.NewFileClient(testName + "file1") + _, err = client.Create(context.Background(), nil) + _require.Nil(err) + client = fsClient.NewFileClient(testName + "file2") + _, err = client.Create(context.Background(), nil) + _require.Nil(err) + dirClient := fsClient.NewDirectoryClient(testName + "dir1") + _, err = dirClient.Create(context.Background(), nil) + _require.Nil(err) + dirClient = fsClient.NewDirectoryClient(testName + "dir2") + _, err = dirClient.Create(context.Background(), nil) + _require.Nil(err) + + opts := filesystem.ListPathsOptions{ + Prefix: to.Ptr("Test"), + } + pager := fsClient.NewListPathsPager(true, &opts) + for pager.More() { + resp, err := pager.NextPage(context.Background()) + _require.Nil(err) + _require.Equal(4, len(resp.Paths)) + if err != nil { + break + } + } +} + +func (s *RecordedTestSuite) TestFilesystemListPathsWithContinuation() { + _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) + + client := fsClient.NewFileClient(testName + "file1") + _, err = client.Create(context.Background(), nil) + _require.Nil(err) + client = fsClient.NewFileClient(testName + "file2") + _, err = client.Create(context.Background(), nil) + _require.Nil(err) + dirClient := fsClient.NewDirectoryClient(testName + "dir1") + _, err = dirClient.Create(context.Background(), nil) + _require.Nil(err) + dirClient = fsClient.NewDirectoryClient(testName + "dir2") + _, err = dirClient.Create(context.Background(), nil) + _require.Nil(err) + + opts := filesystem.ListPathsOptions{ + MaxResults: to.Ptr(int32(3)), + } + pager := fsClient.NewListPathsPager(true, &opts) + + resp, err := pager.NextPage(context.Background()) + _require.Nil(err) + _require.Equal(3, len(resp.Paths)) + _require.NotNil(resp.Continuation) + + token := resp.Continuation + pager = fsClient.NewListPathsPager(true, &filesystem.ListPathsOptions{ + Marker: token, + }) + resp, err = pager.NextPage(context.Background()) + _require.Nil(err) + _require.Equal(2, len(resp.Paths)) + _require.Nil(resp.Continuation) +} + +func (s *RecordedTestSuite) TestFilesystemListDeletedPaths() { + _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) + + client := fsClient.NewFileClient(testName + "file1") + _, err = client.Create(context.Background(), nil) + _require.Nil(err) + client = fsClient.NewFileClient(testName + "file2") + _, err = client.Create(context.Background(), nil) + _require.Nil(err) + dirClient := fsClient.NewDirectoryClient(testName + "dir1") + _, err = dirClient.Create(context.Background(), nil) + _require.Nil(err) + dirClient = fsClient.NewDirectoryClient(testName + "dir2") + _, err = dirClient.Create(context.Background(), nil) + _require.Nil(err) + _, err = dirClient.Delete(context.Background(), nil) + _require.Nil(err) + + pager := fsClient.NewListDeletedPathsPager(nil) + for pager.More() { + resp, err := pager.NextPage(context.Background()) + _require.Nil(err) + _require.Equal(1, len(resp.ListPathsHierarchySegmentResponse.Segment.PathItems)) + if err != nil { + break + } + } +} + +func (s *RecordedTestSuite) TestFilesystemListDeletedPathsWithMaxResults() { + _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) + + client := fsClient.NewFileClient(testName + "file1") + _, err = client.Create(context.Background(), nil) + _require.Nil(err) + _, err = client.Delete(context.Background(), nil) + _require.Nil(err) + client = fsClient.NewFileClient(testName + "file2") + _, err = client.Create(context.Background(), nil) + _require.Nil(err) + _, err = client.Delete(context.Background(), nil) + _require.Nil(err) + dirClient := fsClient.NewDirectoryClient(testName + "dir1") + _, err = dirClient.Create(context.Background(), nil) + _require.Nil(err) + _, err = dirClient.Delete(context.Background(), nil) + _require.Nil(err) + dirClient = fsClient.NewDirectoryClient(testName + "dir2") + _, err = dirClient.Create(context.Background(), nil) + _require.Nil(err) + _, err = dirClient.Delete(context.Background(), nil) + _require.Nil(err) + + opts := filesystem.ListDeletedPathsOptions{ + MaxResults: to.Ptr(int32(2)), + } + pages := 2 + count := 0 + pager := fsClient.NewListDeletedPathsPager(&opts) + for pager.More() { + _, err = pager.NextPage(context.Background()) + _require.Nil(err) + count += 1 + if err != nil { + break + } + } + _require.Equal(pages, count) +} + +func (s *RecordedTestSuite) TestFilesystemListDeletedPathsWithPrefix() { + _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) + + client := fsClient.NewFileClient(testName + "file1") + _, err = client.Create(context.Background(), nil) + _require.Nil(err) + _, err = client.Delete(context.Background(), nil) + _require.Nil(err) + client = fsClient.NewFileClient(testName + "file2") + _, err = client.Create(context.Background(), nil) + _require.Nil(err) + _, err = client.Delete(context.Background(), nil) + _require.Nil(err) + dirClient := fsClient.NewDirectoryClient(testName + "dir1") + _, err = dirClient.Create(context.Background(), nil) + _require.Nil(err) + _, err = dirClient.Delete(context.Background(), nil) + _require.Nil(err) + dirClient = fsClient.NewDirectoryClient(testName + "dir2") + _, err = dirClient.Create(context.Background(), nil) + _require.Nil(err) + _, err = dirClient.Delete(context.Background(), nil) + _require.Nil(err) + + opts := filesystem.ListDeletedPathsOptions{ + Prefix: to.Ptr("Test"), + } + pager := fsClient.NewListDeletedPathsPager(&opts) + for pager.More() { + resp, err := pager.NextPage(context.Background()) + _require.Nil(err) + _require.Equal(4, len(resp.ListPathsHierarchySegmentResponse.Segment.PathItems)) + if err != nil { + break + } + } +} + +func (s *RecordedTestSuite) TestFilesystemListDeletedPathsWithContinuation() { + _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) + + client := fsClient.NewFileClient(testName + "file1") + _, err = client.Create(context.Background(), nil) + _require.Nil(err) + _, err = client.Delete(context.Background(), nil) + _require.Nil(err) + client = fsClient.NewFileClient(testName + "file2") + _, err = client.Create(context.Background(), nil) + _require.Nil(err) + _, err = client.Delete(context.Background(), nil) + _require.Nil(err) + dirClient := fsClient.NewDirectoryClient(testName + "dir1") + _, err = dirClient.Create(context.Background(), nil) + _require.Nil(err) + _, err = dirClient.Delete(context.Background(), nil) + _require.Nil(err) + dirClient = fsClient.NewDirectoryClient(testName + "dir2") + _, err = dirClient.Create(context.Background(), nil) + _require.Nil(err) + _, err = dirClient.Delete(context.Background(), nil) + _require.Nil(err) + + opts := filesystem.ListDeletedPathsOptions{ + MaxResults: to.Ptr(int32(3)), + } + pager := fsClient.NewListDeletedPathsPager(&opts) + + resp, err := pager.NextPage(context.Background()) + _require.Nil(err) + _require.Equal(3, len(resp.ListPathsHierarchySegmentResponse.Segment.PathItems)) + _require.NotNil(resp.NextMarker) + + token := resp.NextMarker + pager = fsClient.NewListDeletedPathsPager(&filesystem.ListDeletedPathsOptions{ + Marker: token, + }) + resp, err = pager.NextPage(context.Background()) + _require.Nil(err) + _require.Equal(1, len(resp.ListPathsHierarchySegmentResponse.Segment.PathItems)) + _require.Equal("", *resp.NextMarker) +} + +func (s *UnrecordedTestSuite) TestSASFilesystemCreateAndDeleteFile() { + _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) + + _, err = fsClient.Create(context.Background(), nil) + _require.Nil(err) + defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + + // Adding SAS and options + permissions := sas.FilesystemPermissions{ + Read: true, + Add: true, + Write: true, + Create: true, + Delete: true, + } + expiry := time.Now().Add(time.Hour) + + // filesystemSASURL is created with GetSASURL + sasUrl, err := fsClient.GetSASURL(permissions, expiry, nil) + _require.Nil(err) + + // Create filesystem client with sasUrl + client, err := filesystem.NewClientWithNoCredential(sasUrl, nil) + _require.Nil(err) + + fClient := client.NewFileClient(testcommon.GenerateFileName(testName)) + _, err = fClient.Create(context.Background(), nil) + _require.Nil(err) + + _, err = fClient.Delete(context.Background(), nil) + _require.Nil(err) +} + +func (s *UnrecordedTestSuite) TestSASFilesystemCreateAndDeleteDirectory() { + _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) + + _, err = fsClient.Create(context.Background(), nil) + _require.Nil(err) + defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + + // Adding SAS and options + permissions := sas.FilesystemPermissions{ + Read: true, + Add: true, + Write: true, + Create: true, + Delete: true, + } + expiry := time.Now().Add(time.Hour) + + // filesystemSASURL is created with GetSASURL + sasUrl, err := fsClient.GetSASURL(permissions, expiry, nil) + _require.Nil(err) + + // Create filesystem client with sasUrl + client, err := filesystem.NewClientWithNoCredential(sasUrl, nil) + _require.Nil(err) + + dClient := client.NewDirectoryClient(testcommon.GenerateDirName(testName)) + _, err = dClient.Create(context.Background(), nil) + _require.Nil(err) + + _, err = dClient.Delete(context.Background(), nil) + _require.Nil(err) +} diff --git a/sdk/storage/azdatalake/filesystem/constants.go b/sdk/storage/azdatalake/filesystem/constants.go index 3e0c373b87a1..1b2916076c46 100644 --- a/sdk/storage/azdatalake/filesystem/constants.go +++ b/sdk/storage/azdatalake/filesystem/constants.go @@ -6,7 +6,10 @@ package filesystem -import "github.com/Azure/azure-sdk-for-go/sdk/storage/azblob" +import ( + "github.com/Azure/azure-sdk-for-go/sdk/storage/azblob" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake" +) // PublicAccessType defines values for AccessType - private (default) or file or filesystem. type PublicAccessType = azblob.PublicAccessType @@ -15,3 +18,40 @@ const ( File PublicAccessType = azblob.PublicAccessTypeBlob Filesystem PublicAccessType = azblob.PublicAccessTypeContainer ) + +// StatusType defines values for StatusType +type StatusType = azdatalake.StatusType + +const ( + StatusTypeLocked StatusType = azdatalake.StatusTypeLocked + StatusTypeUnlocked StatusType = azdatalake.StatusTypeUnlocked +) + +// PossibleStatusTypeValues returns the possible values for the StatusType const type. +func PossibleStatusTypeValues() []StatusType { + return azdatalake.PossibleStatusTypeValues() +} + +// DurationType defines values for DurationType +type DurationType = azdatalake.DurationType + +const ( + DurationTypeInfinite DurationType = azdatalake.DurationTypeInfinite + DurationTypeFixed DurationType = azdatalake.DurationTypeFixed +) + +// PossibleDurationTypeValues returns the possible values for the DurationType const type. +func PossibleDurationTypeValues() []DurationType { + return azdatalake.PossibleDurationTypeValues() +} + +// StateType defines values for StateType +type StateType = azdatalake.StateType + +const ( + StateTypeAvailable StateType = azdatalake.StateTypeAvailable + StateTypeLeased StateType = azdatalake.StateTypeLeased + StateTypeExpired StateType = azdatalake.StateTypeExpired + StateTypeBreaking StateType = azdatalake.StateTypeBreaking + StateTypeBroken StateType = azdatalake.StateTypeBroken +) diff --git a/sdk/storage/azdatalake/filesystem/models.go b/sdk/storage/azdatalake/filesystem/models.go index e0d6f6ce0b86..50944097d146 100644 --- a/sdk/storage/azdatalake/filesystem/models.go +++ b/sdk/storage/azdatalake/filesystem/models.go @@ -126,19 +126,6 @@ func (o *GetAccessPolicyOptions) format() *container.GetAccessPolicyOptions { } } -// CPKScopeInfo contains a group of parameters for the FilesystemClient.Create method. -type CPKScopeInfo = container.CPKScopeInfo - -// AccessPolicy - An Access policy. -type AccessPolicy = container.AccessPolicy - -// AccessPolicyPermission type simplifies creating the permissions string for a container's access policy. -// Initialize an instance of this type and then call its String method to set AccessPolicy's Permission field. -type AccessPolicyPermission = exported.AccessPolicyPermission - -// SignedIdentifier - signed identifier. -type SignedIdentifier = container.SignedIdentifier - // ListPathsOptions contains the optional parameters for the Filesystem.ListPaths operation. type ListPathsOptions struct { Marker *string @@ -199,17 +186,30 @@ func (o *GetSASURLOptions) format() time.Time { return st } -// UndeletePathOptions contains the optional parameters for the Filesystem.UndeletePath operation. -type UndeletePathOptions struct { - // placeholder -} +//// UndeletePathOptions contains the optional parameters for the Filesystem.UndeletePath operation. +//type UndeletePathOptions struct { +// // placeholder +//} +// +//func (o *UndeletePathOptions) format() *UndeletePathOptions { +// if o == nil { +// return nil +// } +// return &UndeletePathOptions{} +//} -func (o *UndeletePathOptions) format() *UndeletePathOptions { - if o == nil { - return nil - } - return &UndeletePathOptions{} -} +// CPKScopeInfo contains a group of parameters for the FilesystemClient.Create method. +type CPKScopeInfo = container.CPKScopeInfo + +// AccessPolicy - An Access policy. +type AccessPolicy = container.AccessPolicy + +// AccessPolicyPermission type simplifies creating the permissions string for a container's access policy. +// Initialize an instance of this type and then call its String method to set AccessPolicy's Permission field. +type AccessPolicyPermission = exported.AccessPolicyPermission + +// SignedIdentifier - signed identifier. +type SignedIdentifier = container.SignedIdentifier // SharedKeyCredential contains an account's name and its primary or secondary key. type SharedKeyCredential = exported.SharedKeyCredential @@ -223,11 +223,17 @@ type LeaseAccessConditions = exported.LeaseAccessConditions // ModifiedAccessConditions contains a group of parameters for specifying access conditions. type ModifiedAccessConditions = exported.ModifiedAccessConditions -// PathList contains the path list +// PathList contains the path list from the ListPaths operation type PathList = generated.PathList -// Path contains the path properties +// Path contains the path properties from the ListPaths operation type Path = generated.Path -// UndeletePathResponse contains the response from method FilesystemClient.UndeletePath. -type UndeletePathResponse = generated.PathClientUndeleteResponse +// PathItem contains the response from method FilesystemClient.ListBlobsHierarchySegment. +type PathItem = generated.PathItemInternal + +// PathProperties contains the response from method FilesystemClient.ListBlobsHierarchySegment. +type PathProperties = generated.PathPropertiesInternal + +// PathPrefix contains the response from method FilesystemClient.ListBlobsHierarchySegment. +type PathPrefix = generated.PathPrefix diff --git a/sdk/storage/azdatalake/filesystem/responses.go b/sdk/storage/azdatalake/filesystem/responses.go index d32f0aed538d..5651a4a77a9c 100644 --- a/sdk/storage/azdatalake/filesystem/responses.go +++ b/sdk/storage/azdatalake/filesystem/responses.go @@ -9,23 +9,10 @@ package filesystem import ( "github.com/Azure/azure-sdk-for-go/sdk/azcore" "github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/container" - "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake" "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/internal/generated" "time" ) -// CreateResponse contains the response from method FilesystemClient.Create. -type CreateResponse = container.CreateResponse - -// DeleteResponse contains the response from method FilesystemClient.Delete. -type DeleteResponse = container.DeleteResponse - -// SetMetadataResponse contains the response from method FilesystemClient.SetMetadata. -type SetMetadataResponse = container.SetMetadataResponse - -// SetAccessPolicyResponse contains the response from method FilesystemClient.SetAccessPolicy. -type SetAccessPolicyResponse = container.SetAccessPolicyResponse - // GetAccessPolicyResponse contains the response from method FilesystemClient.GetAccessPolicy. type GetAccessPolicyResponse struct { // PublicAccess contains the information returned from the x-ms-blob-public-access header response. @@ -99,13 +86,13 @@ type GetPropertiesResponse struct { LastModified *time.Time // LeaseDuration contains the information returned from the x-ms-lease-duration header response. - LeaseDuration *azdatalake.DurationType + LeaseDuration *DurationType // LeaseState contains the information returned from the x-ms-lease-state header response. - LeaseState *azdatalake.StateType + LeaseState *StateType // LeaseStatus contains the information returned from the x-ms-lease-status header response. - LeaseStatus *azdatalake.StatusType + LeaseStatus *StatusType // Metadata contains the information returned from the x-ms-meta header response. Metadata map[string]*string @@ -137,11 +124,29 @@ func formatFilesystemProperties(r *GetPropertiesResponse, contResp *container.Ge r.Version = contResp.Version } +// CreateResponse contains the response from method FilesystemClient.Create. +type CreateResponse = container.CreateResponse + +// DeleteResponse contains the response from method FilesystemClient.Delete. +type DeleteResponse = container.DeleteResponse + +// SetMetadataResponse contains the response from method FilesystemClient.SetMetadata. +type SetMetadataResponse = container.SetMetadataResponse + +// SetAccessPolicyResponse contains the response from method FilesystemClient.SetAccessPolicy. +type SetAccessPolicyResponse = container.SetAccessPolicyResponse + // ListPathsSegmentResponse contains the response from method FilesystemClient.ListPathsSegment. type ListPathsSegmentResponse = generated.FileSystemClientListPathsResponse +// UndeletePathResponse contains the response from method FilesystemClient.UndeletePath. +type UndeletePathResponse = generated.PathClientUndeleteResponse + // ListDeletedPathsSegmentResponse contains the response from method FilesystemClient.ListPathsSegment. -type ListDeletedPathsSegmentResponse = generated.FileSystemClientListBlobHierarchySegmentResponse +type ListDeletedPathsSegmentResponse = generated.FileSystemClientListPathHierarchySegmentResponse + +// ListPathsHierarchySegmentResponse contains the response from method FilesystemClient.ListBlobsHierarchySegment. +type ListPathsHierarchySegmentResponse = generated.ListPathsHierarchySegmentResponse -// ListBlobsHierarchySegmentResponse contains the response from method FilesystemClient.ListBlobsHierarchySegment. -type ListBlobsHierarchySegmentResponse = generated.ListBlobsHierarchySegmentResponse +// PathHierarchyListSegment contains the response from method FilesystemClient.ListBlobsHierarchySegment. +type PathHierarchyListSegment = generated.PathHierarchyListSegment diff --git a/sdk/storage/azdatalake/internal/base/clients.go b/sdk/storage/azdatalake/internal/base/clients.go index cab52ce400b2..cc4af2b63e93 100644 --- a/sdk/storage/azdatalake/internal/base/clients.go +++ b/sdk/storage/azdatalake/internal/base/clients.go @@ -14,6 +14,7 @@ import ( "github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/service" "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/generated_blob" ) // ClientOptions contains the optional parameters when creating a Client. @@ -65,10 +66,10 @@ func NewFilesystemClient(fsURL string, fsURLWithBlobEndpoint string, client *con } } -func NewServiceClient(serviceURL string, serviceURLWithBlobEndpoint string, client *service.Client, azClient *azcore.Client, sharedKey *exported.SharedKeyCredential, identityCred *azcore.TokenCredential, options *ClientOptions) *CompositeClient[generated.ServiceClient, generated.ServiceClient, service.Client] { - return &CompositeClient[generated.ServiceClient, generated.ServiceClient, service.Client]{ +func NewServiceClient(serviceURL string, serviceURLWithBlobEndpoint string, client *service.Client, azClient *azcore.Client, sharedKey *exported.SharedKeyCredential, identityCred *azcore.TokenCredential, options *ClientOptions) *CompositeClient[generated.ServiceClient, generated_blob.ServiceClient, service.Client] { + return &CompositeClient[generated.ServiceClient, generated_blob.ServiceClient, service.Client]{ innerT: generated.NewServiceClient(serviceURL, azClient), - innerK: generated.NewServiceClient(serviceURLWithBlobEndpoint, azClient), + innerK: generated_blob.NewServiceClient(serviceURLWithBlobEndpoint, azClient), sharedKey: sharedKey, identityCred: identityCred, innerU: client, @@ -76,10 +77,10 @@ func NewServiceClient(serviceURL string, serviceURLWithBlobEndpoint string, clie } } -func NewPathClient(pathURL string, pathURLWithBlobEndpoint string, client *blockblob.Client, azClient *azcore.Client, sharedKey *exported.SharedKeyCredential, identityCred *azcore.TokenCredential, options *ClientOptions) *CompositeClient[generated.PathClient, generated.PathClient, blockblob.Client] { - return &CompositeClient[generated.PathClient, generated.PathClient, blockblob.Client]{ +func NewPathClient(pathURL string, pathURLWithBlobEndpoint string, client *blockblob.Client, azClient *azcore.Client, sharedKey *exported.SharedKeyCredential, identityCred *azcore.TokenCredential, options *ClientOptions) *CompositeClient[generated.PathClient, generated_blob.BlobClient, blockblob.Client] { + return &CompositeClient[generated.PathClient, generated_blob.BlobClient, blockblob.Client]{ innerT: generated.NewPathClient(pathURL, azClient), - innerK: generated.NewPathClient(pathURLWithBlobEndpoint, azClient), + innerK: generated_blob.NewBlobClient(pathURLWithBlobEndpoint, azClient), sharedKey: sharedKey, identityCred: identityCred, innerU: client, diff --git a/sdk/storage/azdatalake/internal/exported/access_conditions.go b/sdk/storage/azdatalake/internal/exported/access_conditions.go index 9e6fb3850bbd..624efc449132 100644 --- a/sdk/storage/azdatalake/internal/exported/access_conditions.go +++ b/sdk/storage/azdatalake/internal/exported/access_conditions.go @@ -1,3 +1,9 @@ +//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 exported import ( diff --git a/sdk/storage/azdatalake/internal/exported/set_expiry.go b/sdk/storage/azdatalake/internal/exported/set_expiry.go index 2b8e156c315f..5938518bbdba 100644 --- a/sdk/storage/azdatalake/internal/exported/set_expiry.go +++ b/sdk/storage/azdatalake/internal/exported/set_expiry.go @@ -7,17 +7,17 @@ package exported import ( + "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/internal/generated_blob" "net/http" "strconv" "time" "github.com/Azure/azure-sdk-for-go/sdk/azcore/to" - "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/internal/generated" ) // SetExpiryType defines values for ExpiryType type SetExpiryType interface { - Format(o *SetExpiryOptions) (generated.ExpiryOptions, *generated.PathClientSetExpiryOptions) + Format(o *SetExpiryOptions) (generated_blob.ExpiryOptions, *generated_blob.BlobClientSetExpiryOptions) notPubliclyImplementable() } @@ -40,32 +40,32 @@ type SetExpiryOptions struct { // placeholder for future options } -func (e SetExpiryTypeAbsolute) Format(o *SetExpiryOptions) (generated.ExpiryOptions, *generated.PathClientSetExpiryOptions) { - return generated.ExpiryOptionsAbsolute, &generated.PathClientSetExpiryOptions{ +func (e SetExpiryTypeAbsolute) Format(o *SetExpiryOptions) (generated_blob.ExpiryOptions, *generated_blob.BlobClientSetExpiryOptions) { + return generated_blob.ExpiryOptionsAbsolute, &generated_blob.BlobClientSetExpiryOptions{ ExpiresOn: to.Ptr(time.Time(e).UTC().Format(http.TimeFormat)), } } func (e SetExpiryTypeAbsolute) notPubliclyImplementable() {} -func (e SetExpiryTypeRelativeToNow) Format(o *SetExpiryOptions) (generated.ExpiryOptions, *generated.PathClientSetExpiryOptions) { - return generated.ExpiryOptionsRelativeToNow, &generated.PathClientSetExpiryOptions{ +func (e SetExpiryTypeRelativeToNow) Format(o *SetExpiryOptions) (generated_blob.ExpiryOptions, *generated_blob.BlobClientSetExpiryOptions) { + return generated_blob.ExpiryOptionsRelativeToNow, &generated_blob.BlobClientSetExpiryOptions{ ExpiresOn: to.Ptr(strconv.FormatInt(time.Duration(e).Milliseconds(), 10)), } } func (e SetExpiryTypeRelativeToNow) notPubliclyImplementable() {} -func (e SetExpiryTypeRelativeToCreation) Format(o *SetExpiryOptions) (generated.ExpiryOptions, *generated.PathClientSetExpiryOptions) { - return generated.ExpiryOptionsRelativeToCreation, &generated.PathClientSetExpiryOptions{ +func (e SetExpiryTypeRelativeToCreation) Format(o *SetExpiryOptions) (generated_blob.ExpiryOptions, *generated_blob.BlobClientSetExpiryOptions) { + return generated_blob.ExpiryOptionsRelativeToCreation, &generated_blob.BlobClientSetExpiryOptions{ ExpiresOn: to.Ptr(strconv.FormatInt(time.Duration(e).Milliseconds(), 10)), } } func (e SetExpiryTypeRelativeToCreation) notPubliclyImplementable() {} -func (e SetExpiryTypeNever) Format(o *SetExpiryOptions) (generated.ExpiryOptions, *generated.PathClientSetExpiryOptions) { - return generated.ExpiryOptionsNeverExpire, &generated.PathClientSetExpiryOptions{} +func (e SetExpiryTypeNever) Format(o *SetExpiryOptions) (generated_blob.ExpiryOptions, *generated_blob.BlobClientSetExpiryOptions) { + return generated_blob.ExpiryOptionsNeverExpire, &generated_blob.BlobClientSetExpiryOptions{} } func (e SetExpiryTypeNever) notPubliclyImplementable() {} diff --git a/sdk/storage/azdatalake/internal/exported/user_delegation_credential.go b/sdk/storage/azdatalake/internal/exported/user_delegation_credential.go index 047e265e046e..a2a362d883a7 100644 --- a/sdk/storage/azdatalake/internal/exported/user_delegation_credential.go +++ b/sdk/storage/azdatalake/internal/exported/user_delegation_credential.go @@ -10,7 +10,7 @@ import ( "crypto/hmac" "crypto/sha256" "encoding/base64" - "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/internal/generated" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/internal/generated_blob" ) // NewUserDelegationCredential creates a new UserDelegationCredential using a Storage account's Name and a user delegation Key from it @@ -22,7 +22,7 @@ func NewUserDelegationCredential(accountName string, udk UserDelegationKey) *Use } // UserDelegationKey contains UserDelegationKey. -type UserDelegationKey = generated.UserDelegationKey +type UserDelegationKey = generated_blob.UserDelegationKey // UserDelegationCredential contains an account's name and its user delegation key. type UserDelegationCredential struct { diff --git a/sdk/storage/azdatalake/internal/generated/autorest.md b/sdk/storage/azdatalake/internal/generated/autorest.md index 260f00f66118..56ce2831277a 100644 --- a/sdk/storage/azdatalake/internal/generated/autorest.md +++ b/sdk/storage/azdatalake/internal/generated/autorest.md @@ -243,3 +243,36 @@ directive: replace (/req\.Raw\(\)\.Header\[\"x-ms-immutability-policy-until-date\"\]\s+=\s+\[\]string\{options\.ImmutabilityPolicyExpiry\.Format\(time\.RFC1123\)\}/g, `req.Raw().Header["x-ms-immutability-policy-until-date"] = []string{(*options.ImmutabilityPolicyExpiry).In(gmt).Format(time.RFC1123)}`); +``` + +### Change container prefix to filesystem +``` yaml +directive: + - from: source-file-go + where: $ + transform: >- + return $. + replace(/PublicAccessTypeBlob/g, 'PublicAccessTypeFile'). + replace(/PublicAccessTypeContainer/g, 'PublicAccessTypeFilesystem'). + replace(/FileSystemClientListBlobHierarchySegmentResponse/g, 'FileSystemClientListPathHierarchySegmentResponse'). + replace(/ListBlobsHierarchySegmentResponse/g, 'ListPathsHierarchySegmentResponse'). + replace(/ContainerName\s*\*string/g, 'FileSystemName *string'). + replace(/BlobHierarchyListSegment/g, 'PathHierarchyListSegment'). + replace(/BlobItems/g, 'PathItems'). + replace(/BlobItem/g, 'PathItem'). + replace(/BlobPrefix/g, 'PathPrefix'). + replace(/BlobPrefixes/g, 'PathPrefixes'). + replace(/BlobProperties/g, 'PathProperties'). + replace(/ContainerProperties/g, 'FileSystemProperties'); +``` + +### TODO: FIX THE BELOW IN UNMARSHALASJSON +### Change path props to string +``` yaml +directive: +- from: swagger-document + where: $.definitions.Path.properties + transform: > + $.isDirectory.type = "string"; + $.contentLength.type = "string"; +``` \ No newline at end of file diff --git a/sdk/storage/azdatalake/internal/generated/user_delegation_key.go b/sdk/storage/azdatalake/internal/generated/user_delegation_key.go deleted file mode 100644 index 367765fa19cd..000000000000 --- a/sdk/storage/azdatalake/internal/generated/user_delegation_key.go +++ /dev/null @@ -1,144 +0,0 @@ -//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 generated - -import ( - "context" - "github.com/Azure/azure-sdk-for-go/sdk/azcore/policy" - "github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime" - "net/http" - "strconv" - "time" -) - -// KeyInfo - Key information -type KeyInfo struct { - // REQUIRED; The date-time the key expires in ISO 8601 UTC time - Expiry *string `xml:"Expiry"` - - // REQUIRED; The date-time the key is active in ISO 8601 UTC time - Start *string `xml:"Start"` -} - -// ServiceClientGetUserDelegationKeyOptions contains the optional parameters for the ServiceClient.GetUserDelegationKey method. -type ServiceClientGetUserDelegationKeyOptions struct { - // Provides a client-generated, opaque value with a 1 KB character limit that is recorded in the analytics logs when storage - // analytics logging is enabled. - RequestID *string - // The timeout parameter is expressed in seconds. For more information, see Setting Timeouts for Blob Service Operations. - // [https://docs.microsoft.com/en-us/rest/api/storageservices/fileservices/setting-timeouts-for-blob-service-operations] - Timeout *int32 -} - -// ServiceClientGetUserDelegationKeyResponse contains the response from method ServiceClient.GetUserDelegationKey. -type ServiceClientGetUserDelegationKeyResponse struct { - UserDelegationKey - // ClientRequestID contains the information returned from the x-ms-client-request-id header response. - ClientRequestID *string `xml:"ClientRequestID"` - - // Date contains the information returned from the Date header response. - Date *time.Time `xml:"Date"` - - // RequestID contains the information returned from the x-ms-request-id header response. - RequestID *string `xml:"RequestID"` - - // Version contains the information returned from the x-ms-version header response. - Version *string `xml:"Version"` -} - -// UserDelegationKey - A user delegation key -type UserDelegationKey struct { - // REQUIRED; The date-time the key expires - SignedExpiry *time.Time `xml:"SignedExpiry"` - - // REQUIRED; The Azure Active Directory object ID in GUID format. - SignedOID *string `xml:"SignedOid"` - - // REQUIRED; Abbreviation of the Azure Storage service that accepts the key - SignedService *string `xml:"SignedService"` - - // REQUIRED; The date-time the key is active - SignedStart *time.Time `xml:"SignedStart"` - - // REQUIRED; The Azure Active Directory tenant ID in GUID format - SignedTID *string `xml:"SignedTid"` - - // REQUIRED; The service version that created the key - SignedVersion *string `xml:"SignedVersion"` - - // REQUIRED; The key as a base64 string - Value *string `xml:"Value"` -} - -// GetUserDelegationKey - Retrieves a user delegation key for the Blob service. This is only a valid operation when using -// bearer token authentication. -// If the operation fails it returns an *azcore.ResponseError type. -// -// Generated from API version 2020-10-02 -// - keyInfo - Key information -// - options - ServiceClientGetUserDelegationKeyOptions contains the optional parameters for the ServiceClient.GetUserDelegationKey -// method. -func (client *ServiceClient) GetUserDelegationKey(ctx context.Context, keyInfo KeyInfo, options *ServiceClientGetUserDelegationKeyOptions) (ServiceClientGetUserDelegationKeyResponse, error) { - req, err := client.getUserDelegationKeyCreateRequest(ctx, keyInfo, options) - if err != nil { - return ServiceClientGetUserDelegationKeyResponse{}, err - } - resp, err := client.internal.Pipeline().Do(req) - if err != nil { - return ServiceClientGetUserDelegationKeyResponse{}, err - } - if !runtime.HasStatusCode(resp, http.StatusOK) { - return ServiceClientGetUserDelegationKeyResponse{}, runtime.NewResponseError(resp) - } - return client.getUserDelegationKeyHandleResponse(resp) -} - -// getUserDelegationKeyCreateRequest creates the GetUserDelegationKey request. -func (client *ServiceClient) getUserDelegationKeyCreateRequest(ctx context.Context, keyInfo KeyInfo, options *ServiceClientGetUserDelegationKeyOptions) (*policy.Request, error) { - req, err := runtime.NewRequest(ctx, http.MethodPost, client.endpoint) - if err != nil { - return nil, err - } - reqQP := req.Raw().URL.Query() - reqQP.Set("restype", "service") - reqQP.Set("comp", "userdelegationkey") - if options != nil && options.Timeout != nil { - reqQP.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) - } - req.Raw().URL.RawQuery = reqQP.Encode() - req.Raw().Header["x-ms-version"] = []string{"2020-10-02"} - if options != nil && options.RequestID != nil { - req.Raw().Header["x-ms-client-request-id"] = []string{*options.RequestID} - } - req.Raw().Header["Accept"] = []string{"application/xml"} - return req, runtime.MarshalAsXML(req, keyInfo) -} - -// getUserDelegationKeyHandleResponse handles the GetUserDelegationKey response. -func (client *ServiceClient) getUserDelegationKeyHandleResponse(resp *http.Response) (ServiceClientGetUserDelegationKeyResponse, error) { - result := ServiceClientGetUserDelegationKeyResponse{} - if val := resp.Header.Get("x-ms-client-request-id"); val != "" { - result.ClientRequestID = &val - } - if val := resp.Header.Get("x-ms-request-id"); val != "" { - result.RequestID = &val - } - if val := resp.Header.Get("x-ms-version"); val != "" { - result.Version = &val - } - if val := resp.Header.Get("Date"); val != "" { - date, err := time.Parse(time.RFC1123, val) - if err != nil { - return ServiceClientGetUserDelegationKeyResponse{}, err - } - result.Date = &date - } - if err := runtime.UnmarshalAsXML(resp, &result.UserDelegationKey); err != nil { - return ServiceClientGetUserDelegationKeyResponse{}, err - } - return result, nil -} diff --git a/sdk/storage/azdatalake/internal/generated/zz_filesystem_client.go b/sdk/storage/azdatalake/internal/generated/zz_filesystem_client.go index 99894e0fc566..377a623ea155 100644 --- a/sdk/storage/azdatalake/internal/generated/zz_filesystem_client.go +++ b/sdk/storage/azdatalake/internal/generated/zz_filesystem_client.go @@ -300,8 +300,8 @@ func (client *FileSystemClient) ListBlobHierarchySegmentCreateRequest(ctx contex } // listBlobHierarchySegmentHandleResponse handles the ListBlobHierarchySegment response. -func (client *FileSystemClient) ListBlobHierarchySegmentHandleResponse(resp *http.Response) (FileSystemClientListBlobHierarchySegmentResponse, error) { - result := FileSystemClientListBlobHierarchySegmentResponse{} +func (client *FileSystemClient) ListBlobHierarchySegmentHandleResponse(resp *http.Response) (FileSystemClientListPathHierarchySegmentResponse, error) { + result := FileSystemClientListPathHierarchySegmentResponse{} if val := resp.Header.Get("Content-Type"); val != "" { result.ContentType = &val } @@ -317,12 +317,12 @@ func (client *FileSystemClient) ListBlobHierarchySegmentHandleResponse(resp *htt if val := resp.Header.Get("Date"); val != "" { date, err := time.Parse(time.RFC1123, val) if err != nil { - return FileSystemClientListBlobHierarchySegmentResponse{}, err + return FileSystemClientListPathHierarchySegmentResponse{}, err } result.Date = &date } - if err := runtime.UnmarshalAsXML(resp, &result.ListBlobsHierarchySegmentResponse); err != nil { - return FileSystemClientListBlobHierarchySegmentResponse{}, err + if err := runtime.UnmarshalAsXML(resp, &result.ListPathsHierarchySegmentResponse); err != nil { + return FileSystemClientListPathHierarchySegmentResponse{}, err } return result, nil } diff --git a/sdk/storage/azdatalake/internal/generated/zz_models.go b/sdk/storage/azdatalake/internal/generated/zz_models.go index b9c912bcd46b..64f0139f6536 100644 --- a/sdk/storage/azdatalake/internal/generated/zz_models.go +++ b/sdk/storage/azdatalake/internal/generated/zz_models.go @@ -20,14 +20,14 @@ type ACLFailedEntry struct { Type *string } -type BlobHierarchyListSegment struct { +type PathHierarchyListSegment struct { // REQUIRED - BlobItems []*BlobItemInternal `xml:"Blob"` - BlobPrefixes []*BlobPrefix `xml:"BlobPrefix"` + PathItems []*PathItemInternal `xml:"Blob"` + PathPrefixes []*PathPrefix `xml:"PathPrefix"` } -// BlobItemInternal - An Azure Storage blob -type BlobItemInternal struct { +// PathItemInternal - An Azure Storage blob +type PathItemInternal struct { // REQUIRED Deleted *bool `xml:"Deleted"` @@ -35,7 +35,7 @@ type BlobItemInternal struct { Name *string `xml:"Name"` // REQUIRED; Properties of a blob - Properties *BlobPropertiesInternal `xml:"Properties"` + Properties *PathPropertiesInternal `xml:"Properties"` // REQUIRED Snapshot *string `xml:"Snapshot"` @@ -44,13 +44,13 @@ type BlobItemInternal struct { VersionID *string `xml:"VersionId"` } -type BlobPrefix struct { +type PathPrefix struct { // REQUIRED Name *string `xml:"Name"` } -// BlobPropertiesInternal - Properties of a blob -type BlobPropertiesInternal struct { +// PathPropertiesInternal - Properties of a blob +type PathPropertiesInternal struct { // REQUIRED ETag *azcore.ETag `xml:"Etag"` @@ -149,7 +149,7 @@ type FileSystemClientGetPropertiesOptions struct { // FileSystemClientListBlobHierarchySegmentOptions contains the optional parameters for the FileSystemClient.NewListBlobHierarchySegmentPager // method. type FileSystemClientListBlobHierarchySegmentOptions struct { - // When the request includes this parameter, the operation returns a BlobPrefix element in the response body that acts as + // When the request includes this parameter, the operation returns a PathPrefix element in the response body that acts as // a placeholder for all blobs whose names begin with the same substring up to the // appearance of the delimiter character. The delimiter may be a single character or a string. Delimiter *string @@ -230,13 +230,13 @@ type LeaseAccessConditions struct { LeaseID *string } -// ListBlobsHierarchySegmentResponse - An enumeration of blobs -type ListBlobsHierarchySegmentResponse struct { +// ListPathsHierarchySegmentResponse - An enumeration of blobs +type ListPathsHierarchySegmentResponse struct { // REQUIRED - ContainerName *string `xml:"ContainerName,attr"` + FileSystemName *string `xml:"ContainerName,attr"` // REQUIRED - Segment *BlobHierarchyListSegment `xml:"Blobs"` + Segment *PathHierarchyListSegment `xml:"Blobs"` // REQUIRED ServiceEndpoint *string `xml:"ServiceEndpoint,attr"` @@ -260,7 +260,7 @@ type ModifiedAccessConditions struct { } type Path struct { - ContentLength *int64 + ContentLength *string CreationTime *string ETag *string @@ -268,7 +268,7 @@ type Path struct { EncryptionScope *string ExpiryTime *string Group *string - IsDirectory *bool + IsDirectory *string LastModified *string Name *string Owner *string diff --git a/sdk/storage/azdatalake/internal/generated/zz_models_serde.go b/sdk/storage/azdatalake/internal/generated/zz_models_serde.go index 0bcadcc50c20..f118d2a055aa 100644 --- a/sdk/storage/azdatalake/internal/generated/zz_models_serde.go +++ b/sdk/storage/azdatalake/internal/generated/zz_models_serde.go @@ -54,28 +54,28 @@ func (a *ACLFailedEntry) UnmarshalJSON(data []byte) error { return nil } -// MarshalXML implements the xml.Marshaller interface for type BlobHierarchyListSegment. -func (b BlobHierarchyListSegment) MarshalXML(enc *xml.Encoder, start xml.StartElement) error { - type alias BlobHierarchyListSegment +// MarshalXML implements the xml.Marshaller interface for type PathHierarchyListSegment. +func (b PathHierarchyListSegment) MarshalXML(enc *xml.Encoder, start xml.StartElement) error { + type alias PathHierarchyListSegment aux := &struct { *alias - BlobItems *[]*BlobItemInternal `xml:"Blob"` - BlobPrefixes *[]*BlobPrefix `xml:"BlobPrefix"` + PathItems *[]*PathItemInternal `xml:"Blob"` + PathPrefixes *[]*PathPrefix `xml:"PathPrefix"` }{ alias: (*alias)(&b), } - if b.BlobItems != nil { - aux.BlobItems = &b.BlobItems + if b.PathItems != nil { + aux.PathItems = &b.PathItems } - if b.BlobPrefixes != nil { - aux.BlobPrefixes = &b.BlobPrefixes + if b.PathPrefixes != nil { + aux.PathPrefixes = &b.PathPrefixes } return enc.EncodeElement(aux, start) } -// MarshalXML implements the xml.Marshaller interface for type BlobPropertiesInternal. -func (b BlobPropertiesInternal) MarshalXML(enc *xml.Encoder, start xml.StartElement) error { - type alias BlobPropertiesInternal +// MarshalXML implements the xml.Marshaller interface for type PathPropertiesInternal. +func (b PathPropertiesInternal) MarshalXML(enc *xml.Encoder, start xml.StartElement) error { + type alias PathPropertiesInternal aux := &struct { *alias AccessTierChangeTime *timeRFC1123 `xml:"AccessTierChangeTime"` @@ -105,9 +105,9 @@ func (b BlobPropertiesInternal) MarshalXML(enc *xml.Encoder, start xml.StartElem return enc.EncodeElement(aux, start) } -// UnmarshalXML implements the xml.Unmarshaller interface for type BlobPropertiesInternal. -func (b *BlobPropertiesInternal) UnmarshalXML(dec *xml.Decoder, start xml.StartElement) error { - type alias BlobPropertiesInternal +// UnmarshalXML implements the xml.Unmarshaller interface for type PathPropertiesInternal. +func (b *PathPropertiesInternal) UnmarshalXML(dec *xml.Decoder, start xml.StartElement) error { + type alias PathPropertiesInternal aux := &struct { *alias AccessTierChangeTime *timeRFC1123 `xml:"AccessTierChangeTime"` diff --git a/sdk/storage/azdatalake/internal/generated/zz_response_types.go b/sdk/storage/azdatalake/internal/generated/zz_response_types.go index 0c55d6312788..58112b532f0c 100644 --- a/sdk/storage/azdatalake/internal/generated/zz_response_types.go +++ b/sdk/storage/azdatalake/internal/generated/zz_response_types.go @@ -72,9 +72,9 @@ type FileSystemClientGetPropertiesResponse struct { Version *string } -// FileSystemClientListBlobHierarchySegmentResponse contains the response from method FileSystemClient.NewListBlobHierarchySegmentPager. -type FileSystemClientListBlobHierarchySegmentResponse struct { - ListBlobsHierarchySegmentResponse +// FileSystemClientListPathHierarchySegmentResponse contains the response from method FileSystemClient.NewListBlobHierarchySegmentPager. +type FileSystemClientListPathHierarchySegmentResponse struct { + ListPathsHierarchySegmentResponse // ClientRequestID contains the information returned from the x-ms-client-request-id header response. ClientRequestID *string `xml:"ClientRequestID"` diff --git a/sdk/storage/azdatalake/internal/generated_blob/autorest.md b/sdk/storage/azdatalake/internal/generated_blob/autorest.md new file mode 100644 index 000000000000..f0e08dcb686d --- /dev/null +++ b/sdk/storage/azdatalake/internal/generated_blob/autorest.md @@ -0,0 +1,480 @@ +# Code Generation - Azure Blob SDK for Golang + +### Settings + +```yaml +go: true +clear-output-folder: false +version: "^3.0.0" +license-header: MICROSOFT_MIT_NO_VERSION +input-file: "https://raw.githubusercontent.com/Azure/azure-rest-api-specs/e515b6251fdc21015282d2e84b85beec7c091763/specification/storage/data-plane/Microsoft.BlobStorage/preview/2020-10-02/blob.json" +credential-scope: "https://storage.azure.com/.default" +output-folder: ../generated_blob +file-prefix: "zz_" +openapi-type: "data-plane" +verbose: true +security: AzureKey +modelerfour: + group-parameters: false + seal-single-value-enum-by-default: true + lenient-model-deduplication: true +export-clients: true +use: "@autorest/go@4.0.0-preview.49" +``` + +### Undo breaking change with BlobName +``` yaml +directive: +- from: zz_models.go + where: $ + transform: >- + return $. + replace(/Name\s+\*BlobName/g, `Name *string`); +``` + +### Removing UnmarshalXML for BlobItems to create customer UnmarshalXML function +```yaml +directive: +- from: swagger-document + where: $.definitions + transform: > + $.BlobItemInternal["x-ms-go-omit-serde-methods"] = true; +``` + +### Remove pager methods and export various generated methods in container client + +``` yaml +directive: + - from: zz_container_client.go + where: $ + transform: >- + return $. + replace(/func \(client \*ContainerClient\) NewListBlobFlatSegmentPager\(.+\/\/ listBlobFlatSegmentCreateRequest creates the ListBlobFlatSegment request/s, `//\n// listBlobFlatSegmentCreateRequest creates the ListBlobFlatSegment request`). + replace(/\(client \*ContainerClient\) listBlobFlatSegmentCreateRequest\(/, `(client *ContainerClient) ListBlobFlatSegmentCreateRequest(`). + replace(/\(client \*ContainerClient\) listBlobFlatSegmentHandleResponse\(/, `(client *ContainerClient) ListBlobFlatSegmentHandleResponse(`); +``` + +### Remove pager methods and export various generated methods in service client + +``` yaml +directive: + - from: zz_service_client.go + where: $ + transform: >- + return $. + replace(/func \(client \*ServiceClient\) NewListContainersSegmentPager\(.+\/\/ listContainersSegmentCreateRequest creates the ListContainersSegment request/s, `//\n// listContainersSegmentCreateRequest creates the ListContainersSegment request`). + replace(/\(client \*ServiceClient\) listContainersSegmentCreateRequest\(/, `(client *ServiceClient) ListContainersSegmentCreateRequest(`). + replace(/\(client \*ServiceClient\) listContainersSegmentHandleResponse\(/, `(client *ServiceClient) ListContainersSegmentHandleResponse(`); +``` + +### Fix BlobMetadata. + +``` yaml +directive: +- from: swagger-document + where: $.definitions + transform: > + delete $.BlobMetadata["properties"]; + +``` + +### Don't include container name or blob in path - we have direct URIs. + +``` yaml +directive: +- from: swagger-document + where: $["x-ms-paths"] + transform: > + for (const property in $) + { + if (property.includes('/{containerName}/{blob}')) + { + $[property]["parameters"] = $[property]["parameters"].filter(function(param) { return (typeof param['$ref'] === "undefined") || (false == param['$ref'].endsWith("#/parameters/ContainerName") && false == param['$ref'].endsWith("#/parameters/Blob"))}); + } + else if (property.includes('/{containerName}')) + { + $[property]["parameters"] = $[property]["parameters"].filter(function(param) { return (typeof param['$ref'] === "undefined") || (false == param['$ref'].endsWith("#/parameters/ContainerName"))}); + } + } +``` + +### Remove DataLake stuff. + +``` yaml +directive: +- from: swagger-document + where: $["x-ms-paths"] + transform: > + for (const property in $) + { + if (property.includes('filesystem')) + { + delete $[property]; + } + } +``` + +### Remove DataLakeStorageError + +``` yaml +directive: +- from: swagger-document + where: $.definitions + transform: > + delete $.DataLakeStorageError; +``` + +### Fix 304s + +``` yaml +directive: +- from: swagger-document + where: $["x-ms-paths"]["/{containerName}/{blob}"] + transform: > + $.get.responses["304"] = { + "description": "The condition specified using HTTP conditional header(s) is not met.", + "x-az-response-name": "ConditionNotMetError", + "headers": { "x-ms-error-code": { "x-ms-client-name": "ErrorCode", "type": "string" } } + }; +``` + +### Fix GeoReplication + +``` yaml +directive: +- from: swagger-document + where: $.definitions + transform: > + delete $.GeoReplication.properties.Status["x-ms-enum"]; + $.GeoReplication.properties.Status["x-ms-enum"] = { + "name": "BlobGeoReplicationStatus", + "modelAsString": false + }; +``` + +### Fix RehydratePriority + +``` yaml +directive: +- from: swagger-document + where: $.definitions + transform: > + delete $.RehydratePriority["x-ms-enum"]; + $.RehydratePriority["x-ms-enum"] = { + "name": "RehydratePriority", + "modelAsString": false + }; +``` + +### Fix BlobDeleteType + +``` yaml +directive: +- from: swagger-document + where: $.parameters + transform: > + delete $.BlobDeleteType.enum; + $.BlobDeleteType.enum = [ + "None", + "Permanent" + ]; +``` + +### Fix EncryptionAlgorithm + +``` yaml +directive: +- from: swagger-document + where: $.parameters + transform: > + delete $.EncryptionAlgorithm.enum; + $.EncryptionAlgorithm.enum = [ + "None", + "AES256" + ]; +``` + +### Fix XML string "ObjectReplicationMetadata" to "OrMetadata" + +``` yaml +directive: +- from: swagger-document + where: $.definitions + transform: > + $.BlobItemInternal.properties["OrMetadata"] = $.BlobItemInternal.properties["ObjectReplicationMetadata"]; + delete $.BlobItemInternal.properties["ObjectReplicationMetadata"]; +``` + +# Export various createRequest/HandleResponse methods + +``` yaml +directive: +- from: zz_container_client.go + where: $ + transform: >- + return $. + replace(/listBlobHierarchySegmentCreateRequest/g, function(_, s) { return `ListBlobHierarchySegmentCreateRequest` }). + replace(/listBlobHierarchySegmentHandleResponse/g, function(_, s) { return `ListBlobHierarchySegmentHandleResponse` }); + +- from: zz_pageblob_client.go + where: $ + transform: >- + return $. + replace(/getPageRanges(Diff)?CreateRequest/g, function(_, s) { if (s === undefined) { s = '' }; return `GetPageRanges${s}CreateRequest` }). + replace(/getPageRanges(Diff)?HandleResponse/g, function(_, s) { if (s === undefined) { s = '' }; return `GetPageRanges${s}HandleResponse` }); +``` + +### Clean up some const type names so they don't stutter + +``` yaml +directive: +- from: swagger-document + where: $.parameters['BlobDeleteType'] + transform: > + $["x-ms-enum"].name = "DeleteType"; + $["x-ms-client-name"] = "DeleteType"; + +- from: swagger-document + where: $.parameters['BlobExpiryOptions'] + transform: > + $["x-ms-enum"].name = "ExpiryOptions"; + $["x-ms-client-name"].name = "ExpiryOptions"; + +- from: swagger-document + where: $["x-ms-paths"][*].*.responses[*].headers["x-ms-immutability-policy-mode"] + transform: > + $["x-ms-client-name"].name = "ImmutabilityPolicyMode"; + $.enum = [ "Mutable", "Unlocked", "Locked"]; + $["x-ms-enum"] = { "name": "ImmutabilityPolicyMode", "modelAsString": false }; + +- from: swagger-document + where: $.parameters['ImmutabilityPolicyMode'] + transform: > + $["x-ms-enum"].name = "ImmutabilityPolicySetting"; + $["x-ms-client-name"].name = "ImmutabilityPolicySetting"; + +- from: swagger-document + where: $.definitions['BlobPropertiesInternal'] + transform: > + $.properties.ImmutabilityPolicyMode["x-ms-enum"].name = "ImmutabilityPolicyMode"; +``` + +### use azcore.ETag + +``` yaml +directive: +- from: zz_models.go + where: $ + transform: >- + return $. + replace(/import "time"/, `import (\n\t"time"\n\t"github.com/Azure/azure-sdk-for-go/sdk/azcore"\n)`). + replace(/Etag\s+\*string/g, `ETag *azcore.ETag`). + replace(/IfMatch\s+\*string/g, `IfMatch *azcore.ETag`). + replace(/IfNoneMatch\s+\*string/g, `IfNoneMatch *azcore.ETag`). + replace(/SourceIfMatch\s+\*string/g, `SourceIfMatch *azcore.ETag`). + replace(/SourceIfNoneMatch\s+\*string/g, `SourceIfNoneMatch *azcore.ETag`); + +- from: zz_response_types.go + where: $ + transform: >- + return $. + replace(/"time"/, `"time"\n\t"github.com/Azure/azure-sdk-for-go/sdk/azcore"`). + replace(/ETag\s+\*string/g, `ETag *azcore.ETag`); + +- from: + - zz_appendblob_client.go + - zz_blob_client.go + - zz_blockblob_client.go + - zz_container_client.go + - zz_pageblob_client.go + where: $ + transform: >- + return $. + replace(/"github\.com\/Azure\/azure\-sdk\-for\-go\/sdk\/azcore\/policy"/, `"github.com/Azure/azure-sdk-for-go/sdk/azcore"\n\t"github.com/Azure/azure-sdk-for-go/sdk/azcore/policy"`). + replace(/result\.ETag\s+=\s+&val/g, `result.ETag = (*azcore.ETag)(&val)`). + replace(/\*modifiedAccessConditions.IfMatch/g, `string(*modifiedAccessConditions.IfMatch)`). + replace(/\*modifiedAccessConditions.IfNoneMatch/g, `string(*modifiedAccessConditions.IfNoneMatch)`). + replace(/\*sourceModifiedAccessConditions.SourceIfMatch/g, `string(*sourceModifiedAccessConditions.SourceIfMatch)`). + replace(/\*sourceModifiedAccessConditions.SourceIfNoneMatch/g, `string(*sourceModifiedAccessConditions.SourceIfNoneMatch)`); +``` + +### Unsure why this casing changed, but fixing it + +``` yaml +directive: +- from: zz_models.go + where: $ + transform: >- + return $. + replace(/SignedOid\s+\*string/g, `SignedOID *string`). + replace(/SignedTid\s+\*string/g, `SignedTID *string`); +``` + +### Fixing Typo with StorageErrorCodeIncrementalCopyOfEarlierVersionSnapshotNotAllowed + +``` yaml +directive: +- from: zz_constants.go + where: $ + transform: >- + return $. + replace(/IncrementalCopyOfEralierVersionSnapshotNotAllowed/g, "IncrementalCopyOfEarlierVersionSnapshotNotAllowed"); +``` + +### Fix up x-ms-content-crc64 header response name + +``` yaml +directive: +- from: swagger-document + where: $.x-ms-paths.*.*.responses.*.headers.x-ms-content-crc64 + transform: > + $["x-ms-client-name"] = "ContentCRC64" +``` + +``` yaml +directive: +- rename-model: + from: BlobItemInternal + to: BlobItem +- rename-model: + from: BlobPropertiesInternal + to: BlobProperties +``` + +### Updating encoding URL, Golang adds '+' which disrupts encoding with service + +``` yaml +directive: + - from: zz_service_client.go + where: $ + transform: >- + return $. + replace(/req.Raw\(\).URL.RawQuery \= reqQP.Encode\(\)/, `req.Raw().URL.RawQuery = strings.Replace(reqQP.Encode(), "+", "%20", -1)`) +``` + +### Change `where` parameter in blob filtering to be required + +``` yaml +directive: +- from: swagger-document + where: $.parameters.FilterBlobsWhere + transform: > + $.required = true; +``` + +### Change `Duration` parameter in leases to be required + +``` yaml +directive: +- from: swagger-document + where: $.parameters.LeaseDuration + transform: > + $.required = true; +``` + +### Change CPK acronym to be all caps + +``` yaml +directive: + - from: source-file-go + where: $ + transform: >- + return $. + replace(/Cpk/g, "CPK"); +``` + +### Change CORS acronym to be all caps + +``` yaml +directive: + - from: source-file-go + where: $ + transform: >- + return $. + replace(/Cors/g, "CORS"); +``` + +### Change cors xml to be correct + +``` yaml +directive: + - from: source-file-go + where: $ + transform: >- + return $. + replace(/xml:"CORS>CORSRule"/g, "xml:\"Cors>CorsRule\""); +``` + +### Fix Content-Type header in submit batch request + +``` yaml +directive: +- from: + - zz_container_client.go + - zz_service_client.go + where: $ + transform: >- + return $. + replace (/req.SetBody\(body\,\s+\"application\/xml\"\)/g, `req.SetBody(body, multipartContentType)`); +``` + +### Fix response status code check in submit batch request + +``` yaml +directive: +- from: zz_service_client.go + where: $ + transform: >- + return $. + replace(/if\s+!runtime\.HasStatusCode\(resp,\s+http\.StatusOK\)\s+\{\s*\n\t\treturn\s+ServiceClientSubmitBatchResponse\{\}\,\s+runtime\.NewResponseError\(resp\)\s*\n\t\}/g, + `if !runtime.HasStatusCode(resp, http.StatusAccepted) {\n\t\treturn ServiceClientSubmitBatchResponse{}, runtime.NewResponseError(resp)\n\t}`); +``` + +### Convert time to GMT for If-Modified-Since and If-Unmodified-Since request headers + +``` yaml +directive: +- from: + - zz_container_client.go + - zz_blob_client.go + - zz_appendblob_client.go + - zz_blockblob_client.go + - zz_pageblob_client.go + where: $ + transform: >- + return $. + replace (/req\.Raw\(\)\.Header\[\"If-Modified-Since\"\]\s+=\s+\[\]string\{modifiedAccessConditions\.IfModifiedSince\.Format\(time\.RFC1123\)\}/g, + `req.Raw().Header["If-Modified-Since"] = []string{(*modifiedAccessConditions.IfModifiedSince).In(gmt).Format(time.RFC1123)}`). + replace (/req\.Raw\(\)\.Header\[\"If-Unmodified-Since\"\]\s+=\s+\[\]string\{modifiedAccessConditions\.IfUnmodifiedSince\.Format\(time\.RFC1123\)\}/g, + `req.Raw().Header["If-Unmodified-Since"] = []string{(*modifiedAccessConditions.IfUnmodifiedSince).In(gmt).Format(time.RFC1123)}`). + replace (/req\.Raw\(\)\.Header\[\"x-ms-source-if-modified-since\"\]\s+=\s+\[\]string\{sourceModifiedAccessConditions\.SourceIfModifiedSince\.Format\(time\.RFC1123\)\}/g, + `req.Raw().Header["x-ms-source-if-modified-since"] = []string{(*sourceModifiedAccessConditions.SourceIfModifiedSince).In(gmt).Format(time.RFC1123)}`). + replace (/req\.Raw\(\)\.Header\[\"x-ms-source-if-unmodified-since\"\]\s+=\s+\[\]string\{sourceModifiedAccessConditions\.SourceIfUnmodifiedSince\.Format\(time\.RFC1123\)\}/g, + `req.Raw().Header["x-ms-source-if-unmodified-since"] = []string{(*sourceModifiedAccessConditions.SourceIfUnmodifiedSince).In(gmt).Format(time.RFC1123)}`). + replace (/req\.Raw\(\)\.Header\[\"x-ms-immutability-policy-until-date\"\]\s+=\s+\[\]string\{options\.ImmutabilityPolicyExpiry\.Format\(time\.RFC1123\)\}/g, + `req.Raw().Header["x-ms-immutability-policy-until-date"] = []string{(*options.ImmutabilityPolicyExpiry).In(gmt).Format(time.RFC1123)}`); +``` + +### Change container prefix to filesystem +``` yaml +directive: + - from: source-file-go + where: $ + transform: >- + return $. + replace(/ServiceClientListContainersSegmentResponse/g, 'ServiceClientListFileSystemsSegmentResponse'). + replace(/ListContainersSegmentResponse/g, 'ListFileSystemsSegmentResponse'). + replace(/ContainerItem/g, 'FileSystemItem'). + replace(/PublicAccessTypeBlob/g, 'PublicAccessTypeFile'). + replace(/PublicAccessTypeContainer/g, 'PublicAccessTypeFileSystem'). + replace(/ContainerClientListBlobHierarchySegmentResponse/g, 'FileSystemClientListPathHierarchySegmentResponse'). + replace(/ListBlobsHierarchySegmentResponse/g, 'ListPathsHierarchySegmentResponse'). + replace(/(^|[^"])ContainerName/g, '$1FilesystemName'). + replace(/BlobHierarchyListSegment/g, 'PathHierarchyListSegment'). + replace(/BlobItems/g, 'PathItems'). + replace(/BlobItem/g, 'PathItem'). + replace(/BlobPrefix/g, 'PathPrefix'). + replace(/BlobPrefixes/g, 'PathPrefixes'). + replace(/BlobProperties/g, 'PathProperties'). + replace(/ContainerProperties/g, 'FileSystemProperties'); +``` diff --git a/sdk/storage/azdatalake/internal/generated_blob/blob_client.go b/sdk/storage/azdatalake/internal/generated_blob/blob_client.go new file mode 100644 index 000000000000..b5db4b2b68a5 --- /dev/null +++ b/sdk/storage/azdatalake/internal/generated_blob/blob_client.go @@ -0,0 +1,44 @@ +//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 generated_blob + +import ( + "context" + "github.com/Azure/azure-sdk-for-go/sdk/azcore" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/policy" + "time" +) + +// used to convert times from UTC to GMT before sending across the wire +var gmt = time.FixedZone("GMT", 0) + +func (client *BlobClient) Endpoint() string { + return client.endpoint +} + +func (client *BlobClient) InternalClient() *azcore.Client { + return client.internal +} + +func (client *BlobClient) DeleteCreateRequest(ctx context.Context, options *BlobClientDeleteOptions, leaseAccessConditions *LeaseAccessConditions, modifiedAccessConditions *ModifiedAccessConditions) (*policy.Request, error) { + return client.deleteCreateRequest(ctx, options, leaseAccessConditions, modifiedAccessConditions) +} + +func (client *BlobClient) SetTierCreateRequest(ctx context.Context, tier AccessTier, options *BlobClientSetTierOptions, leaseAccessConditions *LeaseAccessConditions, modifiedAccessConditions *ModifiedAccessConditions) (*policy.Request, error) { + return client.setTierCreateRequest(ctx, tier, options, leaseAccessConditions, modifiedAccessConditions) +} + +// NewBlobClient creates a new instance of BlobClient with the specified values. +// - endpoint - The URL of the service account, container, or blob that is the target of the desired operation. +// - azClient - azcore.Client is a basic HTTP client. It consists of a pipeline and tracing provider. +func NewBlobClient(endpoint string, azClient *azcore.Client) *BlobClient { + client := &BlobClient{ + internal: azClient, + endpoint: endpoint, + } + return client +} diff --git a/sdk/storage/azdatalake/internal/generated_blob/build.go b/sdk/storage/azdatalake/internal/generated_blob/build.go new file mode 100644 index 000000000000..b1a3b508ab34 --- /dev/null +++ b/sdk/storage/azdatalake/internal/generated_blob/build.go @@ -0,0 +1,10 @@ +//go:build go1.18 +// +build go1.18 + +//go:generate autorest ./autorest.md +//go:generate gofmt -w . + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See License.txt in the project root for license information. + +package generated_blob diff --git a/sdk/storage/azdatalake/internal/generated_blob/container_client.go b/sdk/storage/azdatalake/internal/generated_blob/container_client.go new file mode 100644 index 000000000000..441eab0fcbe9 --- /dev/null +++ b/sdk/storage/azdatalake/internal/generated_blob/container_client.go @@ -0,0 +1,30 @@ +//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 generated_blob + +import ( + "github.com/Azure/azure-sdk-for-go/sdk/azcore" +) + +func (client *ContainerClient) Endpoint() string { + return client.endpoint +} + +func (client *ContainerClient) InternalClient() *azcore.Client { + return client.internal +} + +// NewContainerClient creates a new instance of ContainerClient with the specified values. +// - endpoint - The URL of the service account, container, or blob that is the target of the desired operation. +// - pl - the pipeline used for sending requests and handling responses. +func NewContainerClient(endpoint string, azClient *azcore.Client) *ContainerClient { + client := &ContainerClient{ + internal: azClient, + endpoint: endpoint, + } + return client +} diff --git a/sdk/storage/azdatalake/internal/generated_blob/models.go b/sdk/storage/azdatalake/internal/generated_blob/models.go new file mode 100644 index 000000000000..630cd80fbc45 --- /dev/null +++ b/sdk/storage/azdatalake/internal/generated_blob/models.go @@ -0,0 +1,65 @@ +//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 generated_blob + +type TransactionalContentSetter interface { + SetCRC64([]byte) + SetMD5([]byte) +} + +func (a *AppendBlobClientAppendBlockOptions) SetCRC64(v []byte) { + a.TransactionalContentCRC64 = v +} + +func (a *AppendBlobClientAppendBlockOptions) SetMD5(v []byte) { + a.TransactionalContentMD5 = v +} + +func (b *BlockBlobClientStageBlockOptions) SetCRC64(v []byte) { + b.TransactionalContentCRC64 = v +} + +func (b *BlockBlobClientStageBlockOptions) SetMD5(v []byte) { + b.TransactionalContentMD5 = v +} + +func (p *PageBlobClientUploadPagesOptions) SetCRC64(v []byte) { + p.TransactionalContentCRC64 = v +} + +func (p *PageBlobClientUploadPagesOptions) SetMD5(v []byte) { + p.TransactionalContentMD5 = v +} + +type SourceContentSetter interface { + SetSourceContentCRC64(v []byte) + SetSourceContentMD5(v []byte) +} + +func (a *AppendBlobClientAppendBlockFromURLOptions) SetSourceContentCRC64(v []byte) { + a.SourceContentcrc64 = v +} + +func (a *AppendBlobClientAppendBlockFromURLOptions) SetSourceContentMD5(v []byte) { + a.SourceContentMD5 = v +} + +func (b *BlockBlobClientStageBlockFromURLOptions) SetSourceContentCRC64(v []byte) { + b.SourceContentcrc64 = v +} + +func (b *BlockBlobClientStageBlockFromURLOptions) SetSourceContentMD5(v []byte) { + b.SourceContentMD5 = v +} + +func (p *PageBlobClientUploadPagesFromURLOptions) SetSourceContentCRC64(v []byte) { + p.SourceContentcrc64 = v +} + +func (p *PageBlobClientUploadPagesFromURLOptions) SetSourceContentMD5(v []byte) { + p.SourceContentMD5 = v +} diff --git a/sdk/storage/azdatalake/internal/generated_blob/service_client.go b/sdk/storage/azdatalake/internal/generated_blob/service_client.go new file mode 100644 index 000000000000..05798c7efdca --- /dev/null +++ b/sdk/storage/azdatalake/internal/generated_blob/service_client.go @@ -0,0 +1,30 @@ +//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 generated_blob + +import ( + "github.com/Azure/azure-sdk-for-go/sdk/azcore" +) + +func (client *ServiceClient) Endpoint() string { + return client.endpoint +} + +func (client *ServiceClient) InternalClient() *azcore.Client { + return client.internal +} + +// NewServiceClient creates a new instance of ServiceClient with the specified values. +// - endpoint - The URL of the service account, container, or blob that is the target of the desired operation. +// - azClient - azcore.Client is a basic HTTP client. It consists of a pipeline and tracing provider. +func NewServiceClient(endpoint string, azClient *azcore.Client) *ServiceClient { + client := &ServiceClient{ + internal: azClient, + endpoint: endpoint, + } + return client +} diff --git a/sdk/storage/azdatalake/internal/generated_blob/zz_appendblob_client.go b/sdk/storage/azdatalake/internal/generated_blob/zz_appendblob_client.go new file mode 100644 index 000000000000..f58dba665ddf --- /dev/null +++ b/sdk/storage/azdatalake/internal/generated_blob/zz_appendblob_client.go @@ -0,0 +1,651 @@ +//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. +// Code generated by Microsoft (R) AutoRest Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. +// DO NOT EDIT. + +package generated_blob + +import ( + "context" + "encoding/base64" + "github.com/Azure/azure-sdk-for-go/sdk/azcore" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/policy" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime" + "io" + "net/http" + "strconv" + "time" +) + +// AppendBlobClient contains the methods for the AppendBlob group. +// Don't use this type directly, use a constructor function instead. +type AppendBlobClient struct { + internal *azcore.Client + endpoint string +} + +// AppendBlock - The Append Block operation commits a new block of data to the end of an existing append blob. The Append +// Block operation is permitted only if the blob was created with x-ms-blob-type set to +// AppendBlob. Append Block is supported only on version 2015-02-21 version or later. +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2020-10-02 +// - contentLength - The length of the request. +// - body - Initial data +// - options - AppendBlobClientAppendBlockOptions contains the optional parameters for the AppendBlobClient.AppendBlock method. +// - LeaseAccessConditions - LeaseAccessConditions contains a group of parameters for the ContainerClient.GetProperties method. +// - AppendPositionAccessConditions - AppendPositionAccessConditions contains a group of parameters for the AppendBlobClient.AppendBlock +// method. +// - CPKInfo - CPKInfo contains a group of parameters for the BlobClient.Download method. +// - CPKScopeInfo - CPKScopeInfo contains a group of parameters for the BlobClient.SetMetadata method. +// - ModifiedAccessConditions - ModifiedAccessConditions contains a group of parameters for the ContainerClient.Delete method. +func (client *AppendBlobClient) AppendBlock(ctx context.Context, contentLength int64, body io.ReadSeekCloser, options *AppendBlobClientAppendBlockOptions, leaseAccessConditions *LeaseAccessConditions, appendPositionAccessConditions *AppendPositionAccessConditions, cpkInfo *CPKInfo, cpkScopeInfo *CPKScopeInfo, modifiedAccessConditions *ModifiedAccessConditions) (AppendBlobClientAppendBlockResponse, error) { + req, err := client.appendBlockCreateRequest(ctx, contentLength, body, options, leaseAccessConditions, appendPositionAccessConditions, cpkInfo, cpkScopeInfo, modifiedAccessConditions) + if err != nil { + return AppendBlobClientAppendBlockResponse{}, err + } + resp, err := client.internal.Pipeline().Do(req) + if err != nil { + return AppendBlobClientAppendBlockResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusCreated) { + return AppendBlobClientAppendBlockResponse{}, runtime.NewResponseError(resp) + } + return client.appendBlockHandleResponse(resp) +} + +// appendBlockCreateRequest creates the AppendBlock request. +func (client *AppendBlobClient) appendBlockCreateRequest(ctx context.Context, contentLength int64, body io.ReadSeekCloser, options *AppendBlobClientAppendBlockOptions, leaseAccessConditions *LeaseAccessConditions, appendPositionAccessConditions *AppendPositionAccessConditions, cpkInfo *CPKInfo, cpkScopeInfo *CPKScopeInfo, modifiedAccessConditions *ModifiedAccessConditions) (*policy.Request, error) { + req, err := runtime.NewRequest(ctx, http.MethodPut, client.endpoint) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("comp", "appendblock") + if options != nil && options.Timeout != nil { + reqQP.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + } + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["Content-Length"] = []string{strconv.FormatInt(contentLength, 10)} + if options != nil && options.TransactionalContentMD5 != nil { + req.Raw().Header["Content-MD5"] = []string{base64.StdEncoding.EncodeToString(options.TransactionalContentMD5)} + } + if options != nil && options.TransactionalContentCRC64 != nil { + req.Raw().Header["x-ms-content-crc64"] = []string{base64.StdEncoding.EncodeToString(options.TransactionalContentCRC64)} + } + if leaseAccessConditions != nil && leaseAccessConditions.LeaseID != nil { + req.Raw().Header["x-ms-lease-id"] = []string{*leaseAccessConditions.LeaseID} + } + if appendPositionAccessConditions != nil && appendPositionAccessConditions.MaxSize != nil { + req.Raw().Header["x-ms-blob-condition-maxsize"] = []string{strconv.FormatInt(*appendPositionAccessConditions.MaxSize, 10)} + } + if appendPositionAccessConditions != nil && appendPositionAccessConditions.AppendPosition != nil { + req.Raw().Header["x-ms-blob-condition-appendpos"] = []string{strconv.FormatInt(*appendPositionAccessConditions.AppendPosition, 10)} + } + if cpkInfo != nil && cpkInfo.EncryptionKey != nil { + req.Raw().Header["x-ms-encryption-key"] = []string{*cpkInfo.EncryptionKey} + } + if cpkInfo != nil && cpkInfo.EncryptionKeySHA256 != nil { + req.Raw().Header["x-ms-encryption-key-sha256"] = []string{*cpkInfo.EncryptionKeySHA256} + } + if cpkInfo != nil && cpkInfo.EncryptionAlgorithm != nil { + req.Raw().Header["x-ms-encryption-algorithm"] = []string{string(*cpkInfo.EncryptionAlgorithm)} + } + if cpkScopeInfo != nil && cpkScopeInfo.EncryptionScope != nil { + req.Raw().Header["x-ms-encryption-scope"] = []string{*cpkScopeInfo.EncryptionScope} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfModifiedSince != nil { + req.Raw().Header["If-Modified-Since"] = []string{(*modifiedAccessConditions.IfModifiedSince).In(gmt).Format(time.RFC1123)} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfUnmodifiedSince != nil { + req.Raw().Header["If-Unmodified-Since"] = []string{(*modifiedAccessConditions.IfUnmodifiedSince).In(gmt).Format(time.RFC1123)} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfMatch != nil { + req.Raw().Header["If-Match"] = []string{string(*modifiedAccessConditions.IfMatch)} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfNoneMatch != nil { + req.Raw().Header["If-None-Match"] = []string{string(*modifiedAccessConditions.IfNoneMatch)} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfTags != nil { + req.Raw().Header["x-ms-if-tags"] = []string{*modifiedAccessConditions.IfTags} + } + req.Raw().Header["x-ms-version"] = []string{"2020-10-02"} + if options != nil && options.RequestID != nil { + req.Raw().Header["x-ms-client-request-id"] = []string{*options.RequestID} + } + req.Raw().Header["Accept"] = []string{"application/xml"} + if err := req.SetBody(body, "application/octet-stream"); err != nil { + return nil, err + } + return req, nil +} + +// appendBlockHandleResponse handles the AppendBlock response. +func (client *AppendBlobClient) appendBlockHandleResponse(resp *http.Response) (AppendBlobClientAppendBlockResponse, error) { + result := AppendBlobClientAppendBlockResponse{} + if val := resp.Header.Get("ETag"); val != "" { + result.ETag = (*azcore.ETag)(&val) + } + if val := resp.Header.Get("Last-Modified"); val != "" { + lastModified, err := time.Parse(time.RFC1123, val) + if err != nil { + return AppendBlobClientAppendBlockResponse{}, err + } + result.LastModified = &lastModified + } + if val := resp.Header.Get("Content-MD5"); val != "" { + contentMD5, err := base64.StdEncoding.DecodeString(val) + if err != nil { + return AppendBlobClientAppendBlockResponse{}, err + } + result.ContentMD5 = contentMD5 + } + if val := resp.Header.Get("x-ms-content-crc64"); val != "" { + contentCRC64, err := base64.StdEncoding.DecodeString(val) + if err != nil { + return AppendBlobClientAppendBlockResponse{}, err + } + result.ContentCRC64 = contentCRC64 + } + if val := resp.Header.Get("x-ms-client-request-id"); val != "" { + result.ClientRequestID = &val + } + if val := resp.Header.Get("x-ms-request-id"); val != "" { + result.RequestID = &val + } + if val := resp.Header.Get("x-ms-version"); val != "" { + result.Version = &val + } + if val := resp.Header.Get("Date"); val != "" { + date, err := time.Parse(time.RFC1123, val) + if err != nil { + return AppendBlobClientAppendBlockResponse{}, err + } + result.Date = &date + } + if val := resp.Header.Get("x-ms-blob-append-offset"); val != "" { + result.BlobAppendOffset = &val + } + if val := resp.Header.Get("x-ms-blob-committed-block-count"); val != "" { + blobCommittedBlockCount32, err := strconv.ParseInt(val, 10, 32) + blobCommittedBlockCount := int32(blobCommittedBlockCount32) + if err != nil { + return AppendBlobClientAppendBlockResponse{}, err + } + result.BlobCommittedBlockCount = &blobCommittedBlockCount + } + if val := resp.Header.Get("x-ms-request-server-encrypted"); val != "" { + isServerEncrypted, err := strconv.ParseBool(val) + if err != nil { + return AppendBlobClientAppendBlockResponse{}, err + } + result.IsServerEncrypted = &isServerEncrypted + } + if val := resp.Header.Get("x-ms-encryption-key-sha256"); val != "" { + result.EncryptionKeySHA256 = &val + } + if val := resp.Header.Get("x-ms-encryption-scope"); val != "" { + result.EncryptionScope = &val + } + return result, nil +} + +// AppendBlockFromURL - The Append Block operation commits a new block of data to the end of an existing append blob where +// the contents are read from a source url. The Append Block operation is permitted only if the blob was +// created with x-ms-blob-type set to AppendBlob. Append Block is supported only on version 2015-02-21 version or later. +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2020-10-02 +// - sourceURL - Specify a URL to the copy source. +// - contentLength - The length of the request. +// - options - AppendBlobClientAppendBlockFromURLOptions contains the optional parameters for the AppendBlobClient.AppendBlockFromURL +// method. +// - CPKInfo - CPKInfo contains a group of parameters for the BlobClient.Download method. +// - CPKScopeInfo - CPKScopeInfo contains a group of parameters for the BlobClient.SetMetadata method. +// - LeaseAccessConditions - LeaseAccessConditions contains a group of parameters for the ContainerClient.GetProperties method. +// - AppendPositionAccessConditions - AppendPositionAccessConditions contains a group of parameters for the AppendBlobClient.AppendBlock +// method. +// - ModifiedAccessConditions - ModifiedAccessConditions contains a group of parameters for the ContainerClient.Delete method. +// - SourceModifiedAccessConditions - SourceModifiedAccessConditions contains a group of parameters for the BlobClient.StartCopyFromURL +// method. +func (client *AppendBlobClient) AppendBlockFromURL(ctx context.Context, sourceURL string, contentLength int64, options *AppendBlobClientAppendBlockFromURLOptions, cpkInfo *CPKInfo, cpkScopeInfo *CPKScopeInfo, leaseAccessConditions *LeaseAccessConditions, appendPositionAccessConditions *AppendPositionAccessConditions, modifiedAccessConditions *ModifiedAccessConditions, sourceModifiedAccessConditions *SourceModifiedAccessConditions) (AppendBlobClientAppendBlockFromURLResponse, error) { + req, err := client.appendBlockFromURLCreateRequest(ctx, sourceURL, contentLength, options, cpkInfo, cpkScopeInfo, leaseAccessConditions, appendPositionAccessConditions, modifiedAccessConditions, sourceModifiedAccessConditions) + if err != nil { + return AppendBlobClientAppendBlockFromURLResponse{}, err + } + resp, err := client.internal.Pipeline().Do(req) + if err != nil { + return AppendBlobClientAppendBlockFromURLResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusCreated) { + return AppendBlobClientAppendBlockFromURLResponse{}, runtime.NewResponseError(resp) + } + return client.appendBlockFromURLHandleResponse(resp) +} + +// appendBlockFromURLCreateRequest creates the AppendBlockFromURL request. +func (client *AppendBlobClient) appendBlockFromURLCreateRequest(ctx context.Context, sourceURL string, contentLength int64, options *AppendBlobClientAppendBlockFromURLOptions, cpkInfo *CPKInfo, cpkScopeInfo *CPKScopeInfo, leaseAccessConditions *LeaseAccessConditions, appendPositionAccessConditions *AppendPositionAccessConditions, modifiedAccessConditions *ModifiedAccessConditions, sourceModifiedAccessConditions *SourceModifiedAccessConditions) (*policy.Request, error) { + req, err := runtime.NewRequest(ctx, http.MethodPut, client.endpoint) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("comp", "appendblock") + if options != nil && options.Timeout != nil { + reqQP.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + } + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["x-ms-copy-source"] = []string{sourceURL} + if options != nil && options.SourceRange != nil { + req.Raw().Header["x-ms-source-range"] = []string{*options.SourceRange} + } + if options != nil && options.SourceContentMD5 != nil { + req.Raw().Header["x-ms-source-content-md5"] = []string{base64.StdEncoding.EncodeToString(options.SourceContentMD5)} + } + if options != nil && options.SourceContentcrc64 != nil { + req.Raw().Header["x-ms-source-content-crc64"] = []string{base64.StdEncoding.EncodeToString(options.SourceContentcrc64)} + } + req.Raw().Header["Content-Length"] = []string{strconv.FormatInt(contentLength, 10)} + if options != nil && options.TransactionalContentMD5 != nil { + req.Raw().Header["Content-MD5"] = []string{base64.StdEncoding.EncodeToString(options.TransactionalContentMD5)} + } + if cpkInfo != nil && cpkInfo.EncryptionKey != nil { + req.Raw().Header["x-ms-encryption-key"] = []string{*cpkInfo.EncryptionKey} + } + if cpkInfo != nil && cpkInfo.EncryptionKeySHA256 != nil { + req.Raw().Header["x-ms-encryption-key-sha256"] = []string{*cpkInfo.EncryptionKeySHA256} + } + if cpkInfo != nil && cpkInfo.EncryptionAlgorithm != nil { + req.Raw().Header["x-ms-encryption-algorithm"] = []string{string(*cpkInfo.EncryptionAlgorithm)} + } + if cpkScopeInfo != nil && cpkScopeInfo.EncryptionScope != nil { + req.Raw().Header["x-ms-encryption-scope"] = []string{*cpkScopeInfo.EncryptionScope} + } + if leaseAccessConditions != nil && leaseAccessConditions.LeaseID != nil { + req.Raw().Header["x-ms-lease-id"] = []string{*leaseAccessConditions.LeaseID} + } + if appendPositionAccessConditions != nil && appendPositionAccessConditions.MaxSize != nil { + req.Raw().Header["x-ms-blob-condition-maxsize"] = []string{strconv.FormatInt(*appendPositionAccessConditions.MaxSize, 10)} + } + if appendPositionAccessConditions != nil && appendPositionAccessConditions.AppendPosition != nil { + req.Raw().Header["x-ms-blob-condition-appendpos"] = []string{strconv.FormatInt(*appendPositionAccessConditions.AppendPosition, 10)} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfModifiedSince != nil { + req.Raw().Header["If-Modified-Since"] = []string{(*modifiedAccessConditions.IfModifiedSince).In(gmt).Format(time.RFC1123)} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfUnmodifiedSince != nil { + req.Raw().Header["If-Unmodified-Since"] = []string{(*modifiedAccessConditions.IfUnmodifiedSince).In(gmt).Format(time.RFC1123)} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfMatch != nil { + req.Raw().Header["If-Match"] = []string{string(*modifiedAccessConditions.IfMatch)} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfNoneMatch != nil { + req.Raw().Header["If-None-Match"] = []string{string(*modifiedAccessConditions.IfNoneMatch)} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfTags != nil { + req.Raw().Header["x-ms-if-tags"] = []string{*modifiedAccessConditions.IfTags} + } + if sourceModifiedAccessConditions != nil && sourceModifiedAccessConditions.SourceIfModifiedSince != nil { + req.Raw().Header["x-ms-source-if-modified-since"] = []string{(*sourceModifiedAccessConditions.SourceIfModifiedSince).In(gmt).Format(time.RFC1123)} + } + if sourceModifiedAccessConditions != nil && sourceModifiedAccessConditions.SourceIfUnmodifiedSince != nil { + req.Raw().Header["x-ms-source-if-unmodified-since"] = []string{(*sourceModifiedAccessConditions.SourceIfUnmodifiedSince).In(gmt).Format(time.RFC1123)} + } + if sourceModifiedAccessConditions != nil && sourceModifiedAccessConditions.SourceIfMatch != nil { + req.Raw().Header["x-ms-source-if-match"] = []string{string(*sourceModifiedAccessConditions.SourceIfMatch)} + } + if sourceModifiedAccessConditions != nil && sourceModifiedAccessConditions.SourceIfNoneMatch != nil { + req.Raw().Header["x-ms-source-if-none-match"] = []string{string(*sourceModifiedAccessConditions.SourceIfNoneMatch)} + } + req.Raw().Header["x-ms-version"] = []string{"2020-10-02"} + if options != nil && options.RequestID != nil { + req.Raw().Header["x-ms-client-request-id"] = []string{*options.RequestID} + } + if options != nil && options.CopySourceAuthorization != nil { + req.Raw().Header["x-ms-copy-source-authorization"] = []string{*options.CopySourceAuthorization} + } + req.Raw().Header["Accept"] = []string{"application/xml"} + return req, nil +} + +// appendBlockFromURLHandleResponse handles the AppendBlockFromURL response. +func (client *AppendBlobClient) appendBlockFromURLHandleResponse(resp *http.Response) (AppendBlobClientAppendBlockFromURLResponse, error) { + result := AppendBlobClientAppendBlockFromURLResponse{} + if val := resp.Header.Get("ETag"); val != "" { + result.ETag = (*azcore.ETag)(&val) + } + if val := resp.Header.Get("Last-Modified"); val != "" { + lastModified, err := time.Parse(time.RFC1123, val) + if err != nil { + return AppendBlobClientAppendBlockFromURLResponse{}, err + } + result.LastModified = &lastModified + } + if val := resp.Header.Get("Content-MD5"); val != "" { + contentMD5, err := base64.StdEncoding.DecodeString(val) + if err != nil { + return AppendBlobClientAppendBlockFromURLResponse{}, err + } + result.ContentMD5 = contentMD5 + } + if val := resp.Header.Get("x-ms-content-crc64"); val != "" { + contentCRC64, err := base64.StdEncoding.DecodeString(val) + if err != nil { + return AppendBlobClientAppendBlockFromURLResponse{}, err + } + result.ContentCRC64 = contentCRC64 + } + if val := resp.Header.Get("x-ms-request-id"); val != "" { + result.RequestID = &val + } + if val := resp.Header.Get("x-ms-version"); val != "" { + result.Version = &val + } + if val := resp.Header.Get("Date"); val != "" { + date, err := time.Parse(time.RFC1123, val) + if err != nil { + return AppendBlobClientAppendBlockFromURLResponse{}, err + } + result.Date = &date + } + if val := resp.Header.Get("x-ms-blob-append-offset"); val != "" { + result.BlobAppendOffset = &val + } + if val := resp.Header.Get("x-ms-blob-committed-block-count"); val != "" { + blobCommittedBlockCount32, err := strconv.ParseInt(val, 10, 32) + blobCommittedBlockCount := int32(blobCommittedBlockCount32) + if err != nil { + return AppendBlobClientAppendBlockFromURLResponse{}, err + } + result.BlobCommittedBlockCount = &blobCommittedBlockCount + } + if val := resp.Header.Get("x-ms-encryption-key-sha256"); val != "" { + result.EncryptionKeySHA256 = &val + } + if val := resp.Header.Get("x-ms-encryption-scope"); val != "" { + result.EncryptionScope = &val + } + if val := resp.Header.Get("x-ms-request-server-encrypted"); val != "" { + isServerEncrypted, err := strconv.ParseBool(val) + if err != nil { + return AppendBlobClientAppendBlockFromURLResponse{}, err + } + result.IsServerEncrypted = &isServerEncrypted + } + return result, nil +} + +// Create - The Create Append Blob operation creates a new append blob. +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2020-10-02 +// - contentLength - The length of the request. +// - options - AppendBlobClientCreateOptions contains the optional parameters for the AppendBlobClient.Create method. +// - BlobHTTPHeaders - BlobHTTPHeaders contains a group of parameters for the BlobClient.SetHTTPHeaders method. +// - LeaseAccessConditions - LeaseAccessConditions contains a group of parameters for the ContainerClient.GetProperties method. +// - CPKInfo - CPKInfo contains a group of parameters for the BlobClient.Download method. +// - CPKScopeInfo - CPKScopeInfo contains a group of parameters for the BlobClient.SetMetadata method. +// - ModifiedAccessConditions - ModifiedAccessConditions contains a group of parameters for the ContainerClient.Delete method. +func (client *AppendBlobClient) Create(ctx context.Context, contentLength int64, options *AppendBlobClientCreateOptions, blobHTTPHeaders *BlobHTTPHeaders, leaseAccessConditions *LeaseAccessConditions, cpkInfo *CPKInfo, cpkScopeInfo *CPKScopeInfo, modifiedAccessConditions *ModifiedAccessConditions) (AppendBlobClientCreateResponse, error) { + req, err := client.createCreateRequest(ctx, contentLength, options, blobHTTPHeaders, leaseAccessConditions, cpkInfo, cpkScopeInfo, modifiedAccessConditions) + if err != nil { + return AppendBlobClientCreateResponse{}, err + } + resp, err := client.internal.Pipeline().Do(req) + if err != nil { + return AppendBlobClientCreateResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusCreated) { + return AppendBlobClientCreateResponse{}, runtime.NewResponseError(resp) + } + return client.createHandleResponse(resp) +} + +// createCreateRequest creates the Create request. +func (client *AppendBlobClient) createCreateRequest(ctx context.Context, contentLength int64, options *AppendBlobClientCreateOptions, blobHTTPHeaders *BlobHTTPHeaders, leaseAccessConditions *LeaseAccessConditions, cpkInfo *CPKInfo, cpkScopeInfo *CPKScopeInfo, modifiedAccessConditions *ModifiedAccessConditions) (*policy.Request, error) { + req, err := runtime.NewRequest(ctx, http.MethodPut, client.endpoint) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + if options != nil && options.Timeout != nil { + reqQP.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + } + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["x-ms-blob-type"] = []string{"AppendBlob"} + req.Raw().Header["Content-Length"] = []string{strconv.FormatInt(contentLength, 10)} + if blobHTTPHeaders != nil && blobHTTPHeaders.BlobContentType != nil { + req.Raw().Header["x-ms-blob-content-type"] = []string{*blobHTTPHeaders.BlobContentType} + } + if blobHTTPHeaders != nil && blobHTTPHeaders.BlobContentEncoding != nil { + req.Raw().Header["x-ms-blob-content-encoding"] = []string{*blobHTTPHeaders.BlobContentEncoding} + } + if blobHTTPHeaders != nil && blobHTTPHeaders.BlobContentLanguage != nil { + req.Raw().Header["x-ms-blob-content-language"] = []string{*blobHTTPHeaders.BlobContentLanguage} + } + if blobHTTPHeaders != nil && blobHTTPHeaders.BlobContentMD5 != nil { + req.Raw().Header["x-ms-blob-content-md5"] = []string{base64.StdEncoding.EncodeToString(blobHTTPHeaders.BlobContentMD5)} + } + if blobHTTPHeaders != nil && blobHTTPHeaders.BlobCacheControl != nil { + req.Raw().Header["x-ms-blob-cache-control"] = []string{*blobHTTPHeaders.BlobCacheControl} + } + if options != nil && options.Metadata != nil { + for k, v := range options.Metadata { + if v != nil { + req.Raw().Header["x-ms-meta-"+k] = []string{*v} + } + } + } + if leaseAccessConditions != nil && leaseAccessConditions.LeaseID != nil { + req.Raw().Header["x-ms-lease-id"] = []string{*leaseAccessConditions.LeaseID} + } + if blobHTTPHeaders != nil && blobHTTPHeaders.BlobContentDisposition != nil { + req.Raw().Header["x-ms-blob-content-disposition"] = []string{*blobHTTPHeaders.BlobContentDisposition} + } + if cpkInfo != nil && cpkInfo.EncryptionKey != nil { + req.Raw().Header["x-ms-encryption-key"] = []string{*cpkInfo.EncryptionKey} + } + if cpkInfo != nil && cpkInfo.EncryptionKeySHA256 != nil { + req.Raw().Header["x-ms-encryption-key-sha256"] = []string{*cpkInfo.EncryptionKeySHA256} + } + if cpkInfo != nil && cpkInfo.EncryptionAlgorithm != nil { + req.Raw().Header["x-ms-encryption-algorithm"] = []string{string(*cpkInfo.EncryptionAlgorithm)} + } + if cpkScopeInfo != nil && cpkScopeInfo.EncryptionScope != nil { + req.Raw().Header["x-ms-encryption-scope"] = []string{*cpkScopeInfo.EncryptionScope} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfModifiedSince != nil { + req.Raw().Header["If-Modified-Since"] = []string{(*modifiedAccessConditions.IfModifiedSince).In(gmt).Format(time.RFC1123)} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfUnmodifiedSince != nil { + req.Raw().Header["If-Unmodified-Since"] = []string{(*modifiedAccessConditions.IfUnmodifiedSince).In(gmt).Format(time.RFC1123)} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfMatch != nil { + req.Raw().Header["If-Match"] = []string{string(*modifiedAccessConditions.IfMatch)} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfNoneMatch != nil { + req.Raw().Header["If-None-Match"] = []string{string(*modifiedAccessConditions.IfNoneMatch)} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfTags != nil { + req.Raw().Header["x-ms-if-tags"] = []string{*modifiedAccessConditions.IfTags} + } + req.Raw().Header["x-ms-version"] = []string{"2020-10-02"} + if options != nil && options.RequestID != nil { + req.Raw().Header["x-ms-client-request-id"] = []string{*options.RequestID} + } + if options != nil && options.BlobTagsString != nil { + req.Raw().Header["x-ms-tags"] = []string{*options.BlobTagsString} + } + if options != nil && options.ImmutabilityPolicyExpiry != nil { + req.Raw().Header["x-ms-immutability-policy-until-date"] = []string{(*options.ImmutabilityPolicyExpiry).In(gmt).Format(time.RFC1123)} + } + if options != nil && options.ImmutabilityPolicyMode != nil { + req.Raw().Header["x-ms-immutability-policy-mode"] = []string{string(*options.ImmutabilityPolicyMode)} + } + if options != nil && options.LegalHold != nil { + req.Raw().Header["x-ms-legal-hold"] = []string{strconv.FormatBool(*options.LegalHold)} + } + req.Raw().Header["Accept"] = []string{"application/xml"} + return req, nil +} + +// createHandleResponse handles the Create response. +func (client *AppendBlobClient) createHandleResponse(resp *http.Response) (AppendBlobClientCreateResponse, error) { + result := AppendBlobClientCreateResponse{} + if val := resp.Header.Get("ETag"); val != "" { + result.ETag = (*azcore.ETag)(&val) + } + if val := resp.Header.Get("Last-Modified"); val != "" { + lastModified, err := time.Parse(time.RFC1123, val) + if err != nil { + return AppendBlobClientCreateResponse{}, err + } + result.LastModified = &lastModified + } + if val := resp.Header.Get("Content-MD5"); val != "" { + contentMD5, err := base64.StdEncoding.DecodeString(val) + if err != nil { + return AppendBlobClientCreateResponse{}, err + } + result.ContentMD5 = contentMD5 + } + if val := resp.Header.Get("x-ms-client-request-id"); val != "" { + result.ClientRequestID = &val + } + if val := resp.Header.Get("x-ms-request-id"); val != "" { + result.RequestID = &val + } + if val := resp.Header.Get("x-ms-version"); val != "" { + result.Version = &val + } + if val := resp.Header.Get("x-ms-version-id"); val != "" { + result.VersionID = &val + } + if val := resp.Header.Get("Date"); val != "" { + date, err := time.Parse(time.RFC1123, val) + if err != nil { + return AppendBlobClientCreateResponse{}, err + } + result.Date = &date + } + if val := resp.Header.Get("x-ms-request-server-encrypted"); val != "" { + isServerEncrypted, err := strconv.ParseBool(val) + if err != nil { + return AppendBlobClientCreateResponse{}, err + } + result.IsServerEncrypted = &isServerEncrypted + } + if val := resp.Header.Get("x-ms-encryption-key-sha256"); val != "" { + result.EncryptionKeySHA256 = &val + } + if val := resp.Header.Get("x-ms-encryption-scope"); val != "" { + result.EncryptionScope = &val + } + return result, nil +} + +// Seal - The Seal operation seals the Append Blob to make it read-only. Seal is supported only on version 2019-12-12 version +// or later. +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2020-10-02 +// - options - AppendBlobClientSealOptions contains the optional parameters for the AppendBlobClient.Seal method. +// - LeaseAccessConditions - LeaseAccessConditions contains a group of parameters for the ContainerClient.GetProperties method. +// - ModifiedAccessConditions - ModifiedAccessConditions contains a group of parameters for the ContainerClient.Delete method. +// - AppendPositionAccessConditions - AppendPositionAccessConditions contains a group of parameters for the AppendBlobClient.AppendBlock +// method. +func (client *AppendBlobClient) Seal(ctx context.Context, options *AppendBlobClientSealOptions, leaseAccessConditions *LeaseAccessConditions, modifiedAccessConditions *ModifiedAccessConditions, appendPositionAccessConditions *AppendPositionAccessConditions) (AppendBlobClientSealResponse, error) { + req, err := client.sealCreateRequest(ctx, options, leaseAccessConditions, modifiedAccessConditions, appendPositionAccessConditions) + if err != nil { + return AppendBlobClientSealResponse{}, err + } + resp, err := client.internal.Pipeline().Do(req) + if err != nil { + return AppendBlobClientSealResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusOK) { + return AppendBlobClientSealResponse{}, runtime.NewResponseError(resp) + } + return client.sealHandleResponse(resp) +} + +// sealCreateRequest creates the Seal request. +func (client *AppendBlobClient) sealCreateRequest(ctx context.Context, options *AppendBlobClientSealOptions, leaseAccessConditions *LeaseAccessConditions, modifiedAccessConditions *ModifiedAccessConditions, appendPositionAccessConditions *AppendPositionAccessConditions) (*policy.Request, error) { + req, err := runtime.NewRequest(ctx, http.MethodPut, client.endpoint) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("comp", "seal") + if options != nil && options.Timeout != nil { + reqQP.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + } + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["x-ms-version"] = []string{"2020-10-02"} + if options != nil && options.RequestID != nil { + req.Raw().Header["x-ms-client-request-id"] = []string{*options.RequestID} + } + if leaseAccessConditions != nil && leaseAccessConditions.LeaseID != nil { + req.Raw().Header["x-ms-lease-id"] = []string{*leaseAccessConditions.LeaseID} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfModifiedSince != nil { + req.Raw().Header["If-Modified-Since"] = []string{(*modifiedAccessConditions.IfModifiedSince).In(gmt).Format(time.RFC1123)} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfUnmodifiedSince != nil { + req.Raw().Header["If-Unmodified-Since"] = []string{(*modifiedAccessConditions.IfUnmodifiedSince).In(gmt).Format(time.RFC1123)} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfMatch != nil { + req.Raw().Header["If-Match"] = []string{string(*modifiedAccessConditions.IfMatch)} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfNoneMatch != nil { + req.Raw().Header["If-None-Match"] = []string{string(*modifiedAccessConditions.IfNoneMatch)} + } + if appendPositionAccessConditions != nil && appendPositionAccessConditions.AppendPosition != nil { + req.Raw().Header["x-ms-blob-condition-appendpos"] = []string{strconv.FormatInt(*appendPositionAccessConditions.AppendPosition, 10)} + } + req.Raw().Header["Accept"] = []string{"application/xml"} + return req, nil +} + +// sealHandleResponse handles the Seal response. +func (client *AppendBlobClient) sealHandleResponse(resp *http.Response) (AppendBlobClientSealResponse, error) { + result := AppendBlobClientSealResponse{} + if val := resp.Header.Get("ETag"); val != "" { + result.ETag = (*azcore.ETag)(&val) + } + if val := resp.Header.Get("Last-Modified"); val != "" { + lastModified, err := time.Parse(time.RFC1123, val) + if err != nil { + return AppendBlobClientSealResponse{}, err + } + result.LastModified = &lastModified + } + if val := resp.Header.Get("x-ms-client-request-id"); val != "" { + result.ClientRequestID = &val + } + if val := resp.Header.Get("x-ms-request-id"); val != "" { + result.RequestID = &val + } + if val := resp.Header.Get("x-ms-version"); val != "" { + result.Version = &val + } + if val := resp.Header.Get("Date"); val != "" { + date, err := time.Parse(time.RFC1123, val) + if err != nil { + return AppendBlobClientSealResponse{}, err + } + result.Date = &date + } + if val := resp.Header.Get("x-ms-blob-sealed"); val != "" { + isSealed, err := strconv.ParseBool(val) + if err != nil { + return AppendBlobClientSealResponse{}, err + } + result.IsSealed = &isSealed + } + return result, nil +} diff --git a/sdk/storage/azdatalake/internal/generated_blob/zz_blob_client.go b/sdk/storage/azdatalake/internal/generated_blob/zz_blob_client.go new file mode 100644 index 000000000000..73bfa9187875 --- /dev/null +++ b/sdk/storage/azdatalake/internal/generated_blob/zz_blob_client.go @@ -0,0 +1,2874 @@ +//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. +// Code generated by Microsoft (R) AutoRest Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. +// DO NOT EDIT. + +package generated_blob + +import ( + "context" + "encoding/base64" + "github.com/Azure/azure-sdk-for-go/sdk/azcore" + "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/azcore/to" + "net/http" + "strconv" + "strings" + "time" +) + +// BlobClient contains the methods for the Blob group. +// Don't use this type directly, use a constructor function instead. +type BlobClient struct { + internal *azcore.Client + endpoint string +} + +// AbortCopyFromURL - The Abort Copy From URL operation aborts a pending Copy From URL operation, and leaves a destination +// blob with zero length and full metadata. +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2020-10-02 +// - copyID - The copy identifier provided in the x-ms-copy-id header of the original Copy Blob operation. +// - options - BlobClientAbortCopyFromURLOptions contains the optional parameters for the BlobClient.AbortCopyFromURL method. +// - LeaseAccessConditions - LeaseAccessConditions contains a group of parameters for the ContainerClient.GetProperties method. +func (client *BlobClient) AbortCopyFromURL(ctx context.Context, copyID string, options *BlobClientAbortCopyFromURLOptions, leaseAccessConditions *LeaseAccessConditions) (BlobClientAbortCopyFromURLResponse, error) { + req, err := client.abortCopyFromURLCreateRequest(ctx, copyID, options, leaseAccessConditions) + if err != nil { + return BlobClientAbortCopyFromURLResponse{}, err + } + resp, err := client.internal.Pipeline().Do(req) + if err != nil { + return BlobClientAbortCopyFromURLResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusNoContent) { + return BlobClientAbortCopyFromURLResponse{}, runtime.NewResponseError(resp) + } + return client.abortCopyFromURLHandleResponse(resp) +} + +// abortCopyFromURLCreateRequest creates the AbortCopyFromURL request. +func (client *BlobClient) abortCopyFromURLCreateRequest(ctx context.Context, copyID string, options *BlobClientAbortCopyFromURLOptions, leaseAccessConditions *LeaseAccessConditions) (*policy.Request, error) { + req, err := runtime.NewRequest(ctx, http.MethodPut, client.endpoint) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("comp", "copy") + reqQP.Set("copyid", copyID) + if options != nil && options.Timeout != nil { + reqQP.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + } + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["x-ms-copy-action"] = []string{"abort"} + if leaseAccessConditions != nil && leaseAccessConditions.LeaseID != nil { + req.Raw().Header["x-ms-lease-id"] = []string{*leaseAccessConditions.LeaseID} + } + req.Raw().Header["x-ms-version"] = []string{"2020-10-02"} + if options != nil && options.RequestID != nil { + req.Raw().Header["x-ms-client-request-id"] = []string{*options.RequestID} + } + req.Raw().Header["Accept"] = []string{"application/xml"} + return req, nil +} + +// abortCopyFromURLHandleResponse handles the AbortCopyFromURL response. +func (client *BlobClient) abortCopyFromURLHandleResponse(resp *http.Response) (BlobClientAbortCopyFromURLResponse, error) { + result := BlobClientAbortCopyFromURLResponse{} + if val := resp.Header.Get("x-ms-client-request-id"); val != "" { + result.ClientRequestID = &val + } + if val := resp.Header.Get("x-ms-request-id"); val != "" { + result.RequestID = &val + } + if val := resp.Header.Get("x-ms-version"); val != "" { + result.Version = &val + } + if val := resp.Header.Get("Date"); val != "" { + date, err := time.Parse(time.RFC1123, val) + if err != nil { + return BlobClientAbortCopyFromURLResponse{}, err + } + result.Date = &date + } + return result, nil +} + +// AcquireLease - [Update] The Lease Blob operation establishes and manages a lock on a blob for write and delete operations +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2020-10-02 +// - duration - 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. A lease duration cannot be changed using +// renew or change. +// - options - BlobClientAcquireLeaseOptions contains the optional parameters for the BlobClient.AcquireLease method. +// - ModifiedAccessConditions - ModifiedAccessConditions contains a group of parameters for the ContainerClient.Delete method. +func (client *BlobClient) AcquireLease(ctx context.Context, duration int32, options *BlobClientAcquireLeaseOptions, modifiedAccessConditions *ModifiedAccessConditions) (BlobClientAcquireLeaseResponse, error) { + req, err := client.acquireLeaseCreateRequest(ctx, duration, options, modifiedAccessConditions) + if err != nil { + return BlobClientAcquireLeaseResponse{}, err + } + resp, err := client.internal.Pipeline().Do(req) + if err != nil { + return BlobClientAcquireLeaseResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusCreated) { + return BlobClientAcquireLeaseResponse{}, runtime.NewResponseError(resp) + } + return client.acquireLeaseHandleResponse(resp) +} + +// acquireLeaseCreateRequest creates the AcquireLease request. +func (client *BlobClient) acquireLeaseCreateRequest(ctx context.Context, duration int32, options *BlobClientAcquireLeaseOptions, modifiedAccessConditions *ModifiedAccessConditions) (*policy.Request, error) { + req, err := runtime.NewRequest(ctx, http.MethodPut, client.endpoint) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("comp", "lease") + if options != nil && options.Timeout != nil { + reqQP.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + } + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["x-ms-lease-action"] = []string{"acquire"} + req.Raw().Header["x-ms-lease-duration"] = []string{strconv.FormatInt(int64(duration), 10)} + if options != nil && options.ProposedLeaseID != nil { + req.Raw().Header["x-ms-proposed-lease-id"] = []string{*options.ProposedLeaseID} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfModifiedSince != nil { + req.Raw().Header["If-Modified-Since"] = []string{(*modifiedAccessConditions.IfModifiedSince).In(gmt).Format(time.RFC1123)} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfUnmodifiedSince != nil { + req.Raw().Header["If-Unmodified-Since"] = []string{(*modifiedAccessConditions.IfUnmodifiedSince).In(gmt).Format(time.RFC1123)} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfMatch != nil { + req.Raw().Header["If-Match"] = []string{string(*modifiedAccessConditions.IfMatch)} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfNoneMatch != nil { + req.Raw().Header["If-None-Match"] = []string{string(*modifiedAccessConditions.IfNoneMatch)} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfTags != nil { + req.Raw().Header["x-ms-if-tags"] = []string{*modifiedAccessConditions.IfTags} + } + req.Raw().Header["x-ms-version"] = []string{"2020-10-02"} + if options != nil && options.RequestID != nil { + req.Raw().Header["x-ms-client-request-id"] = []string{*options.RequestID} + } + req.Raw().Header["Accept"] = []string{"application/xml"} + return req, nil +} + +// acquireLeaseHandleResponse handles the AcquireLease response. +func (client *BlobClient) acquireLeaseHandleResponse(resp *http.Response) (BlobClientAcquireLeaseResponse, error) { + result := BlobClientAcquireLeaseResponse{} + if val := resp.Header.Get("ETag"); val != "" { + result.ETag = (*azcore.ETag)(&val) + } + if val := resp.Header.Get("Last-Modified"); val != "" { + lastModified, err := time.Parse(time.RFC1123, val) + if err != nil { + return BlobClientAcquireLeaseResponse{}, err + } + result.LastModified = &lastModified + } + if val := resp.Header.Get("x-ms-lease-id"); val != "" { + result.LeaseID = &val + } + if val := resp.Header.Get("x-ms-client-request-id"); val != "" { + result.ClientRequestID = &val + } + if val := resp.Header.Get("x-ms-request-id"); val != "" { + result.RequestID = &val + } + if val := resp.Header.Get("x-ms-version"); val != "" { + result.Version = &val + } + if val := resp.Header.Get("Date"); val != "" { + date, err := time.Parse(time.RFC1123, val) + if err != nil { + return BlobClientAcquireLeaseResponse{}, err + } + result.Date = &date + } + return result, nil +} + +// BreakLease - [Update] The Lease Blob operation establishes and manages a lock on a blob for write and delete operations +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2020-10-02 +// - options - BlobClientBreakLeaseOptions contains the optional parameters for the BlobClient.BreakLease method. +// - ModifiedAccessConditions - ModifiedAccessConditions contains a group of parameters for the ContainerClient.Delete method. +func (client *BlobClient) BreakLease(ctx context.Context, options *BlobClientBreakLeaseOptions, modifiedAccessConditions *ModifiedAccessConditions) (BlobClientBreakLeaseResponse, error) { + req, err := client.breakLeaseCreateRequest(ctx, options, modifiedAccessConditions) + if err != nil { + return BlobClientBreakLeaseResponse{}, err + } + resp, err := client.internal.Pipeline().Do(req) + if err != nil { + return BlobClientBreakLeaseResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusAccepted) { + return BlobClientBreakLeaseResponse{}, runtime.NewResponseError(resp) + } + return client.breakLeaseHandleResponse(resp) +} + +// breakLeaseCreateRequest creates the BreakLease request. +func (client *BlobClient) breakLeaseCreateRequest(ctx context.Context, options *BlobClientBreakLeaseOptions, modifiedAccessConditions *ModifiedAccessConditions) (*policy.Request, error) { + req, err := runtime.NewRequest(ctx, http.MethodPut, client.endpoint) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("comp", "lease") + if options != nil && options.Timeout != nil { + reqQP.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + } + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["x-ms-lease-action"] = []string{"break"} + if options != nil && options.BreakPeriod != nil { + req.Raw().Header["x-ms-lease-break-period"] = []string{strconv.FormatInt(int64(*options.BreakPeriod), 10)} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfModifiedSince != nil { + req.Raw().Header["If-Modified-Since"] = []string{(*modifiedAccessConditions.IfModifiedSince).In(gmt).Format(time.RFC1123)} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfUnmodifiedSince != nil { + req.Raw().Header["If-Unmodified-Since"] = []string{(*modifiedAccessConditions.IfUnmodifiedSince).In(gmt).Format(time.RFC1123)} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfMatch != nil { + req.Raw().Header["If-Match"] = []string{string(*modifiedAccessConditions.IfMatch)} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfNoneMatch != nil { + req.Raw().Header["If-None-Match"] = []string{string(*modifiedAccessConditions.IfNoneMatch)} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfTags != nil { + req.Raw().Header["x-ms-if-tags"] = []string{*modifiedAccessConditions.IfTags} + } + req.Raw().Header["x-ms-version"] = []string{"2020-10-02"} + if options != nil && options.RequestID != nil { + req.Raw().Header["x-ms-client-request-id"] = []string{*options.RequestID} + } + req.Raw().Header["Accept"] = []string{"application/xml"} + return req, nil +} + +// breakLeaseHandleResponse handles the BreakLease response. +func (client *BlobClient) breakLeaseHandleResponse(resp *http.Response) (BlobClientBreakLeaseResponse, error) { + result := BlobClientBreakLeaseResponse{} + if val := resp.Header.Get("ETag"); val != "" { + result.ETag = (*azcore.ETag)(&val) + } + if val := resp.Header.Get("Last-Modified"); val != "" { + lastModified, err := time.Parse(time.RFC1123, val) + if err != nil { + return BlobClientBreakLeaseResponse{}, err + } + result.LastModified = &lastModified + } + if val := resp.Header.Get("x-ms-lease-time"); val != "" { + leaseTime32, err := strconv.ParseInt(val, 10, 32) + leaseTime := int32(leaseTime32) + if err != nil { + return BlobClientBreakLeaseResponse{}, err + } + result.LeaseTime = &leaseTime + } + if val := resp.Header.Get("x-ms-client-request-id"); val != "" { + result.ClientRequestID = &val + } + if val := resp.Header.Get("x-ms-request-id"); val != "" { + result.RequestID = &val + } + if val := resp.Header.Get("x-ms-version"); val != "" { + result.Version = &val + } + if val := resp.Header.Get("Date"); val != "" { + date, err := time.Parse(time.RFC1123, val) + if err != nil { + return BlobClientBreakLeaseResponse{}, err + } + result.Date = &date + } + return result, nil +} + +// ChangeLease - [Update] The Lease Blob operation establishes and manages a lock on a blob for write and delete operations +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2020-10-02 +// - leaseID - Specifies the current lease ID on the resource. +// - proposedLeaseID - Proposed lease ID, in a GUID string format. The Blob service returns 400 (Invalid request) if the proposed +// lease ID is not in the correct format. See Guid Constructor (String) for a list of valid GUID +// string formats. +// - options - BlobClientChangeLeaseOptions contains the optional parameters for the BlobClient.ChangeLease method. +// - ModifiedAccessConditions - ModifiedAccessConditions contains a group of parameters for the ContainerClient.Delete method. +func (client *BlobClient) ChangeLease(ctx context.Context, leaseID string, proposedLeaseID string, options *BlobClientChangeLeaseOptions, modifiedAccessConditions *ModifiedAccessConditions) (BlobClientChangeLeaseResponse, error) { + req, err := client.changeLeaseCreateRequest(ctx, leaseID, proposedLeaseID, options, modifiedAccessConditions) + if err != nil { + return BlobClientChangeLeaseResponse{}, err + } + resp, err := client.internal.Pipeline().Do(req) + if err != nil { + return BlobClientChangeLeaseResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusOK) { + return BlobClientChangeLeaseResponse{}, runtime.NewResponseError(resp) + } + return client.changeLeaseHandleResponse(resp) +} + +// changeLeaseCreateRequest creates the ChangeLease request. +func (client *BlobClient) changeLeaseCreateRequest(ctx context.Context, leaseID string, proposedLeaseID string, options *BlobClientChangeLeaseOptions, modifiedAccessConditions *ModifiedAccessConditions) (*policy.Request, error) { + req, err := runtime.NewRequest(ctx, http.MethodPut, client.endpoint) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("comp", "lease") + if options != nil && options.Timeout != nil { + reqQP.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + } + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["x-ms-lease-action"] = []string{"change"} + req.Raw().Header["x-ms-lease-id"] = []string{leaseID} + req.Raw().Header["x-ms-proposed-lease-id"] = []string{proposedLeaseID} + if modifiedAccessConditions != nil && modifiedAccessConditions.IfModifiedSince != nil { + req.Raw().Header["If-Modified-Since"] = []string{(*modifiedAccessConditions.IfModifiedSince).In(gmt).Format(time.RFC1123)} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfUnmodifiedSince != nil { + req.Raw().Header["If-Unmodified-Since"] = []string{(*modifiedAccessConditions.IfUnmodifiedSince).In(gmt).Format(time.RFC1123)} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfMatch != nil { + req.Raw().Header["If-Match"] = []string{string(*modifiedAccessConditions.IfMatch)} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfNoneMatch != nil { + req.Raw().Header["If-None-Match"] = []string{string(*modifiedAccessConditions.IfNoneMatch)} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfTags != nil { + req.Raw().Header["x-ms-if-tags"] = []string{*modifiedAccessConditions.IfTags} + } + req.Raw().Header["x-ms-version"] = []string{"2020-10-02"} + if options != nil && options.RequestID != nil { + req.Raw().Header["x-ms-client-request-id"] = []string{*options.RequestID} + } + req.Raw().Header["Accept"] = []string{"application/xml"} + return req, nil +} + +// changeLeaseHandleResponse handles the ChangeLease response. +func (client *BlobClient) changeLeaseHandleResponse(resp *http.Response) (BlobClientChangeLeaseResponse, error) { + result := BlobClientChangeLeaseResponse{} + if val := resp.Header.Get("ETag"); val != "" { + result.ETag = (*azcore.ETag)(&val) + } + if val := resp.Header.Get("Last-Modified"); val != "" { + lastModified, err := time.Parse(time.RFC1123, val) + if err != nil { + return BlobClientChangeLeaseResponse{}, err + } + result.LastModified = &lastModified + } + if val := resp.Header.Get("x-ms-client-request-id"); val != "" { + result.ClientRequestID = &val + } + if val := resp.Header.Get("x-ms-request-id"); val != "" { + result.RequestID = &val + } + if val := resp.Header.Get("x-ms-lease-id"); val != "" { + result.LeaseID = &val + } + if val := resp.Header.Get("x-ms-version"); val != "" { + result.Version = &val + } + if val := resp.Header.Get("Date"); val != "" { + date, err := time.Parse(time.RFC1123, val) + if err != nil { + return BlobClientChangeLeaseResponse{}, err + } + result.Date = &date + } + return result, nil +} + +// CopyFromURL - The Copy From URL operation copies a blob or an internet resource to a new blob. It will not return a response +// until the copy is complete. +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2020-10-02 +// - copySource - Specifies the name of the source page blob snapshot. This value is a URL of up to 2 KB in length that specifies +// a page blob snapshot. The value should be URL-encoded as it would appear in a request +// URI. The source blob must either be public or must be authenticated via a shared access signature. +// - options - BlobClientCopyFromURLOptions contains the optional parameters for the BlobClient.CopyFromURL method. +// - SourceModifiedAccessConditions - SourceModifiedAccessConditions contains a group of parameters for the BlobClient.StartCopyFromURL +// method. +// - ModifiedAccessConditions - ModifiedAccessConditions contains a group of parameters for the ContainerClient.Delete method. +// - LeaseAccessConditions - LeaseAccessConditions contains a group of parameters for the ContainerClient.GetProperties method. +func (client *BlobClient) CopyFromURL(ctx context.Context, copySource string, options *BlobClientCopyFromURLOptions, sourceModifiedAccessConditions *SourceModifiedAccessConditions, modifiedAccessConditions *ModifiedAccessConditions, leaseAccessConditions *LeaseAccessConditions) (BlobClientCopyFromURLResponse, error) { + req, err := client.copyFromURLCreateRequest(ctx, copySource, options, sourceModifiedAccessConditions, modifiedAccessConditions, leaseAccessConditions) + if err != nil { + return BlobClientCopyFromURLResponse{}, err + } + resp, err := client.internal.Pipeline().Do(req) + if err != nil { + return BlobClientCopyFromURLResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusAccepted) { + return BlobClientCopyFromURLResponse{}, runtime.NewResponseError(resp) + } + return client.copyFromURLHandleResponse(resp) +} + +// copyFromURLCreateRequest creates the CopyFromURL request. +func (client *BlobClient) copyFromURLCreateRequest(ctx context.Context, copySource string, options *BlobClientCopyFromURLOptions, sourceModifiedAccessConditions *SourceModifiedAccessConditions, modifiedAccessConditions *ModifiedAccessConditions, leaseAccessConditions *LeaseAccessConditions) (*policy.Request, error) { + req, err := runtime.NewRequest(ctx, http.MethodPut, client.endpoint) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + if options != nil && options.Timeout != nil { + reqQP.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + } + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["x-ms-requires-sync"] = []string{"true"} + if options != nil && options.Metadata != nil { + for k, v := range options.Metadata { + if v != nil { + req.Raw().Header["x-ms-meta-"+k] = []string{*v} + } + } + } + if options != nil && options.Tier != nil { + req.Raw().Header["x-ms-access-tier"] = []string{string(*options.Tier)} + } + if sourceModifiedAccessConditions != nil && sourceModifiedAccessConditions.SourceIfModifiedSince != nil { + req.Raw().Header["x-ms-source-if-modified-since"] = []string{(*sourceModifiedAccessConditions.SourceIfModifiedSince).In(gmt).Format(time.RFC1123)} + } + if sourceModifiedAccessConditions != nil && sourceModifiedAccessConditions.SourceIfUnmodifiedSince != nil { + req.Raw().Header["x-ms-source-if-unmodified-since"] = []string{(*sourceModifiedAccessConditions.SourceIfUnmodifiedSince).In(gmt).Format(time.RFC1123)} + } + if sourceModifiedAccessConditions != nil && sourceModifiedAccessConditions.SourceIfMatch != nil { + req.Raw().Header["x-ms-source-if-match"] = []string{string(*sourceModifiedAccessConditions.SourceIfMatch)} + } + if sourceModifiedAccessConditions != nil && sourceModifiedAccessConditions.SourceIfNoneMatch != nil { + req.Raw().Header["x-ms-source-if-none-match"] = []string{string(*sourceModifiedAccessConditions.SourceIfNoneMatch)} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfModifiedSince != nil { + req.Raw().Header["If-Modified-Since"] = []string{(*modifiedAccessConditions.IfModifiedSince).In(gmt).Format(time.RFC1123)} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfUnmodifiedSince != nil { + req.Raw().Header["If-Unmodified-Since"] = []string{(*modifiedAccessConditions.IfUnmodifiedSince).In(gmt).Format(time.RFC1123)} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfMatch != nil { + req.Raw().Header["If-Match"] = []string{string(*modifiedAccessConditions.IfMatch)} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfNoneMatch != nil { + req.Raw().Header["If-None-Match"] = []string{string(*modifiedAccessConditions.IfNoneMatch)} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfTags != nil { + req.Raw().Header["x-ms-if-tags"] = []string{*modifiedAccessConditions.IfTags} + } + req.Raw().Header["x-ms-copy-source"] = []string{copySource} + if leaseAccessConditions != nil && leaseAccessConditions.LeaseID != nil { + req.Raw().Header["x-ms-lease-id"] = []string{*leaseAccessConditions.LeaseID} + } + req.Raw().Header["x-ms-version"] = []string{"2020-10-02"} + if options != nil && options.RequestID != nil { + req.Raw().Header["x-ms-client-request-id"] = []string{*options.RequestID} + } + if options != nil && options.SourceContentMD5 != nil { + req.Raw().Header["x-ms-source-content-md5"] = []string{base64.StdEncoding.EncodeToString(options.SourceContentMD5)} + } + if options != nil && options.BlobTagsString != nil { + req.Raw().Header["x-ms-tags"] = []string{*options.BlobTagsString} + } + if options != nil && options.ImmutabilityPolicyExpiry != nil { + req.Raw().Header["x-ms-immutability-policy-until-date"] = []string{(*options.ImmutabilityPolicyExpiry).In(gmt).Format(time.RFC1123)} + } + if options != nil && options.ImmutabilityPolicyMode != nil { + req.Raw().Header["x-ms-immutability-policy-mode"] = []string{string(*options.ImmutabilityPolicyMode)} + } + if options != nil && options.LegalHold != nil { + req.Raw().Header["x-ms-legal-hold"] = []string{strconv.FormatBool(*options.LegalHold)} + } + if options != nil && options.CopySourceAuthorization != nil { + req.Raw().Header["x-ms-copy-source-authorization"] = []string{*options.CopySourceAuthorization} + } + req.Raw().Header["Accept"] = []string{"application/xml"} + return req, nil +} + +// copyFromURLHandleResponse handles the CopyFromURL response. +func (client *BlobClient) copyFromURLHandleResponse(resp *http.Response) (BlobClientCopyFromURLResponse, error) { + result := BlobClientCopyFromURLResponse{} + if val := resp.Header.Get("ETag"); val != "" { + result.ETag = (*azcore.ETag)(&val) + } + if val := resp.Header.Get("Last-Modified"); val != "" { + lastModified, err := time.Parse(time.RFC1123, val) + if err != nil { + return BlobClientCopyFromURLResponse{}, err + } + result.LastModified = &lastModified + } + if val := resp.Header.Get("x-ms-client-request-id"); val != "" { + result.ClientRequestID = &val + } + if val := resp.Header.Get("x-ms-request-id"); val != "" { + result.RequestID = &val + } + if val := resp.Header.Get("x-ms-version"); val != "" { + result.Version = &val + } + if val := resp.Header.Get("x-ms-version-id"); val != "" { + result.VersionID = &val + } + if val := resp.Header.Get("Date"); val != "" { + date, err := time.Parse(time.RFC1123, val) + if err != nil { + return BlobClientCopyFromURLResponse{}, err + } + result.Date = &date + } + if val := resp.Header.Get("x-ms-copy-id"); val != "" { + result.CopyID = &val + } + if val := resp.Header.Get("x-ms-copy-status"); val != "" { + result.CopyStatus = &val + } + if val := resp.Header.Get("Content-MD5"); val != "" { + contentMD5, err := base64.StdEncoding.DecodeString(val) + if err != nil { + return BlobClientCopyFromURLResponse{}, err + } + result.ContentMD5 = contentMD5 + } + if val := resp.Header.Get("x-ms-content-crc64"); val != "" { + contentCRC64, err := base64.StdEncoding.DecodeString(val) + if err != nil { + return BlobClientCopyFromURLResponse{}, err + } + result.ContentCRC64 = contentCRC64 + } + return result, nil +} + +// CreateSnapshot - The Create Snapshot operation creates a read-only snapshot of a blob +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2020-10-02 +// - options - BlobClientCreateSnapshotOptions contains the optional parameters for the BlobClient.CreateSnapshot method. +// - CPKInfo - CPKInfo contains a group of parameters for the BlobClient.Download method. +// - CPKScopeInfo - CPKScopeInfo contains a group of parameters for the BlobClient.SetMetadata method. +// - ModifiedAccessConditions - ModifiedAccessConditions contains a group of parameters for the ContainerClient.Delete method. +// - LeaseAccessConditions - LeaseAccessConditions contains a group of parameters for the ContainerClient.GetProperties method. +func (client *BlobClient) CreateSnapshot(ctx context.Context, options *BlobClientCreateSnapshotOptions, cpkInfo *CPKInfo, cpkScopeInfo *CPKScopeInfo, modifiedAccessConditions *ModifiedAccessConditions, leaseAccessConditions *LeaseAccessConditions) (BlobClientCreateSnapshotResponse, error) { + req, err := client.createSnapshotCreateRequest(ctx, options, cpkInfo, cpkScopeInfo, modifiedAccessConditions, leaseAccessConditions) + if err != nil { + return BlobClientCreateSnapshotResponse{}, err + } + resp, err := client.internal.Pipeline().Do(req) + if err != nil { + return BlobClientCreateSnapshotResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusCreated) { + return BlobClientCreateSnapshotResponse{}, runtime.NewResponseError(resp) + } + return client.createSnapshotHandleResponse(resp) +} + +// createSnapshotCreateRequest creates the CreateSnapshot request. +func (client *BlobClient) createSnapshotCreateRequest(ctx context.Context, options *BlobClientCreateSnapshotOptions, cpkInfo *CPKInfo, cpkScopeInfo *CPKScopeInfo, modifiedAccessConditions *ModifiedAccessConditions, leaseAccessConditions *LeaseAccessConditions) (*policy.Request, error) { + req, err := runtime.NewRequest(ctx, http.MethodPut, client.endpoint) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("comp", "snapshot") + if options != nil && options.Timeout != nil { + reqQP.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + } + req.Raw().URL.RawQuery = reqQP.Encode() + if options != nil && options.Metadata != nil { + for k, v := range options.Metadata { + if v != nil { + req.Raw().Header["x-ms-meta-"+k] = []string{*v} + } + } + } + if cpkInfo != nil && cpkInfo.EncryptionKey != nil { + req.Raw().Header["x-ms-encryption-key"] = []string{*cpkInfo.EncryptionKey} + } + if cpkInfo != nil && cpkInfo.EncryptionKeySHA256 != nil { + req.Raw().Header["x-ms-encryption-key-sha256"] = []string{*cpkInfo.EncryptionKeySHA256} + } + if cpkInfo != nil && cpkInfo.EncryptionAlgorithm != nil { + req.Raw().Header["x-ms-encryption-algorithm"] = []string{string(*cpkInfo.EncryptionAlgorithm)} + } + if cpkScopeInfo != nil && cpkScopeInfo.EncryptionScope != nil { + req.Raw().Header["x-ms-encryption-scope"] = []string{*cpkScopeInfo.EncryptionScope} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfModifiedSince != nil { + req.Raw().Header["If-Modified-Since"] = []string{(*modifiedAccessConditions.IfModifiedSince).In(gmt).Format(time.RFC1123)} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfUnmodifiedSince != nil { + req.Raw().Header["If-Unmodified-Since"] = []string{(*modifiedAccessConditions.IfUnmodifiedSince).In(gmt).Format(time.RFC1123)} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfMatch != nil { + req.Raw().Header["If-Match"] = []string{string(*modifiedAccessConditions.IfMatch)} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfNoneMatch != nil { + req.Raw().Header["If-None-Match"] = []string{string(*modifiedAccessConditions.IfNoneMatch)} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfTags != nil { + req.Raw().Header["x-ms-if-tags"] = []string{*modifiedAccessConditions.IfTags} + } + if leaseAccessConditions != nil && leaseAccessConditions.LeaseID != nil { + req.Raw().Header["x-ms-lease-id"] = []string{*leaseAccessConditions.LeaseID} + } + req.Raw().Header["x-ms-version"] = []string{"2020-10-02"} + if options != nil && options.RequestID != nil { + req.Raw().Header["x-ms-client-request-id"] = []string{*options.RequestID} + } + req.Raw().Header["Accept"] = []string{"application/xml"} + return req, nil +} + +// createSnapshotHandleResponse handles the CreateSnapshot response. +func (client *BlobClient) createSnapshotHandleResponse(resp *http.Response) (BlobClientCreateSnapshotResponse, error) { + result := BlobClientCreateSnapshotResponse{} + if val := resp.Header.Get("x-ms-snapshot"); val != "" { + result.Snapshot = &val + } + if val := resp.Header.Get("ETag"); val != "" { + result.ETag = (*azcore.ETag)(&val) + } + if val := resp.Header.Get("Last-Modified"); val != "" { + lastModified, err := time.Parse(time.RFC1123, val) + if err != nil { + return BlobClientCreateSnapshotResponse{}, err + } + result.LastModified = &lastModified + } + if val := resp.Header.Get("x-ms-client-request-id"); val != "" { + result.ClientRequestID = &val + } + if val := resp.Header.Get("x-ms-request-id"); val != "" { + result.RequestID = &val + } + if val := resp.Header.Get("x-ms-version"); val != "" { + result.Version = &val + } + if val := resp.Header.Get("x-ms-version-id"); val != "" { + result.VersionID = &val + } + if val := resp.Header.Get("Date"); val != "" { + date, err := time.Parse(time.RFC1123, val) + if err != nil { + return BlobClientCreateSnapshotResponse{}, err + } + result.Date = &date + } + if val := resp.Header.Get("x-ms-request-server-encrypted"); val != "" { + isServerEncrypted, err := strconv.ParseBool(val) + if err != nil { + return BlobClientCreateSnapshotResponse{}, err + } + result.IsServerEncrypted = &isServerEncrypted + } + return result, nil +} + +// Delete - If the storage account's soft delete feature is disabled then, when a blob is deleted, it is permanently removed +// from the storage account. If the storage account's soft delete feature is enabled, +// then, when a blob is deleted, it is marked for deletion and becomes inaccessible immediately. However, the blob service +// retains the blob or snapshot for the number of days specified by the +// DeleteRetentionPolicy section of Storage service properties [Set-Blob-Service-Properties.md]. After the specified number +// of days has passed, the blob's data is permanently removed from the storage +// account. Note that you continue to be charged for the soft-deleted blob's storage until it is permanently removed. Use +// the List Blobs API and specify the "include=deleted" query parameter to discover +// which blobs and snapshots have been soft deleted. You can then use the Undelete Blob API to restore a soft-deleted blob. +// All other operations on a soft-deleted blob or snapshot causes the service to +// return an HTTP status code of 404 (ResourceNotFound). +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2020-10-02 +// - options - BlobClientDeleteOptions contains the optional parameters for the BlobClient.Delete method. +// - LeaseAccessConditions - LeaseAccessConditions contains a group of parameters for the ContainerClient.GetProperties method. +// - ModifiedAccessConditions - ModifiedAccessConditions contains a group of parameters for the ContainerClient.Delete method. +func (client *BlobClient) Delete(ctx context.Context, options *BlobClientDeleteOptions, leaseAccessConditions *LeaseAccessConditions, modifiedAccessConditions *ModifiedAccessConditions) (BlobClientDeleteResponse, error) { + req, err := client.deleteCreateRequest(ctx, options, leaseAccessConditions, modifiedAccessConditions) + if err != nil { + return BlobClientDeleteResponse{}, err + } + resp, err := client.internal.Pipeline().Do(req) + if err != nil { + return BlobClientDeleteResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusAccepted) { + return BlobClientDeleteResponse{}, runtime.NewResponseError(resp) + } + return client.deleteHandleResponse(resp) +} + +// deleteCreateRequest creates the Delete request. +func (client *BlobClient) deleteCreateRequest(ctx context.Context, options *BlobClientDeleteOptions, leaseAccessConditions *LeaseAccessConditions, modifiedAccessConditions *ModifiedAccessConditions) (*policy.Request, error) { + req, err := runtime.NewRequest(ctx, http.MethodDelete, client.endpoint) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + if options != nil && options.Snapshot != nil { + reqQP.Set("snapshot", *options.Snapshot) + } + if options != nil && options.VersionID != nil { + reqQP.Set("versionid", *options.VersionID) + } + if options != nil && options.Timeout != nil { + reqQP.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + } + if options != nil && options.DeleteType != nil { + reqQP.Set("deletetype", string(*options.DeleteType)) + } + req.Raw().URL.RawQuery = reqQP.Encode() + if leaseAccessConditions != nil && leaseAccessConditions.LeaseID != nil { + req.Raw().Header["x-ms-lease-id"] = []string{*leaseAccessConditions.LeaseID} + } + if options != nil && options.DeleteSnapshots != nil { + req.Raw().Header["x-ms-delete-snapshots"] = []string{string(*options.DeleteSnapshots)} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfModifiedSince != nil { + req.Raw().Header["If-Modified-Since"] = []string{(*modifiedAccessConditions.IfModifiedSince).In(gmt).Format(time.RFC1123)} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfUnmodifiedSince != nil { + req.Raw().Header["If-Unmodified-Since"] = []string{(*modifiedAccessConditions.IfUnmodifiedSince).In(gmt).Format(time.RFC1123)} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfMatch != nil { + req.Raw().Header["If-Match"] = []string{string(*modifiedAccessConditions.IfMatch)} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfNoneMatch != nil { + req.Raw().Header["If-None-Match"] = []string{string(*modifiedAccessConditions.IfNoneMatch)} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfTags != nil { + req.Raw().Header["x-ms-if-tags"] = []string{*modifiedAccessConditions.IfTags} + } + req.Raw().Header["x-ms-version"] = []string{"2020-10-02"} + if options != nil && options.RequestID != nil { + req.Raw().Header["x-ms-client-request-id"] = []string{*options.RequestID} + } + req.Raw().Header["Accept"] = []string{"application/xml"} + return req, nil +} + +// deleteHandleResponse handles the Delete response. +func (client *BlobClient) deleteHandleResponse(resp *http.Response) (BlobClientDeleteResponse, error) { + result := BlobClientDeleteResponse{} + if val := resp.Header.Get("x-ms-client-request-id"); val != "" { + result.ClientRequestID = &val + } + if val := resp.Header.Get("x-ms-request-id"); val != "" { + result.RequestID = &val + } + if val := resp.Header.Get("x-ms-version"); val != "" { + result.Version = &val + } + if val := resp.Header.Get("Date"); val != "" { + date, err := time.Parse(time.RFC1123, val) + if err != nil { + return BlobClientDeleteResponse{}, err + } + result.Date = &date + } + return result, nil +} + +// DeleteImmutabilityPolicy - The Delete Immutability Policy operation deletes the immutability policy on the blob +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2020-10-02 +// - options - BlobClientDeleteImmutabilityPolicyOptions contains the optional parameters for the BlobClient.DeleteImmutabilityPolicy +// method. +func (client *BlobClient) DeleteImmutabilityPolicy(ctx context.Context, options *BlobClientDeleteImmutabilityPolicyOptions) (BlobClientDeleteImmutabilityPolicyResponse, error) { + req, err := client.deleteImmutabilityPolicyCreateRequest(ctx, options) + if err != nil { + return BlobClientDeleteImmutabilityPolicyResponse{}, err + } + resp, err := client.internal.Pipeline().Do(req) + if err != nil { + return BlobClientDeleteImmutabilityPolicyResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusOK) { + return BlobClientDeleteImmutabilityPolicyResponse{}, runtime.NewResponseError(resp) + } + return client.deleteImmutabilityPolicyHandleResponse(resp) +} + +// deleteImmutabilityPolicyCreateRequest creates the DeleteImmutabilityPolicy request. +func (client *BlobClient) deleteImmutabilityPolicyCreateRequest(ctx context.Context, options *BlobClientDeleteImmutabilityPolicyOptions) (*policy.Request, error) { + req, err := runtime.NewRequest(ctx, http.MethodDelete, client.endpoint) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("comp", "immutabilityPolicies") + if options != nil && options.Timeout != nil { + reqQP.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + } + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["x-ms-version"] = []string{"2020-10-02"} + if options != nil && options.RequestID != nil { + req.Raw().Header["x-ms-client-request-id"] = []string{*options.RequestID} + } + req.Raw().Header["Accept"] = []string{"application/xml"} + return req, nil +} + +// deleteImmutabilityPolicyHandleResponse handles the DeleteImmutabilityPolicy response. +func (client *BlobClient) deleteImmutabilityPolicyHandleResponse(resp *http.Response) (BlobClientDeleteImmutabilityPolicyResponse, error) { + result := BlobClientDeleteImmutabilityPolicyResponse{} + if val := resp.Header.Get("x-ms-client-request-id"); val != "" { + result.ClientRequestID = &val + } + if val := resp.Header.Get("x-ms-request-id"); val != "" { + result.RequestID = &val + } + if val := resp.Header.Get("x-ms-version"); val != "" { + result.Version = &val + } + if val := resp.Header.Get("Date"); val != "" { + date, err := time.Parse(time.RFC1123, val) + if err != nil { + return BlobClientDeleteImmutabilityPolicyResponse{}, err + } + result.Date = &date + } + return result, nil +} + +// Download - The Download operation reads or downloads a blob from the system, including its metadata and properties. You +// can also call Download to read a snapshot. +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2020-10-02 +// - options - BlobClientDownloadOptions contains the optional parameters for the BlobClient.Download method. +// - LeaseAccessConditions - LeaseAccessConditions contains a group of parameters for the ContainerClient.GetProperties method. +// - CPKInfo - CPKInfo contains a group of parameters for the BlobClient.Download method. +// - ModifiedAccessConditions - ModifiedAccessConditions contains a group of parameters for the ContainerClient.Delete method. +func (client *BlobClient) Download(ctx context.Context, options *BlobClientDownloadOptions, leaseAccessConditions *LeaseAccessConditions, cpkInfo *CPKInfo, modifiedAccessConditions *ModifiedAccessConditions) (BlobClientDownloadResponse, error) { + req, err := client.downloadCreateRequest(ctx, options, leaseAccessConditions, cpkInfo, modifiedAccessConditions) + if err != nil { + return BlobClientDownloadResponse{}, err + } + resp, err := client.internal.Pipeline().Do(req) + if err != nil { + return BlobClientDownloadResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusOK, http.StatusPartialContent, http.StatusNotModified) { + return BlobClientDownloadResponse{}, runtime.NewResponseError(resp) + } + return client.downloadHandleResponse(resp) +} + +// downloadCreateRequest creates the Download request. +func (client *BlobClient) downloadCreateRequest(ctx context.Context, options *BlobClientDownloadOptions, leaseAccessConditions *LeaseAccessConditions, cpkInfo *CPKInfo, modifiedAccessConditions *ModifiedAccessConditions) (*policy.Request, error) { + req, err := runtime.NewRequest(ctx, http.MethodGet, client.endpoint) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + if options != nil && options.Snapshot != nil { + reqQP.Set("snapshot", *options.Snapshot) + } + if options != nil && options.VersionID != nil { + reqQP.Set("versionid", *options.VersionID) + } + if options != nil && options.Timeout != nil { + reqQP.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + } + req.Raw().URL.RawQuery = reqQP.Encode() + runtime.SkipBodyDownload(req) + if options != nil && options.Range != nil { + req.Raw().Header["x-ms-range"] = []string{*options.Range} + } + if leaseAccessConditions != nil && leaseAccessConditions.LeaseID != nil { + req.Raw().Header["x-ms-lease-id"] = []string{*leaseAccessConditions.LeaseID} + } + if options != nil && options.RangeGetContentMD5 != nil { + req.Raw().Header["x-ms-range-get-content-md5"] = []string{strconv.FormatBool(*options.RangeGetContentMD5)} + } + if options != nil && options.RangeGetContentCRC64 != nil { + req.Raw().Header["x-ms-range-get-content-crc64"] = []string{strconv.FormatBool(*options.RangeGetContentCRC64)} + } + if cpkInfo != nil && cpkInfo.EncryptionKey != nil { + req.Raw().Header["x-ms-encryption-key"] = []string{*cpkInfo.EncryptionKey} + } + if cpkInfo != nil && cpkInfo.EncryptionKeySHA256 != nil { + req.Raw().Header["x-ms-encryption-key-sha256"] = []string{*cpkInfo.EncryptionKeySHA256} + } + if cpkInfo != nil && cpkInfo.EncryptionAlgorithm != nil { + req.Raw().Header["x-ms-encryption-algorithm"] = []string{string(*cpkInfo.EncryptionAlgorithm)} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfModifiedSince != nil { + req.Raw().Header["If-Modified-Since"] = []string{(*modifiedAccessConditions.IfModifiedSince).In(gmt).Format(time.RFC1123)} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfUnmodifiedSince != nil { + req.Raw().Header["If-Unmodified-Since"] = []string{(*modifiedAccessConditions.IfUnmodifiedSince).In(gmt).Format(time.RFC1123)} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfMatch != nil { + req.Raw().Header["If-Match"] = []string{string(*modifiedAccessConditions.IfMatch)} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfNoneMatch != nil { + req.Raw().Header["If-None-Match"] = []string{string(*modifiedAccessConditions.IfNoneMatch)} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfTags != nil { + req.Raw().Header["x-ms-if-tags"] = []string{*modifiedAccessConditions.IfTags} + } + req.Raw().Header["x-ms-version"] = []string{"2020-10-02"} + if options != nil && options.RequestID != nil { + req.Raw().Header["x-ms-client-request-id"] = []string{*options.RequestID} + } + req.Raw().Header["Accept"] = []string{"application/xml"} + return req, nil +} + +// downloadHandleResponse handles the Download response. +func (client *BlobClient) downloadHandleResponse(resp *http.Response) (BlobClientDownloadResponse, error) { + result := BlobClientDownloadResponse{Body: resp.Body} + if val := resp.Header.Get("Last-Modified"); val != "" { + lastModified, err := time.Parse(time.RFC1123, val) + if err != nil { + return BlobClientDownloadResponse{}, err + } + result.LastModified = &lastModified + } + for hh := range resp.Header { + if len(hh) > len("x-ms-meta-") && strings.EqualFold(hh[:len("x-ms-meta-")], "x-ms-meta-") { + if result.Metadata == nil { + result.Metadata = map[string]*string{} + } + result.Metadata[hh[len("x-ms-meta-"):]] = to.Ptr(resp.Header.Get(hh)) + } + } + if val := resp.Header.Get("x-ms-or-policy-id"); val != "" { + result.ObjectReplicationPolicyID = &val + } + for hh := range resp.Header { + if len(hh) > len("x-ms-or-") && strings.EqualFold(hh[:len("x-ms-or-")], "x-ms-or-") { + if result.Metadata == nil { + result.Metadata = map[string]*string{} + } + result.Metadata[hh[len("x-ms-or-"):]] = to.Ptr(resp.Header.Get(hh)) + } + } + if val := resp.Header.Get("Content-Length"); val != "" { + contentLength, err := strconv.ParseInt(val, 10, 64) + if err != nil { + return BlobClientDownloadResponse{}, err + } + result.ContentLength = &contentLength + } + if val := resp.Header.Get("Content-Type"); val != "" { + result.ContentType = &val + } + if val := resp.Header.Get("Content-Range"); val != "" { + result.ContentRange = &val + } + if val := resp.Header.Get("ETag"); val != "" { + result.ETag = (*azcore.ETag)(&val) + } + if val := resp.Header.Get("Content-MD5"); val != "" { + contentMD5, err := base64.StdEncoding.DecodeString(val) + if err != nil { + return BlobClientDownloadResponse{}, err + } + result.ContentMD5 = contentMD5 + } + if val := resp.Header.Get("Content-Encoding"); val != "" { + result.ContentEncoding = &val + } + if val := resp.Header.Get("Cache-Control"); val != "" { + result.CacheControl = &val + } + if val := resp.Header.Get("Content-Disposition"); val != "" { + result.ContentDisposition = &val + } + if val := resp.Header.Get("Content-Language"); val != "" { + result.ContentLanguage = &val + } + if val := resp.Header.Get("x-ms-blob-sequence-number"); val != "" { + blobSequenceNumber, err := strconv.ParseInt(val, 10, 64) + if err != nil { + return BlobClientDownloadResponse{}, err + } + result.BlobSequenceNumber = &blobSequenceNumber + } + if val := resp.Header.Get("x-ms-blob-type"); val != "" { + result.BlobType = (*BlobType)(&val) + } + if val := resp.Header.Get("x-ms-copy-completion-time"); val != "" { + copyCompletionTime, err := time.Parse(time.RFC1123, val) + if err != nil { + return BlobClientDownloadResponse{}, err + } + result.CopyCompletionTime = ©CompletionTime + } + if val := resp.Header.Get("x-ms-copy-status-description"); val != "" { + result.CopyStatusDescription = &val + } + if val := resp.Header.Get("x-ms-copy-id"); val != "" { + result.CopyID = &val + } + if val := resp.Header.Get("x-ms-copy-progress"); val != "" { + result.CopyProgress = &val + } + if val := resp.Header.Get("x-ms-copy-source"); val != "" { + result.CopySource = &val + } + if val := resp.Header.Get("x-ms-copy-status"); val != "" { + result.CopyStatus = (*CopyStatusType)(&val) + } + if val := resp.Header.Get("x-ms-lease-duration"); val != "" { + result.LeaseDuration = (*LeaseDurationType)(&val) + } + if val := resp.Header.Get("x-ms-lease-state"); val != "" { + result.LeaseState = (*LeaseStateType)(&val) + } + if val := resp.Header.Get("x-ms-lease-status"); val != "" { + result.LeaseStatus = (*LeaseStatusType)(&val) + } + if val := resp.Header.Get("x-ms-client-request-id"); val != "" { + result.ClientRequestID = &val + } + if val := resp.Header.Get("x-ms-request-id"); val != "" { + result.RequestID = &val + } + if val := resp.Header.Get("x-ms-version"); val != "" { + result.Version = &val + } + if val := resp.Header.Get("x-ms-version-id"); val != "" { + result.VersionID = &val + } + if val := resp.Header.Get("x-ms-is-current-version"); val != "" { + isCurrentVersion, err := strconv.ParseBool(val) + if err != nil { + return BlobClientDownloadResponse{}, err + } + result.IsCurrentVersion = &isCurrentVersion + } + if val := resp.Header.Get("Accept-Ranges"); val != "" { + result.AcceptRanges = &val + } + if val := resp.Header.Get("Date"); val != "" { + date, err := time.Parse(time.RFC1123, val) + if err != nil { + return BlobClientDownloadResponse{}, err + } + result.Date = &date + } + if val := resp.Header.Get("x-ms-blob-committed-block-count"); val != "" { + blobCommittedBlockCount32, err := strconv.ParseInt(val, 10, 32) + blobCommittedBlockCount := int32(blobCommittedBlockCount32) + if err != nil { + return BlobClientDownloadResponse{}, err + } + result.BlobCommittedBlockCount = &blobCommittedBlockCount + } + if val := resp.Header.Get("x-ms-server-encrypted"); val != "" { + isServerEncrypted, err := strconv.ParseBool(val) + if err != nil { + return BlobClientDownloadResponse{}, err + } + result.IsServerEncrypted = &isServerEncrypted + } + if val := resp.Header.Get("x-ms-encryption-key-sha256"); val != "" { + result.EncryptionKeySHA256 = &val + } + if val := resp.Header.Get("x-ms-encryption-scope"); val != "" { + result.EncryptionScope = &val + } + if val := resp.Header.Get("x-ms-blob-content-md5"); val != "" { + blobContentMD5, err := base64.StdEncoding.DecodeString(val) + if err != nil { + return BlobClientDownloadResponse{}, err + } + result.BlobContentMD5 = blobContentMD5 + } + if val := resp.Header.Get("x-ms-tag-count"); val != "" { + tagCount, err := strconv.ParseInt(val, 10, 64) + if err != nil { + return BlobClientDownloadResponse{}, err + } + result.TagCount = &tagCount + } + if val := resp.Header.Get("x-ms-blob-sealed"); val != "" { + isSealed, err := strconv.ParseBool(val) + if err != nil { + return BlobClientDownloadResponse{}, err + } + result.IsSealed = &isSealed + } + if val := resp.Header.Get("x-ms-last-access-time"); val != "" { + lastAccessed, err := time.Parse(time.RFC1123, val) + if err != nil { + return BlobClientDownloadResponse{}, err + } + result.LastAccessed = &lastAccessed + } + if val := resp.Header.Get("x-ms-immutability-policy-until-date"); val != "" { + immutabilityPolicyExpiresOn, err := time.Parse(time.RFC1123, val) + if err != nil { + return BlobClientDownloadResponse{}, err + } + result.ImmutabilityPolicyExpiresOn = &immutabilityPolicyExpiresOn + } + if val := resp.Header.Get("x-ms-immutability-policy-mode"); val != "" { + result.ImmutabilityPolicyMode = (*ImmutabilityPolicyMode)(&val) + } + if val := resp.Header.Get("x-ms-legal-hold"); val != "" { + legalHold, err := strconv.ParseBool(val) + if err != nil { + return BlobClientDownloadResponse{}, err + } + result.LegalHold = &legalHold + } + if val := resp.Header.Get("x-ms-content-crc64"); val != "" { + contentCRC64, err := base64.StdEncoding.DecodeString(val) + if err != nil { + return BlobClientDownloadResponse{}, err + } + result.ContentCRC64 = contentCRC64 + } + if val := resp.Header.Get("x-ms-error-code"); val != "" { + result.ErrorCode = &val + } + return result, nil +} + +// GetAccountInfo - Returns the sku name and account kind +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2020-10-02 +// - options - BlobClientGetAccountInfoOptions contains the optional parameters for the BlobClient.GetAccountInfo method. +func (client *BlobClient) GetAccountInfo(ctx context.Context, options *BlobClientGetAccountInfoOptions) (BlobClientGetAccountInfoResponse, error) { + req, err := client.getAccountInfoCreateRequest(ctx, options) + if err != nil { + return BlobClientGetAccountInfoResponse{}, err + } + resp, err := client.internal.Pipeline().Do(req) + if err != nil { + return BlobClientGetAccountInfoResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusOK) { + return BlobClientGetAccountInfoResponse{}, runtime.NewResponseError(resp) + } + return client.getAccountInfoHandleResponse(resp) +} + +// getAccountInfoCreateRequest creates the GetAccountInfo request. +func (client *BlobClient) getAccountInfoCreateRequest(ctx context.Context, options *BlobClientGetAccountInfoOptions) (*policy.Request, error) { + req, err := runtime.NewRequest(ctx, http.MethodGet, client.endpoint) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("restype", "account") + reqQP.Set("comp", "properties") + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["x-ms-version"] = []string{"2020-10-02"} + req.Raw().Header["Accept"] = []string{"application/xml"} + return req, nil +} + +// getAccountInfoHandleResponse handles the GetAccountInfo response. +func (client *BlobClient) getAccountInfoHandleResponse(resp *http.Response) (BlobClientGetAccountInfoResponse, error) { + result := BlobClientGetAccountInfoResponse{} + if val := resp.Header.Get("x-ms-client-request-id"); val != "" { + result.ClientRequestID = &val + } + if val := resp.Header.Get("x-ms-request-id"); val != "" { + result.RequestID = &val + } + if val := resp.Header.Get("x-ms-version"); val != "" { + result.Version = &val + } + if val := resp.Header.Get("Date"); val != "" { + date, err := time.Parse(time.RFC1123, val) + if err != nil { + return BlobClientGetAccountInfoResponse{}, err + } + result.Date = &date + } + if val := resp.Header.Get("x-ms-sku-name"); val != "" { + result.SKUName = (*SKUName)(&val) + } + if val := resp.Header.Get("x-ms-account-kind"); val != "" { + result.AccountKind = (*AccountKind)(&val) + } + return result, nil +} + +// GetProperties - The Get Properties operation returns all user-defined metadata, standard HTTP properties, and system properties +// for the blob. It does not return the content of the blob. +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2020-10-02 +// - options - BlobClientGetPropertiesOptions contains the optional parameters for the BlobClient.GetProperties method. +// - LeaseAccessConditions - LeaseAccessConditions contains a group of parameters for the ContainerClient.GetProperties method. +// - CPKInfo - CPKInfo contains a group of parameters for the BlobClient.Download method. +// - ModifiedAccessConditions - ModifiedAccessConditions contains a group of parameters for the ContainerClient.Delete method. +func (client *BlobClient) GetProperties(ctx context.Context, options *BlobClientGetPropertiesOptions, leaseAccessConditions *LeaseAccessConditions, cpkInfo *CPKInfo, modifiedAccessConditions *ModifiedAccessConditions) (BlobClientGetPropertiesResponse, error) { + req, err := client.getPropertiesCreateRequest(ctx, options, leaseAccessConditions, cpkInfo, modifiedAccessConditions) + if err != nil { + return BlobClientGetPropertiesResponse{}, err + } + resp, err := client.internal.Pipeline().Do(req) + if err != nil { + return BlobClientGetPropertiesResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusOK) { + return BlobClientGetPropertiesResponse{}, runtime.NewResponseError(resp) + } + return client.getPropertiesHandleResponse(resp) +} + +// getPropertiesCreateRequest creates the GetProperties request. +func (client *BlobClient) getPropertiesCreateRequest(ctx context.Context, options *BlobClientGetPropertiesOptions, leaseAccessConditions *LeaseAccessConditions, cpkInfo *CPKInfo, modifiedAccessConditions *ModifiedAccessConditions) (*policy.Request, error) { + req, err := runtime.NewRequest(ctx, http.MethodHead, client.endpoint) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + if options != nil && options.Snapshot != nil { + reqQP.Set("snapshot", *options.Snapshot) + } + if options != nil && options.VersionID != nil { + reqQP.Set("versionid", *options.VersionID) + } + if options != nil && options.Timeout != nil { + reqQP.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + } + req.Raw().URL.RawQuery = reqQP.Encode() + if leaseAccessConditions != nil && leaseAccessConditions.LeaseID != nil { + req.Raw().Header["x-ms-lease-id"] = []string{*leaseAccessConditions.LeaseID} + } + if cpkInfo != nil && cpkInfo.EncryptionKey != nil { + req.Raw().Header["x-ms-encryption-key"] = []string{*cpkInfo.EncryptionKey} + } + if cpkInfo != nil && cpkInfo.EncryptionKeySHA256 != nil { + req.Raw().Header["x-ms-encryption-key-sha256"] = []string{*cpkInfo.EncryptionKeySHA256} + } + if cpkInfo != nil && cpkInfo.EncryptionAlgorithm != nil { + req.Raw().Header["x-ms-encryption-algorithm"] = []string{string(*cpkInfo.EncryptionAlgorithm)} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfModifiedSince != nil { + req.Raw().Header["If-Modified-Since"] = []string{(*modifiedAccessConditions.IfModifiedSince).In(gmt).Format(time.RFC1123)} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfUnmodifiedSince != nil { + req.Raw().Header["If-Unmodified-Since"] = []string{(*modifiedAccessConditions.IfUnmodifiedSince).In(gmt).Format(time.RFC1123)} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfMatch != nil { + req.Raw().Header["If-Match"] = []string{string(*modifiedAccessConditions.IfMatch)} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfNoneMatch != nil { + req.Raw().Header["If-None-Match"] = []string{string(*modifiedAccessConditions.IfNoneMatch)} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfTags != nil { + req.Raw().Header["x-ms-if-tags"] = []string{*modifiedAccessConditions.IfTags} + } + req.Raw().Header["x-ms-version"] = []string{"2020-10-02"} + if options != nil && options.RequestID != nil { + req.Raw().Header["x-ms-client-request-id"] = []string{*options.RequestID} + } + req.Raw().Header["Accept"] = []string{"application/xml"} + return req, nil +} + +// getPropertiesHandleResponse handles the GetProperties response. +func (client *BlobClient) getPropertiesHandleResponse(resp *http.Response) (BlobClientGetPropertiesResponse, error) { + result := BlobClientGetPropertiesResponse{} + if val := resp.Header.Get("Last-Modified"); val != "" { + lastModified, err := time.Parse(time.RFC1123, val) + if err != nil { + return BlobClientGetPropertiesResponse{}, err + } + result.LastModified = &lastModified + } + if val := resp.Header.Get("x-ms-creation-time"); val != "" { + creationTime, err := time.Parse(time.RFC1123, val) + if err != nil { + return BlobClientGetPropertiesResponse{}, err + } + result.CreationTime = &creationTime + } + for hh := range resp.Header { + if len(hh) > len("x-ms-meta-") && strings.EqualFold(hh[:len("x-ms-meta-")], "x-ms-meta-") { + if result.Metadata == nil { + result.Metadata = map[string]*string{} + } + result.Metadata[hh[len("x-ms-meta-"):]] = to.Ptr(resp.Header.Get(hh)) + } + } + if val := resp.Header.Get("x-ms-or-policy-id"); val != "" { + result.ObjectReplicationPolicyID = &val + } + for hh := range resp.Header { + if len(hh) > len("x-ms-or-") && strings.EqualFold(hh[:len("x-ms-or-")], "x-ms-or-") { + if result.Metadata == nil { + result.Metadata = map[string]*string{} + } + result.Metadata[hh[len("x-ms-or-"):]] = to.Ptr(resp.Header.Get(hh)) + } + } + if val := resp.Header.Get("x-ms-blob-type"); val != "" { + result.BlobType = (*BlobType)(&val) + } + if val := resp.Header.Get("x-ms-copy-completion-time"); val != "" { + copyCompletionTime, err := time.Parse(time.RFC1123, val) + if err != nil { + return BlobClientGetPropertiesResponse{}, err + } + result.CopyCompletionTime = ©CompletionTime + } + if val := resp.Header.Get("x-ms-copy-status-description"); val != "" { + result.CopyStatusDescription = &val + } + if val := resp.Header.Get("x-ms-copy-id"); val != "" { + result.CopyID = &val + } + if val := resp.Header.Get("x-ms-copy-progress"); val != "" { + result.CopyProgress = &val + } + if val := resp.Header.Get("x-ms-copy-source"); val != "" { + result.CopySource = &val + } + if val := resp.Header.Get("x-ms-copy-status"); val != "" { + result.CopyStatus = (*CopyStatusType)(&val) + } + if val := resp.Header.Get("x-ms-incremental-copy"); val != "" { + isIncrementalCopy, err := strconv.ParseBool(val) + if err != nil { + return BlobClientGetPropertiesResponse{}, err + } + result.IsIncrementalCopy = &isIncrementalCopy + } + if val := resp.Header.Get("x-ms-copy-destination-snapshot"); val != "" { + result.DestinationSnapshot = &val + } + if val := resp.Header.Get("x-ms-lease-duration"); val != "" { + result.LeaseDuration = (*LeaseDurationType)(&val) + } + if val := resp.Header.Get("x-ms-lease-state"); val != "" { + result.LeaseState = (*LeaseStateType)(&val) + } + if val := resp.Header.Get("x-ms-lease-status"); val != "" { + result.LeaseStatus = (*LeaseStatusType)(&val) + } + if val := resp.Header.Get("Content-Length"); val != "" { + contentLength, err := strconv.ParseInt(val, 10, 64) + if err != nil { + return BlobClientGetPropertiesResponse{}, err + } + result.ContentLength = &contentLength + } + if val := resp.Header.Get("Content-Type"); val != "" { + result.ContentType = &val + } + if val := resp.Header.Get("ETag"); val != "" { + result.ETag = (*azcore.ETag)(&val) + } + if val := resp.Header.Get("Content-MD5"); val != "" { + contentMD5, err := base64.StdEncoding.DecodeString(val) + if err != nil { + return BlobClientGetPropertiesResponse{}, err + } + result.ContentMD5 = contentMD5 + } + if val := resp.Header.Get("Content-Encoding"); val != "" { + result.ContentEncoding = &val + } + if val := resp.Header.Get("Content-Disposition"); val != "" { + result.ContentDisposition = &val + } + if val := resp.Header.Get("Content-Language"); val != "" { + result.ContentLanguage = &val + } + if val := resp.Header.Get("Cache-Control"); val != "" { + result.CacheControl = &val + } + if val := resp.Header.Get("x-ms-blob-sequence-number"); val != "" { + blobSequenceNumber, err := strconv.ParseInt(val, 10, 64) + if err != nil { + return BlobClientGetPropertiesResponse{}, err + } + result.BlobSequenceNumber = &blobSequenceNumber + } + if val := resp.Header.Get("x-ms-client-request-id"); val != "" { + result.ClientRequestID = &val + } + if val := resp.Header.Get("x-ms-request-id"); val != "" { + result.RequestID = &val + } + if val := resp.Header.Get("x-ms-version"); val != "" { + result.Version = &val + } + if val := resp.Header.Get("Date"); val != "" { + date, err := time.Parse(time.RFC1123, val) + if err != nil { + return BlobClientGetPropertiesResponse{}, err + } + result.Date = &date + } + if val := resp.Header.Get("Accept-Ranges"); val != "" { + result.AcceptRanges = &val + } + if val := resp.Header.Get("x-ms-blob-committed-block-count"); val != "" { + blobCommittedBlockCount32, err := strconv.ParseInt(val, 10, 32) + blobCommittedBlockCount := int32(blobCommittedBlockCount32) + if err != nil { + return BlobClientGetPropertiesResponse{}, err + } + result.BlobCommittedBlockCount = &blobCommittedBlockCount + } + if val := resp.Header.Get("x-ms-server-encrypted"); val != "" { + isServerEncrypted, err := strconv.ParseBool(val) + if err != nil { + return BlobClientGetPropertiesResponse{}, err + } + result.IsServerEncrypted = &isServerEncrypted + } + if val := resp.Header.Get("x-ms-encryption-key-sha256"); val != "" { + result.EncryptionKeySHA256 = &val + } + if val := resp.Header.Get("x-ms-encryption-scope"); val != "" { + result.EncryptionScope = &val + } + if val := resp.Header.Get("x-ms-access-tier"); val != "" { + result.AccessTier = &val + } + if val := resp.Header.Get("x-ms-access-tier-inferred"); val != "" { + accessTierInferred, err := strconv.ParseBool(val) + if err != nil { + return BlobClientGetPropertiesResponse{}, err + } + result.AccessTierInferred = &accessTierInferred + } + if val := resp.Header.Get("x-ms-archive-status"); val != "" { + result.ArchiveStatus = &val + } + if val := resp.Header.Get("x-ms-access-tier-change-time"); val != "" { + accessTierChangeTime, err := time.Parse(time.RFC1123, val) + if err != nil { + return BlobClientGetPropertiesResponse{}, err + } + result.AccessTierChangeTime = &accessTierChangeTime + } + if val := resp.Header.Get("x-ms-version-id"); val != "" { + result.VersionID = &val + } + if val := resp.Header.Get("x-ms-is-current-version"); val != "" { + isCurrentVersion, err := strconv.ParseBool(val) + if err != nil { + return BlobClientGetPropertiesResponse{}, err + } + result.IsCurrentVersion = &isCurrentVersion + } + if val := resp.Header.Get("x-ms-tag-count"); val != "" { + tagCount, err := strconv.ParseInt(val, 10, 64) + if err != nil { + return BlobClientGetPropertiesResponse{}, err + } + result.TagCount = &tagCount + } + if val := resp.Header.Get("x-ms-expiry-time"); val != "" { + expiresOn, err := time.Parse(time.RFC1123, val) + if err != nil { + return BlobClientGetPropertiesResponse{}, err + } + result.ExpiresOn = &expiresOn + } + if val := resp.Header.Get("x-ms-blob-sealed"); val != "" { + isSealed, err := strconv.ParseBool(val) + if err != nil { + return BlobClientGetPropertiesResponse{}, err + } + result.IsSealed = &isSealed + } + if val := resp.Header.Get("x-ms-rehydrate-priority"); val != "" { + result.RehydratePriority = &val + } + if val := resp.Header.Get("x-ms-last-access-time"); val != "" { + lastAccessed, err := time.Parse(time.RFC1123, val) + if err != nil { + return BlobClientGetPropertiesResponse{}, err + } + result.LastAccessed = &lastAccessed + } + if val := resp.Header.Get("x-ms-immutability-policy-until-date"); val != "" { + immutabilityPolicyExpiresOn, err := time.Parse(time.RFC1123, val) + if err != nil { + return BlobClientGetPropertiesResponse{}, err + } + result.ImmutabilityPolicyExpiresOn = &immutabilityPolicyExpiresOn + } + if val := resp.Header.Get("x-ms-immutability-policy-mode"); val != "" { + result.ImmutabilityPolicyMode = (*ImmutabilityPolicyMode)(&val) + } + if val := resp.Header.Get("x-ms-legal-hold"); val != "" { + legalHold, err := strconv.ParseBool(val) + if err != nil { + return BlobClientGetPropertiesResponse{}, err + } + result.LegalHold = &legalHold + } + return result, nil +} + +// GetTags - The Get Tags operation enables users to get the tags associated with a blob. +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2020-10-02 +// - options - BlobClientGetTagsOptions contains the optional parameters for the BlobClient.GetTags method. +// - ModifiedAccessConditions - ModifiedAccessConditions contains a group of parameters for the ContainerClient.Delete method. +// - LeaseAccessConditions - LeaseAccessConditions contains a group of parameters for the ContainerClient.GetProperties method. +func (client *BlobClient) GetTags(ctx context.Context, options *BlobClientGetTagsOptions, modifiedAccessConditions *ModifiedAccessConditions, leaseAccessConditions *LeaseAccessConditions) (BlobClientGetTagsResponse, error) { + req, err := client.getTagsCreateRequest(ctx, options, modifiedAccessConditions, leaseAccessConditions) + if err != nil { + return BlobClientGetTagsResponse{}, err + } + resp, err := client.internal.Pipeline().Do(req) + if err != nil { + return BlobClientGetTagsResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusOK) { + return BlobClientGetTagsResponse{}, runtime.NewResponseError(resp) + } + return client.getTagsHandleResponse(resp) +} + +// getTagsCreateRequest creates the GetTags request. +func (client *BlobClient) getTagsCreateRequest(ctx context.Context, options *BlobClientGetTagsOptions, modifiedAccessConditions *ModifiedAccessConditions, leaseAccessConditions *LeaseAccessConditions) (*policy.Request, error) { + req, err := runtime.NewRequest(ctx, http.MethodGet, client.endpoint) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("comp", "tags") + if options != nil && options.Timeout != nil { + reqQP.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + } + if options != nil && options.Snapshot != nil { + reqQP.Set("snapshot", *options.Snapshot) + } + if options != nil && options.VersionID != nil { + reqQP.Set("versionid", *options.VersionID) + } + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["x-ms-version"] = []string{"2020-10-02"} + if options != nil && options.RequestID != nil { + req.Raw().Header["x-ms-client-request-id"] = []string{*options.RequestID} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfTags != nil { + req.Raw().Header["x-ms-if-tags"] = []string{*modifiedAccessConditions.IfTags} + } + if leaseAccessConditions != nil && leaseAccessConditions.LeaseID != nil { + req.Raw().Header["x-ms-lease-id"] = []string{*leaseAccessConditions.LeaseID} + } + req.Raw().Header["Accept"] = []string{"application/xml"} + return req, nil +} + +// getTagsHandleResponse handles the GetTags response. +func (client *BlobClient) getTagsHandleResponse(resp *http.Response) (BlobClientGetTagsResponse, error) { + result := BlobClientGetTagsResponse{} + if val := resp.Header.Get("x-ms-client-request-id"); val != "" { + result.ClientRequestID = &val + } + if val := resp.Header.Get("x-ms-request-id"); val != "" { + result.RequestID = &val + } + if val := resp.Header.Get("x-ms-version"); val != "" { + result.Version = &val + } + if val := resp.Header.Get("Date"); val != "" { + date, err := time.Parse(time.RFC1123, val) + if err != nil { + return BlobClientGetTagsResponse{}, err + } + result.Date = &date + } + if err := runtime.UnmarshalAsXML(resp, &result.BlobTags); err != nil { + return BlobClientGetTagsResponse{}, err + } + return result, nil +} + +// Query - The Query operation enables users to select/project on blob data by providing simple query expressions. +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2020-10-02 +// - options - BlobClientQueryOptions contains the optional parameters for the BlobClient.Query method. +// - LeaseAccessConditions - LeaseAccessConditions contains a group of parameters for the ContainerClient.GetProperties method. +// - CPKInfo - CPKInfo contains a group of parameters for the BlobClient.Download method. +// - ModifiedAccessConditions - ModifiedAccessConditions contains a group of parameters for the ContainerClient.Delete method. +func (client *BlobClient) Query(ctx context.Context, options *BlobClientQueryOptions, leaseAccessConditions *LeaseAccessConditions, cpkInfo *CPKInfo, modifiedAccessConditions *ModifiedAccessConditions) (BlobClientQueryResponse, error) { + req, err := client.queryCreateRequest(ctx, options, leaseAccessConditions, cpkInfo, modifiedAccessConditions) + if err != nil { + return BlobClientQueryResponse{}, err + } + resp, err := client.internal.Pipeline().Do(req) + if err != nil { + return BlobClientQueryResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusOK, http.StatusPartialContent) { + return BlobClientQueryResponse{}, runtime.NewResponseError(resp) + } + return client.queryHandleResponse(resp) +} + +// queryCreateRequest creates the Query request. +func (client *BlobClient) queryCreateRequest(ctx context.Context, options *BlobClientQueryOptions, leaseAccessConditions *LeaseAccessConditions, cpkInfo *CPKInfo, modifiedAccessConditions *ModifiedAccessConditions) (*policy.Request, error) { + req, err := runtime.NewRequest(ctx, http.MethodPost, client.endpoint) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("comp", "query") + if options != nil && options.Snapshot != nil { + reqQP.Set("snapshot", *options.Snapshot) + } + if options != nil && options.Timeout != nil { + reqQP.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + } + req.Raw().URL.RawQuery = reqQP.Encode() + runtime.SkipBodyDownload(req) + if leaseAccessConditions != nil && leaseAccessConditions.LeaseID != nil { + req.Raw().Header["x-ms-lease-id"] = []string{*leaseAccessConditions.LeaseID} + } + if cpkInfo != nil && cpkInfo.EncryptionKey != nil { + req.Raw().Header["x-ms-encryption-key"] = []string{*cpkInfo.EncryptionKey} + } + if cpkInfo != nil && cpkInfo.EncryptionKeySHA256 != nil { + req.Raw().Header["x-ms-encryption-key-sha256"] = []string{*cpkInfo.EncryptionKeySHA256} + } + if cpkInfo != nil && cpkInfo.EncryptionAlgorithm != nil { + req.Raw().Header["x-ms-encryption-algorithm"] = []string{string(*cpkInfo.EncryptionAlgorithm)} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfModifiedSince != nil { + req.Raw().Header["If-Modified-Since"] = []string{(*modifiedAccessConditions.IfModifiedSince).In(gmt).Format(time.RFC1123)} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfUnmodifiedSince != nil { + req.Raw().Header["If-Unmodified-Since"] = []string{(*modifiedAccessConditions.IfUnmodifiedSince).In(gmt).Format(time.RFC1123)} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfMatch != nil { + req.Raw().Header["If-Match"] = []string{string(*modifiedAccessConditions.IfMatch)} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfNoneMatch != nil { + req.Raw().Header["If-None-Match"] = []string{string(*modifiedAccessConditions.IfNoneMatch)} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfTags != nil { + req.Raw().Header["x-ms-if-tags"] = []string{*modifiedAccessConditions.IfTags} + } + req.Raw().Header["x-ms-version"] = []string{"2020-10-02"} + if options != nil && options.RequestID != nil { + req.Raw().Header["x-ms-client-request-id"] = []string{*options.RequestID} + } + req.Raw().Header["Accept"] = []string{"application/xml"} + if options != nil && options.QueryRequest != nil { + if err := runtime.MarshalAsXML(req, *options.QueryRequest); err != nil { + return nil, err + } + return req, nil + } + return req, nil +} + +// queryHandleResponse handles the Query response. +func (client *BlobClient) queryHandleResponse(resp *http.Response) (BlobClientQueryResponse, error) { + result := BlobClientQueryResponse{Body: resp.Body} + if val := resp.Header.Get("Last-Modified"); val != "" { + lastModified, err := time.Parse(time.RFC1123, val) + if err != nil { + return BlobClientQueryResponse{}, err + } + result.LastModified = &lastModified + } + for hh := range resp.Header { + if len(hh) > len("x-ms-meta-") && strings.EqualFold(hh[:len("x-ms-meta-")], "x-ms-meta-") { + if result.Metadata == nil { + result.Metadata = map[string]*string{} + } + result.Metadata[hh[len("x-ms-meta-"):]] = to.Ptr(resp.Header.Get(hh)) + } + } + if val := resp.Header.Get("Content-Length"); val != "" { + contentLength, err := strconv.ParseInt(val, 10, 64) + if err != nil { + return BlobClientQueryResponse{}, err + } + result.ContentLength = &contentLength + } + if val := resp.Header.Get("Content-Type"); val != "" { + result.ContentType = &val + } + if val := resp.Header.Get("Content-Range"); val != "" { + result.ContentRange = &val + } + if val := resp.Header.Get("ETag"); val != "" { + result.ETag = (*azcore.ETag)(&val) + } + if val := resp.Header.Get("Content-MD5"); val != "" { + contentMD5, err := base64.StdEncoding.DecodeString(val) + if err != nil { + return BlobClientQueryResponse{}, err + } + result.ContentMD5 = contentMD5 + } + if val := resp.Header.Get("Content-Encoding"); val != "" { + result.ContentEncoding = &val + } + if val := resp.Header.Get("Cache-Control"); val != "" { + result.CacheControl = &val + } + if val := resp.Header.Get("Content-Disposition"); val != "" { + result.ContentDisposition = &val + } + if val := resp.Header.Get("Content-Language"); val != "" { + result.ContentLanguage = &val + } + if val := resp.Header.Get("x-ms-blob-sequence-number"); val != "" { + blobSequenceNumber, err := strconv.ParseInt(val, 10, 64) + if err != nil { + return BlobClientQueryResponse{}, err + } + result.BlobSequenceNumber = &blobSequenceNumber + } + if val := resp.Header.Get("x-ms-blob-type"); val != "" { + result.BlobType = (*BlobType)(&val) + } + if val := resp.Header.Get("x-ms-copy-completion-time"); val != "" { + copyCompletionTime, err := time.Parse(time.RFC1123, val) + if err != nil { + return BlobClientQueryResponse{}, err + } + result.CopyCompletionTime = ©CompletionTime + } + if val := resp.Header.Get("x-ms-copy-status-description"); val != "" { + result.CopyStatusDescription = &val + } + if val := resp.Header.Get("x-ms-copy-id"); val != "" { + result.CopyID = &val + } + if val := resp.Header.Get("x-ms-copy-progress"); val != "" { + result.CopyProgress = &val + } + if val := resp.Header.Get("x-ms-copy-source"); val != "" { + result.CopySource = &val + } + if val := resp.Header.Get("x-ms-copy-status"); val != "" { + result.CopyStatus = (*CopyStatusType)(&val) + } + if val := resp.Header.Get("x-ms-lease-duration"); val != "" { + result.LeaseDuration = (*LeaseDurationType)(&val) + } + if val := resp.Header.Get("x-ms-lease-state"); val != "" { + result.LeaseState = (*LeaseStateType)(&val) + } + if val := resp.Header.Get("x-ms-lease-status"); val != "" { + result.LeaseStatus = (*LeaseStatusType)(&val) + } + if val := resp.Header.Get("x-ms-client-request-id"); val != "" { + result.ClientRequestID = &val + } + if val := resp.Header.Get("x-ms-request-id"); val != "" { + result.RequestID = &val + } + if val := resp.Header.Get("x-ms-version"); val != "" { + result.Version = &val + } + if val := resp.Header.Get("Accept-Ranges"); val != "" { + result.AcceptRanges = &val + } + if val := resp.Header.Get("Date"); val != "" { + date, err := time.Parse(time.RFC1123, val) + if err != nil { + return BlobClientQueryResponse{}, err + } + result.Date = &date + } + if val := resp.Header.Get("x-ms-blob-committed-block-count"); val != "" { + blobCommittedBlockCount32, err := strconv.ParseInt(val, 10, 32) + blobCommittedBlockCount := int32(blobCommittedBlockCount32) + if err != nil { + return BlobClientQueryResponse{}, err + } + result.BlobCommittedBlockCount = &blobCommittedBlockCount + } + if val := resp.Header.Get("x-ms-server-encrypted"); val != "" { + isServerEncrypted, err := strconv.ParseBool(val) + if err != nil { + return BlobClientQueryResponse{}, err + } + result.IsServerEncrypted = &isServerEncrypted + } + if val := resp.Header.Get("x-ms-encryption-key-sha256"); val != "" { + result.EncryptionKeySHA256 = &val + } + if val := resp.Header.Get("x-ms-encryption-scope"); val != "" { + result.EncryptionScope = &val + } + if val := resp.Header.Get("x-ms-blob-content-md5"); val != "" { + blobContentMD5, err := base64.StdEncoding.DecodeString(val) + if err != nil { + return BlobClientQueryResponse{}, err + } + result.BlobContentMD5 = blobContentMD5 + } + if val := resp.Header.Get("x-ms-content-crc64"); val != "" { + contentCRC64, err := base64.StdEncoding.DecodeString(val) + if err != nil { + return BlobClientQueryResponse{}, err + } + result.ContentCRC64 = contentCRC64 + } + return result, nil +} + +// ReleaseLease - [Update] The Lease Blob operation establishes and manages a lock on a blob for write and delete operations +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2020-10-02 +// - leaseID - Specifies the current lease ID on the resource. +// - options - BlobClientReleaseLeaseOptions contains the optional parameters for the BlobClient.ReleaseLease method. +// - ModifiedAccessConditions - ModifiedAccessConditions contains a group of parameters for the ContainerClient.Delete method. +func (client *BlobClient) ReleaseLease(ctx context.Context, leaseID string, options *BlobClientReleaseLeaseOptions, modifiedAccessConditions *ModifiedAccessConditions) (BlobClientReleaseLeaseResponse, error) { + req, err := client.releaseLeaseCreateRequest(ctx, leaseID, options, modifiedAccessConditions) + if err != nil { + return BlobClientReleaseLeaseResponse{}, err + } + resp, err := client.internal.Pipeline().Do(req) + if err != nil { + return BlobClientReleaseLeaseResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusOK) { + return BlobClientReleaseLeaseResponse{}, runtime.NewResponseError(resp) + } + return client.releaseLeaseHandleResponse(resp) +} + +// releaseLeaseCreateRequest creates the ReleaseLease request. +func (client *BlobClient) releaseLeaseCreateRequest(ctx context.Context, leaseID string, options *BlobClientReleaseLeaseOptions, modifiedAccessConditions *ModifiedAccessConditions) (*policy.Request, error) { + req, err := runtime.NewRequest(ctx, http.MethodPut, client.endpoint) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("comp", "lease") + if options != nil && options.Timeout != nil { + reqQP.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + } + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["x-ms-lease-action"] = []string{"release"} + req.Raw().Header["x-ms-lease-id"] = []string{leaseID} + if modifiedAccessConditions != nil && modifiedAccessConditions.IfModifiedSince != nil { + req.Raw().Header["If-Modified-Since"] = []string{(*modifiedAccessConditions.IfModifiedSince).In(gmt).Format(time.RFC1123)} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfUnmodifiedSince != nil { + req.Raw().Header["If-Unmodified-Since"] = []string{(*modifiedAccessConditions.IfUnmodifiedSince).In(gmt).Format(time.RFC1123)} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfMatch != nil { + req.Raw().Header["If-Match"] = []string{string(*modifiedAccessConditions.IfMatch)} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfNoneMatch != nil { + req.Raw().Header["If-None-Match"] = []string{string(*modifiedAccessConditions.IfNoneMatch)} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfTags != nil { + req.Raw().Header["x-ms-if-tags"] = []string{*modifiedAccessConditions.IfTags} + } + req.Raw().Header["x-ms-version"] = []string{"2020-10-02"} + if options != nil && options.RequestID != nil { + req.Raw().Header["x-ms-client-request-id"] = []string{*options.RequestID} + } + req.Raw().Header["Accept"] = []string{"application/xml"} + return req, nil +} + +// releaseLeaseHandleResponse handles the ReleaseLease response. +func (client *BlobClient) releaseLeaseHandleResponse(resp *http.Response) (BlobClientReleaseLeaseResponse, error) { + result := BlobClientReleaseLeaseResponse{} + if val := resp.Header.Get("ETag"); val != "" { + result.ETag = (*azcore.ETag)(&val) + } + if val := resp.Header.Get("Last-Modified"); val != "" { + lastModified, err := time.Parse(time.RFC1123, val) + if err != nil { + return BlobClientReleaseLeaseResponse{}, err + } + result.LastModified = &lastModified + } + if val := resp.Header.Get("x-ms-client-request-id"); val != "" { + result.ClientRequestID = &val + } + if val := resp.Header.Get("x-ms-request-id"); val != "" { + result.RequestID = &val + } + if val := resp.Header.Get("x-ms-version"); val != "" { + result.Version = &val + } + if val := resp.Header.Get("Date"); val != "" { + date, err := time.Parse(time.RFC1123, val) + if err != nil { + return BlobClientReleaseLeaseResponse{}, err + } + result.Date = &date + } + return result, nil +} + +// RenewLease - [Update] The Lease Blob operation establishes and manages a lock on a blob for write and delete operations +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2020-10-02 +// - leaseID - Specifies the current lease ID on the resource. +// - options - BlobClientRenewLeaseOptions contains the optional parameters for the BlobClient.RenewLease method. +// - ModifiedAccessConditions - ModifiedAccessConditions contains a group of parameters for the ContainerClient.Delete method. +func (client *BlobClient) RenewLease(ctx context.Context, leaseID string, options *BlobClientRenewLeaseOptions, modifiedAccessConditions *ModifiedAccessConditions) (BlobClientRenewLeaseResponse, error) { + req, err := client.renewLeaseCreateRequest(ctx, leaseID, options, modifiedAccessConditions) + if err != nil { + return BlobClientRenewLeaseResponse{}, err + } + resp, err := client.internal.Pipeline().Do(req) + if err != nil { + return BlobClientRenewLeaseResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusOK) { + return BlobClientRenewLeaseResponse{}, runtime.NewResponseError(resp) + } + return client.renewLeaseHandleResponse(resp) +} + +// renewLeaseCreateRequest creates the RenewLease request. +func (client *BlobClient) renewLeaseCreateRequest(ctx context.Context, leaseID string, options *BlobClientRenewLeaseOptions, modifiedAccessConditions *ModifiedAccessConditions) (*policy.Request, error) { + req, err := runtime.NewRequest(ctx, http.MethodPut, client.endpoint) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("comp", "lease") + if options != nil && options.Timeout != nil { + reqQP.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + } + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["x-ms-lease-action"] = []string{"renew"} + req.Raw().Header["x-ms-lease-id"] = []string{leaseID} + if modifiedAccessConditions != nil && modifiedAccessConditions.IfModifiedSince != nil { + req.Raw().Header["If-Modified-Since"] = []string{(*modifiedAccessConditions.IfModifiedSince).In(gmt).Format(time.RFC1123)} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfUnmodifiedSince != nil { + req.Raw().Header["If-Unmodified-Since"] = []string{(*modifiedAccessConditions.IfUnmodifiedSince).In(gmt).Format(time.RFC1123)} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfMatch != nil { + req.Raw().Header["If-Match"] = []string{string(*modifiedAccessConditions.IfMatch)} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfNoneMatch != nil { + req.Raw().Header["If-None-Match"] = []string{string(*modifiedAccessConditions.IfNoneMatch)} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfTags != nil { + req.Raw().Header["x-ms-if-tags"] = []string{*modifiedAccessConditions.IfTags} + } + req.Raw().Header["x-ms-version"] = []string{"2020-10-02"} + if options != nil && options.RequestID != nil { + req.Raw().Header["x-ms-client-request-id"] = []string{*options.RequestID} + } + req.Raw().Header["Accept"] = []string{"application/xml"} + return req, nil +} + +// renewLeaseHandleResponse handles the RenewLease response. +func (client *BlobClient) renewLeaseHandleResponse(resp *http.Response) (BlobClientRenewLeaseResponse, error) { + result := BlobClientRenewLeaseResponse{} + if val := resp.Header.Get("ETag"); val != "" { + result.ETag = (*azcore.ETag)(&val) + } + if val := resp.Header.Get("Last-Modified"); val != "" { + lastModified, err := time.Parse(time.RFC1123, val) + if err != nil { + return BlobClientRenewLeaseResponse{}, err + } + result.LastModified = &lastModified + } + if val := resp.Header.Get("x-ms-lease-id"); val != "" { + result.LeaseID = &val + } + if val := resp.Header.Get("x-ms-client-request-id"); val != "" { + result.ClientRequestID = &val + } + if val := resp.Header.Get("x-ms-request-id"); val != "" { + result.RequestID = &val + } + if val := resp.Header.Get("x-ms-version"); val != "" { + result.Version = &val + } + if val := resp.Header.Get("Date"); val != "" { + date, err := time.Parse(time.RFC1123, val) + if err != nil { + return BlobClientRenewLeaseResponse{}, err + } + result.Date = &date + } + return result, nil +} + +// SetExpiry - Sets the time a blob will expire and be deleted. +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2020-10-02 +// - expiryOptions - Required. Indicates mode of the expiry time +// - options - BlobClientSetExpiryOptions contains the optional parameters for the BlobClient.SetExpiry method. +func (client *BlobClient) SetExpiry(ctx context.Context, expiryOptions ExpiryOptions, options *BlobClientSetExpiryOptions) (BlobClientSetExpiryResponse, error) { + req, err := client.setExpiryCreateRequest(ctx, expiryOptions, options) + if err != nil { + return BlobClientSetExpiryResponse{}, err + } + resp, err := client.internal.Pipeline().Do(req) + if err != nil { + return BlobClientSetExpiryResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusOK) { + return BlobClientSetExpiryResponse{}, runtime.NewResponseError(resp) + } + return client.setExpiryHandleResponse(resp) +} + +// setExpiryCreateRequest creates the SetExpiry request. +func (client *BlobClient) setExpiryCreateRequest(ctx context.Context, expiryOptions ExpiryOptions, options *BlobClientSetExpiryOptions) (*policy.Request, error) { + req, err := runtime.NewRequest(ctx, http.MethodPut, client.endpoint) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("comp", "expiry") + if options != nil && options.Timeout != nil { + reqQP.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + } + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["x-ms-version"] = []string{"2020-10-02"} + if options != nil && options.RequestID != nil { + req.Raw().Header["x-ms-client-request-id"] = []string{*options.RequestID} + } + req.Raw().Header["x-ms-expiry-option"] = []string{string(expiryOptions)} + if options != nil && options.ExpiresOn != nil { + req.Raw().Header["x-ms-expiry-time"] = []string{*options.ExpiresOn} + } + req.Raw().Header["Accept"] = []string{"application/xml"} + return req, nil +} + +// setExpiryHandleResponse handles the SetExpiry response. +func (client *BlobClient) setExpiryHandleResponse(resp *http.Response) (BlobClientSetExpiryResponse, error) { + result := BlobClientSetExpiryResponse{} + if val := resp.Header.Get("ETag"); val != "" { + result.ETag = (*azcore.ETag)(&val) + } + if val := resp.Header.Get("Last-Modified"); val != "" { + lastModified, err := time.Parse(time.RFC1123, val) + if err != nil { + return BlobClientSetExpiryResponse{}, err + } + result.LastModified = &lastModified + } + if val := resp.Header.Get("x-ms-client-request-id"); val != "" { + result.ClientRequestID = &val + } + if val := resp.Header.Get("x-ms-request-id"); val != "" { + result.RequestID = &val + } + if val := resp.Header.Get("x-ms-version"); val != "" { + result.Version = &val + } + if val := resp.Header.Get("Date"); val != "" { + date, err := time.Parse(time.RFC1123, val) + if err != nil { + return BlobClientSetExpiryResponse{}, err + } + result.Date = &date + } + return result, nil +} + +// SetHTTPHeaders - The Set HTTP Headers operation sets system properties on the blob +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2020-10-02 +// - options - BlobClientSetHTTPHeadersOptions contains the optional parameters for the BlobClient.SetHTTPHeaders method. +// - BlobHTTPHeaders - BlobHTTPHeaders contains a group of parameters for the BlobClient.SetHTTPHeaders method. +// - LeaseAccessConditions - LeaseAccessConditions contains a group of parameters for the ContainerClient.GetProperties method. +// - ModifiedAccessConditions - ModifiedAccessConditions contains a group of parameters for the ContainerClient.Delete method. +func (client *BlobClient) SetHTTPHeaders(ctx context.Context, options *BlobClientSetHTTPHeadersOptions, blobHTTPHeaders *BlobHTTPHeaders, leaseAccessConditions *LeaseAccessConditions, modifiedAccessConditions *ModifiedAccessConditions) (BlobClientSetHTTPHeadersResponse, error) { + req, err := client.setHTTPHeadersCreateRequest(ctx, options, blobHTTPHeaders, leaseAccessConditions, modifiedAccessConditions) + if err != nil { + return BlobClientSetHTTPHeadersResponse{}, err + } + resp, err := client.internal.Pipeline().Do(req) + if err != nil { + return BlobClientSetHTTPHeadersResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusOK) { + return BlobClientSetHTTPHeadersResponse{}, runtime.NewResponseError(resp) + } + return client.setHTTPHeadersHandleResponse(resp) +} + +// setHTTPHeadersCreateRequest creates the SetHTTPHeaders request. +func (client *BlobClient) setHTTPHeadersCreateRequest(ctx context.Context, options *BlobClientSetHTTPHeadersOptions, blobHTTPHeaders *BlobHTTPHeaders, leaseAccessConditions *LeaseAccessConditions, modifiedAccessConditions *ModifiedAccessConditions) (*policy.Request, error) { + req, err := runtime.NewRequest(ctx, http.MethodPut, client.endpoint) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("comp", "properties") + if options != nil && options.Timeout != nil { + reqQP.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + } + req.Raw().URL.RawQuery = reqQP.Encode() + if blobHTTPHeaders != nil && blobHTTPHeaders.BlobCacheControl != nil { + req.Raw().Header["x-ms-blob-cache-control"] = []string{*blobHTTPHeaders.BlobCacheControl} + } + if blobHTTPHeaders != nil && blobHTTPHeaders.BlobContentType != nil { + req.Raw().Header["x-ms-blob-content-type"] = []string{*blobHTTPHeaders.BlobContentType} + } + if blobHTTPHeaders != nil && blobHTTPHeaders.BlobContentMD5 != nil { + req.Raw().Header["x-ms-blob-content-md5"] = []string{base64.StdEncoding.EncodeToString(blobHTTPHeaders.BlobContentMD5)} + } + if blobHTTPHeaders != nil && blobHTTPHeaders.BlobContentEncoding != nil { + req.Raw().Header["x-ms-blob-content-encoding"] = []string{*blobHTTPHeaders.BlobContentEncoding} + } + if blobHTTPHeaders != nil && blobHTTPHeaders.BlobContentLanguage != nil { + req.Raw().Header["x-ms-blob-content-language"] = []string{*blobHTTPHeaders.BlobContentLanguage} + } + if leaseAccessConditions != nil && leaseAccessConditions.LeaseID != nil { + req.Raw().Header["x-ms-lease-id"] = []string{*leaseAccessConditions.LeaseID} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfModifiedSince != nil { + req.Raw().Header["If-Modified-Since"] = []string{(*modifiedAccessConditions.IfModifiedSince).In(gmt).Format(time.RFC1123)} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfUnmodifiedSince != nil { + req.Raw().Header["If-Unmodified-Since"] = []string{(*modifiedAccessConditions.IfUnmodifiedSince).In(gmt).Format(time.RFC1123)} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfMatch != nil { + req.Raw().Header["If-Match"] = []string{string(*modifiedAccessConditions.IfMatch)} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfNoneMatch != nil { + req.Raw().Header["If-None-Match"] = []string{string(*modifiedAccessConditions.IfNoneMatch)} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfTags != nil { + req.Raw().Header["x-ms-if-tags"] = []string{*modifiedAccessConditions.IfTags} + } + if blobHTTPHeaders != nil && blobHTTPHeaders.BlobContentDisposition != nil { + req.Raw().Header["x-ms-blob-content-disposition"] = []string{*blobHTTPHeaders.BlobContentDisposition} + } + req.Raw().Header["x-ms-version"] = []string{"2020-10-02"} + if options != nil && options.RequestID != nil { + req.Raw().Header["x-ms-client-request-id"] = []string{*options.RequestID} + } + req.Raw().Header["Accept"] = []string{"application/xml"} + return req, nil +} + +// setHTTPHeadersHandleResponse handles the SetHTTPHeaders response. +func (client *BlobClient) setHTTPHeadersHandleResponse(resp *http.Response) (BlobClientSetHTTPHeadersResponse, error) { + result := BlobClientSetHTTPHeadersResponse{} + if val := resp.Header.Get("ETag"); val != "" { + result.ETag = (*azcore.ETag)(&val) + } + if val := resp.Header.Get("Last-Modified"); val != "" { + lastModified, err := time.Parse(time.RFC1123, val) + if err != nil { + return BlobClientSetHTTPHeadersResponse{}, err + } + result.LastModified = &lastModified + } + if val := resp.Header.Get("x-ms-blob-sequence-number"); val != "" { + blobSequenceNumber, err := strconv.ParseInt(val, 10, 64) + if err != nil { + return BlobClientSetHTTPHeadersResponse{}, err + } + result.BlobSequenceNumber = &blobSequenceNumber + } + if val := resp.Header.Get("x-ms-client-request-id"); val != "" { + result.ClientRequestID = &val + } + if val := resp.Header.Get("x-ms-request-id"); val != "" { + result.RequestID = &val + } + if val := resp.Header.Get("x-ms-version"); val != "" { + result.Version = &val + } + if val := resp.Header.Get("Date"); val != "" { + date, err := time.Parse(time.RFC1123, val) + if err != nil { + return BlobClientSetHTTPHeadersResponse{}, err + } + result.Date = &date + } + return result, nil +} + +// SetImmutabilityPolicy - The Set Immutability Policy operation sets the immutability policy on the blob +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2020-10-02 +// - options - BlobClientSetImmutabilityPolicyOptions contains the optional parameters for the BlobClient.SetImmutabilityPolicy +// method. +// - ModifiedAccessConditions - ModifiedAccessConditions contains a group of parameters for the ContainerClient.Delete method. +func (client *BlobClient) SetImmutabilityPolicy(ctx context.Context, options *BlobClientSetImmutabilityPolicyOptions, modifiedAccessConditions *ModifiedAccessConditions) (BlobClientSetImmutabilityPolicyResponse, error) { + req, err := client.setImmutabilityPolicyCreateRequest(ctx, options, modifiedAccessConditions) + if err != nil { + return BlobClientSetImmutabilityPolicyResponse{}, err + } + resp, err := client.internal.Pipeline().Do(req) + if err != nil { + return BlobClientSetImmutabilityPolicyResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusOK) { + return BlobClientSetImmutabilityPolicyResponse{}, runtime.NewResponseError(resp) + } + return client.setImmutabilityPolicyHandleResponse(resp) +} + +// setImmutabilityPolicyCreateRequest creates the SetImmutabilityPolicy request. +func (client *BlobClient) setImmutabilityPolicyCreateRequest(ctx context.Context, options *BlobClientSetImmutabilityPolicyOptions, modifiedAccessConditions *ModifiedAccessConditions) (*policy.Request, error) { + req, err := runtime.NewRequest(ctx, http.MethodPut, client.endpoint) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("comp", "immutabilityPolicies") + if options != nil && options.Timeout != nil { + reqQP.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + } + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["x-ms-version"] = []string{"2020-10-02"} + if options != nil && options.RequestID != nil { + req.Raw().Header["x-ms-client-request-id"] = []string{*options.RequestID} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfUnmodifiedSince != nil { + req.Raw().Header["If-Unmodified-Since"] = []string{(*modifiedAccessConditions.IfUnmodifiedSince).In(gmt).Format(time.RFC1123)} + } + if options != nil && options.ImmutabilityPolicyExpiry != nil { + req.Raw().Header["x-ms-immutability-policy-until-date"] = []string{(*options.ImmutabilityPolicyExpiry).In(gmt).Format(time.RFC1123)} + } + if options != nil && options.ImmutabilityPolicyMode != nil { + req.Raw().Header["x-ms-immutability-policy-mode"] = []string{string(*options.ImmutabilityPolicyMode)} + } + req.Raw().Header["Accept"] = []string{"application/xml"} + return req, nil +} + +// setImmutabilityPolicyHandleResponse handles the SetImmutabilityPolicy response. +func (client *BlobClient) setImmutabilityPolicyHandleResponse(resp *http.Response) (BlobClientSetImmutabilityPolicyResponse, error) { + result := BlobClientSetImmutabilityPolicyResponse{} + if val := resp.Header.Get("x-ms-client-request-id"); val != "" { + result.ClientRequestID = &val + } + if val := resp.Header.Get("x-ms-request-id"); val != "" { + result.RequestID = &val + } + if val := resp.Header.Get("x-ms-version"); val != "" { + result.Version = &val + } + if val := resp.Header.Get("Date"); val != "" { + date, err := time.Parse(time.RFC1123, val) + if err != nil { + return BlobClientSetImmutabilityPolicyResponse{}, err + } + result.Date = &date + } + if val := resp.Header.Get("x-ms-immutability-policy-until-date"); val != "" { + immutabilityPolicyExpiry, err := time.Parse(time.RFC1123, val) + if err != nil { + return BlobClientSetImmutabilityPolicyResponse{}, err + } + result.ImmutabilityPolicyExpiry = &immutabilityPolicyExpiry + } + if val := resp.Header.Get("x-ms-immutability-policy-mode"); val != "" { + result.ImmutabilityPolicyMode = (*ImmutabilityPolicyMode)(&val) + } + return result, nil +} + +// SetLegalHold - The Set Legal Hold operation sets a legal hold on the blob. +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2020-10-02 +// - legalHold - Specified if a legal hold should be set on the blob. +// - options - BlobClientSetLegalHoldOptions contains the optional parameters for the BlobClient.SetLegalHold method. +func (client *BlobClient) SetLegalHold(ctx context.Context, legalHold bool, options *BlobClientSetLegalHoldOptions) (BlobClientSetLegalHoldResponse, error) { + req, err := client.setLegalHoldCreateRequest(ctx, legalHold, options) + if err != nil { + return BlobClientSetLegalHoldResponse{}, err + } + resp, err := client.internal.Pipeline().Do(req) + if err != nil { + return BlobClientSetLegalHoldResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusOK) { + return BlobClientSetLegalHoldResponse{}, runtime.NewResponseError(resp) + } + return client.setLegalHoldHandleResponse(resp) +} + +// setLegalHoldCreateRequest creates the SetLegalHold request. +func (client *BlobClient) setLegalHoldCreateRequest(ctx context.Context, legalHold bool, options *BlobClientSetLegalHoldOptions) (*policy.Request, error) { + req, err := runtime.NewRequest(ctx, http.MethodPut, client.endpoint) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("comp", "legalhold") + if options != nil && options.Timeout != nil { + reqQP.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + } + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["x-ms-version"] = []string{"2020-10-02"} + if options != nil && options.RequestID != nil { + req.Raw().Header["x-ms-client-request-id"] = []string{*options.RequestID} + } + req.Raw().Header["x-ms-legal-hold"] = []string{strconv.FormatBool(legalHold)} + req.Raw().Header["Accept"] = []string{"application/xml"} + return req, nil +} + +// setLegalHoldHandleResponse handles the SetLegalHold response. +func (client *BlobClient) setLegalHoldHandleResponse(resp *http.Response) (BlobClientSetLegalHoldResponse, error) { + result := BlobClientSetLegalHoldResponse{} + if val := resp.Header.Get("x-ms-client-request-id"); val != "" { + result.ClientRequestID = &val + } + if val := resp.Header.Get("x-ms-request-id"); val != "" { + result.RequestID = &val + } + if val := resp.Header.Get("x-ms-version"); val != "" { + result.Version = &val + } + if val := resp.Header.Get("Date"); val != "" { + date, err := time.Parse(time.RFC1123, val) + if err != nil { + return BlobClientSetLegalHoldResponse{}, err + } + result.Date = &date + } + if val := resp.Header.Get("x-ms-legal-hold"); val != "" { + legalHold, err := strconv.ParseBool(val) + if err != nil { + return BlobClientSetLegalHoldResponse{}, err + } + result.LegalHold = &legalHold + } + return result, nil +} + +// SetMetadata - The Set Blob Metadata operation sets user-defined metadata for the specified blob as one or more name-value +// pairs +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2020-10-02 +// - options - BlobClientSetMetadataOptions contains the optional parameters for the BlobClient.SetMetadata method. +// - LeaseAccessConditions - LeaseAccessConditions contains a group of parameters for the ContainerClient.GetProperties method. +// - CPKInfo - CPKInfo contains a group of parameters for the BlobClient.Download method. +// - CPKScopeInfo - CPKScopeInfo contains a group of parameters for the BlobClient.SetMetadata method. +// - ModifiedAccessConditions - ModifiedAccessConditions contains a group of parameters for the ContainerClient.Delete method. +func (client *BlobClient) SetMetadata(ctx context.Context, options *BlobClientSetMetadataOptions, leaseAccessConditions *LeaseAccessConditions, cpkInfo *CPKInfo, cpkScopeInfo *CPKScopeInfo, modifiedAccessConditions *ModifiedAccessConditions) (BlobClientSetMetadataResponse, error) { + req, err := client.setMetadataCreateRequest(ctx, options, leaseAccessConditions, cpkInfo, cpkScopeInfo, modifiedAccessConditions) + if err != nil { + return BlobClientSetMetadataResponse{}, err + } + resp, err := client.internal.Pipeline().Do(req) + if err != nil { + return BlobClientSetMetadataResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusOK) { + return BlobClientSetMetadataResponse{}, runtime.NewResponseError(resp) + } + return client.setMetadataHandleResponse(resp) +} + +// setMetadataCreateRequest creates the SetMetadata request. +func (client *BlobClient) setMetadataCreateRequest(ctx context.Context, options *BlobClientSetMetadataOptions, leaseAccessConditions *LeaseAccessConditions, cpkInfo *CPKInfo, cpkScopeInfo *CPKScopeInfo, modifiedAccessConditions *ModifiedAccessConditions) (*policy.Request, error) { + req, err := runtime.NewRequest(ctx, http.MethodPut, client.endpoint) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("comp", "metadata") + if options != nil && options.Timeout != nil { + reqQP.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + } + req.Raw().URL.RawQuery = reqQP.Encode() + if options != nil && options.Metadata != nil { + for k, v := range options.Metadata { + if v != nil { + req.Raw().Header["x-ms-meta-"+k] = []string{*v} + } + } + } + if leaseAccessConditions != nil && leaseAccessConditions.LeaseID != nil { + req.Raw().Header["x-ms-lease-id"] = []string{*leaseAccessConditions.LeaseID} + } + if cpkInfo != nil && cpkInfo.EncryptionKey != nil { + req.Raw().Header["x-ms-encryption-key"] = []string{*cpkInfo.EncryptionKey} + } + if cpkInfo != nil && cpkInfo.EncryptionKeySHA256 != nil { + req.Raw().Header["x-ms-encryption-key-sha256"] = []string{*cpkInfo.EncryptionKeySHA256} + } + if cpkInfo != nil && cpkInfo.EncryptionAlgorithm != nil { + req.Raw().Header["x-ms-encryption-algorithm"] = []string{string(*cpkInfo.EncryptionAlgorithm)} + } + if cpkScopeInfo != nil && cpkScopeInfo.EncryptionScope != nil { + req.Raw().Header["x-ms-encryption-scope"] = []string{*cpkScopeInfo.EncryptionScope} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfModifiedSince != nil { + req.Raw().Header["If-Modified-Since"] = []string{(*modifiedAccessConditions.IfModifiedSince).In(gmt).Format(time.RFC1123)} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfUnmodifiedSince != nil { + req.Raw().Header["If-Unmodified-Since"] = []string{(*modifiedAccessConditions.IfUnmodifiedSince).In(gmt).Format(time.RFC1123)} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfMatch != nil { + req.Raw().Header["If-Match"] = []string{string(*modifiedAccessConditions.IfMatch)} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfNoneMatch != nil { + req.Raw().Header["If-None-Match"] = []string{string(*modifiedAccessConditions.IfNoneMatch)} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfTags != nil { + req.Raw().Header["x-ms-if-tags"] = []string{*modifiedAccessConditions.IfTags} + } + req.Raw().Header["x-ms-version"] = []string{"2020-10-02"} + if options != nil && options.RequestID != nil { + req.Raw().Header["x-ms-client-request-id"] = []string{*options.RequestID} + } + req.Raw().Header["Accept"] = []string{"application/xml"} + return req, nil +} + +// setMetadataHandleResponse handles the SetMetadata response. +func (client *BlobClient) setMetadataHandleResponse(resp *http.Response) (BlobClientSetMetadataResponse, error) { + result := BlobClientSetMetadataResponse{} + if val := resp.Header.Get("ETag"); val != "" { + result.ETag = (*azcore.ETag)(&val) + } + if val := resp.Header.Get("Last-Modified"); val != "" { + lastModified, err := time.Parse(time.RFC1123, val) + if err != nil { + return BlobClientSetMetadataResponse{}, err + } + result.LastModified = &lastModified + } + if val := resp.Header.Get("x-ms-client-request-id"); val != "" { + result.ClientRequestID = &val + } + if val := resp.Header.Get("x-ms-request-id"); val != "" { + result.RequestID = &val + } + if val := resp.Header.Get("x-ms-version"); val != "" { + result.Version = &val + } + if val := resp.Header.Get("x-ms-version-id"); val != "" { + result.VersionID = &val + } + if val := resp.Header.Get("Date"); val != "" { + date, err := time.Parse(time.RFC1123, val) + if err != nil { + return BlobClientSetMetadataResponse{}, err + } + result.Date = &date + } + if val := resp.Header.Get("x-ms-request-server-encrypted"); val != "" { + isServerEncrypted, err := strconv.ParseBool(val) + if err != nil { + return BlobClientSetMetadataResponse{}, err + } + result.IsServerEncrypted = &isServerEncrypted + } + if val := resp.Header.Get("x-ms-encryption-key-sha256"); val != "" { + result.EncryptionKeySHA256 = &val + } + if val := resp.Header.Get("x-ms-encryption-scope"); val != "" { + result.EncryptionScope = &val + } + return result, nil +} + +// SetTags - The Set Tags operation enables users to set tags on a blob. +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2020-10-02 +// - tags - Blob tags +// - options - BlobClientSetTagsOptions contains the optional parameters for the BlobClient.SetTags method. +// - ModifiedAccessConditions - ModifiedAccessConditions contains a group of parameters for the ContainerClient.Delete method. +// - LeaseAccessConditions - LeaseAccessConditions contains a group of parameters for the ContainerClient.GetProperties method. +func (client *BlobClient) SetTags(ctx context.Context, tags BlobTags, options *BlobClientSetTagsOptions, modifiedAccessConditions *ModifiedAccessConditions, leaseAccessConditions *LeaseAccessConditions) (BlobClientSetTagsResponse, error) { + req, err := client.setTagsCreateRequest(ctx, tags, options, modifiedAccessConditions, leaseAccessConditions) + if err != nil { + return BlobClientSetTagsResponse{}, err + } + resp, err := client.internal.Pipeline().Do(req) + if err != nil { + return BlobClientSetTagsResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusNoContent) { + return BlobClientSetTagsResponse{}, runtime.NewResponseError(resp) + } + return client.setTagsHandleResponse(resp) +} + +// setTagsCreateRequest creates the SetTags request. +func (client *BlobClient) setTagsCreateRequest(ctx context.Context, tags BlobTags, options *BlobClientSetTagsOptions, modifiedAccessConditions *ModifiedAccessConditions, leaseAccessConditions *LeaseAccessConditions) (*policy.Request, error) { + req, err := runtime.NewRequest(ctx, http.MethodPut, client.endpoint) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("comp", "tags") + if options != nil && options.Timeout != nil { + reqQP.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + } + if options != nil && options.VersionID != nil { + reqQP.Set("versionid", *options.VersionID) + } + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["x-ms-version"] = []string{"2020-10-02"} + if options != nil && options.TransactionalContentMD5 != nil { + req.Raw().Header["Content-MD5"] = []string{base64.StdEncoding.EncodeToString(options.TransactionalContentMD5)} + } + if options != nil && options.TransactionalContentCRC64 != nil { + req.Raw().Header["x-ms-content-crc64"] = []string{base64.StdEncoding.EncodeToString(options.TransactionalContentCRC64)} + } + if options != nil && options.RequestID != nil { + req.Raw().Header["x-ms-client-request-id"] = []string{*options.RequestID} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfTags != nil { + req.Raw().Header["x-ms-if-tags"] = []string{*modifiedAccessConditions.IfTags} + } + if leaseAccessConditions != nil && leaseAccessConditions.LeaseID != nil { + req.Raw().Header["x-ms-lease-id"] = []string{*leaseAccessConditions.LeaseID} + } + req.Raw().Header["Accept"] = []string{"application/xml"} + if err := runtime.MarshalAsXML(req, tags); err != nil { + return nil, err + } + return req, nil +} + +// setTagsHandleResponse handles the SetTags response. +func (client *BlobClient) setTagsHandleResponse(resp *http.Response) (BlobClientSetTagsResponse, error) { + result := BlobClientSetTagsResponse{} + if val := resp.Header.Get("x-ms-client-request-id"); val != "" { + result.ClientRequestID = &val + } + if val := resp.Header.Get("x-ms-request-id"); val != "" { + result.RequestID = &val + } + if val := resp.Header.Get("x-ms-version"); val != "" { + result.Version = &val + } + if val := resp.Header.Get("Date"); val != "" { + date, err := time.Parse(time.RFC1123, val) + if err != nil { + return BlobClientSetTagsResponse{}, err + } + result.Date = &date + } + return result, nil +} + +// SetTier - The Set Tier operation sets the tier on a blob. The operation is allowed on a page blob in a premium storage +// account and on a block blob in a blob storage account (locally redundant storage only). A +// premium page blob's tier determines the allowed size, IOPS, and bandwidth of the blob. A block blob's tier determines Hot/Cool/Archive +// storage type. This operation does not update the blob's ETag. +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2020-10-02 +// - tier - Indicates the tier to be set on the blob. +// - options - BlobClientSetTierOptions contains the optional parameters for the BlobClient.SetTier method. +// - LeaseAccessConditions - LeaseAccessConditions contains a group of parameters for the ContainerClient.GetProperties method. +// - ModifiedAccessConditions - ModifiedAccessConditions contains a group of parameters for the ContainerClient.Delete method. +func (client *BlobClient) SetTier(ctx context.Context, tier AccessTier, options *BlobClientSetTierOptions, leaseAccessConditions *LeaseAccessConditions, modifiedAccessConditions *ModifiedAccessConditions) (BlobClientSetTierResponse, error) { + req, err := client.setTierCreateRequest(ctx, tier, options, leaseAccessConditions, modifiedAccessConditions) + if err != nil { + return BlobClientSetTierResponse{}, err + } + resp, err := client.internal.Pipeline().Do(req) + if err != nil { + return BlobClientSetTierResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusOK, http.StatusAccepted) { + return BlobClientSetTierResponse{}, runtime.NewResponseError(resp) + } + return client.setTierHandleResponse(resp) +} + +// setTierCreateRequest creates the SetTier request. +func (client *BlobClient) setTierCreateRequest(ctx context.Context, tier AccessTier, options *BlobClientSetTierOptions, leaseAccessConditions *LeaseAccessConditions, modifiedAccessConditions *ModifiedAccessConditions) (*policy.Request, error) { + req, err := runtime.NewRequest(ctx, http.MethodPut, client.endpoint) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("comp", "tier") + if options != nil && options.Snapshot != nil { + reqQP.Set("snapshot", *options.Snapshot) + } + if options != nil && options.VersionID != nil { + reqQP.Set("versionid", *options.VersionID) + } + if options != nil && options.Timeout != nil { + reqQP.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + } + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["x-ms-access-tier"] = []string{string(tier)} + if options != nil && options.RehydratePriority != nil { + req.Raw().Header["x-ms-rehydrate-priority"] = []string{string(*options.RehydratePriority)} + } + req.Raw().Header["x-ms-version"] = []string{"2020-10-02"} + if options != nil && options.RequestID != nil { + req.Raw().Header["x-ms-client-request-id"] = []string{*options.RequestID} + } + if leaseAccessConditions != nil && leaseAccessConditions.LeaseID != nil { + req.Raw().Header["x-ms-lease-id"] = []string{*leaseAccessConditions.LeaseID} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfTags != nil { + req.Raw().Header["x-ms-if-tags"] = []string{*modifiedAccessConditions.IfTags} + } + req.Raw().Header["Accept"] = []string{"application/xml"} + return req, nil +} + +// setTierHandleResponse handles the SetTier response. +func (client *BlobClient) setTierHandleResponse(resp *http.Response) (BlobClientSetTierResponse, error) { + result := BlobClientSetTierResponse{} + if val := resp.Header.Get("x-ms-client-request-id"); val != "" { + result.ClientRequestID = &val + } + if val := resp.Header.Get("x-ms-request-id"); val != "" { + result.RequestID = &val + } + if val := resp.Header.Get("x-ms-version"); val != "" { + result.Version = &val + } + return result, nil +} + +// StartCopyFromURL - The Start Copy From URL operation copies a blob or an internet resource to a new blob. +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2020-10-02 +// - copySource - Specifies the name of the source page blob snapshot. This value is a URL of up to 2 KB in length that specifies +// a page blob snapshot. The value should be URL-encoded as it would appear in a request +// URI. The source blob must either be public or must be authenticated via a shared access signature. +// - options - BlobClientStartCopyFromURLOptions contains the optional parameters for the BlobClient.StartCopyFromURL method. +// - SourceModifiedAccessConditions - SourceModifiedAccessConditions contains a group of parameters for the BlobClient.StartCopyFromURL +// method. +// - ModifiedAccessConditions - ModifiedAccessConditions contains a group of parameters for the ContainerClient.Delete method. +// - LeaseAccessConditions - LeaseAccessConditions contains a group of parameters for the ContainerClient.GetProperties method. +func (client *BlobClient) StartCopyFromURL(ctx context.Context, copySource string, options *BlobClientStartCopyFromURLOptions, sourceModifiedAccessConditions *SourceModifiedAccessConditions, modifiedAccessConditions *ModifiedAccessConditions, leaseAccessConditions *LeaseAccessConditions) (BlobClientStartCopyFromURLResponse, error) { + req, err := client.startCopyFromURLCreateRequest(ctx, copySource, options, sourceModifiedAccessConditions, modifiedAccessConditions, leaseAccessConditions) + if err != nil { + return BlobClientStartCopyFromURLResponse{}, err + } + resp, err := client.internal.Pipeline().Do(req) + if err != nil { + return BlobClientStartCopyFromURLResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusAccepted) { + return BlobClientStartCopyFromURLResponse{}, runtime.NewResponseError(resp) + } + return client.startCopyFromURLHandleResponse(resp) +} + +// startCopyFromURLCreateRequest creates the StartCopyFromURL request. +func (client *BlobClient) startCopyFromURLCreateRequest(ctx context.Context, copySource string, options *BlobClientStartCopyFromURLOptions, sourceModifiedAccessConditions *SourceModifiedAccessConditions, modifiedAccessConditions *ModifiedAccessConditions, leaseAccessConditions *LeaseAccessConditions) (*policy.Request, error) { + req, err := runtime.NewRequest(ctx, http.MethodPut, client.endpoint) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + if options != nil && options.Timeout != nil { + reqQP.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + } + req.Raw().URL.RawQuery = reqQP.Encode() + if options != nil && options.Metadata != nil { + for k, v := range options.Metadata { + if v != nil { + req.Raw().Header["x-ms-meta-"+k] = []string{*v} + } + } + } + if options != nil && options.Tier != nil { + req.Raw().Header["x-ms-access-tier"] = []string{string(*options.Tier)} + } + if options != nil && options.RehydratePriority != nil { + req.Raw().Header["x-ms-rehydrate-priority"] = []string{string(*options.RehydratePriority)} + } + if sourceModifiedAccessConditions != nil && sourceModifiedAccessConditions.SourceIfModifiedSince != nil { + req.Raw().Header["x-ms-source-if-modified-since"] = []string{(*sourceModifiedAccessConditions.SourceIfModifiedSince).In(gmt).Format(time.RFC1123)} + } + if sourceModifiedAccessConditions != nil && sourceModifiedAccessConditions.SourceIfUnmodifiedSince != nil { + req.Raw().Header["x-ms-source-if-unmodified-since"] = []string{(*sourceModifiedAccessConditions.SourceIfUnmodifiedSince).In(gmt).Format(time.RFC1123)} + } + if sourceModifiedAccessConditions != nil && sourceModifiedAccessConditions.SourceIfMatch != nil { + req.Raw().Header["x-ms-source-if-match"] = []string{string(*sourceModifiedAccessConditions.SourceIfMatch)} + } + if sourceModifiedAccessConditions != nil && sourceModifiedAccessConditions.SourceIfNoneMatch != nil { + req.Raw().Header["x-ms-source-if-none-match"] = []string{string(*sourceModifiedAccessConditions.SourceIfNoneMatch)} + } + if sourceModifiedAccessConditions != nil && sourceModifiedAccessConditions.SourceIfTags != nil { + req.Raw().Header["x-ms-source-if-tags"] = []string{*sourceModifiedAccessConditions.SourceIfTags} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfModifiedSince != nil { + req.Raw().Header["If-Modified-Since"] = []string{(*modifiedAccessConditions.IfModifiedSince).In(gmt).Format(time.RFC1123)} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfUnmodifiedSince != nil { + req.Raw().Header["If-Unmodified-Since"] = []string{(*modifiedAccessConditions.IfUnmodifiedSince).In(gmt).Format(time.RFC1123)} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfMatch != nil { + req.Raw().Header["If-Match"] = []string{string(*modifiedAccessConditions.IfMatch)} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfNoneMatch != nil { + req.Raw().Header["If-None-Match"] = []string{string(*modifiedAccessConditions.IfNoneMatch)} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfTags != nil { + req.Raw().Header["x-ms-if-tags"] = []string{*modifiedAccessConditions.IfTags} + } + req.Raw().Header["x-ms-copy-source"] = []string{copySource} + if leaseAccessConditions != nil && leaseAccessConditions.LeaseID != nil { + req.Raw().Header["x-ms-lease-id"] = []string{*leaseAccessConditions.LeaseID} + } + req.Raw().Header["x-ms-version"] = []string{"2020-10-02"} + if options != nil && options.RequestID != nil { + req.Raw().Header["x-ms-client-request-id"] = []string{*options.RequestID} + } + if options != nil && options.BlobTagsString != nil { + req.Raw().Header["x-ms-tags"] = []string{*options.BlobTagsString} + } + if options != nil && options.SealBlob != nil { + req.Raw().Header["x-ms-seal-blob"] = []string{strconv.FormatBool(*options.SealBlob)} + } + if options != nil && options.ImmutabilityPolicyExpiry != nil { + req.Raw().Header["x-ms-immutability-policy-until-date"] = []string{(*options.ImmutabilityPolicyExpiry).In(gmt).Format(time.RFC1123)} + } + if options != nil && options.ImmutabilityPolicyMode != nil { + req.Raw().Header["x-ms-immutability-policy-mode"] = []string{string(*options.ImmutabilityPolicyMode)} + } + if options != nil && options.LegalHold != nil { + req.Raw().Header["x-ms-legal-hold"] = []string{strconv.FormatBool(*options.LegalHold)} + } + req.Raw().Header["Accept"] = []string{"application/xml"} + return req, nil +} + +// startCopyFromURLHandleResponse handles the StartCopyFromURL response. +func (client *BlobClient) startCopyFromURLHandleResponse(resp *http.Response) (BlobClientStartCopyFromURLResponse, error) { + result := BlobClientStartCopyFromURLResponse{} + if val := resp.Header.Get("ETag"); val != "" { + result.ETag = (*azcore.ETag)(&val) + } + if val := resp.Header.Get("Last-Modified"); val != "" { + lastModified, err := time.Parse(time.RFC1123, val) + if err != nil { + return BlobClientStartCopyFromURLResponse{}, err + } + result.LastModified = &lastModified + } + if val := resp.Header.Get("x-ms-client-request-id"); val != "" { + result.ClientRequestID = &val + } + if val := resp.Header.Get("x-ms-request-id"); val != "" { + result.RequestID = &val + } + if val := resp.Header.Get("x-ms-version"); val != "" { + result.Version = &val + } + if val := resp.Header.Get("x-ms-version-id"); val != "" { + result.VersionID = &val + } + if val := resp.Header.Get("Date"); val != "" { + date, err := time.Parse(time.RFC1123, val) + if err != nil { + return BlobClientStartCopyFromURLResponse{}, err + } + result.Date = &date + } + if val := resp.Header.Get("x-ms-copy-id"); val != "" { + result.CopyID = &val + } + if val := resp.Header.Get("x-ms-copy-status"); val != "" { + result.CopyStatus = (*CopyStatusType)(&val) + } + return result, nil +} + +// Undelete - Undelete a blob that was previously soft deleted +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2020-10-02 +// - options - BlobClientUndeleteOptions contains the optional parameters for the BlobClient.Undelete method. +func (client *BlobClient) Undelete(ctx context.Context, options *BlobClientUndeleteOptions) (BlobClientUndeleteResponse, error) { + req, err := client.undeleteCreateRequest(ctx, options) + if err != nil { + return BlobClientUndeleteResponse{}, err + } + resp, err := client.internal.Pipeline().Do(req) + if err != nil { + return BlobClientUndeleteResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusOK) { + return BlobClientUndeleteResponse{}, runtime.NewResponseError(resp) + } + return client.undeleteHandleResponse(resp) +} + +// undeleteCreateRequest creates the Undelete request. +func (client *BlobClient) undeleteCreateRequest(ctx context.Context, options *BlobClientUndeleteOptions) (*policy.Request, error) { + req, err := runtime.NewRequest(ctx, http.MethodPut, client.endpoint) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("comp", "undelete") + if options != nil && options.Timeout != nil { + reqQP.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + } + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["x-ms-version"] = []string{"2020-10-02"} + if options != nil && options.RequestID != nil { + req.Raw().Header["x-ms-client-request-id"] = []string{*options.RequestID} + } + req.Raw().Header["Accept"] = []string{"application/xml"} + return req, nil +} + +// undeleteHandleResponse handles the Undelete response. +func (client *BlobClient) undeleteHandleResponse(resp *http.Response) (BlobClientUndeleteResponse, error) { + result := BlobClientUndeleteResponse{} + if val := resp.Header.Get("x-ms-client-request-id"); val != "" { + result.ClientRequestID = &val + } + if val := resp.Header.Get("x-ms-request-id"); val != "" { + result.RequestID = &val + } + if val := resp.Header.Get("x-ms-version"); val != "" { + result.Version = &val + } + if val := resp.Header.Get("Date"); val != "" { + date, err := time.Parse(time.RFC1123, val) + if err != nil { + return BlobClientUndeleteResponse{}, err + } + result.Date = &date + } + return result, nil +} diff --git a/sdk/storage/azdatalake/internal/generated_blob/zz_blockblob_client.go b/sdk/storage/azdatalake/internal/generated_blob/zz_blockblob_client.go new file mode 100644 index 000000000000..09b4362dbb6d --- /dev/null +++ b/sdk/storage/azdatalake/internal/generated_blob/zz_blockblob_client.go @@ -0,0 +1,970 @@ +//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. +// Code generated by Microsoft (R) AutoRest Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. +// DO NOT EDIT. + +package generated_blob + +import ( + "context" + "encoding/base64" + "github.com/Azure/azure-sdk-for-go/sdk/azcore" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/policy" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime" + "io" + "net/http" + "strconv" + "time" +) + +// BlockBlobClient contains the methods for the BlockBlob group. +// Don't use this type directly, use a constructor function instead. +type BlockBlobClient struct { + internal *azcore.Client + endpoint string +} + +// CommitBlockList - The Commit Block List operation writes a blob by specifying the list of block IDs that make up the blob. +// In order to be written as part of a blob, a block must have been successfully written to the +// server in a prior Put Block operation. You can call Put Block List to update a blob by uploading only those blocks that +// have changed, then committing the new and existing blocks together. You can do +// this by specifying whether to commit a block from the committed block list or from the uncommitted block list, or to commit +// the most recently uploaded version of the block, whichever list it may +// belong to. +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2020-10-02 +// - blocks - Blob Blocks. +// - options - BlockBlobClientCommitBlockListOptions contains the optional parameters for the BlockBlobClient.CommitBlockList +// method. +// - BlobHTTPHeaders - BlobHTTPHeaders contains a group of parameters for the BlobClient.SetHTTPHeaders method. +// - LeaseAccessConditions - LeaseAccessConditions contains a group of parameters for the ContainerClient.GetProperties method. +// - CPKInfo - CPKInfo contains a group of parameters for the BlobClient.Download method. +// - CPKScopeInfo - CPKScopeInfo contains a group of parameters for the BlobClient.SetMetadata method. +// - ModifiedAccessConditions - ModifiedAccessConditions contains a group of parameters for the ContainerClient.Delete method. +func (client *BlockBlobClient) CommitBlockList(ctx context.Context, blocks BlockLookupList, options *BlockBlobClientCommitBlockListOptions, blobHTTPHeaders *BlobHTTPHeaders, leaseAccessConditions *LeaseAccessConditions, cpkInfo *CPKInfo, cpkScopeInfo *CPKScopeInfo, modifiedAccessConditions *ModifiedAccessConditions) (BlockBlobClientCommitBlockListResponse, error) { + req, err := client.commitBlockListCreateRequest(ctx, blocks, options, blobHTTPHeaders, leaseAccessConditions, cpkInfo, cpkScopeInfo, modifiedAccessConditions) + if err != nil { + return BlockBlobClientCommitBlockListResponse{}, err + } + resp, err := client.internal.Pipeline().Do(req) + if err != nil { + return BlockBlobClientCommitBlockListResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusCreated) { + return BlockBlobClientCommitBlockListResponse{}, runtime.NewResponseError(resp) + } + return client.commitBlockListHandleResponse(resp) +} + +// commitBlockListCreateRequest creates the CommitBlockList request. +func (client *BlockBlobClient) commitBlockListCreateRequest(ctx context.Context, blocks BlockLookupList, options *BlockBlobClientCommitBlockListOptions, blobHTTPHeaders *BlobHTTPHeaders, leaseAccessConditions *LeaseAccessConditions, cpkInfo *CPKInfo, cpkScopeInfo *CPKScopeInfo, modifiedAccessConditions *ModifiedAccessConditions) (*policy.Request, error) { + req, err := runtime.NewRequest(ctx, http.MethodPut, client.endpoint) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("comp", "blocklist") + if options != nil && options.Timeout != nil { + reqQP.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + } + req.Raw().URL.RawQuery = reqQP.Encode() + if blobHTTPHeaders != nil && blobHTTPHeaders.BlobCacheControl != nil { + req.Raw().Header["x-ms-blob-cache-control"] = []string{*blobHTTPHeaders.BlobCacheControl} + } + if blobHTTPHeaders != nil && blobHTTPHeaders.BlobContentType != nil { + req.Raw().Header["x-ms-blob-content-type"] = []string{*blobHTTPHeaders.BlobContentType} + } + if blobHTTPHeaders != nil && blobHTTPHeaders.BlobContentEncoding != nil { + req.Raw().Header["x-ms-blob-content-encoding"] = []string{*blobHTTPHeaders.BlobContentEncoding} + } + if blobHTTPHeaders != nil && blobHTTPHeaders.BlobContentLanguage != nil { + req.Raw().Header["x-ms-blob-content-language"] = []string{*blobHTTPHeaders.BlobContentLanguage} + } + if blobHTTPHeaders != nil && blobHTTPHeaders.BlobContentMD5 != nil { + req.Raw().Header["x-ms-blob-content-md5"] = []string{base64.StdEncoding.EncodeToString(blobHTTPHeaders.BlobContentMD5)} + } + if options != nil && options.TransactionalContentMD5 != nil { + req.Raw().Header["Content-MD5"] = []string{base64.StdEncoding.EncodeToString(options.TransactionalContentMD5)} + } + if options != nil && options.TransactionalContentCRC64 != nil { + req.Raw().Header["x-ms-content-crc64"] = []string{base64.StdEncoding.EncodeToString(options.TransactionalContentCRC64)} + } + if options != nil && options.Metadata != nil { + for k, v := range options.Metadata { + if v != nil { + req.Raw().Header["x-ms-meta-"+k] = []string{*v} + } + } + } + if leaseAccessConditions != nil && leaseAccessConditions.LeaseID != nil { + req.Raw().Header["x-ms-lease-id"] = []string{*leaseAccessConditions.LeaseID} + } + if blobHTTPHeaders != nil && blobHTTPHeaders.BlobContentDisposition != nil { + req.Raw().Header["x-ms-blob-content-disposition"] = []string{*blobHTTPHeaders.BlobContentDisposition} + } + if cpkInfo != nil && cpkInfo.EncryptionKey != nil { + req.Raw().Header["x-ms-encryption-key"] = []string{*cpkInfo.EncryptionKey} + } + if cpkInfo != nil && cpkInfo.EncryptionKeySHA256 != nil { + req.Raw().Header["x-ms-encryption-key-sha256"] = []string{*cpkInfo.EncryptionKeySHA256} + } + if cpkInfo != nil && cpkInfo.EncryptionAlgorithm != nil { + req.Raw().Header["x-ms-encryption-algorithm"] = []string{string(*cpkInfo.EncryptionAlgorithm)} + } + if cpkScopeInfo != nil && cpkScopeInfo.EncryptionScope != nil { + req.Raw().Header["x-ms-encryption-scope"] = []string{*cpkScopeInfo.EncryptionScope} + } + if options != nil && options.Tier != nil { + req.Raw().Header["x-ms-access-tier"] = []string{string(*options.Tier)} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfModifiedSince != nil { + req.Raw().Header["If-Modified-Since"] = []string{(*modifiedAccessConditions.IfModifiedSince).In(gmt).Format(time.RFC1123)} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfUnmodifiedSince != nil { + req.Raw().Header["If-Unmodified-Since"] = []string{(*modifiedAccessConditions.IfUnmodifiedSince).In(gmt).Format(time.RFC1123)} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfMatch != nil { + req.Raw().Header["If-Match"] = []string{string(*modifiedAccessConditions.IfMatch)} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfNoneMatch != nil { + req.Raw().Header["If-None-Match"] = []string{string(*modifiedAccessConditions.IfNoneMatch)} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfTags != nil { + req.Raw().Header["x-ms-if-tags"] = []string{*modifiedAccessConditions.IfTags} + } + req.Raw().Header["x-ms-version"] = []string{"2020-10-02"} + if options != nil && options.RequestID != nil { + req.Raw().Header["x-ms-client-request-id"] = []string{*options.RequestID} + } + if options != nil && options.BlobTagsString != nil { + req.Raw().Header["x-ms-tags"] = []string{*options.BlobTagsString} + } + if options != nil && options.ImmutabilityPolicyExpiry != nil { + req.Raw().Header["x-ms-immutability-policy-until-date"] = []string{(*options.ImmutabilityPolicyExpiry).In(gmt).Format(time.RFC1123)} + } + if options != nil && options.ImmutabilityPolicyMode != nil { + req.Raw().Header["x-ms-immutability-policy-mode"] = []string{string(*options.ImmutabilityPolicyMode)} + } + if options != nil && options.LegalHold != nil { + req.Raw().Header["x-ms-legal-hold"] = []string{strconv.FormatBool(*options.LegalHold)} + } + req.Raw().Header["Accept"] = []string{"application/xml"} + if err := runtime.MarshalAsXML(req, blocks); err != nil { + return nil, err + } + return req, nil +} + +// commitBlockListHandleResponse handles the CommitBlockList response. +func (client *BlockBlobClient) commitBlockListHandleResponse(resp *http.Response) (BlockBlobClientCommitBlockListResponse, error) { + result := BlockBlobClientCommitBlockListResponse{} + if val := resp.Header.Get("ETag"); val != "" { + result.ETag = (*azcore.ETag)(&val) + } + if val := resp.Header.Get("Last-Modified"); val != "" { + lastModified, err := time.Parse(time.RFC1123, val) + if err != nil { + return BlockBlobClientCommitBlockListResponse{}, err + } + result.LastModified = &lastModified + } + if val := resp.Header.Get("Content-MD5"); val != "" { + contentMD5, err := base64.StdEncoding.DecodeString(val) + if err != nil { + return BlockBlobClientCommitBlockListResponse{}, err + } + result.ContentMD5 = contentMD5 + } + if val := resp.Header.Get("x-ms-content-crc64"); val != "" { + contentCRC64, err := base64.StdEncoding.DecodeString(val) + if err != nil { + return BlockBlobClientCommitBlockListResponse{}, err + } + result.ContentCRC64 = contentCRC64 + } + if val := resp.Header.Get("x-ms-client-request-id"); val != "" { + result.ClientRequestID = &val + } + if val := resp.Header.Get("x-ms-request-id"); val != "" { + result.RequestID = &val + } + if val := resp.Header.Get("x-ms-version"); val != "" { + result.Version = &val + } + if val := resp.Header.Get("x-ms-version-id"); val != "" { + result.VersionID = &val + } + if val := resp.Header.Get("Date"); val != "" { + date, err := time.Parse(time.RFC1123, val) + if err != nil { + return BlockBlobClientCommitBlockListResponse{}, err + } + result.Date = &date + } + if val := resp.Header.Get("x-ms-request-server-encrypted"); val != "" { + isServerEncrypted, err := strconv.ParseBool(val) + if err != nil { + return BlockBlobClientCommitBlockListResponse{}, err + } + result.IsServerEncrypted = &isServerEncrypted + } + if val := resp.Header.Get("x-ms-encryption-key-sha256"); val != "" { + result.EncryptionKeySHA256 = &val + } + if val := resp.Header.Get("x-ms-encryption-scope"); val != "" { + result.EncryptionScope = &val + } + return result, nil +} + +// GetBlockList - The Get Block List operation retrieves the list of blocks that have been uploaded as part of a block blob +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2020-10-02 +// - listType - Specifies whether to return the list of committed blocks, the list of uncommitted blocks, or both lists together. +// - options - BlockBlobClientGetBlockListOptions contains the optional parameters for the BlockBlobClient.GetBlockList method. +// - LeaseAccessConditions - LeaseAccessConditions contains a group of parameters for the ContainerClient.GetProperties method. +// - ModifiedAccessConditions - ModifiedAccessConditions contains a group of parameters for the ContainerClient.Delete method. +func (client *BlockBlobClient) GetBlockList(ctx context.Context, listType BlockListType, options *BlockBlobClientGetBlockListOptions, leaseAccessConditions *LeaseAccessConditions, modifiedAccessConditions *ModifiedAccessConditions) (BlockBlobClientGetBlockListResponse, error) { + req, err := client.getBlockListCreateRequest(ctx, listType, options, leaseAccessConditions, modifiedAccessConditions) + if err != nil { + return BlockBlobClientGetBlockListResponse{}, err + } + resp, err := client.internal.Pipeline().Do(req) + if err != nil { + return BlockBlobClientGetBlockListResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusOK) { + return BlockBlobClientGetBlockListResponse{}, runtime.NewResponseError(resp) + } + return client.getBlockListHandleResponse(resp) +} + +// getBlockListCreateRequest creates the GetBlockList request. +func (client *BlockBlobClient) getBlockListCreateRequest(ctx context.Context, listType BlockListType, options *BlockBlobClientGetBlockListOptions, leaseAccessConditions *LeaseAccessConditions, modifiedAccessConditions *ModifiedAccessConditions) (*policy.Request, error) { + req, err := runtime.NewRequest(ctx, http.MethodGet, client.endpoint) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("comp", "blocklist") + if options != nil && options.Snapshot != nil { + reqQP.Set("snapshot", *options.Snapshot) + } + reqQP.Set("blocklisttype", string(listType)) + if options != nil && options.Timeout != nil { + reqQP.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + } + req.Raw().URL.RawQuery = reqQP.Encode() + if leaseAccessConditions != nil && leaseAccessConditions.LeaseID != nil { + req.Raw().Header["x-ms-lease-id"] = []string{*leaseAccessConditions.LeaseID} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfTags != nil { + req.Raw().Header["x-ms-if-tags"] = []string{*modifiedAccessConditions.IfTags} + } + req.Raw().Header["x-ms-version"] = []string{"2020-10-02"} + if options != nil && options.RequestID != nil { + req.Raw().Header["x-ms-client-request-id"] = []string{*options.RequestID} + } + req.Raw().Header["Accept"] = []string{"application/xml"} + return req, nil +} + +// getBlockListHandleResponse handles the GetBlockList response. +func (client *BlockBlobClient) getBlockListHandleResponse(resp *http.Response) (BlockBlobClientGetBlockListResponse, error) { + result := BlockBlobClientGetBlockListResponse{} + if val := resp.Header.Get("Last-Modified"); val != "" { + lastModified, err := time.Parse(time.RFC1123, val) + if err != nil { + return BlockBlobClientGetBlockListResponse{}, err + } + result.LastModified = &lastModified + } + if val := resp.Header.Get("ETag"); val != "" { + result.ETag = (*azcore.ETag)(&val) + } + if val := resp.Header.Get("Content-Type"); val != "" { + result.ContentType = &val + } + if val := resp.Header.Get("x-ms-blob-content-length"); val != "" { + blobContentLength, err := strconv.ParseInt(val, 10, 64) + if err != nil { + return BlockBlobClientGetBlockListResponse{}, err + } + result.BlobContentLength = &blobContentLength + } + if val := resp.Header.Get("x-ms-client-request-id"); val != "" { + result.ClientRequestID = &val + } + if val := resp.Header.Get("x-ms-request-id"); val != "" { + result.RequestID = &val + } + if val := resp.Header.Get("x-ms-version"); val != "" { + result.Version = &val + } + if val := resp.Header.Get("Date"); val != "" { + date, err := time.Parse(time.RFC1123, val) + if err != nil { + return BlockBlobClientGetBlockListResponse{}, err + } + result.Date = &date + } + if err := runtime.UnmarshalAsXML(resp, &result.BlockList); err != nil { + return BlockBlobClientGetBlockListResponse{}, err + } + return result, nil +} + +// PutBlobFromURL - The Put Blob from URL operation creates a new Block Blob where the contents of the blob are read from +// a given URL. This API is supported beginning with the 2020-04-08 version. Partial updates are not +// supported with Put Blob from URL; the content of an existing blob is overwritten with the content of the new blob. To perform +// partial updates to a block blob’s contents using a source URL, use the Put +// Block from URL API in conjunction with Put Block List. +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2020-10-02 +// - contentLength - The length of the request. +// - copySource - Specifies the name of the source page blob snapshot. This value is a URL of up to 2 KB in length that specifies +// a page blob snapshot. The value should be URL-encoded as it would appear in a request +// URI. The source blob must either be public or must be authenticated via a shared access signature. +// - options - BlockBlobClientPutBlobFromURLOptions contains the optional parameters for the BlockBlobClient.PutBlobFromURL +// method. +// - BlobHTTPHeaders - BlobHTTPHeaders contains a group of parameters for the BlobClient.SetHTTPHeaders method. +// - LeaseAccessConditions - LeaseAccessConditions contains a group of parameters for the ContainerClient.GetProperties method. +// - CPKInfo - CPKInfo contains a group of parameters for the BlobClient.Download method. +// - CPKScopeInfo - CPKScopeInfo contains a group of parameters for the BlobClient.SetMetadata method. +// - ModifiedAccessConditions - ModifiedAccessConditions contains a group of parameters for the ContainerClient.Delete method. +// - SourceModifiedAccessConditions - SourceModifiedAccessConditions contains a group of parameters for the BlobClient.StartCopyFromURL +// method. +func (client *BlockBlobClient) PutBlobFromURL(ctx context.Context, contentLength int64, copySource string, options *BlockBlobClientPutBlobFromURLOptions, blobHTTPHeaders *BlobHTTPHeaders, leaseAccessConditions *LeaseAccessConditions, cpkInfo *CPKInfo, cpkScopeInfo *CPKScopeInfo, modifiedAccessConditions *ModifiedAccessConditions, sourceModifiedAccessConditions *SourceModifiedAccessConditions) (BlockBlobClientPutBlobFromURLResponse, error) { + req, err := client.putBlobFromURLCreateRequest(ctx, contentLength, copySource, options, blobHTTPHeaders, leaseAccessConditions, cpkInfo, cpkScopeInfo, modifiedAccessConditions, sourceModifiedAccessConditions) + if err != nil { + return BlockBlobClientPutBlobFromURLResponse{}, err + } + resp, err := client.internal.Pipeline().Do(req) + if err != nil { + return BlockBlobClientPutBlobFromURLResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusCreated) { + return BlockBlobClientPutBlobFromURLResponse{}, runtime.NewResponseError(resp) + } + return client.putBlobFromURLHandleResponse(resp) +} + +// putBlobFromURLCreateRequest creates the PutBlobFromURL request. +func (client *BlockBlobClient) putBlobFromURLCreateRequest(ctx context.Context, contentLength int64, copySource string, options *BlockBlobClientPutBlobFromURLOptions, blobHTTPHeaders *BlobHTTPHeaders, leaseAccessConditions *LeaseAccessConditions, cpkInfo *CPKInfo, cpkScopeInfo *CPKScopeInfo, modifiedAccessConditions *ModifiedAccessConditions, sourceModifiedAccessConditions *SourceModifiedAccessConditions) (*policy.Request, error) { + req, err := runtime.NewRequest(ctx, http.MethodPut, client.endpoint) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + if options != nil && options.Timeout != nil { + reqQP.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + } + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["x-ms-blob-type"] = []string{"BlockBlob"} + if options != nil && options.TransactionalContentMD5 != nil { + req.Raw().Header["Content-MD5"] = []string{base64.StdEncoding.EncodeToString(options.TransactionalContentMD5)} + } + req.Raw().Header["Content-Length"] = []string{strconv.FormatInt(contentLength, 10)} + if blobHTTPHeaders != nil && blobHTTPHeaders.BlobContentType != nil { + req.Raw().Header["x-ms-blob-content-type"] = []string{*blobHTTPHeaders.BlobContentType} + } + if blobHTTPHeaders != nil && blobHTTPHeaders.BlobContentEncoding != nil { + req.Raw().Header["x-ms-blob-content-encoding"] = []string{*blobHTTPHeaders.BlobContentEncoding} + } + if blobHTTPHeaders != nil && blobHTTPHeaders.BlobContentLanguage != nil { + req.Raw().Header["x-ms-blob-content-language"] = []string{*blobHTTPHeaders.BlobContentLanguage} + } + if blobHTTPHeaders != nil && blobHTTPHeaders.BlobContentMD5 != nil { + req.Raw().Header["x-ms-blob-content-md5"] = []string{base64.StdEncoding.EncodeToString(blobHTTPHeaders.BlobContentMD5)} + } + if blobHTTPHeaders != nil && blobHTTPHeaders.BlobCacheControl != nil { + req.Raw().Header["x-ms-blob-cache-control"] = []string{*blobHTTPHeaders.BlobCacheControl} + } + if options != nil && options.Metadata != nil { + for k, v := range options.Metadata { + if v != nil { + req.Raw().Header["x-ms-meta-"+k] = []string{*v} + } + } + } + if leaseAccessConditions != nil && leaseAccessConditions.LeaseID != nil { + req.Raw().Header["x-ms-lease-id"] = []string{*leaseAccessConditions.LeaseID} + } + if blobHTTPHeaders != nil && blobHTTPHeaders.BlobContentDisposition != nil { + req.Raw().Header["x-ms-blob-content-disposition"] = []string{*blobHTTPHeaders.BlobContentDisposition} + } + if cpkInfo != nil && cpkInfo.EncryptionKey != nil { + req.Raw().Header["x-ms-encryption-key"] = []string{*cpkInfo.EncryptionKey} + } + if cpkInfo != nil && cpkInfo.EncryptionKeySHA256 != nil { + req.Raw().Header["x-ms-encryption-key-sha256"] = []string{*cpkInfo.EncryptionKeySHA256} + } + if cpkInfo != nil && cpkInfo.EncryptionAlgorithm != nil { + req.Raw().Header["x-ms-encryption-algorithm"] = []string{string(*cpkInfo.EncryptionAlgorithm)} + } + if cpkScopeInfo != nil && cpkScopeInfo.EncryptionScope != nil { + req.Raw().Header["x-ms-encryption-scope"] = []string{*cpkScopeInfo.EncryptionScope} + } + if options != nil && options.Tier != nil { + req.Raw().Header["x-ms-access-tier"] = []string{string(*options.Tier)} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfModifiedSince != nil { + req.Raw().Header["If-Modified-Since"] = []string{(*modifiedAccessConditions.IfModifiedSince).In(gmt).Format(time.RFC1123)} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfUnmodifiedSince != nil { + req.Raw().Header["If-Unmodified-Since"] = []string{(*modifiedAccessConditions.IfUnmodifiedSince).In(gmt).Format(time.RFC1123)} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfMatch != nil { + req.Raw().Header["If-Match"] = []string{string(*modifiedAccessConditions.IfMatch)} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfNoneMatch != nil { + req.Raw().Header["If-None-Match"] = []string{string(*modifiedAccessConditions.IfNoneMatch)} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfTags != nil { + req.Raw().Header["x-ms-if-tags"] = []string{*modifiedAccessConditions.IfTags} + } + if sourceModifiedAccessConditions != nil && sourceModifiedAccessConditions.SourceIfModifiedSince != nil { + req.Raw().Header["x-ms-source-if-modified-since"] = []string{(*sourceModifiedAccessConditions.SourceIfModifiedSince).In(gmt).Format(time.RFC1123)} + } + if sourceModifiedAccessConditions != nil && sourceModifiedAccessConditions.SourceIfUnmodifiedSince != nil { + req.Raw().Header["x-ms-source-if-unmodified-since"] = []string{(*sourceModifiedAccessConditions.SourceIfUnmodifiedSince).In(gmt).Format(time.RFC1123)} + } + if sourceModifiedAccessConditions != nil && sourceModifiedAccessConditions.SourceIfMatch != nil { + req.Raw().Header["x-ms-source-if-match"] = []string{string(*sourceModifiedAccessConditions.SourceIfMatch)} + } + if sourceModifiedAccessConditions != nil && sourceModifiedAccessConditions.SourceIfNoneMatch != nil { + req.Raw().Header["x-ms-source-if-none-match"] = []string{string(*sourceModifiedAccessConditions.SourceIfNoneMatch)} + } + if sourceModifiedAccessConditions != nil && sourceModifiedAccessConditions.SourceIfTags != nil { + req.Raw().Header["x-ms-source-if-tags"] = []string{*sourceModifiedAccessConditions.SourceIfTags} + } + req.Raw().Header["x-ms-version"] = []string{"2020-10-02"} + if options != nil && options.RequestID != nil { + req.Raw().Header["x-ms-client-request-id"] = []string{*options.RequestID} + } + if options != nil && options.SourceContentMD5 != nil { + req.Raw().Header["x-ms-source-content-md5"] = []string{base64.StdEncoding.EncodeToString(options.SourceContentMD5)} + } + if options != nil && options.BlobTagsString != nil { + req.Raw().Header["x-ms-tags"] = []string{*options.BlobTagsString} + } + req.Raw().Header["x-ms-copy-source"] = []string{copySource} + if options != nil && options.CopySourcePathProperties != nil { + req.Raw().Header["x-ms-copy-source-blob-properties"] = []string{strconv.FormatBool(*options.CopySourcePathProperties)} + } + if options != nil && options.CopySourceAuthorization != nil { + req.Raw().Header["x-ms-copy-source-authorization"] = []string{*options.CopySourceAuthorization} + } + req.Raw().Header["Accept"] = []string{"application/xml"} + return req, nil +} + +// putBlobFromURLHandleResponse handles the PutBlobFromURL response. +func (client *BlockBlobClient) putBlobFromURLHandleResponse(resp *http.Response) (BlockBlobClientPutBlobFromURLResponse, error) { + result := BlockBlobClientPutBlobFromURLResponse{} + if val := resp.Header.Get("ETag"); val != "" { + result.ETag = (*azcore.ETag)(&val) + } + if val := resp.Header.Get("Last-Modified"); val != "" { + lastModified, err := time.Parse(time.RFC1123, val) + if err != nil { + return BlockBlobClientPutBlobFromURLResponse{}, err + } + result.LastModified = &lastModified + } + if val := resp.Header.Get("Content-MD5"); val != "" { + contentMD5, err := base64.StdEncoding.DecodeString(val) + if err != nil { + return BlockBlobClientPutBlobFromURLResponse{}, err + } + result.ContentMD5 = contentMD5 + } + if val := resp.Header.Get("x-ms-client-request-id"); val != "" { + result.ClientRequestID = &val + } + if val := resp.Header.Get("x-ms-request-id"); val != "" { + result.RequestID = &val + } + if val := resp.Header.Get("x-ms-version"); val != "" { + result.Version = &val + } + if val := resp.Header.Get("x-ms-version-id"); val != "" { + result.VersionID = &val + } + if val := resp.Header.Get("Date"); val != "" { + date, err := time.Parse(time.RFC1123, val) + if err != nil { + return BlockBlobClientPutBlobFromURLResponse{}, err + } + result.Date = &date + } + if val := resp.Header.Get("x-ms-request-server-encrypted"); val != "" { + isServerEncrypted, err := strconv.ParseBool(val) + if err != nil { + return BlockBlobClientPutBlobFromURLResponse{}, err + } + result.IsServerEncrypted = &isServerEncrypted + } + if val := resp.Header.Get("x-ms-encryption-key-sha256"); val != "" { + result.EncryptionKeySHA256 = &val + } + if val := resp.Header.Get("x-ms-encryption-scope"); val != "" { + result.EncryptionScope = &val + } + return result, nil +} + +// StageBlock - The Stage Block operation creates a new block to be committed as part of a blob +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2020-10-02 +// - blockID - A valid Base64 string value that identifies the block. Prior to encoding, the string must be less than or equal +// to 64 bytes in size. For a given blob, the length of the value specified for the blockid +// parameter must be the same size for each block. +// - contentLength - The length of the request. +// - body - Initial data +// - options - BlockBlobClientStageBlockOptions contains the optional parameters for the BlockBlobClient.StageBlock method. +// - LeaseAccessConditions - LeaseAccessConditions contains a group of parameters for the ContainerClient.GetProperties method. +// - CPKInfo - CPKInfo contains a group of parameters for the BlobClient.Download method. +// - CPKScopeInfo - CPKScopeInfo contains a group of parameters for the BlobClient.SetMetadata method. +func (client *BlockBlobClient) StageBlock(ctx context.Context, blockID string, contentLength int64, body io.ReadSeekCloser, options *BlockBlobClientStageBlockOptions, leaseAccessConditions *LeaseAccessConditions, cpkInfo *CPKInfo, cpkScopeInfo *CPKScopeInfo) (BlockBlobClientStageBlockResponse, error) { + req, err := client.stageBlockCreateRequest(ctx, blockID, contentLength, body, options, leaseAccessConditions, cpkInfo, cpkScopeInfo) + if err != nil { + return BlockBlobClientStageBlockResponse{}, err + } + resp, err := client.internal.Pipeline().Do(req) + if err != nil { + return BlockBlobClientStageBlockResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusCreated) { + return BlockBlobClientStageBlockResponse{}, runtime.NewResponseError(resp) + } + return client.stageBlockHandleResponse(resp) +} + +// stageBlockCreateRequest creates the StageBlock request. +func (client *BlockBlobClient) stageBlockCreateRequest(ctx context.Context, blockID string, contentLength int64, body io.ReadSeekCloser, options *BlockBlobClientStageBlockOptions, leaseAccessConditions *LeaseAccessConditions, cpkInfo *CPKInfo, cpkScopeInfo *CPKScopeInfo) (*policy.Request, error) { + req, err := runtime.NewRequest(ctx, http.MethodPut, client.endpoint) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("comp", "block") + reqQP.Set("blockid", blockID) + if options != nil && options.Timeout != nil { + reqQP.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + } + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["Content-Length"] = []string{strconv.FormatInt(contentLength, 10)} + if options != nil && options.TransactionalContentMD5 != nil { + req.Raw().Header["Content-MD5"] = []string{base64.StdEncoding.EncodeToString(options.TransactionalContentMD5)} + } + if options != nil && options.TransactionalContentCRC64 != nil { + req.Raw().Header["x-ms-content-crc64"] = []string{base64.StdEncoding.EncodeToString(options.TransactionalContentCRC64)} + } + if leaseAccessConditions != nil && leaseAccessConditions.LeaseID != nil { + req.Raw().Header["x-ms-lease-id"] = []string{*leaseAccessConditions.LeaseID} + } + if cpkInfo != nil && cpkInfo.EncryptionKey != nil { + req.Raw().Header["x-ms-encryption-key"] = []string{*cpkInfo.EncryptionKey} + } + if cpkInfo != nil && cpkInfo.EncryptionKeySHA256 != nil { + req.Raw().Header["x-ms-encryption-key-sha256"] = []string{*cpkInfo.EncryptionKeySHA256} + } + if cpkInfo != nil && cpkInfo.EncryptionAlgorithm != nil { + req.Raw().Header["x-ms-encryption-algorithm"] = []string{string(*cpkInfo.EncryptionAlgorithm)} + } + if cpkScopeInfo != nil && cpkScopeInfo.EncryptionScope != nil { + req.Raw().Header["x-ms-encryption-scope"] = []string{*cpkScopeInfo.EncryptionScope} + } + req.Raw().Header["x-ms-version"] = []string{"2020-10-02"} + if options != nil && options.RequestID != nil { + req.Raw().Header["x-ms-client-request-id"] = []string{*options.RequestID} + } + req.Raw().Header["Accept"] = []string{"application/xml"} + if err := req.SetBody(body, "application/octet-stream"); err != nil { + return nil, err + } + return req, nil +} + +// stageBlockHandleResponse handles the StageBlock response. +func (client *BlockBlobClient) stageBlockHandleResponse(resp *http.Response) (BlockBlobClientStageBlockResponse, error) { + result := BlockBlobClientStageBlockResponse{} + if val := resp.Header.Get("Content-MD5"); val != "" { + contentMD5, err := base64.StdEncoding.DecodeString(val) + if err != nil { + return BlockBlobClientStageBlockResponse{}, err + } + result.ContentMD5 = contentMD5 + } + if val := resp.Header.Get("x-ms-client-request-id"); val != "" { + result.ClientRequestID = &val + } + if val := resp.Header.Get("x-ms-request-id"); val != "" { + result.RequestID = &val + } + if val := resp.Header.Get("x-ms-version"); val != "" { + result.Version = &val + } + if val := resp.Header.Get("Date"); val != "" { + date, err := time.Parse(time.RFC1123, val) + if err != nil { + return BlockBlobClientStageBlockResponse{}, err + } + result.Date = &date + } + if val := resp.Header.Get("x-ms-content-crc64"); val != "" { + contentCRC64, err := base64.StdEncoding.DecodeString(val) + if err != nil { + return BlockBlobClientStageBlockResponse{}, err + } + result.ContentCRC64 = contentCRC64 + } + if val := resp.Header.Get("x-ms-request-server-encrypted"); val != "" { + isServerEncrypted, err := strconv.ParseBool(val) + if err != nil { + return BlockBlobClientStageBlockResponse{}, err + } + result.IsServerEncrypted = &isServerEncrypted + } + if val := resp.Header.Get("x-ms-encryption-key-sha256"); val != "" { + result.EncryptionKeySHA256 = &val + } + if val := resp.Header.Get("x-ms-encryption-scope"); val != "" { + result.EncryptionScope = &val + } + return result, nil +} + +// StageBlockFromURL - The Stage Block operation creates a new block to be committed as part of a blob where the contents +// are read from a URL. +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2020-10-02 +// - blockID - A valid Base64 string value that identifies the block. Prior to encoding, the string must be less than or equal +// to 64 bytes in size. For a given blob, the length of the value specified for the blockid +// parameter must be the same size for each block. +// - contentLength - The length of the request. +// - sourceURL - Specify a URL to the copy source. +// - options - BlockBlobClientStageBlockFromURLOptions contains the optional parameters for the BlockBlobClient.StageBlockFromURL +// method. +// - CPKInfo - CPKInfo contains a group of parameters for the BlobClient.Download method. +// - CPKScopeInfo - CPKScopeInfo contains a group of parameters for the BlobClient.SetMetadata method. +// - LeaseAccessConditions - LeaseAccessConditions contains a group of parameters for the ContainerClient.GetProperties method. +// - SourceModifiedAccessConditions - SourceModifiedAccessConditions contains a group of parameters for the BlobClient.StartCopyFromURL +// method. +func (client *BlockBlobClient) StageBlockFromURL(ctx context.Context, blockID string, contentLength int64, sourceURL string, options *BlockBlobClientStageBlockFromURLOptions, cpkInfo *CPKInfo, cpkScopeInfo *CPKScopeInfo, leaseAccessConditions *LeaseAccessConditions, sourceModifiedAccessConditions *SourceModifiedAccessConditions) (BlockBlobClientStageBlockFromURLResponse, error) { + req, err := client.stageBlockFromURLCreateRequest(ctx, blockID, contentLength, sourceURL, options, cpkInfo, cpkScopeInfo, leaseAccessConditions, sourceModifiedAccessConditions) + if err != nil { + return BlockBlobClientStageBlockFromURLResponse{}, err + } + resp, err := client.internal.Pipeline().Do(req) + if err != nil { + return BlockBlobClientStageBlockFromURLResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusCreated) { + return BlockBlobClientStageBlockFromURLResponse{}, runtime.NewResponseError(resp) + } + return client.stageBlockFromURLHandleResponse(resp) +} + +// stageBlockFromURLCreateRequest creates the StageBlockFromURL request. +func (client *BlockBlobClient) stageBlockFromURLCreateRequest(ctx context.Context, blockID string, contentLength int64, sourceURL string, options *BlockBlobClientStageBlockFromURLOptions, cpkInfo *CPKInfo, cpkScopeInfo *CPKScopeInfo, leaseAccessConditions *LeaseAccessConditions, sourceModifiedAccessConditions *SourceModifiedAccessConditions) (*policy.Request, error) { + req, err := runtime.NewRequest(ctx, http.MethodPut, client.endpoint) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("comp", "block") + reqQP.Set("blockid", blockID) + if options != nil && options.Timeout != nil { + reqQP.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + } + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["Content-Length"] = []string{strconv.FormatInt(contentLength, 10)} + req.Raw().Header["x-ms-copy-source"] = []string{sourceURL} + if options != nil && options.SourceRange != nil { + req.Raw().Header["x-ms-source-range"] = []string{*options.SourceRange} + } + if options != nil && options.SourceContentMD5 != nil { + req.Raw().Header["x-ms-source-content-md5"] = []string{base64.StdEncoding.EncodeToString(options.SourceContentMD5)} + } + if options != nil && options.SourceContentcrc64 != nil { + req.Raw().Header["x-ms-source-content-crc64"] = []string{base64.StdEncoding.EncodeToString(options.SourceContentcrc64)} + } + if cpkInfo != nil && cpkInfo.EncryptionKey != nil { + req.Raw().Header["x-ms-encryption-key"] = []string{*cpkInfo.EncryptionKey} + } + if cpkInfo != nil && cpkInfo.EncryptionKeySHA256 != nil { + req.Raw().Header["x-ms-encryption-key-sha256"] = []string{*cpkInfo.EncryptionKeySHA256} + } + if cpkInfo != nil && cpkInfo.EncryptionAlgorithm != nil { + req.Raw().Header["x-ms-encryption-algorithm"] = []string{string(*cpkInfo.EncryptionAlgorithm)} + } + if cpkScopeInfo != nil && cpkScopeInfo.EncryptionScope != nil { + req.Raw().Header["x-ms-encryption-scope"] = []string{*cpkScopeInfo.EncryptionScope} + } + if leaseAccessConditions != nil && leaseAccessConditions.LeaseID != nil { + req.Raw().Header["x-ms-lease-id"] = []string{*leaseAccessConditions.LeaseID} + } + if sourceModifiedAccessConditions != nil && sourceModifiedAccessConditions.SourceIfModifiedSince != nil { + req.Raw().Header["x-ms-source-if-modified-since"] = []string{(*sourceModifiedAccessConditions.SourceIfModifiedSince).In(gmt).Format(time.RFC1123)} + } + if sourceModifiedAccessConditions != nil && sourceModifiedAccessConditions.SourceIfUnmodifiedSince != nil { + req.Raw().Header["x-ms-source-if-unmodified-since"] = []string{(*sourceModifiedAccessConditions.SourceIfUnmodifiedSince).In(gmt).Format(time.RFC1123)} + } + if sourceModifiedAccessConditions != nil && sourceModifiedAccessConditions.SourceIfMatch != nil { + req.Raw().Header["x-ms-source-if-match"] = []string{string(*sourceModifiedAccessConditions.SourceIfMatch)} + } + if sourceModifiedAccessConditions != nil && sourceModifiedAccessConditions.SourceIfNoneMatch != nil { + req.Raw().Header["x-ms-source-if-none-match"] = []string{string(*sourceModifiedAccessConditions.SourceIfNoneMatch)} + } + req.Raw().Header["x-ms-version"] = []string{"2020-10-02"} + if options != nil && options.RequestID != nil { + req.Raw().Header["x-ms-client-request-id"] = []string{*options.RequestID} + } + if options != nil && options.CopySourceAuthorization != nil { + req.Raw().Header["x-ms-copy-source-authorization"] = []string{*options.CopySourceAuthorization} + } + req.Raw().Header["Accept"] = []string{"application/xml"} + return req, nil +} + +// stageBlockFromURLHandleResponse handles the StageBlockFromURL response. +func (client *BlockBlobClient) stageBlockFromURLHandleResponse(resp *http.Response) (BlockBlobClientStageBlockFromURLResponse, error) { + result := BlockBlobClientStageBlockFromURLResponse{} + if val := resp.Header.Get("Content-MD5"); val != "" { + contentMD5, err := base64.StdEncoding.DecodeString(val) + if err != nil { + return BlockBlobClientStageBlockFromURLResponse{}, err + } + result.ContentMD5 = contentMD5 + } + if val := resp.Header.Get("x-ms-content-crc64"); val != "" { + contentCRC64, err := base64.StdEncoding.DecodeString(val) + if err != nil { + return BlockBlobClientStageBlockFromURLResponse{}, err + } + result.ContentCRC64 = contentCRC64 + } + if val := resp.Header.Get("x-ms-client-request-id"); val != "" { + result.ClientRequestID = &val + } + if val := resp.Header.Get("x-ms-request-id"); val != "" { + result.RequestID = &val + } + if val := resp.Header.Get("x-ms-version"); val != "" { + result.Version = &val + } + if val := resp.Header.Get("Date"); val != "" { + date, err := time.Parse(time.RFC1123, val) + if err != nil { + return BlockBlobClientStageBlockFromURLResponse{}, err + } + result.Date = &date + } + if val := resp.Header.Get("x-ms-request-server-encrypted"); val != "" { + isServerEncrypted, err := strconv.ParseBool(val) + if err != nil { + return BlockBlobClientStageBlockFromURLResponse{}, err + } + result.IsServerEncrypted = &isServerEncrypted + } + if val := resp.Header.Get("x-ms-encryption-key-sha256"); val != "" { + result.EncryptionKeySHA256 = &val + } + if val := resp.Header.Get("x-ms-encryption-scope"); val != "" { + result.EncryptionScope = &val + } + return result, nil +} + +// Upload - The Upload Block Blob operation updates the content of an existing block blob. Updating an existing block blob +// overwrites any existing metadata on the blob. Partial updates are not supported with Put +// Blob; the content of the existing blob is overwritten with the content of the new blob. To perform a partial update of +// the content of a block blob, use the Put Block List operation. +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2020-10-02 +// - contentLength - The length of the request. +// - body - Initial data +// - options - BlockBlobClientUploadOptions contains the optional parameters for the BlockBlobClient.Upload method. +// - BlobHTTPHeaders - BlobHTTPHeaders contains a group of parameters for the BlobClient.SetHTTPHeaders method. +// - LeaseAccessConditions - LeaseAccessConditions contains a group of parameters for the ContainerClient.GetProperties method. +// - CPKInfo - CPKInfo contains a group of parameters for the BlobClient.Download method. +// - CPKScopeInfo - CPKScopeInfo contains a group of parameters for the BlobClient.SetMetadata method. +// - ModifiedAccessConditions - ModifiedAccessConditions contains a group of parameters for the ContainerClient.Delete method. +func (client *BlockBlobClient) Upload(ctx context.Context, contentLength int64, body io.ReadSeekCloser, options *BlockBlobClientUploadOptions, blobHTTPHeaders *BlobHTTPHeaders, leaseAccessConditions *LeaseAccessConditions, cpkInfo *CPKInfo, cpkScopeInfo *CPKScopeInfo, modifiedAccessConditions *ModifiedAccessConditions) (BlockBlobClientUploadResponse, error) { + req, err := client.uploadCreateRequest(ctx, contentLength, body, options, blobHTTPHeaders, leaseAccessConditions, cpkInfo, cpkScopeInfo, modifiedAccessConditions) + if err != nil { + return BlockBlobClientUploadResponse{}, err + } + resp, err := client.internal.Pipeline().Do(req) + if err != nil { + return BlockBlobClientUploadResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusCreated) { + return BlockBlobClientUploadResponse{}, runtime.NewResponseError(resp) + } + return client.uploadHandleResponse(resp) +} + +// uploadCreateRequest creates the Upload request. +func (client *BlockBlobClient) uploadCreateRequest(ctx context.Context, contentLength int64, body io.ReadSeekCloser, options *BlockBlobClientUploadOptions, blobHTTPHeaders *BlobHTTPHeaders, leaseAccessConditions *LeaseAccessConditions, cpkInfo *CPKInfo, cpkScopeInfo *CPKScopeInfo, modifiedAccessConditions *ModifiedAccessConditions) (*policy.Request, error) { + req, err := runtime.NewRequest(ctx, http.MethodPut, client.endpoint) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + if options != nil && options.Timeout != nil { + reqQP.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + } + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["x-ms-blob-type"] = []string{"BlockBlob"} + if options != nil && options.TransactionalContentMD5 != nil { + req.Raw().Header["Content-MD5"] = []string{base64.StdEncoding.EncodeToString(options.TransactionalContentMD5)} + } + req.Raw().Header["Content-Length"] = []string{strconv.FormatInt(contentLength, 10)} + if blobHTTPHeaders != nil && blobHTTPHeaders.BlobContentType != nil { + req.Raw().Header["x-ms-blob-content-type"] = []string{*blobHTTPHeaders.BlobContentType} + } + if blobHTTPHeaders != nil && blobHTTPHeaders.BlobContentEncoding != nil { + req.Raw().Header["x-ms-blob-content-encoding"] = []string{*blobHTTPHeaders.BlobContentEncoding} + } + if blobHTTPHeaders != nil && blobHTTPHeaders.BlobContentLanguage != nil { + req.Raw().Header["x-ms-blob-content-language"] = []string{*blobHTTPHeaders.BlobContentLanguage} + } + if blobHTTPHeaders != nil && blobHTTPHeaders.BlobContentMD5 != nil { + req.Raw().Header["x-ms-blob-content-md5"] = []string{base64.StdEncoding.EncodeToString(blobHTTPHeaders.BlobContentMD5)} + } + if blobHTTPHeaders != nil && blobHTTPHeaders.BlobCacheControl != nil { + req.Raw().Header["x-ms-blob-cache-control"] = []string{*blobHTTPHeaders.BlobCacheControl} + } + if options != nil && options.Metadata != nil { + for k, v := range options.Metadata { + if v != nil { + req.Raw().Header["x-ms-meta-"+k] = []string{*v} + } + } + } + if leaseAccessConditions != nil && leaseAccessConditions.LeaseID != nil { + req.Raw().Header["x-ms-lease-id"] = []string{*leaseAccessConditions.LeaseID} + } + if blobHTTPHeaders != nil && blobHTTPHeaders.BlobContentDisposition != nil { + req.Raw().Header["x-ms-blob-content-disposition"] = []string{*blobHTTPHeaders.BlobContentDisposition} + } + if cpkInfo != nil && cpkInfo.EncryptionKey != nil { + req.Raw().Header["x-ms-encryption-key"] = []string{*cpkInfo.EncryptionKey} + } + if cpkInfo != nil && cpkInfo.EncryptionKeySHA256 != nil { + req.Raw().Header["x-ms-encryption-key-sha256"] = []string{*cpkInfo.EncryptionKeySHA256} + } + if cpkInfo != nil && cpkInfo.EncryptionAlgorithm != nil { + req.Raw().Header["x-ms-encryption-algorithm"] = []string{string(*cpkInfo.EncryptionAlgorithm)} + } + if cpkScopeInfo != nil && cpkScopeInfo.EncryptionScope != nil { + req.Raw().Header["x-ms-encryption-scope"] = []string{*cpkScopeInfo.EncryptionScope} + } + if options != nil && options.Tier != nil { + req.Raw().Header["x-ms-access-tier"] = []string{string(*options.Tier)} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfModifiedSince != nil { + req.Raw().Header["If-Modified-Since"] = []string{(*modifiedAccessConditions.IfModifiedSince).In(gmt).Format(time.RFC1123)} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfUnmodifiedSince != nil { + req.Raw().Header["If-Unmodified-Since"] = []string{(*modifiedAccessConditions.IfUnmodifiedSince).In(gmt).Format(time.RFC1123)} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfMatch != nil { + req.Raw().Header["If-Match"] = []string{string(*modifiedAccessConditions.IfMatch)} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfNoneMatch != nil { + req.Raw().Header["If-None-Match"] = []string{string(*modifiedAccessConditions.IfNoneMatch)} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfTags != nil { + req.Raw().Header["x-ms-if-tags"] = []string{*modifiedAccessConditions.IfTags} + } + req.Raw().Header["x-ms-version"] = []string{"2020-10-02"} + if options != nil && options.RequestID != nil { + req.Raw().Header["x-ms-client-request-id"] = []string{*options.RequestID} + } + if options != nil && options.BlobTagsString != nil { + req.Raw().Header["x-ms-tags"] = []string{*options.BlobTagsString} + } + if options != nil && options.ImmutabilityPolicyExpiry != nil { + req.Raw().Header["x-ms-immutability-policy-until-date"] = []string{(*options.ImmutabilityPolicyExpiry).In(gmt).Format(time.RFC1123)} + } + if options != nil && options.ImmutabilityPolicyMode != nil { + req.Raw().Header["x-ms-immutability-policy-mode"] = []string{string(*options.ImmutabilityPolicyMode)} + } + if options != nil && options.LegalHold != nil { + req.Raw().Header["x-ms-legal-hold"] = []string{strconv.FormatBool(*options.LegalHold)} + } + req.Raw().Header["Accept"] = []string{"application/xml"} + if err := req.SetBody(body, "application/octet-stream"); err != nil { + return nil, err + } + return req, nil +} + +// uploadHandleResponse handles the Upload response. +func (client *BlockBlobClient) uploadHandleResponse(resp *http.Response) (BlockBlobClientUploadResponse, error) { + result := BlockBlobClientUploadResponse{} + if val := resp.Header.Get("ETag"); val != "" { + result.ETag = (*azcore.ETag)(&val) + } + if val := resp.Header.Get("Last-Modified"); val != "" { + lastModified, err := time.Parse(time.RFC1123, val) + if err != nil { + return BlockBlobClientUploadResponse{}, err + } + result.LastModified = &lastModified + } + if val := resp.Header.Get("Content-MD5"); val != "" { + contentMD5, err := base64.StdEncoding.DecodeString(val) + if err != nil { + return BlockBlobClientUploadResponse{}, err + } + result.ContentMD5 = contentMD5 + } + if val := resp.Header.Get("x-ms-client-request-id"); val != "" { + result.ClientRequestID = &val + } + if val := resp.Header.Get("x-ms-request-id"); val != "" { + result.RequestID = &val + } + if val := resp.Header.Get("x-ms-version"); val != "" { + result.Version = &val + } + if val := resp.Header.Get("x-ms-version-id"); val != "" { + result.VersionID = &val + } + if val := resp.Header.Get("Date"); val != "" { + date, err := time.Parse(time.RFC1123, val) + if err != nil { + return BlockBlobClientUploadResponse{}, err + } + result.Date = &date + } + if val := resp.Header.Get("x-ms-request-server-encrypted"); val != "" { + isServerEncrypted, err := strconv.ParseBool(val) + if err != nil { + return BlockBlobClientUploadResponse{}, err + } + result.IsServerEncrypted = &isServerEncrypted + } + if val := resp.Header.Get("x-ms-encryption-key-sha256"); val != "" { + result.EncryptionKeySHA256 = &val + } + if val := resp.Header.Get("x-ms-encryption-scope"); val != "" { + result.EncryptionScope = &val + } + return result, nil +} diff --git a/sdk/storage/azdatalake/internal/generated_blob/zz_constants.go b/sdk/storage/azdatalake/internal/generated_blob/zz_constants.go new file mode 100644 index 000000000000..aba25231b855 --- /dev/null +++ b/sdk/storage/azdatalake/internal/generated_blob/zz_constants.go @@ -0,0 +1,714 @@ +//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. +// Code generated by Microsoft (R) AutoRest Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. +// DO NOT EDIT. + +package generated_blob + +type AccessTier string + +const ( + AccessTierArchive AccessTier = "Archive" + AccessTierCool AccessTier = "Cool" + AccessTierHot AccessTier = "Hot" + AccessTierP10 AccessTier = "P10" + AccessTierP15 AccessTier = "P15" + AccessTierP20 AccessTier = "P20" + AccessTierP30 AccessTier = "P30" + AccessTierP4 AccessTier = "P4" + AccessTierP40 AccessTier = "P40" + AccessTierP50 AccessTier = "P50" + AccessTierP6 AccessTier = "P6" + AccessTierP60 AccessTier = "P60" + AccessTierP70 AccessTier = "P70" + AccessTierP80 AccessTier = "P80" + AccessTierPremium AccessTier = "Premium" +) + +// PossibleAccessTierValues returns the possible values for the AccessTier const type. +func PossibleAccessTierValues() []AccessTier { + return []AccessTier{ + AccessTierArchive, + AccessTierCool, + AccessTierHot, + AccessTierP10, + AccessTierP15, + AccessTierP20, + AccessTierP30, + AccessTierP4, + AccessTierP40, + AccessTierP50, + AccessTierP6, + AccessTierP60, + AccessTierP70, + AccessTierP80, + AccessTierPremium, + } +} + +type AccountKind string + +const ( + AccountKindBlobStorage AccountKind = "BlobStorage" + AccountKindBlockBlobStorage AccountKind = "BlockBlobStorage" + AccountKindFileStorage AccountKind = "FileStorage" + AccountKindStorage AccountKind = "Storage" + AccountKindStorageV2 AccountKind = "StorageV2" +) + +// PossibleAccountKindValues returns the possible values for the AccountKind const type. +func PossibleAccountKindValues() []AccountKind { + return []AccountKind{ + AccountKindBlobStorage, + AccountKindBlockBlobStorage, + AccountKindFileStorage, + AccountKindStorage, + AccountKindStorageV2, + } +} + +type ArchiveStatus string + +const ( + ArchiveStatusRehydratePendingToCool ArchiveStatus = "rehydrate-pending-to-cool" + ArchiveStatusRehydratePendingToHot ArchiveStatus = "rehydrate-pending-to-hot" +) + +// PossibleArchiveStatusValues returns the possible values for the ArchiveStatus const type. +func PossibleArchiveStatusValues() []ArchiveStatus { + return []ArchiveStatus{ + ArchiveStatusRehydratePendingToCool, + ArchiveStatusRehydratePendingToHot, + } +} + +// BlobGeoReplicationStatus - The status of the secondary location +type BlobGeoReplicationStatus string + +const ( + BlobGeoReplicationStatusBootstrap BlobGeoReplicationStatus = "bootstrap" + BlobGeoReplicationStatusLive BlobGeoReplicationStatus = "live" + BlobGeoReplicationStatusUnavailable BlobGeoReplicationStatus = "unavailable" +) + +// PossibleBlobGeoReplicationStatusValues returns the possible values for the BlobGeoReplicationStatus const type. +func PossibleBlobGeoReplicationStatusValues() []BlobGeoReplicationStatus { + return []BlobGeoReplicationStatus{ + BlobGeoReplicationStatusBootstrap, + BlobGeoReplicationStatusLive, + BlobGeoReplicationStatusUnavailable, + } +} + +type BlobType string + +const ( + BlobTypeAppendBlob BlobType = "AppendBlob" + BlobTypeBlockBlob BlobType = "BlockBlob" + BlobTypePageBlob BlobType = "PageBlob" +) + +// PossibleBlobTypeValues returns the possible values for the BlobType const type. +func PossibleBlobTypeValues() []BlobType { + return []BlobType{ + BlobTypeAppendBlob, + BlobTypeBlockBlob, + BlobTypePageBlob, + } +} + +type BlockListType string + +const ( + BlockListTypeAll BlockListType = "all" + BlockListTypeCommitted BlockListType = "committed" + BlockListTypeUncommitted BlockListType = "uncommitted" +) + +// PossibleBlockListTypeValues returns the possible values for the BlockListType const type. +func PossibleBlockListTypeValues() []BlockListType { + return []BlockListType{ + BlockListTypeAll, + BlockListTypeCommitted, + BlockListTypeUncommitted, + } +} + +type CopyStatusType string + +const ( + CopyStatusTypeAborted CopyStatusType = "aborted" + CopyStatusTypeFailed CopyStatusType = "failed" + CopyStatusTypePending CopyStatusType = "pending" + CopyStatusTypeSuccess CopyStatusType = "success" +) + +// PossibleCopyStatusTypeValues returns the possible values for the CopyStatusType const type. +func PossibleCopyStatusTypeValues() []CopyStatusType { + return []CopyStatusType{ + CopyStatusTypeAborted, + CopyStatusTypeFailed, + CopyStatusTypePending, + CopyStatusTypeSuccess, + } +} + +type DeleteSnapshotsOptionType string + +const ( + DeleteSnapshotsOptionTypeInclude DeleteSnapshotsOptionType = "include" + DeleteSnapshotsOptionTypeOnly DeleteSnapshotsOptionType = "only" +) + +// PossibleDeleteSnapshotsOptionTypeValues returns the possible values for the DeleteSnapshotsOptionType const type. +func PossibleDeleteSnapshotsOptionTypeValues() []DeleteSnapshotsOptionType { + return []DeleteSnapshotsOptionType{ + DeleteSnapshotsOptionTypeInclude, + DeleteSnapshotsOptionTypeOnly, + } +} + +type DeleteType string + +const ( + DeleteTypeNone DeleteType = "None" + DeleteTypePermanent DeleteType = "Permanent" +) + +// PossibleDeleteTypeValues returns the possible values for the DeleteType const type. +func PossibleDeleteTypeValues() []DeleteType { + return []DeleteType{ + DeleteTypeNone, + DeleteTypePermanent, + } +} + +type EncryptionAlgorithmType string + +const ( + EncryptionAlgorithmTypeAES256 EncryptionAlgorithmType = "AES256" + EncryptionAlgorithmTypeNone EncryptionAlgorithmType = "None" +) + +// PossibleEncryptionAlgorithmTypeValues returns the possible values for the EncryptionAlgorithmType const type. +func PossibleEncryptionAlgorithmTypeValues() []EncryptionAlgorithmType { + return []EncryptionAlgorithmType{ + EncryptionAlgorithmTypeAES256, + EncryptionAlgorithmTypeNone, + } +} + +type ExpiryOptions string + +const ( + ExpiryOptionsAbsolute ExpiryOptions = "Absolute" + ExpiryOptionsNeverExpire ExpiryOptions = "NeverExpire" + ExpiryOptionsRelativeToCreation ExpiryOptions = "RelativeToCreation" + ExpiryOptionsRelativeToNow ExpiryOptions = "RelativeToNow" +) + +// PossibleExpiryOptionsValues returns the possible values for the ExpiryOptions const type. +func PossibleExpiryOptionsValues() []ExpiryOptions { + return []ExpiryOptions{ + ExpiryOptionsAbsolute, + ExpiryOptionsNeverExpire, + ExpiryOptionsRelativeToCreation, + ExpiryOptionsRelativeToNow, + } +} + +type ImmutabilityPolicyMode string + +const ( + ImmutabilityPolicyModeLocked ImmutabilityPolicyMode = "Locked" + ImmutabilityPolicyModeMutable ImmutabilityPolicyMode = "Mutable" + ImmutabilityPolicyModeUnlocked ImmutabilityPolicyMode = "Unlocked" +) + +// PossibleImmutabilityPolicyModeValues returns the possible values for the ImmutabilityPolicyMode const type. +func PossibleImmutabilityPolicyModeValues() []ImmutabilityPolicyMode { + return []ImmutabilityPolicyMode{ + ImmutabilityPolicyModeLocked, + ImmutabilityPolicyModeMutable, + ImmutabilityPolicyModeUnlocked, + } +} + +type ImmutabilityPolicySetting string + +const ( + ImmutabilityPolicySettingLocked ImmutabilityPolicySetting = "Locked" + ImmutabilityPolicySettingUnlocked ImmutabilityPolicySetting = "Unlocked" +) + +// PossibleImmutabilityPolicySettingValues returns the possible values for the ImmutabilityPolicySetting const type. +func PossibleImmutabilityPolicySettingValues() []ImmutabilityPolicySetting { + return []ImmutabilityPolicySetting{ + ImmutabilityPolicySettingLocked, + ImmutabilityPolicySettingUnlocked, + } +} + +type LeaseDurationType string + +const ( + LeaseDurationTypeFixed LeaseDurationType = "fixed" + LeaseDurationTypeInfinite LeaseDurationType = "infinite" +) + +// PossibleLeaseDurationTypeValues returns the possible values for the LeaseDurationType const type. +func PossibleLeaseDurationTypeValues() []LeaseDurationType { + return []LeaseDurationType{ + LeaseDurationTypeFixed, + LeaseDurationTypeInfinite, + } +} + +type LeaseStateType string + +const ( + LeaseStateTypeAvailable LeaseStateType = "available" + LeaseStateTypeBreaking LeaseStateType = "breaking" + LeaseStateTypeBroken LeaseStateType = "broken" + LeaseStateTypeExpired LeaseStateType = "expired" + LeaseStateTypeLeased LeaseStateType = "leased" +) + +// PossibleLeaseStateTypeValues returns the possible values for the LeaseStateType const type. +func PossibleLeaseStateTypeValues() []LeaseStateType { + return []LeaseStateType{ + LeaseStateTypeAvailable, + LeaseStateTypeBreaking, + LeaseStateTypeBroken, + LeaseStateTypeExpired, + LeaseStateTypeLeased, + } +} + +type LeaseStatusType string + +const ( + LeaseStatusTypeLocked LeaseStatusType = "locked" + LeaseStatusTypeUnlocked LeaseStatusType = "unlocked" +) + +// PossibleLeaseStatusTypeValues returns the possible values for the LeaseStatusType const type. +func PossibleLeaseStatusTypeValues() []LeaseStatusType { + return []LeaseStatusType{ + LeaseStatusTypeLocked, + LeaseStatusTypeUnlocked, + } +} + +type ListBlobsIncludeItem string + +const ( + ListBlobsIncludeItemCopy ListBlobsIncludeItem = "copy" + ListBlobsIncludeItemDeleted ListBlobsIncludeItem = "deleted" + ListBlobsIncludeItemDeletedwithversions ListBlobsIncludeItem = "deletedwithversions" + ListBlobsIncludeItemImmutabilitypolicy ListBlobsIncludeItem = "immutabilitypolicy" + ListBlobsIncludeItemLegalhold ListBlobsIncludeItem = "legalhold" + ListBlobsIncludeItemMetadata ListBlobsIncludeItem = "metadata" + ListBlobsIncludeItemSnapshots ListBlobsIncludeItem = "snapshots" + ListBlobsIncludeItemTags ListBlobsIncludeItem = "tags" + ListBlobsIncludeItemUncommittedblobs ListBlobsIncludeItem = "uncommittedblobs" + ListBlobsIncludeItemVersions ListBlobsIncludeItem = "versions" +) + +// PossibleListBlobsIncludeItemValues returns the possible values for the ListBlobsIncludeItem const type. +func PossibleListBlobsIncludeItemValues() []ListBlobsIncludeItem { + return []ListBlobsIncludeItem{ + ListBlobsIncludeItemCopy, + ListBlobsIncludeItemDeleted, + ListBlobsIncludeItemDeletedwithversions, + ListBlobsIncludeItemImmutabilitypolicy, + ListBlobsIncludeItemLegalhold, + ListBlobsIncludeItemMetadata, + ListBlobsIncludeItemSnapshots, + ListBlobsIncludeItemTags, + ListBlobsIncludeItemUncommittedblobs, + ListBlobsIncludeItemVersions, + } +} + +type ListContainersIncludeType string + +const ( + ListContainersIncludeTypeDeleted ListContainersIncludeType = "deleted" + ListContainersIncludeTypeMetadata ListContainersIncludeType = "metadata" + ListContainersIncludeTypeSystem ListContainersIncludeType = "system" +) + +// PossibleListContainersIncludeTypeValues returns the possible values for the ListContainersIncludeType const type. +func PossibleListContainersIncludeTypeValues() []ListContainersIncludeType { + return []ListContainersIncludeType{ + ListContainersIncludeTypeDeleted, + ListContainersIncludeTypeMetadata, + ListContainersIncludeTypeSystem, + } +} + +type PremiumPageBlobAccessTier string + +const ( + PremiumPageBlobAccessTierP10 PremiumPageBlobAccessTier = "P10" + PremiumPageBlobAccessTierP15 PremiumPageBlobAccessTier = "P15" + PremiumPageBlobAccessTierP20 PremiumPageBlobAccessTier = "P20" + PremiumPageBlobAccessTierP30 PremiumPageBlobAccessTier = "P30" + PremiumPageBlobAccessTierP4 PremiumPageBlobAccessTier = "P4" + PremiumPageBlobAccessTierP40 PremiumPageBlobAccessTier = "P40" + PremiumPageBlobAccessTierP50 PremiumPageBlobAccessTier = "P50" + PremiumPageBlobAccessTierP6 PremiumPageBlobAccessTier = "P6" + PremiumPageBlobAccessTierP60 PremiumPageBlobAccessTier = "P60" + PremiumPageBlobAccessTierP70 PremiumPageBlobAccessTier = "P70" + PremiumPageBlobAccessTierP80 PremiumPageBlobAccessTier = "P80" +) + +// PossiblePremiumPageBlobAccessTierValues returns the possible values for the PremiumPageBlobAccessTier const type. +func PossiblePremiumPageBlobAccessTierValues() []PremiumPageBlobAccessTier { + return []PremiumPageBlobAccessTier{ + PremiumPageBlobAccessTierP10, + PremiumPageBlobAccessTierP15, + PremiumPageBlobAccessTierP20, + PremiumPageBlobAccessTierP30, + PremiumPageBlobAccessTierP4, + PremiumPageBlobAccessTierP40, + PremiumPageBlobAccessTierP50, + PremiumPageBlobAccessTierP6, + PremiumPageBlobAccessTierP60, + PremiumPageBlobAccessTierP70, + PremiumPageBlobAccessTierP80, + } +} + +type PublicAccessType string + +const ( + PublicAccessTypeFile PublicAccessType = "blob" + PublicAccessTypeFileSystem PublicAccessType = "container" +) + +// PossiblePublicAccessTypeValues returns the possible values for the PublicAccessType const type. +func PossiblePublicAccessTypeValues() []PublicAccessType { + return []PublicAccessType{ + PublicAccessTypeFile, + PublicAccessTypeFileSystem, + } +} + +// QueryFormatType - The quick query format type. +type QueryFormatType string + +const ( + QueryFormatTypeArrow QueryFormatType = "arrow" + QueryFormatTypeDelimited QueryFormatType = "delimited" + QueryFormatTypeJSON QueryFormatType = "json" + QueryFormatTypeParquet QueryFormatType = "parquet" +) + +// PossibleQueryFormatTypeValues returns the possible values for the QueryFormatType const type. +func PossibleQueryFormatTypeValues() []QueryFormatType { + return []QueryFormatType{ + QueryFormatTypeArrow, + QueryFormatTypeDelimited, + QueryFormatTypeJSON, + QueryFormatTypeParquet, + } +} + +// RehydratePriority - If an object is in rehydrate pending state then this header is returned with priority of rehydrate. +// Valid values are High and Standard. +type RehydratePriority string + +const ( + RehydratePriorityHigh RehydratePriority = "High" + RehydratePriorityStandard RehydratePriority = "Standard" +) + +// PossibleRehydratePriorityValues returns the possible values for the RehydratePriority const type. +func PossibleRehydratePriorityValues() []RehydratePriority { + return []RehydratePriority{ + RehydratePriorityHigh, + RehydratePriorityStandard, + } +} + +type SKUName string + +const ( + SKUNamePremiumLRS SKUName = "Premium_LRS" + SKUNameStandardGRS SKUName = "Standard_GRS" + SKUNameStandardLRS SKUName = "Standard_LRS" + SKUNameStandardRAGRS SKUName = "Standard_RAGRS" + SKUNameStandardZRS SKUName = "Standard_ZRS" +) + +// PossibleSKUNameValues returns the possible values for the SKUName const type. +func PossibleSKUNameValues() []SKUName { + return []SKUName{ + SKUNamePremiumLRS, + SKUNameStandardGRS, + SKUNameStandardLRS, + SKUNameStandardRAGRS, + SKUNameStandardZRS, + } +} + +type SequenceNumberActionType string + +const ( + SequenceNumberActionTypeIncrement SequenceNumberActionType = "increment" + SequenceNumberActionTypeMax SequenceNumberActionType = "max" + SequenceNumberActionTypeUpdate SequenceNumberActionType = "update" +) + +// PossibleSequenceNumberActionTypeValues returns the possible values for the SequenceNumberActionType const type. +func PossibleSequenceNumberActionTypeValues() []SequenceNumberActionType { + return []SequenceNumberActionType{ + SequenceNumberActionTypeIncrement, + SequenceNumberActionTypeMax, + SequenceNumberActionTypeUpdate, + } +} + +// StorageErrorCode - Error codes returned by the service +type StorageErrorCode string + +const ( + StorageErrorCodeAccountAlreadyExists StorageErrorCode = "AccountAlreadyExists" + StorageErrorCodeAccountBeingCreated StorageErrorCode = "AccountBeingCreated" + StorageErrorCodeAccountIsDisabled StorageErrorCode = "AccountIsDisabled" + StorageErrorCodeAppendPositionConditionNotMet StorageErrorCode = "AppendPositionConditionNotMet" + StorageErrorCodeAuthenticationFailed StorageErrorCode = "AuthenticationFailed" + StorageErrorCodeAuthorizationFailure StorageErrorCode = "AuthorizationFailure" + StorageErrorCodeAuthorizationPermissionMismatch StorageErrorCode = "AuthorizationPermissionMismatch" + StorageErrorCodeAuthorizationProtocolMismatch StorageErrorCode = "AuthorizationProtocolMismatch" + StorageErrorCodeAuthorizationResourceTypeMismatch StorageErrorCode = "AuthorizationResourceTypeMismatch" + StorageErrorCodeAuthorizationServiceMismatch StorageErrorCode = "AuthorizationServiceMismatch" + StorageErrorCodeAuthorizationSourceIPMismatch StorageErrorCode = "AuthorizationSourceIPMismatch" + StorageErrorCodeBlobAlreadyExists StorageErrorCode = "BlobAlreadyExists" + StorageErrorCodeBlobArchived StorageErrorCode = "BlobArchived" + StorageErrorCodeBlobBeingRehydrated StorageErrorCode = "BlobBeingRehydrated" + StorageErrorCodeBlobImmutableDueToPolicy StorageErrorCode = "BlobImmutableDueToPolicy" + StorageErrorCodeBlobNotArchived StorageErrorCode = "BlobNotArchived" + StorageErrorCodeBlobNotFound StorageErrorCode = "BlobNotFound" + StorageErrorCodeBlobOverwritten StorageErrorCode = "BlobOverwritten" + StorageErrorCodeBlobTierInadequateForContentLength StorageErrorCode = "BlobTierInadequateForContentLength" + StorageErrorCodeBlobUsesCustomerSpecifiedEncryption StorageErrorCode = "BlobUsesCustomerSpecifiedEncryption" + StorageErrorCodeBlockCountExceedsLimit StorageErrorCode = "BlockCountExceedsLimit" + StorageErrorCodeBlockListTooLong StorageErrorCode = "BlockListTooLong" + StorageErrorCodeCannotChangeToLowerTier StorageErrorCode = "CannotChangeToLowerTier" + StorageErrorCodeCannotVerifyCopySource StorageErrorCode = "CannotVerifyCopySource" + StorageErrorCodeConditionHeadersNotSupported StorageErrorCode = "ConditionHeadersNotSupported" + StorageErrorCodeConditionNotMet StorageErrorCode = "ConditionNotMet" + StorageErrorCodeContainerAlreadyExists StorageErrorCode = "ContainerAlreadyExists" + StorageErrorCodeContainerBeingDeleted StorageErrorCode = "ContainerBeingDeleted" + StorageErrorCodeContainerDisabled StorageErrorCode = "ContainerDisabled" + StorageErrorCodeContainerNotFound StorageErrorCode = "ContainerNotFound" + StorageErrorCodeContentLengthLargerThanTierLimit StorageErrorCode = "ContentLengthLargerThanTierLimit" + StorageErrorCodeCopyAcrossAccountsNotSupported StorageErrorCode = "CopyAcrossAccountsNotSupported" + StorageErrorCodeCopyIDMismatch StorageErrorCode = "CopyIdMismatch" + StorageErrorCodeEmptyMetadataKey StorageErrorCode = "EmptyMetadataKey" + StorageErrorCodeFeatureVersionMismatch StorageErrorCode = "FeatureVersionMismatch" + StorageErrorCodeIncrementalCopyBlobMismatch StorageErrorCode = "IncrementalCopyBlobMismatch" + StorageErrorCodeIncrementalCopyOfEarlierVersionSnapshotNotAllowed StorageErrorCode = "IncrementalCopyOfEarlierVersionSnapshotNotAllowed" + StorageErrorCodeIncrementalCopySourceMustBeSnapshot StorageErrorCode = "IncrementalCopySourceMustBeSnapshot" + StorageErrorCodeInfiniteLeaseDurationRequired StorageErrorCode = "InfiniteLeaseDurationRequired" + StorageErrorCodeInsufficientAccountPermissions StorageErrorCode = "InsufficientAccountPermissions" + StorageErrorCodeInternalError StorageErrorCode = "InternalError" + StorageErrorCodeInvalidAuthenticationInfo StorageErrorCode = "InvalidAuthenticationInfo" + StorageErrorCodeInvalidBlobOrBlock StorageErrorCode = "InvalidBlobOrBlock" + StorageErrorCodeInvalidBlobTier StorageErrorCode = "InvalidBlobTier" + StorageErrorCodeInvalidBlobType StorageErrorCode = "InvalidBlobType" + StorageErrorCodeInvalidBlockID StorageErrorCode = "InvalidBlockId" + StorageErrorCodeInvalidBlockList StorageErrorCode = "InvalidBlockList" + StorageErrorCodeInvalidHTTPVerb StorageErrorCode = "InvalidHttpVerb" + StorageErrorCodeInvalidHeaderValue StorageErrorCode = "InvalidHeaderValue" + StorageErrorCodeInvalidInput StorageErrorCode = "InvalidInput" + StorageErrorCodeInvalidMD5 StorageErrorCode = "InvalidMd5" + StorageErrorCodeInvalidMetadata StorageErrorCode = "InvalidMetadata" + StorageErrorCodeInvalidOperation StorageErrorCode = "InvalidOperation" + StorageErrorCodeInvalidPageRange StorageErrorCode = "InvalidPageRange" + StorageErrorCodeInvalidQueryParameterValue StorageErrorCode = "InvalidQueryParameterValue" + StorageErrorCodeInvalidRange StorageErrorCode = "InvalidRange" + StorageErrorCodeInvalidResourceName StorageErrorCode = "InvalidResourceName" + StorageErrorCodeInvalidSourceBlobType StorageErrorCode = "InvalidSourceBlobType" + StorageErrorCodeInvalidSourceBlobURL StorageErrorCode = "InvalidSourceBlobUrl" + StorageErrorCodeInvalidURI StorageErrorCode = "InvalidUri" + StorageErrorCodeInvalidVersionForPageBlobOperation StorageErrorCode = "InvalidVersionForPageBlobOperation" + StorageErrorCodeInvalidXMLDocument StorageErrorCode = "InvalidXmlDocument" + StorageErrorCodeInvalidXMLNodeValue StorageErrorCode = "InvalidXmlNodeValue" + StorageErrorCodeLeaseAlreadyBroken StorageErrorCode = "LeaseAlreadyBroken" + StorageErrorCodeLeaseAlreadyPresent StorageErrorCode = "LeaseAlreadyPresent" + StorageErrorCodeLeaseIDMismatchWithBlobOperation StorageErrorCode = "LeaseIdMismatchWithBlobOperation" + StorageErrorCodeLeaseIDMismatchWithContainerOperation StorageErrorCode = "LeaseIdMismatchWithContainerOperation" + StorageErrorCodeLeaseIDMismatchWithLeaseOperation StorageErrorCode = "LeaseIdMismatchWithLeaseOperation" + StorageErrorCodeLeaseIDMissing StorageErrorCode = "LeaseIdMissing" + StorageErrorCodeLeaseIsBreakingAndCannotBeAcquired StorageErrorCode = "LeaseIsBreakingAndCannotBeAcquired" + StorageErrorCodeLeaseIsBreakingAndCannotBeChanged StorageErrorCode = "LeaseIsBreakingAndCannotBeChanged" + StorageErrorCodeLeaseIsBrokenAndCannotBeRenewed StorageErrorCode = "LeaseIsBrokenAndCannotBeRenewed" + StorageErrorCodeLeaseLost StorageErrorCode = "LeaseLost" + StorageErrorCodeLeaseNotPresentWithBlobOperation StorageErrorCode = "LeaseNotPresentWithBlobOperation" + StorageErrorCodeLeaseNotPresentWithContainerOperation StorageErrorCode = "LeaseNotPresentWithContainerOperation" + StorageErrorCodeLeaseNotPresentWithLeaseOperation StorageErrorCode = "LeaseNotPresentWithLeaseOperation" + StorageErrorCodeMD5Mismatch StorageErrorCode = "Md5Mismatch" + StorageErrorCodeMaxBlobSizeConditionNotMet StorageErrorCode = "MaxBlobSizeConditionNotMet" + StorageErrorCodeMetadataTooLarge StorageErrorCode = "MetadataTooLarge" + StorageErrorCodeMissingContentLengthHeader StorageErrorCode = "MissingContentLengthHeader" + StorageErrorCodeMissingRequiredHeader StorageErrorCode = "MissingRequiredHeader" + StorageErrorCodeMissingRequiredQueryParameter StorageErrorCode = "MissingRequiredQueryParameter" + StorageErrorCodeMissingRequiredXMLNode StorageErrorCode = "MissingRequiredXmlNode" + StorageErrorCodeMultipleConditionHeadersNotSupported StorageErrorCode = "MultipleConditionHeadersNotSupported" + StorageErrorCodeNoAuthenticationInformation StorageErrorCode = "NoAuthenticationInformation" + StorageErrorCodeNoPendingCopyOperation StorageErrorCode = "NoPendingCopyOperation" + StorageErrorCodeOperationNotAllowedOnIncrementalCopyBlob StorageErrorCode = "OperationNotAllowedOnIncrementalCopyBlob" + StorageErrorCodeOperationTimedOut StorageErrorCode = "OperationTimedOut" + StorageErrorCodeOutOfRangeInput StorageErrorCode = "OutOfRangeInput" + StorageErrorCodeOutOfRangeQueryParameterValue StorageErrorCode = "OutOfRangeQueryParameterValue" + StorageErrorCodePendingCopyOperation StorageErrorCode = "PendingCopyOperation" + StorageErrorCodePreviousSnapshotCannotBeNewer StorageErrorCode = "PreviousSnapshotCannotBeNewer" + StorageErrorCodePreviousSnapshotNotFound StorageErrorCode = "PreviousSnapshotNotFound" + StorageErrorCodePreviousSnapshotOperationNotSupported StorageErrorCode = "PreviousSnapshotOperationNotSupported" + StorageErrorCodeRequestBodyTooLarge StorageErrorCode = "RequestBodyTooLarge" + StorageErrorCodeRequestURLFailedToParse StorageErrorCode = "RequestUrlFailedToParse" + StorageErrorCodeResourceAlreadyExists StorageErrorCode = "ResourceAlreadyExists" + StorageErrorCodeResourceNotFound StorageErrorCode = "ResourceNotFound" + StorageErrorCodeResourceTypeMismatch StorageErrorCode = "ResourceTypeMismatch" + StorageErrorCodeSequenceNumberConditionNotMet StorageErrorCode = "SequenceNumberConditionNotMet" + StorageErrorCodeSequenceNumberIncrementTooLarge StorageErrorCode = "SequenceNumberIncrementTooLarge" + StorageErrorCodeServerBusy StorageErrorCode = "ServerBusy" + StorageErrorCodeSnapshotCountExceeded StorageErrorCode = "SnapshotCountExceeded" + StorageErrorCodeSnapshotOperationRateExceeded StorageErrorCode = "SnapshotOperationRateExceeded" + StorageErrorCodeSnapshotsPresent StorageErrorCode = "SnapshotsPresent" + StorageErrorCodeSourceConditionNotMet StorageErrorCode = "SourceConditionNotMet" + StorageErrorCodeSystemInUse StorageErrorCode = "SystemInUse" + StorageErrorCodeTargetConditionNotMet StorageErrorCode = "TargetConditionNotMet" + StorageErrorCodeUnauthorizedBlobOverwrite StorageErrorCode = "UnauthorizedBlobOverwrite" + StorageErrorCodeUnsupportedHTTPVerb StorageErrorCode = "UnsupportedHttpVerb" + StorageErrorCodeUnsupportedHeader StorageErrorCode = "UnsupportedHeader" + StorageErrorCodeUnsupportedQueryParameter StorageErrorCode = "UnsupportedQueryParameter" + StorageErrorCodeUnsupportedXMLNode StorageErrorCode = "UnsupportedXmlNode" +) + +// PossibleStorageErrorCodeValues returns the possible values for the StorageErrorCode const type. +func PossibleStorageErrorCodeValues() []StorageErrorCode { + return []StorageErrorCode{ + StorageErrorCodeAccountAlreadyExists, + StorageErrorCodeAccountBeingCreated, + StorageErrorCodeAccountIsDisabled, + StorageErrorCodeAppendPositionConditionNotMet, + StorageErrorCodeAuthenticationFailed, + StorageErrorCodeAuthorizationFailure, + StorageErrorCodeAuthorizationPermissionMismatch, + StorageErrorCodeAuthorizationProtocolMismatch, + StorageErrorCodeAuthorizationResourceTypeMismatch, + StorageErrorCodeAuthorizationServiceMismatch, + StorageErrorCodeAuthorizationSourceIPMismatch, + StorageErrorCodeBlobAlreadyExists, + StorageErrorCodeBlobArchived, + StorageErrorCodeBlobBeingRehydrated, + StorageErrorCodeBlobImmutableDueToPolicy, + StorageErrorCodeBlobNotArchived, + StorageErrorCodeBlobNotFound, + StorageErrorCodeBlobOverwritten, + StorageErrorCodeBlobTierInadequateForContentLength, + StorageErrorCodeBlobUsesCustomerSpecifiedEncryption, + StorageErrorCodeBlockCountExceedsLimit, + StorageErrorCodeBlockListTooLong, + StorageErrorCodeCannotChangeToLowerTier, + StorageErrorCodeCannotVerifyCopySource, + StorageErrorCodeConditionHeadersNotSupported, + StorageErrorCodeConditionNotMet, + StorageErrorCodeContainerAlreadyExists, + StorageErrorCodeContainerBeingDeleted, + StorageErrorCodeContainerDisabled, + StorageErrorCodeContainerNotFound, + StorageErrorCodeContentLengthLargerThanTierLimit, + StorageErrorCodeCopyAcrossAccountsNotSupported, + StorageErrorCodeCopyIDMismatch, + StorageErrorCodeEmptyMetadataKey, + StorageErrorCodeFeatureVersionMismatch, + StorageErrorCodeIncrementalCopyBlobMismatch, + StorageErrorCodeIncrementalCopyOfEarlierVersionSnapshotNotAllowed, + StorageErrorCodeIncrementalCopySourceMustBeSnapshot, + StorageErrorCodeInfiniteLeaseDurationRequired, + StorageErrorCodeInsufficientAccountPermissions, + StorageErrorCodeInternalError, + StorageErrorCodeInvalidAuthenticationInfo, + StorageErrorCodeInvalidBlobOrBlock, + StorageErrorCodeInvalidBlobTier, + StorageErrorCodeInvalidBlobType, + StorageErrorCodeInvalidBlockID, + StorageErrorCodeInvalidBlockList, + StorageErrorCodeInvalidHTTPVerb, + StorageErrorCodeInvalidHeaderValue, + StorageErrorCodeInvalidInput, + StorageErrorCodeInvalidMD5, + StorageErrorCodeInvalidMetadata, + StorageErrorCodeInvalidOperation, + StorageErrorCodeInvalidPageRange, + StorageErrorCodeInvalidQueryParameterValue, + StorageErrorCodeInvalidRange, + StorageErrorCodeInvalidResourceName, + StorageErrorCodeInvalidSourceBlobType, + StorageErrorCodeInvalidSourceBlobURL, + StorageErrorCodeInvalidURI, + StorageErrorCodeInvalidVersionForPageBlobOperation, + StorageErrorCodeInvalidXMLDocument, + StorageErrorCodeInvalidXMLNodeValue, + StorageErrorCodeLeaseAlreadyBroken, + StorageErrorCodeLeaseAlreadyPresent, + StorageErrorCodeLeaseIDMismatchWithBlobOperation, + StorageErrorCodeLeaseIDMismatchWithContainerOperation, + StorageErrorCodeLeaseIDMismatchWithLeaseOperation, + StorageErrorCodeLeaseIDMissing, + StorageErrorCodeLeaseIsBreakingAndCannotBeAcquired, + StorageErrorCodeLeaseIsBreakingAndCannotBeChanged, + StorageErrorCodeLeaseIsBrokenAndCannotBeRenewed, + StorageErrorCodeLeaseLost, + StorageErrorCodeLeaseNotPresentWithBlobOperation, + StorageErrorCodeLeaseNotPresentWithContainerOperation, + StorageErrorCodeLeaseNotPresentWithLeaseOperation, + StorageErrorCodeMD5Mismatch, + StorageErrorCodeMaxBlobSizeConditionNotMet, + StorageErrorCodeMetadataTooLarge, + StorageErrorCodeMissingContentLengthHeader, + StorageErrorCodeMissingRequiredHeader, + StorageErrorCodeMissingRequiredQueryParameter, + StorageErrorCodeMissingRequiredXMLNode, + StorageErrorCodeMultipleConditionHeadersNotSupported, + StorageErrorCodeNoAuthenticationInformation, + StorageErrorCodeNoPendingCopyOperation, + StorageErrorCodeOperationNotAllowedOnIncrementalCopyBlob, + StorageErrorCodeOperationTimedOut, + StorageErrorCodeOutOfRangeInput, + StorageErrorCodeOutOfRangeQueryParameterValue, + StorageErrorCodePendingCopyOperation, + StorageErrorCodePreviousSnapshotCannotBeNewer, + StorageErrorCodePreviousSnapshotNotFound, + StorageErrorCodePreviousSnapshotOperationNotSupported, + StorageErrorCodeRequestBodyTooLarge, + StorageErrorCodeRequestURLFailedToParse, + StorageErrorCodeResourceAlreadyExists, + StorageErrorCodeResourceNotFound, + StorageErrorCodeResourceTypeMismatch, + StorageErrorCodeSequenceNumberConditionNotMet, + StorageErrorCodeSequenceNumberIncrementTooLarge, + StorageErrorCodeServerBusy, + StorageErrorCodeSnapshotCountExceeded, + StorageErrorCodeSnapshotOperationRateExceeded, + StorageErrorCodeSnapshotsPresent, + StorageErrorCodeSourceConditionNotMet, + StorageErrorCodeSystemInUse, + StorageErrorCodeTargetConditionNotMet, + StorageErrorCodeUnauthorizedBlobOverwrite, + StorageErrorCodeUnsupportedHTTPVerb, + StorageErrorCodeUnsupportedHeader, + StorageErrorCodeUnsupportedQueryParameter, + StorageErrorCodeUnsupportedXMLNode, + } +} diff --git a/sdk/storage/azdatalake/internal/generated_blob/zz_container_client.go b/sdk/storage/azdatalake/internal/generated_blob/zz_container_client.go new file mode 100644 index 000000000000..778da1718b7c --- /dev/null +++ b/sdk/storage/azdatalake/internal/generated_blob/zz_container_client.go @@ -0,0 +1,1473 @@ +//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. +// Code generated by Microsoft (R) AutoRest Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. +// DO NOT EDIT. + +package generated_blob + +import ( + "context" + "encoding/xml" + "fmt" + "github.com/Azure/azure-sdk-for-go/sdk/azcore" + "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/azcore/to" + "io" + "net/http" + "strconv" + "strings" + "time" +) + +// ContainerClient contains the methods for the Container group. +// Don't use this type directly, use a constructor function instead. +type ContainerClient struct { + internal *azcore.Client + endpoint string +} + +// AcquireLease - [Update] establishes and manages a lock on a container for delete operations. The lock duration can be 15 +// to 60 seconds, or can be infinite +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2020-10-02 +// - duration - 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. A lease duration cannot be changed using +// renew or change. +// - options - ContainerClientAcquireLeaseOptions contains the optional parameters for the ContainerClient.AcquireLease method. +// - ModifiedAccessConditions - ModifiedAccessConditions contains a group of parameters for the ContainerClient.Delete method. +func (client *ContainerClient) AcquireLease(ctx context.Context, duration int32, options *ContainerClientAcquireLeaseOptions, modifiedAccessConditions *ModifiedAccessConditions) (ContainerClientAcquireLeaseResponse, error) { + req, err := client.acquireLeaseCreateRequest(ctx, duration, options, modifiedAccessConditions) + if err != nil { + return ContainerClientAcquireLeaseResponse{}, err + } + resp, err := client.internal.Pipeline().Do(req) + if err != nil { + return ContainerClientAcquireLeaseResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusCreated) { + return ContainerClientAcquireLeaseResponse{}, runtime.NewResponseError(resp) + } + return client.acquireLeaseHandleResponse(resp) +} + +// acquireLeaseCreateRequest creates the AcquireLease request. +func (client *ContainerClient) acquireLeaseCreateRequest(ctx context.Context, duration int32, options *ContainerClientAcquireLeaseOptions, modifiedAccessConditions *ModifiedAccessConditions) (*policy.Request, error) { + req, err := runtime.NewRequest(ctx, http.MethodPut, client.endpoint) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("comp", "lease") + reqQP.Set("restype", "container") + if options != nil && options.Timeout != nil { + reqQP.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + } + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["x-ms-lease-action"] = []string{"acquire"} + req.Raw().Header["x-ms-lease-duration"] = []string{strconv.FormatInt(int64(duration), 10)} + if options != nil && options.ProposedLeaseID != nil { + req.Raw().Header["x-ms-proposed-lease-id"] = []string{*options.ProposedLeaseID} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfModifiedSince != nil { + req.Raw().Header["If-Modified-Since"] = []string{(*modifiedAccessConditions.IfModifiedSince).In(gmt).Format(time.RFC1123)} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfUnmodifiedSince != nil { + req.Raw().Header["If-Unmodified-Since"] = []string{(*modifiedAccessConditions.IfUnmodifiedSince).In(gmt).Format(time.RFC1123)} + } + req.Raw().Header["x-ms-version"] = []string{"2020-10-02"} + if options != nil && options.RequestID != nil { + req.Raw().Header["x-ms-client-request-id"] = []string{*options.RequestID} + } + req.Raw().Header["Accept"] = []string{"application/xml"} + return req, nil +} + +// acquireLeaseHandleResponse handles the AcquireLease response. +func (client *ContainerClient) acquireLeaseHandleResponse(resp *http.Response) (ContainerClientAcquireLeaseResponse, error) { + result := ContainerClientAcquireLeaseResponse{} + if val := resp.Header.Get("ETag"); val != "" { + result.ETag = (*azcore.ETag)(&val) + } + if val := resp.Header.Get("Last-Modified"); val != "" { + lastModified, err := time.Parse(time.RFC1123, val) + if err != nil { + return ContainerClientAcquireLeaseResponse{}, err + } + result.LastModified = &lastModified + } + if val := resp.Header.Get("x-ms-lease-id"); val != "" { + result.LeaseID = &val + } + if val := resp.Header.Get("x-ms-client-request-id"); val != "" { + result.ClientRequestID = &val + } + if val := resp.Header.Get("x-ms-request-id"); val != "" { + result.RequestID = &val + } + if val := resp.Header.Get("x-ms-version"); val != "" { + result.Version = &val + } + if val := resp.Header.Get("Date"); val != "" { + date, err := time.Parse(time.RFC1123, val) + if err != nil { + return ContainerClientAcquireLeaseResponse{}, err + } + result.Date = &date + } + return result, nil +} + +// BreakLease - [Update] establishes and manages a lock on a container for delete operations. The lock duration can be 15 +// to 60 seconds, or can be infinite +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2020-10-02 +// - options - ContainerClientBreakLeaseOptions contains the optional parameters for the ContainerClient.BreakLease method. +// - ModifiedAccessConditions - ModifiedAccessConditions contains a group of parameters for the ContainerClient.Delete method. +func (client *ContainerClient) BreakLease(ctx context.Context, options *ContainerClientBreakLeaseOptions, modifiedAccessConditions *ModifiedAccessConditions) (ContainerClientBreakLeaseResponse, error) { + req, err := client.breakLeaseCreateRequest(ctx, options, modifiedAccessConditions) + if err != nil { + return ContainerClientBreakLeaseResponse{}, err + } + resp, err := client.internal.Pipeline().Do(req) + if err != nil { + return ContainerClientBreakLeaseResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusAccepted) { + return ContainerClientBreakLeaseResponse{}, runtime.NewResponseError(resp) + } + return client.breakLeaseHandleResponse(resp) +} + +// breakLeaseCreateRequest creates the BreakLease request. +func (client *ContainerClient) breakLeaseCreateRequest(ctx context.Context, options *ContainerClientBreakLeaseOptions, modifiedAccessConditions *ModifiedAccessConditions) (*policy.Request, error) { + req, err := runtime.NewRequest(ctx, http.MethodPut, client.endpoint) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("comp", "lease") + reqQP.Set("restype", "container") + if options != nil && options.Timeout != nil { + reqQP.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + } + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["x-ms-lease-action"] = []string{"break"} + if options != nil && options.BreakPeriod != nil { + req.Raw().Header["x-ms-lease-break-period"] = []string{strconv.FormatInt(int64(*options.BreakPeriod), 10)} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfModifiedSince != nil { + req.Raw().Header["If-Modified-Since"] = []string{(*modifiedAccessConditions.IfModifiedSince).In(gmt).Format(time.RFC1123)} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfUnmodifiedSince != nil { + req.Raw().Header["If-Unmodified-Since"] = []string{(*modifiedAccessConditions.IfUnmodifiedSince).In(gmt).Format(time.RFC1123)} + } + req.Raw().Header["x-ms-version"] = []string{"2020-10-02"} + if options != nil && options.RequestID != nil { + req.Raw().Header["x-ms-client-request-id"] = []string{*options.RequestID} + } + req.Raw().Header["Accept"] = []string{"application/xml"} + return req, nil +} + +// breakLeaseHandleResponse handles the BreakLease response. +func (client *ContainerClient) breakLeaseHandleResponse(resp *http.Response) (ContainerClientBreakLeaseResponse, error) { + result := ContainerClientBreakLeaseResponse{} + if val := resp.Header.Get("ETag"); val != "" { + result.ETag = (*azcore.ETag)(&val) + } + if val := resp.Header.Get("Last-Modified"); val != "" { + lastModified, err := time.Parse(time.RFC1123, val) + if err != nil { + return ContainerClientBreakLeaseResponse{}, err + } + result.LastModified = &lastModified + } + if val := resp.Header.Get("x-ms-lease-time"); val != "" { + leaseTime32, err := strconv.ParseInt(val, 10, 32) + leaseTime := int32(leaseTime32) + if err != nil { + return ContainerClientBreakLeaseResponse{}, err + } + result.LeaseTime = &leaseTime + } + if val := resp.Header.Get("x-ms-client-request-id"); val != "" { + result.ClientRequestID = &val + } + if val := resp.Header.Get("x-ms-request-id"); val != "" { + result.RequestID = &val + } + if val := resp.Header.Get("x-ms-version"); val != "" { + result.Version = &val + } + if val := resp.Header.Get("Date"); val != "" { + date, err := time.Parse(time.RFC1123, val) + if err != nil { + return ContainerClientBreakLeaseResponse{}, err + } + result.Date = &date + } + return result, nil +} + +// ChangeLease - [Update] establishes and manages a lock on a container for delete operations. The lock duration can be 15 +// to 60 seconds, or can be infinite +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2020-10-02 +// - leaseID - Specifies the current lease ID on the resource. +// - proposedLeaseID - Proposed lease ID, in a GUID string format. The Blob service returns 400 (Invalid request) if the proposed +// lease ID is not in the correct format. See Guid Constructor (String) for a list of valid GUID +// string formats. +// - options - ContainerClientChangeLeaseOptions contains the optional parameters for the ContainerClient.ChangeLease method. +// - ModifiedAccessConditions - ModifiedAccessConditions contains a group of parameters for the ContainerClient.Delete method. +func (client *ContainerClient) ChangeLease(ctx context.Context, leaseID string, proposedLeaseID string, options *ContainerClientChangeLeaseOptions, modifiedAccessConditions *ModifiedAccessConditions) (ContainerClientChangeLeaseResponse, error) { + req, err := client.changeLeaseCreateRequest(ctx, leaseID, proposedLeaseID, options, modifiedAccessConditions) + if err != nil { + return ContainerClientChangeLeaseResponse{}, err + } + resp, err := client.internal.Pipeline().Do(req) + if err != nil { + return ContainerClientChangeLeaseResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusOK) { + return ContainerClientChangeLeaseResponse{}, runtime.NewResponseError(resp) + } + return client.changeLeaseHandleResponse(resp) +} + +// changeLeaseCreateRequest creates the ChangeLease request. +func (client *ContainerClient) changeLeaseCreateRequest(ctx context.Context, leaseID string, proposedLeaseID string, options *ContainerClientChangeLeaseOptions, modifiedAccessConditions *ModifiedAccessConditions) (*policy.Request, error) { + req, err := runtime.NewRequest(ctx, http.MethodPut, client.endpoint) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("comp", "lease") + reqQP.Set("restype", "container") + if options != nil && options.Timeout != nil { + reqQP.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + } + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["x-ms-lease-action"] = []string{"change"} + req.Raw().Header["x-ms-lease-id"] = []string{leaseID} + req.Raw().Header["x-ms-proposed-lease-id"] = []string{proposedLeaseID} + if modifiedAccessConditions != nil && modifiedAccessConditions.IfModifiedSince != nil { + req.Raw().Header["If-Modified-Since"] = []string{(*modifiedAccessConditions.IfModifiedSince).In(gmt).Format(time.RFC1123)} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfUnmodifiedSince != nil { + req.Raw().Header["If-Unmodified-Since"] = []string{(*modifiedAccessConditions.IfUnmodifiedSince).In(gmt).Format(time.RFC1123)} + } + req.Raw().Header["x-ms-version"] = []string{"2020-10-02"} + if options != nil && options.RequestID != nil { + req.Raw().Header["x-ms-client-request-id"] = []string{*options.RequestID} + } + req.Raw().Header["Accept"] = []string{"application/xml"} + return req, nil +} + +// changeLeaseHandleResponse handles the ChangeLease response. +func (client *ContainerClient) changeLeaseHandleResponse(resp *http.Response) (ContainerClientChangeLeaseResponse, error) { + result := ContainerClientChangeLeaseResponse{} + if val := resp.Header.Get("ETag"); val != "" { + result.ETag = (*azcore.ETag)(&val) + } + if val := resp.Header.Get("Last-Modified"); val != "" { + lastModified, err := time.Parse(time.RFC1123, val) + if err != nil { + return ContainerClientChangeLeaseResponse{}, err + } + result.LastModified = &lastModified + } + if val := resp.Header.Get("x-ms-lease-id"); val != "" { + result.LeaseID = &val + } + if val := resp.Header.Get("x-ms-client-request-id"); val != "" { + result.ClientRequestID = &val + } + if val := resp.Header.Get("x-ms-request-id"); val != "" { + result.RequestID = &val + } + if val := resp.Header.Get("x-ms-version"); val != "" { + result.Version = &val + } + if val := resp.Header.Get("Date"); val != "" { + date, err := time.Parse(time.RFC1123, val) + if err != nil { + return ContainerClientChangeLeaseResponse{}, err + } + result.Date = &date + } + return result, nil +} + +// Create - creates a new container under the specified account. If the container with the same name already exists, the operation +// fails +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2020-10-02 +// - options - ContainerClientCreateOptions contains the optional parameters for the ContainerClient.Create method. +// - ContainerCPKScopeInfo - ContainerCPKScopeInfo contains a group of parameters for the ContainerClient.Create method. +func (client *ContainerClient) Create(ctx context.Context, options *ContainerClientCreateOptions, containerCPKScopeInfo *ContainerCPKScopeInfo) (ContainerClientCreateResponse, error) { + req, err := client.createCreateRequest(ctx, options, containerCPKScopeInfo) + if err != nil { + return ContainerClientCreateResponse{}, err + } + resp, err := client.internal.Pipeline().Do(req) + if err != nil { + return ContainerClientCreateResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusCreated) { + return ContainerClientCreateResponse{}, runtime.NewResponseError(resp) + } + return client.createHandleResponse(resp) +} + +// createCreateRequest creates the Create request. +func (client *ContainerClient) createCreateRequest(ctx context.Context, options *ContainerClientCreateOptions, containerCPKScopeInfo *ContainerCPKScopeInfo) (*policy.Request, error) { + req, err := runtime.NewRequest(ctx, http.MethodPut, client.endpoint) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("restype", "container") + if options != nil && options.Timeout != nil { + reqQP.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + } + req.Raw().URL.RawQuery = reqQP.Encode() + if options != nil && options.Metadata != nil { + for k, v := range options.Metadata { + if v != nil { + req.Raw().Header["x-ms-meta-"+k] = []string{*v} + } + } + } + if options != nil && options.Access != nil { + req.Raw().Header["x-ms-blob-public-access"] = []string{string(*options.Access)} + } + req.Raw().Header["x-ms-version"] = []string{"2020-10-02"} + if options != nil && options.RequestID != nil { + req.Raw().Header["x-ms-client-request-id"] = []string{*options.RequestID} + } + if containerCPKScopeInfo != nil && containerCPKScopeInfo.DefaultEncryptionScope != nil { + req.Raw().Header["x-ms-default-encryption-scope"] = []string{*containerCPKScopeInfo.DefaultEncryptionScope} + } + if containerCPKScopeInfo != nil && containerCPKScopeInfo.PreventEncryptionScopeOverride != nil { + req.Raw().Header["x-ms-deny-encryption-scope-override"] = []string{strconv.FormatBool(*containerCPKScopeInfo.PreventEncryptionScopeOverride)} + } + req.Raw().Header["Accept"] = []string{"application/xml"} + return req, nil +} + +// createHandleResponse handles the Create response. +func (client *ContainerClient) createHandleResponse(resp *http.Response) (ContainerClientCreateResponse, error) { + result := ContainerClientCreateResponse{} + if val := resp.Header.Get("ETag"); val != "" { + result.ETag = (*azcore.ETag)(&val) + } + if val := resp.Header.Get("Last-Modified"); val != "" { + lastModified, err := time.Parse(time.RFC1123, val) + if err != nil { + return ContainerClientCreateResponse{}, err + } + result.LastModified = &lastModified + } + if val := resp.Header.Get("x-ms-client-request-id"); val != "" { + result.ClientRequestID = &val + } + if val := resp.Header.Get("x-ms-request-id"); val != "" { + result.RequestID = &val + } + if val := resp.Header.Get("x-ms-version"); val != "" { + result.Version = &val + } + if val := resp.Header.Get("Date"); val != "" { + date, err := time.Parse(time.RFC1123, val) + if err != nil { + return ContainerClientCreateResponse{}, err + } + result.Date = &date + } + return result, nil +} + +// Delete - operation marks the specified container for deletion. The container and any blobs contained within it are later +// deleted during garbage collection +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2020-10-02 +// - options - ContainerClientDeleteOptions contains the optional parameters for the ContainerClient.Delete method. +// - LeaseAccessConditions - LeaseAccessConditions contains a group of parameters for the ContainerClient.GetProperties method. +// - ModifiedAccessConditions - ModifiedAccessConditions contains a group of parameters for the ContainerClient.Delete method. +func (client *ContainerClient) Delete(ctx context.Context, options *ContainerClientDeleteOptions, leaseAccessConditions *LeaseAccessConditions, modifiedAccessConditions *ModifiedAccessConditions) (ContainerClientDeleteResponse, error) { + req, err := client.deleteCreateRequest(ctx, options, leaseAccessConditions, modifiedAccessConditions) + if err != nil { + return ContainerClientDeleteResponse{}, err + } + resp, err := client.internal.Pipeline().Do(req) + if err != nil { + return ContainerClientDeleteResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusAccepted) { + return ContainerClientDeleteResponse{}, runtime.NewResponseError(resp) + } + return client.deleteHandleResponse(resp) +} + +// deleteCreateRequest creates the Delete request. +func (client *ContainerClient) deleteCreateRequest(ctx context.Context, options *ContainerClientDeleteOptions, leaseAccessConditions *LeaseAccessConditions, modifiedAccessConditions *ModifiedAccessConditions) (*policy.Request, error) { + req, err := runtime.NewRequest(ctx, http.MethodDelete, client.endpoint) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("restype", "container") + if options != nil && options.Timeout != nil { + reqQP.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + } + req.Raw().URL.RawQuery = reqQP.Encode() + if leaseAccessConditions != nil && leaseAccessConditions.LeaseID != nil { + req.Raw().Header["x-ms-lease-id"] = []string{*leaseAccessConditions.LeaseID} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfModifiedSince != nil { + req.Raw().Header["If-Modified-Since"] = []string{(*modifiedAccessConditions.IfModifiedSince).In(gmt).Format(time.RFC1123)} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfUnmodifiedSince != nil { + req.Raw().Header["If-Unmodified-Since"] = []string{(*modifiedAccessConditions.IfUnmodifiedSince).In(gmt).Format(time.RFC1123)} + } + req.Raw().Header["x-ms-version"] = []string{"2020-10-02"} + if options != nil && options.RequestID != nil { + req.Raw().Header["x-ms-client-request-id"] = []string{*options.RequestID} + } + req.Raw().Header["Accept"] = []string{"application/xml"} + return req, nil +} + +// deleteHandleResponse handles the Delete response. +func (client *ContainerClient) deleteHandleResponse(resp *http.Response) (ContainerClientDeleteResponse, error) { + result := ContainerClientDeleteResponse{} + if val := resp.Header.Get("x-ms-client-request-id"); val != "" { + result.ClientRequestID = &val + } + if val := resp.Header.Get("x-ms-request-id"); val != "" { + result.RequestID = &val + } + if val := resp.Header.Get("x-ms-version"); val != "" { + result.Version = &val + } + if val := resp.Header.Get("Date"); val != "" { + date, err := time.Parse(time.RFC1123, val) + if err != nil { + return ContainerClientDeleteResponse{}, err + } + result.Date = &date + } + return result, nil +} + +// GetAccessPolicy - gets the permissions for the specified container. The permissions indicate whether container data may +// be accessed publicly. +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2020-10-02 +// - options - ContainerClientGetAccessPolicyOptions contains the optional parameters for the ContainerClient.GetAccessPolicy +// method. +// - LeaseAccessConditions - LeaseAccessConditions contains a group of parameters for the ContainerClient.GetProperties method. +func (client *ContainerClient) GetAccessPolicy(ctx context.Context, options *ContainerClientGetAccessPolicyOptions, leaseAccessConditions *LeaseAccessConditions) (ContainerClientGetAccessPolicyResponse, error) { + req, err := client.getAccessPolicyCreateRequest(ctx, options, leaseAccessConditions) + if err != nil { + return ContainerClientGetAccessPolicyResponse{}, err + } + resp, err := client.internal.Pipeline().Do(req) + if err != nil { + return ContainerClientGetAccessPolicyResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusOK) { + return ContainerClientGetAccessPolicyResponse{}, runtime.NewResponseError(resp) + } + return client.getAccessPolicyHandleResponse(resp) +} + +// getAccessPolicyCreateRequest creates the GetAccessPolicy request. +func (client *ContainerClient) getAccessPolicyCreateRequest(ctx context.Context, options *ContainerClientGetAccessPolicyOptions, leaseAccessConditions *LeaseAccessConditions) (*policy.Request, error) { + req, err := runtime.NewRequest(ctx, http.MethodGet, client.endpoint) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("restype", "container") + reqQP.Set("comp", "acl") + if options != nil && options.Timeout != nil { + reqQP.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + } + req.Raw().URL.RawQuery = reqQP.Encode() + if leaseAccessConditions != nil && leaseAccessConditions.LeaseID != nil { + req.Raw().Header["x-ms-lease-id"] = []string{*leaseAccessConditions.LeaseID} + } + req.Raw().Header["x-ms-version"] = []string{"2020-10-02"} + if options != nil && options.RequestID != nil { + req.Raw().Header["x-ms-client-request-id"] = []string{*options.RequestID} + } + req.Raw().Header["Accept"] = []string{"application/xml"} + return req, nil +} + +// getAccessPolicyHandleResponse handles the GetAccessPolicy response. +func (client *ContainerClient) getAccessPolicyHandleResponse(resp *http.Response) (ContainerClientGetAccessPolicyResponse, error) { + result := ContainerClientGetAccessPolicyResponse{} + if val := resp.Header.Get("x-ms-blob-public-access"); val != "" { + result.BlobPublicAccess = (*PublicAccessType)(&val) + } + if val := resp.Header.Get("ETag"); val != "" { + result.ETag = (*azcore.ETag)(&val) + } + if val := resp.Header.Get("Last-Modified"); val != "" { + lastModified, err := time.Parse(time.RFC1123, val) + if err != nil { + return ContainerClientGetAccessPolicyResponse{}, err + } + result.LastModified = &lastModified + } + if val := resp.Header.Get("x-ms-client-request-id"); val != "" { + result.ClientRequestID = &val + } + if val := resp.Header.Get("x-ms-request-id"); val != "" { + result.RequestID = &val + } + if val := resp.Header.Get("x-ms-version"); val != "" { + result.Version = &val + } + if val := resp.Header.Get("Date"); val != "" { + date, err := time.Parse(time.RFC1123, val) + if err != nil { + return ContainerClientGetAccessPolicyResponse{}, err + } + result.Date = &date + } + if err := runtime.UnmarshalAsXML(resp, &result); err != nil { + return ContainerClientGetAccessPolicyResponse{}, err + } + return result, nil +} + +// GetAccountInfo - Returns the sku name and account kind +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2020-10-02 +// - options - ContainerClientGetAccountInfoOptions contains the optional parameters for the ContainerClient.GetAccountInfo +// method. +func (client *ContainerClient) GetAccountInfo(ctx context.Context, options *ContainerClientGetAccountInfoOptions) (ContainerClientGetAccountInfoResponse, error) { + req, err := client.getAccountInfoCreateRequest(ctx, options) + if err != nil { + return ContainerClientGetAccountInfoResponse{}, err + } + resp, err := client.internal.Pipeline().Do(req) + if err != nil { + return ContainerClientGetAccountInfoResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusOK) { + return ContainerClientGetAccountInfoResponse{}, runtime.NewResponseError(resp) + } + return client.getAccountInfoHandleResponse(resp) +} + +// getAccountInfoCreateRequest creates the GetAccountInfo request. +func (client *ContainerClient) getAccountInfoCreateRequest(ctx context.Context, options *ContainerClientGetAccountInfoOptions) (*policy.Request, error) { + req, err := runtime.NewRequest(ctx, http.MethodGet, client.endpoint) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("restype", "account") + reqQP.Set("comp", "properties") + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["x-ms-version"] = []string{"2020-10-02"} + req.Raw().Header["Accept"] = []string{"application/xml"} + return req, nil +} + +// getAccountInfoHandleResponse handles the GetAccountInfo response. +func (client *ContainerClient) getAccountInfoHandleResponse(resp *http.Response) (ContainerClientGetAccountInfoResponse, error) { + result := ContainerClientGetAccountInfoResponse{} + if val := resp.Header.Get("x-ms-client-request-id"); val != "" { + result.ClientRequestID = &val + } + if val := resp.Header.Get("x-ms-request-id"); val != "" { + result.RequestID = &val + } + if val := resp.Header.Get("x-ms-version"); val != "" { + result.Version = &val + } + if val := resp.Header.Get("Date"); val != "" { + date, err := time.Parse(time.RFC1123, val) + if err != nil { + return ContainerClientGetAccountInfoResponse{}, err + } + result.Date = &date + } + if val := resp.Header.Get("x-ms-sku-name"); val != "" { + result.SKUName = (*SKUName)(&val) + } + if val := resp.Header.Get("x-ms-account-kind"); val != "" { + result.AccountKind = (*AccountKind)(&val) + } + return result, nil +} + +// GetProperties - returns all user-defined metadata and system properties for the specified container. The data returned +// does not include the container's list of blobs +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2020-10-02 +// - options - ContainerClientGetPropertiesOptions contains the optional parameters for the ContainerClient.GetProperties method. +// - LeaseAccessConditions - LeaseAccessConditions contains a group of parameters for the ContainerClient.GetProperties method. +func (client *ContainerClient) GetProperties(ctx context.Context, options *ContainerClientGetPropertiesOptions, leaseAccessConditions *LeaseAccessConditions) (ContainerClientGetPropertiesResponse, error) { + req, err := client.getPropertiesCreateRequest(ctx, options, leaseAccessConditions) + if err != nil { + return ContainerClientGetPropertiesResponse{}, err + } + resp, err := client.internal.Pipeline().Do(req) + if err != nil { + return ContainerClientGetPropertiesResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusOK) { + return ContainerClientGetPropertiesResponse{}, runtime.NewResponseError(resp) + } + return client.getPropertiesHandleResponse(resp) +} + +// getPropertiesCreateRequest creates the GetProperties request. +func (client *ContainerClient) getPropertiesCreateRequest(ctx context.Context, options *ContainerClientGetPropertiesOptions, leaseAccessConditions *LeaseAccessConditions) (*policy.Request, error) { + req, err := runtime.NewRequest(ctx, http.MethodGet, client.endpoint) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("restype", "container") + if options != nil && options.Timeout != nil { + reqQP.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + } + req.Raw().URL.RawQuery = reqQP.Encode() + if leaseAccessConditions != nil && leaseAccessConditions.LeaseID != nil { + req.Raw().Header["x-ms-lease-id"] = []string{*leaseAccessConditions.LeaseID} + } + req.Raw().Header["x-ms-version"] = []string{"2020-10-02"} + if options != nil && options.RequestID != nil { + req.Raw().Header["x-ms-client-request-id"] = []string{*options.RequestID} + } + req.Raw().Header["Accept"] = []string{"application/xml"} + return req, nil +} + +// getPropertiesHandleResponse handles the GetProperties response. +func (client *ContainerClient) getPropertiesHandleResponse(resp *http.Response) (ContainerClientGetPropertiesResponse, error) { + result := ContainerClientGetPropertiesResponse{} + for hh := range resp.Header { + if len(hh) > len("x-ms-meta-") && strings.EqualFold(hh[:len("x-ms-meta-")], "x-ms-meta-") { + if result.Metadata == nil { + result.Metadata = map[string]*string{} + } + result.Metadata[hh[len("x-ms-meta-"):]] = to.Ptr(resp.Header.Get(hh)) + } + } + if val := resp.Header.Get("ETag"); val != "" { + result.ETag = (*azcore.ETag)(&val) + } + if val := resp.Header.Get("Last-Modified"); val != "" { + lastModified, err := time.Parse(time.RFC1123, val) + if err != nil { + return ContainerClientGetPropertiesResponse{}, err + } + result.LastModified = &lastModified + } + if val := resp.Header.Get("x-ms-lease-duration"); val != "" { + result.LeaseDuration = (*LeaseDurationType)(&val) + } + if val := resp.Header.Get("x-ms-lease-state"); val != "" { + result.LeaseState = (*LeaseStateType)(&val) + } + if val := resp.Header.Get("x-ms-lease-status"); val != "" { + result.LeaseStatus = (*LeaseStatusType)(&val) + } + if val := resp.Header.Get("x-ms-client-request-id"); val != "" { + result.ClientRequestID = &val + } + if val := resp.Header.Get("x-ms-request-id"); val != "" { + result.RequestID = &val + } + if val := resp.Header.Get("x-ms-version"); val != "" { + result.Version = &val + } + if val := resp.Header.Get("Date"); val != "" { + date, err := time.Parse(time.RFC1123, val) + if err != nil { + return ContainerClientGetPropertiesResponse{}, err + } + result.Date = &date + } + if val := resp.Header.Get("x-ms-blob-public-access"); val != "" { + result.BlobPublicAccess = (*PublicAccessType)(&val) + } + if val := resp.Header.Get("x-ms-has-immutability-policy"); val != "" { + hasImmutabilityPolicy, err := strconv.ParseBool(val) + if err != nil { + return ContainerClientGetPropertiesResponse{}, err + } + result.HasImmutabilityPolicy = &hasImmutabilityPolicy + } + if val := resp.Header.Get("x-ms-has-legal-hold"); val != "" { + hasLegalHold, err := strconv.ParseBool(val) + if err != nil { + return ContainerClientGetPropertiesResponse{}, err + } + result.HasLegalHold = &hasLegalHold + } + if val := resp.Header.Get("x-ms-default-encryption-scope"); val != "" { + result.DefaultEncryptionScope = &val + } + if val := resp.Header.Get("x-ms-deny-encryption-scope-override"); val != "" { + denyEncryptionScopeOverride, err := strconv.ParseBool(val) + if err != nil { + return ContainerClientGetPropertiesResponse{}, err + } + result.DenyEncryptionScopeOverride = &denyEncryptionScopeOverride + } + if val := resp.Header.Get("x-ms-immutable-storage-with-versioning-enabled"); val != "" { + isImmutableStorageWithVersioningEnabled, err := strconv.ParseBool(val) + if err != nil { + return ContainerClientGetPropertiesResponse{}, err + } + result.IsImmutableStorageWithVersioningEnabled = &isImmutableStorageWithVersioningEnabled + } + return result, nil +} + +// NewListBlobFlatSegmentPager - [Update] The List Blobs operation returns a list of the blobs under the specified container +// +// Generated from API version 2020-10-02 +// - options - ContainerClientListBlobFlatSegmentOptions contains the optional parameters for the ContainerClient.NewListBlobFlatSegmentPager +// method. +// +// listBlobFlatSegmentCreateRequest creates the ListBlobFlatSegment request. +func (client *ContainerClient) ListBlobFlatSegmentCreateRequest(ctx context.Context, options *ContainerClientListBlobFlatSegmentOptions) (*policy.Request, error) { + req, err := runtime.NewRequest(ctx, http.MethodGet, client.endpoint) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("restype", "container") + reqQP.Set("comp", "list") + if options != nil && options.Prefix != nil { + reqQP.Set("prefix", *options.Prefix) + } + if options != nil && options.Marker != nil { + reqQP.Set("marker", *options.Marker) + } + if options != nil && options.Maxresults != nil { + reqQP.Set("maxresults", strconv.FormatInt(int64(*options.Maxresults), 10)) + } + if options != nil && options.Include != nil { + reqQP.Set("include", strings.Join(strings.Fields(strings.Trim(fmt.Sprint(options.Include), "[]")), ",")) + } + if options != nil && options.Timeout != nil { + reqQP.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + } + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["x-ms-version"] = []string{"2020-10-02"} + if options != nil && options.RequestID != nil { + req.Raw().Header["x-ms-client-request-id"] = []string{*options.RequestID} + } + req.Raw().Header["Accept"] = []string{"application/xml"} + return req, nil +} + +// listBlobFlatSegmentHandleResponse handles the ListBlobFlatSegment response. +func (client *ContainerClient) ListBlobFlatSegmentHandleResponse(resp *http.Response) (ContainerClientListBlobFlatSegmentResponse, error) { + result := ContainerClientListBlobFlatSegmentResponse{} + if val := resp.Header.Get("Content-Type"); val != "" { + result.ContentType = &val + } + if val := resp.Header.Get("x-ms-client-request-id"); val != "" { + result.ClientRequestID = &val + } + if val := resp.Header.Get("x-ms-request-id"); val != "" { + result.RequestID = &val + } + if val := resp.Header.Get("x-ms-version"); val != "" { + result.Version = &val + } + if val := resp.Header.Get("Date"); val != "" { + date, err := time.Parse(time.RFC1123, val) + if err != nil { + return ContainerClientListBlobFlatSegmentResponse{}, err + } + result.Date = &date + } + if err := runtime.UnmarshalAsXML(resp, &result.ListBlobsFlatSegmentResponse); err != nil { + return ContainerClientListBlobFlatSegmentResponse{}, err + } + return result, nil +} + +// NewListBlobHierarchySegmentPager - [Update] The List Blobs operation returns a list of the blobs under the specified container +// +// Generated from API version 2020-10-02 +// - delimiter - When the request includes this parameter, the operation returns a PathPrefix element in the response body that +// acts as a placeholder for all blobs whose names begin with the same substring up to the +// appearance of the delimiter character. The delimiter may be a single character or a string. +// - options - ContainerClientListBlobHierarchySegmentOptions contains the optional parameters for the ContainerClient.NewListBlobHierarchySegmentPager +// method. +func (client *ContainerClient) NewListBlobHierarchySegmentPager(delimiter string, options *ContainerClientListBlobHierarchySegmentOptions) *runtime.Pager[FileSystemClientListPathHierarchySegmentResponse] { + return runtime.NewPager(runtime.PagingHandler[FileSystemClientListPathHierarchySegmentResponse]{ + More: func(page FileSystemClientListPathHierarchySegmentResponse) bool { + return page.NextMarker != nil && len(*page.NextMarker) > 0 + }, + Fetcher: func(ctx context.Context, page *FileSystemClientListPathHierarchySegmentResponse) (FileSystemClientListPathHierarchySegmentResponse, error) { + var req *policy.Request + var err error + if page == nil { + req, err = client.ListBlobHierarchySegmentCreateRequest(ctx, delimiter, options) + } else { + req, err = runtime.NewRequest(ctx, http.MethodGet, *page.NextMarker) + } + if err != nil { + return FileSystemClientListPathHierarchySegmentResponse{}, err + } + resp, err := client.internal.Pipeline().Do(req) + if err != nil { + return FileSystemClientListPathHierarchySegmentResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusOK) { + return FileSystemClientListPathHierarchySegmentResponse{}, runtime.NewResponseError(resp) + } + return client.ListBlobHierarchySegmentHandleResponse(resp) + }, + }) +} + +// ListBlobHierarchySegmentCreateRequest creates the ListBlobHierarchySegment request. +func (client *ContainerClient) ListBlobHierarchySegmentCreateRequest(ctx context.Context, delimiter string, options *ContainerClientListBlobHierarchySegmentOptions) (*policy.Request, error) { + req, err := runtime.NewRequest(ctx, http.MethodGet, client.endpoint) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("restype", "container") + reqQP.Set("comp", "list") + if options != nil && options.Prefix != nil { + reqQP.Set("prefix", *options.Prefix) + } + reqQP.Set("delimiter", delimiter) + if options != nil && options.Marker != nil { + reqQP.Set("marker", *options.Marker) + } + if options != nil && options.Maxresults != nil { + reqQP.Set("maxresults", strconv.FormatInt(int64(*options.Maxresults), 10)) + } + if options != nil && options.Include != nil { + reqQP.Set("include", strings.Join(strings.Fields(strings.Trim(fmt.Sprint(options.Include), "[]")), ",")) + } + if options != nil && options.Timeout != nil { + reqQP.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + } + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["x-ms-version"] = []string{"2020-10-02"} + if options != nil && options.RequestID != nil { + req.Raw().Header["x-ms-client-request-id"] = []string{*options.RequestID} + } + req.Raw().Header["Accept"] = []string{"application/xml"} + return req, nil +} + +// ListBlobHierarchySegmentHandleResponse handles the ListBlobHierarchySegment response. +func (client *ContainerClient) ListBlobHierarchySegmentHandleResponse(resp *http.Response) (FileSystemClientListPathHierarchySegmentResponse, error) { + result := FileSystemClientListPathHierarchySegmentResponse{} + if val := resp.Header.Get("Content-Type"); val != "" { + result.ContentType = &val + } + if val := resp.Header.Get("x-ms-client-request-id"); val != "" { + result.ClientRequestID = &val + } + if val := resp.Header.Get("x-ms-request-id"); val != "" { + result.RequestID = &val + } + if val := resp.Header.Get("x-ms-version"); val != "" { + result.Version = &val + } + if val := resp.Header.Get("Date"); val != "" { + date, err := time.Parse(time.RFC1123, val) + if err != nil { + return FileSystemClientListPathHierarchySegmentResponse{}, err + } + result.Date = &date + } + if err := runtime.UnmarshalAsXML(resp, &result.ListPathsHierarchySegmentResponse); err != nil { + return FileSystemClientListPathHierarchySegmentResponse{}, err + } + return result, nil +} + +// ReleaseLease - [Update] establishes and manages a lock on a container for delete operations. The lock duration can be 15 +// to 60 seconds, or can be infinite +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2020-10-02 +// - leaseID - Specifies the current lease ID on the resource. +// - options - ContainerClientReleaseLeaseOptions contains the optional parameters for the ContainerClient.ReleaseLease method. +// - ModifiedAccessConditions - ModifiedAccessConditions contains a group of parameters for the ContainerClient.Delete method. +func (client *ContainerClient) ReleaseLease(ctx context.Context, leaseID string, options *ContainerClientReleaseLeaseOptions, modifiedAccessConditions *ModifiedAccessConditions) (ContainerClientReleaseLeaseResponse, error) { + req, err := client.releaseLeaseCreateRequest(ctx, leaseID, options, modifiedAccessConditions) + if err != nil { + return ContainerClientReleaseLeaseResponse{}, err + } + resp, err := client.internal.Pipeline().Do(req) + if err != nil { + return ContainerClientReleaseLeaseResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusOK) { + return ContainerClientReleaseLeaseResponse{}, runtime.NewResponseError(resp) + } + return client.releaseLeaseHandleResponse(resp) +} + +// releaseLeaseCreateRequest creates the ReleaseLease request. +func (client *ContainerClient) releaseLeaseCreateRequest(ctx context.Context, leaseID string, options *ContainerClientReleaseLeaseOptions, modifiedAccessConditions *ModifiedAccessConditions) (*policy.Request, error) { + req, err := runtime.NewRequest(ctx, http.MethodPut, client.endpoint) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("comp", "lease") + reqQP.Set("restype", "container") + if options != nil && options.Timeout != nil { + reqQP.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + } + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["x-ms-lease-action"] = []string{"release"} + req.Raw().Header["x-ms-lease-id"] = []string{leaseID} + if modifiedAccessConditions != nil && modifiedAccessConditions.IfModifiedSince != nil { + req.Raw().Header["If-Modified-Since"] = []string{(*modifiedAccessConditions.IfModifiedSince).In(gmt).Format(time.RFC1123)} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfUnmodifiedSince != nil { + req.Raw().Header["If-Unmodified-Since"] = []string{(*modifiedAccessConditions.IfUnmodifiedSince).In(gmt).Format(time.RFC1123)} + } + req.Raw().Header["x-ms-version"] = []string{"2020-10-02"} + if options != nil && options.RequestID != nil { + req.Raw().Header["x-ms-client-request-id"] = []string{*options.RequestID} + } + req.Raw().Header["Accept"] = []string{"application/xml"} + return req, nil +} + +// releaseLeaseHandleResponse handles the ReleaseLease response. +func (client *ContainerClient) releaseLeaseHandleResponse(resp *http.Response) (ContainerClientReleaseLeaseResponse, error) { + result := ContainerClientReleaseLeaseResponse{} + if val := resp.Header.Get("ETag"); val != "" { + result.ETag = (*azcore.ETag)(&val) + } + if val := resp.Header.Get("Last-Modified"); val != "" { + lastModified, err := time.Parse(time.RFC1123, val) + if err != nil { + return ContainerClientReleaseLeaseResponse{}, err + } + result.LastModified = &lastModified + } + if val := resp.Header.Get("x-ms-client-request-id"); val != "" { + result.ClientRequestID = &val + } + if val := resp.Header.Get("x-ms-request-id"); val != "" { + result.RequestID = &val + } + if val := resp.Header.Get("x-ms-version"); val != "" { + result.Version = &val + } + if val := resp.Header.Get("Date"); val != "" { + date, err := time.Parse(time.RFC1123, val) + if err != nil { + return ContainerClientReleaseLeaseResponse{}, err + } + result.Date = &date + } + return result, nil +} + +// Rename - Renames an existing container. +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2020-10-02 +// - sourceFilesystemName - Required. Specifies the name of the container to rename. +// - options - ContainerClientRenameOptions contains the optional parameters for the ContainerClient.Rename method. +func (client *ContainerClient) Rename(ctx context.Context, sourceFilesystemName string, options *ContainerClientRenameOptions) (ContainerClientRenameResponse, error) { + req, err := client.renameCreateRequest(ctx, sourceFilesystemName, options) + if err != nil { + return ContainerClientRenameResponse{}, err + } + resp, err := client.internal.Pipeline().Do(req) + if err != nil { + return ContainerClientRenameResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusOK) { + return ContainerClientRenameResponse{}, runtime.NewResponseError(resp) + } + return client.renameHandleResponse(resp) +} + +// renameCreateRequest creates the Rename request. +func (client *ContainerClient) renameCreateRequest(ctx context.Context, sourceFilesystemName string, options *ContainerClientRenameOptions) (*policy.Request, error) { + req, err := runtime.NewRequest(ctx, http.MethodPut, client.endpoint) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("restype", "container") + reqQP.Set("comp", "rename") + if options != nil && options.Timeout != nil { + reqQP.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + } + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["x-ms-version"] = []string{"2020-10-02"} + if options != nil && options.RequestID != nil { + req.Raw().Header["x-ms-client-request-id"] = []string{*options.RequestID} + } + req.Raw().Header["x-ms-source-container-name"] = []string{sourceFilesystemName} + if options != nil && options.SourceLeaseID != nil { + req.Raw().Header["x-ms-source-lease-id"] = []string{*options.SourceLeaseID} + } + req.Raw().Header["Accept"] = []string{"application/xml"} + return req, nil +} + +// renameHandleResponse handles the Rename response. +func (client *ContainerClient) renameHandleResponse(resp *http.Response) (ContainerClientRenameResponse, error) { + result := ContainerClientRenameResponse{} + if val := resp.Header.Get("x-ms-client-request-id"); val != "" { + result.ClientRequestID = &val + } + if val := resp.Header.Get("x-ms-request-id"); val != "" { + result.RequestID = &val + } + if val := resp.Header.Get("x-ms-version"); val != "" { + result.Version = &val + } + if val := resp.Header.Get("Date"); val != "" { + date, err := time.Parse(time.RFC1123, val) + if err != nil { + return ContainerClientRenameResponse{}, err + } + result.Date = &date + } + return result, nil +} + +// RenewLease - [Update] establishes and manages a lock on a container for delete operations. The lock duration can be 15 +// to 60 seconds, or can be infinite +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2020-10-02 +// - leaseID - Specifies the current lease ID on the resource. +// - options - ContainerClientRenewLeaseOptions contains the optional parameters for the ContainerClient.RenewLease method. +// - ModifiedAccessConditions - ModifiedAccessConditions contains a group of parameters for the ContainerClient.Delete method. +func (client *ContainerClient) RenewLease(ctx context.Context, leaseID string, options *ContainerClientRenewLeaseOptions, modifiedAccessConditions *ModifiedAccessConditions) (ContainerClientRenewLeaseResponse, error) { + req, err := client.renewLeaseCreateRequest(ctx, leaseID, options, modifiedAccessConditions) + if err != nil { + return ContainerClientRenewLeaseResponse{}, err + } + resp, err := client.internal.Pipeline().Do(req) + if err != nil { + return ContainerClientRenewLeaseResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusOK) { + return ContainerClientRenewLeaseResponse{}, runtime.NewResponseError(resp) + } + return client.renewLeaseHandleResponse(resp) +} + +// renewLeaseCreateRequest creates the RenewLease request. +func (client *ContainerClient) renewLeaseCreateRequest(ctx context.Context, leaseID string, options *ContainerClientRenewLeaseOptions, modifiedAccessConditions *ModifiedAccessConditions) (*policy.Request, error) { + req, err := runtime.NewRequest(ctx, http.MethodPut, client.endpoint) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("comp", "lease") + reqQP.Set("restype", "container") + if options != nil && options.Timeout != nil { + reqQP.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + } + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["x-ms-lease-action"] = []string{"renew"} + req.Raw().Header["x-ms-lease-id"] = []string{leaseID} + if modifiedAccessConditions != nil && modifiedAccessConditions.IfModifiedSince != nil { + req.Raw().Header["If-Modified-Since"] = []string{(*modifiedAccessConditions.IfModifiedSince).In(gmt).Format(time.RFC1123)} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfUnmodifiedSince != nil { + req.Raw().Header["If-Unmodified-Since"] = []string{(*modifiedAccessConditions.IfUnmodifiedSince).In(gmt).Format(time.RFC1123)} + } + req.Raw().Header["x-ms-version"] = []string{"2020-10-02"} + if options != nil && options.RequestID != nil { + req.Raw().Header["x-ms-client-request-id"] = []string{*options.RequestID} + } + req.Raw().Header["Accept"] = []string{"application/xml"} + return req, nil +} + +// renewLeaseHandleResponse handles the RenewLease response. +func (client *ContainerClient) renewLeaseHandleResponse(resp *http.Response) (ContainerClientRenewLeaseResponse, error) { + result := ContainerClientRenewLeaseResponse{} + if val := resp.Header.Get("ETag"); val != "" { + result.ETag = (*azcore.ETag)(&val) + } + if val := resp.Header.Get("Last-Modified"); val != "" { + lastModified, err := time.Parse(time.RFC1123, val) + if err != nil { + return ContainerClientRenewLeaseResponse{}, err + } + result.LastModified = &lastModified + } + if val := resp.Header.Get("x-ms-lease-id"); val != "" { + result.LeaseID = &val + } + if val := resp.Header.Get("x-ms-client-request-id"); val != "" { + result.ClientRequestID = &val + } + if val := resp.Header.Get("x-ms-request-id"); val != "" { + result.RequestID = &val + } + if val := resp.Header.Get("x-ms-version"); val != "" { + result.Version = &val + } + if val := resp.Header.Get("Date"); val != "" { + date, err := time.Parse(time.RFC1123, val) + if err != nil { + return ContainerClientRenewLeaseResponse{}, err + } + result.Date = &date + } + return result, nil +} + +// Restore - Restores a previously-deleted container. +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2020-10-02 +// - options - ContainerClientRestoreOptions contains the optional parameters for the ContainerClient.Restore method. +func (client *ContainerClient) Restore(ctx context.Context, options *ContainerClientRestoreOptions) (ContainerClientRestoreResponse, error) { + req, err := client.restoreCreateRequest(ctx, options) + if err != nil { + return ContainerClientRestoreResponse{}, err + } + resp, err := client.internal.Pipeline().Do(req) + if err != nil { + return ContainerClientRestoreResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusCreated) { + return ContainerClientRestoreResponse{}, runtime.NewResponseError(resp) + } + return client.restoreHandleResponse(resp) +} + +// restoreCreateRequest creates the Restore request. +func (client *ContainerClient) restoreCreateRequest(ctx context.Context, options *ContainerClientRestoreOptions) (*policy.Request, error) { + req, err := runtime.NewRequest(ctx, http.MethodPut, client.endpoint) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("restype", "container") + reqQP.Set("comp", "undelete") + if options != nil && options.Timeout != nil { + reqQP.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + } + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["x-ms-version"] = []string{"2020-10-02"} + if options != nil && options.RequestID != nil { + req.Raw().Header["x-ms-client-request-id"] = []string{*options.RequestID} + } + if options != nil && options.DeletedFilesystemName != nil { + req.Raw().Header["x-ms-deleted-container-name"] = []string{*options.DeletedFilesystemName} + } + if options != nil && options.DeletedContainerVersion != nil { + req.Raw().Header["x-ms-deleted-container-version"] = []string{*options.DeletedContainerVersion} + } + req.Raw().Header["Accept"] = []string{"application/xml"} + return req, nil +} + +// restoreHandleResponse handles the Restore response. +func (client *ContainerClient) restoreHandleResponse(resp *http.Response) (ContainerClientRestoreResponse, error) { + result := ContainerClientRestoreResponse{} + if val := resp.Header.Get("x-ms-client-request-id"); val != "" { + result.ClientRequestID = &val + } + if val := resp.Header.Get("x-ms-request-id"); val != "" { + result.RequestID = &val + } + if val := resp.Header.Get("x-ms-version"); val != "" { + result.Version = &val + } + if val := resp.Header.Get("Date"); val != "" { + date, err := time.Parse(time.RFC1123, val) + if err != nil { + return ContainerClientRestoreResponse{}, err + } + result.Date = &date + } + return result, nil +} + +// SetAccessPolicy - sets the permissions for the specified container. The permissions indicate whether blobs in a container +// may be accessed publicly. +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2020-10-02 +// - containerACL - the acls for the container +// - options - ContainerClientSetAccessPolicyOptions contains the optional parameters for the ContainerClient.SetAccessPolicy +// method. +// - LeaseAccessConditions - LeaseAccessConditions contains a group of parameters for the ContainerClient.GetProperties method. +// - ModifiedAccessConditions - ModifiedAccessConditions contains a group of parameters for the ContainerClient.Delete method. +func (client *ContainerClient) SetAccessPolicy(ctx context.Context, containerACL []*SignedIdentifier, options *ContainerClientSetAccessPolicyOptions, leaseAccessConditions *LeaseAccessConditions, modifiedAccessConditions *ModifiedAccessConditions) (ContainerClientSetAccessPolicyResponse, error) { + req, err := client.setAccessPolicyCreateRequest(ctx, containerACL, options, leaseAccessConditions, modifiedAccessConditions) + if err != nil { + return ContainerClientSetAccessPolicyResponse{}, err + } + resp, err := client.internal.Pipeline().Do(req) + if err != nil { + return ContainerClientSetAccessPolicyResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusOK) { + return ContainerClientSetAccessPolicyResponse{}, runtime.NewResponseError(resp) + } + return client.setAccessPolicyHandleResponse(resp) +} + +// setAccessPolicyCreateRequest creates the SetAccessPolicy request. +func (client *ContainerClient) setAccessPolicyCreateRequest(ctx context.Context, containerACL []*SignedIdentifier, options *ContainerClientSetAccessPolicyOptions, leaseAccessConditions *LeaseAccessConditions, modifiedAccessConditions *ModifiedAccessConditions) (*policy.Request, error) { + req, err := runtime.NewRequest(ctx, http.MethodPut, client.endpoint) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("restype", "container") + reqQP.Set("comp", "acl") + if options != nil && options.Timeout != nil { + reqQP.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + } + req.Raw().URL.RawQuery = reqQP.Encode() + if leaseAccessConditions != nil && leaseAccessConditions.LeaseID != nil { + req.Raw().Header["x-ms-lease-id"] = []string{*leaseAccessConditions.LeaseID} + } + if options != nil && options.Access != nil { + req.Raw().Header["x-ms-blob-public-access"] = []string{string(*options.Access)} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfModifiedSince != nil { + req.Raw().Header["If-Modified-Since"] = []string{(*modifiedAccessConditions.IfModifiedSince).In(gmt).Format(time.RFC1123)} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfUnmodifiedSince != nil { + req.Raw().Header["If-Unmodified-Since"] = []string{(*modifiedAccessConditions.IfUnmodifiedSince).In(gmt).Format(time.RFC1123)} + } + req.Raw().Header["x-ms-version"] = []string{"2020-10-02"} + if options != nil && options.RequestID != nil { + req.Raw().Header["x-ms-client-request-id"] = []string{*options.RequestID} + } + req.Raw().Header["Accept"] = []string{"application/xml"} + type wrapper struct { + XMLName xml.Name `xml:"SignedIdentifiers"` + ContainerACL *[]*SignedIdentifier `xml:"SignedIdentifier"` + } + if err := runtime.MarshalAsXML(req, wrapper{ContainerACL: &containerACL}); err != nil { + return nil, err + } + return req, nil +} + +// setAccessPolicyHandleResponse handles the SetAccessPolicy response. +func (client *ContainerClient) setAccessPolicyHandleResponse(resp *http.Response) (ContainerClientSetAccessPolicyResponse, error) { + result := ContainerClientSetAccessPolicyResponse{} + if val := resp.Header.Get("ETag"); val != "" { + result.ETag = (*azcore.ETag)(&val) + } + if val := resp.Header.Get("Last-Modified"); val != "" { + lastModified, err := time.Parse(time.RFC1123, val) + if err != nil { + return ContainerClientSetAccessPolicyResponse{}, err + } + result.LastModified = &lastModified + } + if val := resp.Header.Get("x-ms-client-request-id"); val != "" { + result.ClientRequestID = &val + } + if val := resp.Header.Get("x-ms-request-id"); val != "" { + result.RequestID = &val + } + if val := resp.Header.Get("x-ms-version"); val != "" { + result.Version = &val + } + if val := resp.Header.Get("Date"); val != "" { + date, err := time.Parse(time.RFC1123, val) + if err != nil { + return ContainerClientSetAccessPolicyResponse{}, err + } + result.Date = &date + } + return result, nil +} + +// SetMetadata - operation sets one or more user-defined name-value pairs for the specified container. +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2020-10-02 +// - options - ContainerClientSetMetadataOptions contains the optional parameters for the ContainerClient.SetMetadata method. +// - LeaseAccessConditions - LeaseAccessConditions contains a group of parameters for the ContainerClient.GetProperties method. +// - ModifiedAccessConditions - ModifiedAccessConditions contains a group of parameters for the ContainerClient.Delete method. +func (client *ContainerClient) SetMetadata(ctx context.Context, options *ContainerClientSetMetadataOptions, leaseAccessConditions *LeaseAccessConditions, modifiedAccessConditions *ModifiedAccessConditions) (ContainerClientSetMetadataResponse, error) { + req, err := client.setMetadataCreateRequest(ctx, options, leaseAccessConditions, modifiedAccessConditions) + if err != nil { + return ContainerClientSetMetadataResponse{}, err + } + resp, err := client.internal.Pipeline().Do(req) + if err != nil { + return ContainerClientSetMetadataResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusOK) { + return ContainerClientSetMetadataResponse{}, runtime.NewResponseError(resp) + } + return client.setMetadataHandleResponse(resp) +} + +// setMetadataCreateRequest creates the SetMetadata request. +func (client *ContainerClient) setMetadataCreateRequest(ctx context.Context, options *ContainerClientSetMetadataOptions, leaseAccessConditions *LeaseAccessConditions, modifiedAccessConditions *ModifiedAccessConditions) (*policy.Request, error) { + req, err := runtime.NewRequest(ctx, http.MethodPut, client.endpoint) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("restype", "container") + reqQP.Set("comp", "metadata") + if options != nil && options.Timeout != nil { + reqQP.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + } + req.Raw().URL.RawQuery = reqQP.Encode() + if leaseAccessConditions != nil && leaseAccessConditions.LeaseID != nil { + req.Raw().Header["x-ms-lease-id"] = []string{*leaseAccessConditions.LeaseID} + } + if options != nil && options.Metadata != nil { + for k, v := range options.Metadata { + if v != nil { + req.Raw().Header["x-ms-meta-"+k] = []string{*v} + } + } + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfModifiedSince != nil { + req.Raw().Header["If-Modified-Since"] = []string{(*modifiedAccessConditions.IfModifiedSince).In(gmt).Format(time.RFC1123)} + } + req.Raw().Header["x-ms-version"] = []string{"2020-10-02"} + if options != nil && options.RequestID != nil { + req.Raw().Header["x-ms-client-request-id"] = []string{*options.RequestID} + } + req.Raw().Header["Accept"] = []string{"application/xml"} + return req, nil +} + +// setMetadataHandleResponse handles the SetMetadata response. +func (client *ContainerClient) setMetadataHandleResponse(resp *http.Response) (ContainerClientSetMetadataResponse, error) { + result := ContainerClientSetMetadataResponse{} + if val := resp.Header.Get("ETag"); val != "" { + result.ETag = (*azcore.ETag)(&val) + } + if val := resp.Header.Get("Last-Modified"); val != "" { + lastModified, err := time.Parse(time.RFC1123, val) + if err != nil { + return ContainerClientSetMetadataResponse{}, err + } + result.LastModified = &lastModified + } + if val := resp.Header.Get("x-ms-client-request-id"); val != "" { + result.ClientRequestID = &val + } + if val := resp.Header.Get("x-ms-request-id"); val != "" { + result.RequestID = &val + } + if val := resp.Header.Get("x-ms-version"); val != "" { + result.Version = &val + } + if val := resp.Header.Get("Date"); val != "" { + date, err := time.Parse(time.RFC1123, val) + if err != nil { + return ContainerClientSetMetadataResponse{}, err + } + result.Date = &date + } + return result, nil +} + +// SubmitBatch - The Batch operation allows multiple API calls to be embedded into a single HTTP request. +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2020-10-02 +// - contentLength - The length of the request. +// - multipartContentType - Required. The value of this header must be multipart/mixed with a batch boundary. Example header +// value: multipart/mixed; boundary=batch_ +// - body - Initial data +// - options - ContainerClientSubmitBatchOptions contains the optional parameters for the ContainerClient.SubmitBatch method. +func (client *ContainerClient) SubmitBatch(ctx context.Context, contentLength int64, multipartContentType string, body io.ReadSeekCloser, options *ContainerClientSubmitBatchOptions) (ContainerClientSubmitBatchResponse, error) { + req, err := client.submitBatchCreateRequest(ctx, contentLength, multipartContentType, body, options) + if err != nil { + return ContainerClientSubmitBatchResponse{}, err + } + resp, err := client.internal.Pipeline().Do(req) + if err != nil { + return ContainerClientSubmitBatchResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusAccepted) { + return ContainerClientSubmitBatchResponse{}, runtime.NewResponseError(resp) + } + return client.submitBatchHandleResponse(resp) +} + +// submitBatchCreateRequest creates the SubmitBatch request. +func (client *ContainerClient) submitBatchCreateRequest(ctx context.Context, contentLength int64, multipartContentType string, body io.ReadSeekCloser, options *ContainerClientSubmitBatchOptions) (*policy.Request, error) { + req, err := runtime.NewRequest(ctx, http.MethodPost, client.endpoint) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("restype", "container") + reqQP.Set("comp", "batch") + if options != nil && options.Timeout != nil { + reqQP.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + } + req.Raw().URL.RawQuery = reqQP.Encode() + runtime.SkipBodyDownload(req) + req.Raw().Header["Content-Length"] = []string{strconv.FormatInt(contentLength, 10)} + req.Raw().Header["Content-Type"] = []string{multipartContentType} + req.Raw().Header["x-ms-version"] = []string{"2020-10-02"} + if options != nil && options.RequestID != nil { + req.Raw().Header["x-ms-client-request-id"] = []string{*options.RequestID} + } + req.Raw().Header["Accept"] = []string{"application/xml"} + if err := req.SetBody(body, multipartContentType); err != nil { + return nil, err + } + return req, nil +} + +// submitBatchHandleResponse handles the SubmitBatch response. +func (client *ContainerClient) submitBatchHandleResponse(resp *http.Response) (ContainerClientSubmitBatchResponse, error) { + result := ContainerClientSubmitBatchResponse{Body: resp.Body} + if val := resp.Header.Get("Content-Type"); val != "" { + result.ContentType = &val + } + if val := resp.Header.Get("x-ms-request-id"); val != "" { + result.RequestID = &val + } + if val := resp.Header.Get("x-ms-version"); val != "" { + result.Version = &val + } + return result, nil +} diff --git a/sdk/storage/azdatalake/internal/generated_blob/zz_models.go b/sdk/storage/azdatalake/internal/generated_blob/zz_models.go new file mode 100644 index 000000000000..d60fbd9ff1b3 --- /dev/null +++ b/sdk/storage/azdatalake/internal/generated_blob/zz_models.go @@ -0,0 +1,1733 @@ +//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. +// Code generated by Microsoft (R) AutoRest Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. +// DO NOT EDIT. + +package generated_blob + +import ( + "github.com/Azure/azure-sdk-for-go/sdk/azcore" + "time" +) + +// AccessPolicy - An Access policy +type AccessPolicy struct { + // the date-time the policy expires + Expiry *time.Time `xml:"Expiry"` + + // the permissions for the acl policy + Permission *string `xml:"Permission"` + + // the date-time the policy is active + Start *time.Time `xml:"Start"` +} + +// AppendBlobClientAppendBlockFromURLOptions contains the optional parameters for the AppendBlobClient.AppendBlockFromURL +// method. +type AppendBlobClientAppendBlockFromURLOptions struct { + // Only Bearer type is supported. Credentials should be a valid OAuth access token to copy source. + CopySourceAuthorization *string + // Provides a client-generated, opaque value with a 1 KB character limit that is recorded in the analytics logs when storage + // analytics logging is enabled. + RequestID *string + // Specify the md5 calculated for the range of bytes that must be read from the copy source. + SourceContentMD5 []byte + // Specify the crc64 calculated for the range of bytes that must be read from the copy source. + SourceContentcrc64 []byte + // Bytes of source data in the specified range. + SourceRange *string + // The timeout parameter is expressed in seconds. For more information, see Setting Timeouts for Blob Service Operations. + // [https://docs.microsoft.com/en-us/rest/api/storageservices/fileservices/setting-timeouts-for-blob-service-operations] + Timeout *int32 + // Specify the transactional md5 for the body, to be validated by the service. + TransactionalContentMD5 []byte +} + +// AppendBlobClientAppendBlockOptions contains the optional parameters for the AppendBlobClient.AppendBlock method. +type AppendBlobClientAppendBlockOptions struct { + // Provides a client-generated, opaque value with a 1 KB character limit that is recorded in the analytics logs when storage + // analytics logging is enabled. + RequestID *string + // The timeout parameter is expressed in seconds. For more information, see Setting Timeouts for Blob Service Operations. + // [https://docs.microsoft.com/en-us/rest/api/storageservices/fileservices/setting-timeouts-for-blob-service-operations] + Timeout *int32 + // Specify the transactional crc64 for the body, to be validated by the service. + TransactionalContentCRC64 []byte + // Specify the transactional md5 for the body, to be validated by the service. + TransactionalContentMD5 []byte +} + +// AppendBlobClientCreateOptions contains the optional parameters for the AppendBlobClient.Create method. +type AppendBlobClientCreateOptions struct { + // Optional. Used to set blob tags in various blob operations. + BlobTagsString *string + // Specifies the date time when the blobs immutability policy is set to expire. + ImmutabilityPolicyExpiry *time.Time + // Specifies the immutability policy mode to set on the blob. + ImmutabilityPolicyMode *ImmutabilityPolicySetting + // Specified if a legal hold should be set on the blob. + LegalHold *bool + // Optional. Specifies a user-defined name-value pair associated with the blob. If no name-value pairs are specified, the + // operation will copy the metadata from the source blob or file to the destination + // blob. If one or more name-value pairs are specified, the destination blob is created with the specified metadata, and metadata + // is not copied from the source blob or file. Note that beginning with + // version 2009-09-19, metadata names must adhere to the naming rules for C# identifiers. See Naming and Referencing Containers, + // Blobs, and Metadata for more information. + Metadata map[string]*string + // Provides a client-generated, opaque value with a 1 KB character limit that is recorded in the analytics logs when storage + // analytics logging is enabled. + RequestID *string + // The timeout parameter is expressed in seconds. For more information, see Setting Timeouts for Blob Service Operations. + // [https://docs.microsoft.com/en-us/rest/api/storageservices/fileservices/setting-timeouts-for-blob-service-operations] + Timeout *int32 +} + +// AppendBlobClientSealOptions contains the optional parameters for the AppendBlobClient.Seal method. +type AppendBlobClientSealOptions struct { + // Provides a client-generated, opaque value with a 1 KB character limit that is recorded in the analytics logs when storage + // analytics logging is enabled. + RequestID *string + // The timeout parameter is expressed in seconds. For more information, see Setting Timeouts for Blob Service Operations. + // [https://docs.microsoft.com/en-us/rest/api/storageservices/fileservices/setting-timeouts-for-blob-service-operations] + Timeout *int32 +} + +// AppendPositionAccessConditions contains a group of parameters for the AppendBlobClient.AppendBlock method. +type AppendPositionAccessConditions struct { + // Optional conditional header, used only for the Append Block operation. A number indicating the byte offset to compare. + // Append Block will succeed only if the append position is equal to this number. If + // it is not, the request will fail with the AppendPositionConditionNotMet error (HTTP status code 412 - Precondition Failed). + AppendPosition *int64 + // Optional conditional header. The max length in bytes permitted for the append blob. If the Append Block operation would + // cause the blob to exceed that limit or if the blob size is already greater than + // the value specified in this header, the request will fail with MaxBlobSizeConditionNotMet error (HTTP status code 412 - + // Precondition Failed). + MaxSize *int64 +} + +// ArrowConfiguration - Groups the settings used for formatting the response if the response should be Arrow formatted. +type ArrowConfiguration struct { + // REQUIRED + Schema []*ArrowField `xml:"Schema>Field"` +} + +// ArrowField - Groups settings regarding specific field of an arrow schema +type ArrowField struct { + // REQUIRED + Type *string `xml:"Type"` + Name *string `xml:"Name"` + Precision *int32 `xml:"Precision"` + Scale *int32 `xml:"Scale"` +} + +// BlobClientAbortCopyFromURLOptions contains the optional parameters for the BlobClient.AbortCopyFromURL method. +type BlobClientAbortCopyFromURLOptions struct { + // Provides a client-generated, opaque value with a 1 KB character limit that is recorded in the analytics logs when storage + // analytics logging is enabled. + RequestID *string + // The timeout parameter is expressed in seconds. For more information, see Setting Timeouts for Blob Service Operations. + // [https://docs.microsoft.com/en-us/rest/api/storageservices/fileservices/setting-timeouts-for-blob-service-operations] + Timeout *int32 +} + +// BlobClientAcquireLeaseOptions contains the optional parameters for the BlobClient.AcquireLease method. +type BlobClientAcquireLeaseOptions struct { + // Proposed lease ID, in a GUID string format. The Blob service returns 400 (Invalid request) if the proposed lease ID is + // not in the correct format. See Guid Constructor (String) for a list of valid GUID + // string formats. + ProposedLeaseID *string + // Provides a client-generated, opaque value with a 1 KB character limit that is recorded in the analytics logs when storage + // analytics logging is enabled. + RequestID *string + // The timeout parameter is expressed in seconds. For more information, see Setting Timeouts for Blob Service Operations. + // [https://docs.microsoft.com/en-us/rest/api/storageservices/fileservices/setting-timeouts-for-blob-service-operations] + Timeout *int32 +} + +// BlobClientBreakLeaseOptions contains the optional parameters for the BlobClient.BreakLease method. +type BlobClientBreakLeaseOptions struct { + // For a break operation, proposed duration the lease should continue before it is broken, in seconds, between 0 and 60. This + // break period is only used if it is shorter than the time remaining on the + // lease. If longer, the time remaining on the lease is used. A new lease will not be available before the break period has + // expired, but the lease may be held for longer than the break period. If this + // header does not appear with a break operation, a fixed-duration lease breaks after the remaining lease period elapses, + // and an infinite lease breaks immediately. + BreakPeriod *int32 + // Provides a client-generated, opaque value with a 1 KB character limit that is recorded in the analytics logs when storage + // analytics logging is enabled. + RequestID *string + // The timeout parameter is expressed in seconds. For more information, see Setting Timeouts for Blob Service Operations. + // [https://docs.microsoft.com/en-us/rest/api/storageservices/fileservices/setting-timeouts-for-blob-service-operations] + Timeout *int32 +} + +// BlobClientChangeLeaseOptions contains the optional parameters for the BlobClient.ChangeLease method. +type BlobClientChangeLeaseOptions struct { + // Provides a client-generated, opaque value with a 1 KB character limit that is recorded in the analytics logs when storage + // analytics logging is enabled. + RequestID *string + // The timeout parameter is expressed in seconds. For more information, see Setting Timeouts for Blob Service Operations. + // [https://docs.microsoft.com/en-us/rest/api/storageservices/fileservices/setting-timeouts-for-blob-service-operations] + Timeout *int32 +} + +// BlobClientCopyFromURLOptions contains the optional parameters for the BlobClient.CopyFromURL method. +type BlobClientCopyFromURLOptions struct { + // Optional. Used to set blob tags in various blob operations. + BlobTagsString *string + // Only Bearer type is supported. Credentials should be a valid OAuth access token to copy source. + CopySourceAuthorization *string + // Specifies the date time when the blobs immutability policy is set to expire. + ImmutabilityPolicyExpiry *time.Time + // Specifies the immutability policy mode to set on the blob. + ImmutabilityPolicyMode *ImmutabilityPolicySetting + // Specified if a legal hold should be set on the blob. + LegalHold *bool + // Optional. Specifies a user-defined name-value pair associated with the blob. If no name-value pairs are specified, the + // operation will copy the metadata from the source blob or file to the destination + // blob. If one or more name-value pairs are specified, the destination blob is created with the specified metadata, and metadata + // is not copied from the source blob or file. Note that beginning with + // version 2009-09-19, metadata names must adhere to the naming rules for C# identifiers. See Naming and Referencing Containers, + // Blobs, and Metadata for more information. + Metadata map[string]*string + // Provides a client-generated, opaque value with a 1 KB character limit that is recorded in the analytics logs when storage + // analytics logging is enabled. + RequestID *string + // Specify the md5 calculated for the range of bytes that must be read from the copy source. + SourceContentMD5 []byte + // Optional. Indicates the tier to be set on the blob. + Tier *AccessTier + // The timeout parameter is expressed in seconds. For more information, see Setting Timeouts for Blob Service Operations. + // [https://docs.microsoft.com/en-us/rest/api/storageservices/fileservices/setting-timeouts-for-blob-service-operations] + Timeout *int32 +} + +// BlobClientCreateSnapshotOptions contains the optional parameters for the BlobClient.CreateSnapshot method. +type BlobClientCreateSnapshotOptions struct { + // Optional. Specifies a user-defined name-value pair associated with the blob. If no name-value pairs are specified, the + // operation will copy the metadata from the source blob or file to the destination + // blob. If one or more name-value pairs are specified, the destination blob is created with the specified metadata, and metadata + // is not copied from the source blob or file. Note that beginning with + // version 2009-09-19, metadata names must adhere to the naming rules for C# identifiers. See Naming and Referencing Containers, + // Blobs, and Metadata for more information. + Metadata map[string]*string + // Provides a client-generated, opaque value with a 1 KB character limit that is recorded in the analytics logs when storage + // analytics logging is enabled. + RequestID *string + // The timeout parameter is expressed in seconds. For more information, see Setting Timeouts for Blob Service Operations. + // [https://docs.microsoft.com/en-us/rest/api/storageservices/fileservices/setting-timeouts-for-blob-service-operations] + Timeout *int32 +} + +// BlobClientDeleteImmutabilityPolicyOptions contains the optional parameters for the BlobClient.DeleteImmutabilityPolicy +// method. +type BlobClientDeleteImmutabilityPolicyOptions struct { + // Provides a client-generated, opaque value with a 1 KB character limit that is recorded in the analytics logs when storage + // analytics logging is enabled. + RequestID *string + // The timeout parameter is expressed in seconds. For more information, see Setting Timeouts for Blob Service Operations. + // [https://docs.microsoft.com/en-us/rest/api/storageservices/fileservices/setting-timeouts-for-blob-service-operations] + Timeout *int32 +} + +// BlobClientDeleteOptions contains the optional parameters for the BlobClient.Delete method. +type BlobClientDeleteOptions struct { + // Required if the blob has associated snapshots. Specify one of the following two options: include: Delete the base blob + // and all of its snapshots. only: Delete only the blob's snapshots and not the blob + // itself + DeleteSnapshots *DeleteSnapshotsOptionType + // Optional. Only possible value is 'permanent', which specifies to permanently delete a blob if blob soft delete is enabled. + DeleteType *DeleteType + // Provides a client-generated, opaque value with a 1 KB character limit that is recorded in the analytics logs when storage + // analytics logging is enabled. + RequestID *string + // The snapshot parameter is an opaque DateTime value that, when present, specifies the blob snapshot to retrieve. For more + // information on working with blob snapshots, see Creating a Snapshot of a Blob. + // [https://docs.microsoft.com/en-us/rest/api/storageservices/fileservices/creating-a-snapshot-of-a-blob] + Snapshot *string + // The timeout parameter is expressed in seconds. For more information, see Setting Timeouts for Blob Service Operations. + // [https://docs.microsoft.com/en-us/rest/api/storageservices/fileservices/setting-timeouts-for-blob-service-operations] + Timeout *int32 + // The version id parameter is an opaque DateTime value that, when present, specifies the version of the blob to operate on. + // It's for service version 2019-10-10 and newer. + VersionID *string +} + +// BlobClientDownloadOptions contains the optional parameters for the BlobClient.Download method. +type BlobClientDownloadOptions struct { + // Return only the bytes of the blob in the specified range. + Range *string + // When set to true and specified together with the Range, the service returns the CRC64 hash for the range, as long as the + // range is less than or equal to 4 MB in size. + RangeGetContentCRC64 *bool + // When set to true and specified together with the Range, the service returns the MD5 hash for the range, as long as the + // range is less than or equal to 4 MB in size. + RangeGetContentMD5 *bool + // Provides a client-generated, opaque value with a 1 KB character limit that is recorded in the analytics logs when storage + // analytics logging is enabled. + RequestID *string + // The snapshot parameter is an opaque DateTime value that, when present, specifies the blob snapshot to retrieve. For more + // information on working with blob snapshots, see Creating a Snapshot of a Blob. + // [https://docs.microsoft.com/en-us/rest/api/storageservices/fileservices/creating-a-snapshot-of-a-blob] + Snapshot *string + // The timeout parameter is expressed in seconds. For more information, see Setting Timeouts for Blob Service Operations. + // [https://docs.microsoft.com/en-us/rest/api/storageservices/fileservices/setting-timeouts-for-blob-service-operations] + Timeout *int32 + // The version id parameter is an opaque DateTime value that, when present, specifies the version of the blob to operate on. + // It's for service version 2019-10-10 and newer. + VersionID *string +} + +// BlobClientGetAccountInfoOptions contains the optional parameters for the BlobClient.GetAccountInfo method. +type BlobClientGetAccountInfoOptions struct { + // placeholder for future optional parameters +} + +// BlobClientGetPropertiesOptions contains the optional parameters for the BlobClient.GetProperties method. +type BlobClientGetPropertiesOptions struct { + // Provides a client-generated, opaque value with a 1 KB character limit that is recorded in the analytics logs when storage + // analytics logging is enabled. + RequestID *string + // The snapshot parameter is an opaque DateTime value that, when present, specifies the blob snapshot to retrieve. For more + // information on working with blob snapshots, see Creating a Snapshot of a Blob. + // [https://docs.microsoft.com/en-us/rest/api/storageservices/fileservices/creating-a-snapshot-of-a-blob] + Snapshot *string + // The timeout parameter is expressed in seconds. For more information, see Setting Timeouts for Blob Service Operations. + // [https://docs.microsoft.com/en-us/rest/api/storageservices/fileservices/setting-timeouts-for-blob-service-operations] + Timeout *int32 + // The version id parameter is an opaque DateTime value that, when present, specifies the version of the blob to operate on. + // It's for service version 2019-10-10 and newer. + VersionID *string +} + +// BlobClientGetTagsOptions contains the optional parameters for the BlobClient.GetTags method. +type BlobClientGetTagsOptions struct { + // Provides a client-generated, opaque value with a 1 KB character limit that is recorded in the analytics logs when storage + // analytics logging is enabled. + RequestID *string + // The snapshot parameter is an opaque DateTime value that, when present, specifies the blob snapshot to retrieve. For more + // information on working with blob snapshots, see Creating a Snapshot of a Blob. + // [https://docs.microsoft.com/en-us/rest/api/storageservices/fileservices/creating-a-snapshot-of-a-blob] + Snapshot *string + // The timeout parameter is expressed in seconds. For more information, see Setting Timeouts for Blob Service Operations. + // [https://docs.microsoft.com/en-us/rest/api/storageservices/fileservices/setting-timeouts-for-blob-service-operations] + Timeout *int32 + // The version id parameter is an opaque DateTime value that, when present, specifies the version of the blob to operate on. + // It's for service version 2019-10-10 and newer. + VersionID *string +} + +// BlobClientQueryOptions contains the optional parameters for the BlobClient.Query method. +type BlobClientQueryOptions struct { + // the query request + QueryRequest *QueryRequest + // Provides a client-generated, opaque value with a 1 KB character limit that is recorded in the analytics logs when storage + // analytics logging is enabled. + RequestID *string + // The snapshot parameter is an opaque DateTime value that, when present, specifies the blob snapshot to retrieve. For more + // information on working with blob snapshots, see Creating a Snapshot of a Blob. + // [https://docs.microsoft.com/en-us/rest/api/storageservices/fileservices/creating-a-snapshot-of-a-blob] + Snapshot *string + // The timeout parameter is expressed in seconds. For more information, see Setting Timeouts for Blob Service Operations. + // [https://docs.microsoft.com/en-us/rest/api/storageservices/fileservices/setting-timeouts-for-blob-service-operations] + Timeout *int32 +} + +// BlobClientReleaseLeaseOptions contains the optional parameters for the BlobClient.ReleaseLease method. +type BlobClientReleaseLeaseOptions struct { + // Provides a client-generated, opaque value with a 1 KB character limit that is recorded in the analytics logs when storage + // analytics logging is enabled. + RequestID *string + // The timeout parameter is expressed in seconds. For more information, see Setting Timeouts for Blob Service Operations. + // [https://docs.microsoft.com/en-us/rest/api/storageservices/fileservices/setting-timeouts-for-blob-service-operations] + Timeout *int32 +} + +// BlobClientRenewLeaseOptions contains the optional parameters for the BlobClient.RenewLease method. +type BlobClientRenewLeaseOptions struct { + // Provides a client-generated, opaque value with a 1 KB character limit that is recorded in the analytics logs when storage + // analytics logging is enabled. + RequestID *string + // The timeout parameter is expressed in seconds. For more information, see Setting Timeouts for Blob Service Operations. + // [https://docs.microsoft.com/en-us/rest/api/storageservices/fileservices/setting-timeouts-for-blob-service-operations] + Timeout *int32 +} + +// BlobClientSetExpiryOptions contains the optional parameters for the BlobClient.SetExpiry method. +type BlobClientSetExpiryOptions struct { + // The time to set the blob to expiry + ExpiresOn *string + // Provides a client-generated, opaque value with a 1 KB character limit that is recorded in the analytics logs when storage + // analytics logging is enabled. + RequestID *string + // The timeout parameter is expressed in seconds. For more information, see Setting Timeouts for Blob Service Operations. + // [https://docs.microsoft.com/en-us/rest/api/storageservices/fileservices/setting-timeouts-for-blob-service-operations] + Timeout *int32 +} + +// BlobClientSetHTTPHeadersOptions contains the optional parameters for the BlobClient.SetHTTPHeaders method. +type BlobClientSetHTTPHeadersOptions struct { + // Provides a client-generated, opaque value with a 1 KB character limit that is recorded in the analytics logs when storage + // analytics logging is enabled. + RequestID *string + // The timeout parameter is expressed in seconds. For more information, see Setting Timeouts for Blob Service Operations. + // [https://docs.microsoft.com/en-us/rest/api/storageservices/fileservices/setting-timeouts-for-blob-service-operations] + Timeout *int32 +} + +// BlobClientSetImmutabilityPolicyOptions contains the optional parameters for the BlobClient.SetImmutabilityPolicy method. +type BlobClientSetImmutabilityPolicyOptions struct { + // Specifies the date time when the blobs immutability policy is set to expire. + ImmutabilityPolicyExpiry *time.Time + // Specifies the immutability policy mode to set on the blob. + ImmutabilityPolicyMode *ImmutabilityPolicySetting + // Provides a client-generated, opaque value with a 1 KB character limit that is recorded in the analytics logs when storage + // analytics logging is enabled. + RequestID *string + // The timeout parameter is expressed in seconds. For more information, see Setting Timeouts for Blob Service Operations. + // [https://docs.microsoft.com/en-us/rest/api/storageservices/fileservices/setting-timeouts-for-blob-service-operations] + Timeout *int32 +} + +// BlobClientSetLegalHoldOptions contains the optional parameters for the BlobClient.SetLegalHold method. +type BlobClientSetLegalHoldOptions struct { + // Provides a client-generated, opaque value with a 1 KB character limit that is recorded in the analytics logs when storage + // analytics logging is enabled. + RequestID *string + // The timeout parameter is expressed in seconds. For more information, see Setting Timeouts for Blob Service Operations. + // [https://docs.microsoft.com/en-us/rest/api/storageservices/fileservices/setting-timeouts-for-blob-service-operations] + Timeout *int32 +} + +// BlobClientSetMetadataOptions contains the optional parameters for the BlobClient.SetMetadata method. +type BlobClientSetMetadataOptions struct { + // Optional. Specifies a user-defined name-value pair associated with the blob. If no name-value pairs are specified, the + // operation will copy the metadata from the source blob or file to the destination + // blob. If one or more name-value pairs are specified, the destination blob is created with the specified metadata, and metadata + // is not copied from the source blob or file. Note that beginning with + // version 2009-09-19, metadata names must adhere to the naming rules for C# identifiers. See Naming and Referencing Containers, + // Blobs, and Metadata for more information. + Metadata map[string]*string + // Provides a client-generated, opaque value with a 1 KB character limit that is recorded in the analytics logs when storage + // analytics logging is enabled. + RequestID *string + // The timeout parameter is expressed in seconds. For more information, see Setting Timeouts for Blob Service Operations. + // [https://docs.microsoft.com/en-us/rest/api/storageservices/fileservices/setting-timeouts-for-blob-service-operations] + Timeout *int32 +} + +// BlobClientSetTagsOptions contains the optional parameters for the BlobClient.SetTags method. +type BlobClientSetTagsOptions struct { + // Provides a client-generated, opaque value with a 1 KB character limit that is recorded in the analytics logs when storage + // analytics logging is enabled. + RequestID *string + // The timeout parameter is expressed in seconds. For more information, see Setting Timeouts for Blob Service Operations. + // [https://docs.microsoft.com/en-us/rest/api/storageservices/fileservices/setting-timeouts-for-blob-service-operations] + Timeout *int32 + // Specify the transactional crc64 for the body, to be validated by the service. + TransactionalContentCRC64 []byte + // Specify the transactional md5 for the body, to be validated by the service. + TransactionalContentMD5 []byte + // The version id parameter is an opaque DateTime value that, when present, specifies the version of the blob to operate on. + // It's for service version 2019-10-10 and newer. + VersionID *string +} + +// BlobClientSetTierOptions contains the optional parameters for the BlobClient.SetTier method. +type BlobClientSetTierOptions struct { + // Optional: Indicates the priority with which to rehydrate an archived blob. + RehydratePriority *RehydratePriority + // Provides a client-generated, opaque value with a 1 KB character limit that is recorded in the analytics logs when storage + // analytics logging is enabled. + RequestID *string + // The snapshot parameter is an opaque DateTime value that, when present, specifies the blob snapshot to retrieve. For more + // information on working with blob snapshots, see Creating a Snapshot of a Blob. + // [https://docs.microsoft.com/en-us/rest/api/storageservices/fileservices/creating-a-snapshot-of-a-blob] + Snapshot *string + // The timeout parameter is expressed in seconds. For more information, see Setting Timeouts for Blob Service Operations. + // [https://docs.microsoft.com/en-us/rest/api/storageservices/fileservices/setting-timeouts-for-blob-service-operations] + Timeout *int32 + // The version id parameter is an opaque DateTime value that, when present, specifies the version of the blob to operate on. + // It's for service version 2019-10-10 and newer. + VersionID *string +} + +// BlobClientStartCopyFromURLOptions contains the optional parameters for the BlobClient.StartCopyFromURL method. +type BlobClientStartCopyFromURLOptions struct { + // Optional. Used to set blob tags in various blob operations. + BlobTagsString *string + // Specifies the date time when the blobs immutability policy is set to expire. + ImmutabilityPolicyExpiry *time.Time + // Specifies the immutability policy mode to set on the blob. + ImmutabilityPolicyMode *ImmutabilityPolicySetting + // Specified if a legal hold should be set on the blob. + LegalHold *bool + // Optional. Specifies a user-defined name-value pair associated with the blob. If no name-value pairs are specified, the + // operation will copy the metadata from the source blob or file to the destination + // blob. If one or more name-value pairs are specified, the destination blob is created with the specified metadata, and metadata + // is not copied from the source blob or file. Note that beginning with + // version 2009-09-19, metadata names must adhere to the naming rules for C# identifiers. See Naming and Referencing Containers, + // Blobs, and Metadata for more information. + Metadata map[string]*string + // Optional: Indicates the priority with which to rehydrate an archived blob. + RehydratePriority *RehydratePriority + // Provides a client-generated, opaque value with a 1 KB character limit that is recorded in the analytics logs when storage + // analytics logging is enabled. + RequestID *string + // Overrides the sealed state of the destination blob. Service version 2019-12-12 and newer. + SealBlob *bool + // Optional. Indicates the tier to be set on the blob. + Tier *AccessTier + // The timeout parameter is expressed in seconds. For more information, see Setting Timeouts for Blob Service Operations. + // [https://docs.microsoft.com/en-us/rest/api/storageservices/fileservices/setting-timeouts-for-blob-service-operations] + Timeout *int32 +} + +// BlobClientUndeleteOptions contains the optional parameters for the BlobClient.Undelete method. +type BlobClientUndeleteOptions struct { + // Provides a client-generated, opaque value with a 1 KB character limit that is recorded in the analytics logs when storage + // analytics logging is enabled. + RequestID *string + // The timeout parameter is expressed in seconds. For more information, see Setting Timeouts for Blob Service Operations. + // [https://docs.microsoft.com/en-us/rest/api/storageservices/fileservices/setting-timeouts-for-blob-service-operations] + Timeout *int32 +} + +type BlobFlatListSegment struct { + // REQUIRED + PathItems []*PathItem `xml:"Blob"` +} + +// BlobHTTPHeaders contains a group of parameters for the BlobClient.SetHTTPHeaders method. +type BlobHTTPHeaders struct { + // Optional. Sets the blob's cache control. If specified, this property is stored with the blob and returned with a read request. + BlobCacheControl *string + // Optional. Sets the blob's Content-Disposition header. + BlobContentDisposition *string + // Optional. Sets the blob's content encoding. If specified, this property is stored with the blob and returned with a read + // request. + BlobContentEncoding *string + // Optional. Set the blob's content language. If specified, this property is stored with the blob and returned with a read + // request. + BlobContentLanguage *string + // Optional. An MD5 hash of the blob content. Note that this hash is not validated, as the hashes for the individual blocks + // were validated when each was uploaded. + BlobContentMD5 []byte + // Optional. Sets the blob's content type. If specified, this property is stored with the blob and returned with a read request. + BlobContentType *string +} + +type PathHierarchyListSegment struct { + // REQUIRED + PathItems []*PathItem `xml:"Blob"` + PathPrefixes []*PathPrefix `xml:"PathPrefix"` +} + +// PathItem - An Azure Storage blob +type PathItem struct { + // REQUIRED + Deleted *bool `xml:"Deleted"` + + // REQUIRED + Name *string `xml:"Name"` + + // REQUIRED; Properties of a blob + Properties *PathProperties `xml:"Properties"` + + // REQUIRED + Snapshot *string `xml:"Snapshot"` + + // Blob tags + BlobTags *BlobTags `xml:"Tags"` + HasVersionsOnly *bool `xml:"HasVersionsOnly"` + IsCurrentVersion *bool `xml:"IsCurrentVersion"` + + // Dictionary of + Metadata map[string]*string `xml:"Metadata"` + + // Dictionary of + OrMetadata map[string]*string `xml:"OrMetadata"` + VersionID *string `xml:"VersionId"` +} + +type PathPrefix struct { + // REQUIRED + Name *string `xml:"Name"` +} + +// PathProperties - Properties of a blob +type PathProperties struct { + // REQUIRED + ETag *azcore.ETag `xml:"Etag"` + + // REQUIRED + LastModified *time.Time `xml:"Last-Modified"` + AccessTier *AccessTier `xml:"AccessTier"` + AccessTierChangeTime *time.Time `xml:"AccessTierChangeTime"` + AccessTierInferred *bool `xml:"AccessTierInferred"` + ArchiveStatus *ArchiveStatus `xml:"ArchiveStatus"` + BlobSequenceNumber *int64 `xml:"x-ms-blob-sequence-number"` + BlobType *BlobType `xml:"BlobType"` + CacheControl *string `xml:"Cache-Control"` + ContentDisposition *string `xml:"Content-Disposition"` + ContentEncoding *string `xml:"Content-Encoding"` + ContentLanguage *string `xml:"Content-Language"` + + // Size in bytes + ContentLength *int64 `xml:"Content-Length"` + ContentMD5 []byte `xml:"Content-MD5"` + ContentType *string `xml:"Content-Type"` + CopyCompletionTime *time.Time `xml:"CopyCompletionTime"` + CopyID *string `xml:"CopyId"` + CopyProgress *string `xml:"CopyProgress"` + CopySource *string `xml:"CopySource"` + CopyStatus *CopyStatusType `xml:"CopyStatus"` + CopyStatusDescription *string `xml:"CopyStatusDescription"` + CreationTime *time.Time `xml:"Creation-Time"` + CustomerProvidedKeySHA256 *string `xml:"CustomerProvidedKeySha256"` + DeletedTime *time.Time `xml:"DeletedTime"` + DestinationSnapshot *string `xml:"DestinationSnapshot"` + + // The name of the encryption scope under which the blob is encrypted. + EncryptionScope *string `xml:"EncryptionScope"` + ExpiresOn *time.Time `xml:"Expiry-Time"` + ImmutabilityPolicyExpiresOn *time.Time `xml:"ImmutabilityPolicyUntilDate"` + ImmutabilityPolicyMode *ImmutabilityPolicyMode `xml:"ImmutabilityPolicyMode"` + IncrementalCopy *bool `xml:"IncrementalCopy"` + IsSealed *bool `xml:"Sealed"` + LastAccessedOn *time.Time `xml:"LastAccessTime"` + LeaseDuration *LeaseDurationType `xml:"LeaseDuration"` + LeaseState *LeaseStateType `xml:"LeaseState"` + LeaseStatus *LeaseStatusType `xml:"LeaseStatus"` + LegalHold *bool `xml:"LegalHold"` + + // If an object is in rehydrate pending state then this header is returned with priority of rehydrate. Valid values are High + // and Standard. + RehydratePriority *RehydratePriority `xml:"RehydratePriority"` + RemainingRetentionDays *int32 `xml:"RemainingRetentionDays"` + ServerEncrypted *bool `xml:"ServerEncrypted"` + TagCount *int32 `xml:"TagCount"` +} + +type BlobTag struct { + // REQUIRED + Key *string `xml:"Key"` + + // REQUIRED + Value *string `xml:"Value"` +} + +// BlobTags - Blob tags +type BlobTags struct { + // REQUIRED + BlobTagSet []*BlobTag `xml:"TagSet>Tag"` +} + +// Block - Represents a single block in a block blob. It describes the block's ID and size. +type Block struct { + // REQUIRED; The base64 encoded block ID. + Name *string `xml:"Name"` + + // REQUIRED; The block size in bytes. + Size *int64 `xml:"Size"` +} + +// BlockBlobClientCommitBlockListOptions contains the optional parameters for the BlockBlobClient.CommitBlockList method. +type BlockBlobClientCommitBlockListOptions struct { + // Optional. Used to set blob tags in various blob operations. + BlobTagsString *string + // Specifies the date time when the blobs immutability policy is set to expire. + ImmutabilityPolicyExpiry *time.Time + // Specifies the immutability policy mode to set on the blob. + ImmutabilityPolicyMode *ImmutabilityPolicySetting + // Specified if a legal hold should be set on the blob. + LegalHold *bool + // Optional. Specifies a user-defined name-value pair associated with the blob. If no name-value pairs are specified, the + // operation will copy the metadata from the source blob or file to the destination + // blob. If one or more name-value pairs are specified, the destination blob is created with the specified metadata, and metadata + // is not copied from the source blob or file. Note that beginning with + // version 2009-09-19, metadata names must adhere to the naming rules for C# identifiers. See Naming and Referencing Containers, + // Blobs, and Metadata for more information. + Metadata map[string]*string + // Provides a client-generated, opaque value with a 1 KB character limit that is recorded in the analytics logs when storage + // analytics logging is enabled. + RequestID *string + // Optional. Indicates the tier to be set on the blob. + Tier *AccessTier + // The timeout parameter is expressed in seconds. For more information, see Setting Timeouts for Blob Service Operations. + // [https://docs.microsoft.com/en-us/rest/api/storageservices/fileservices/setting-timeouts-for-blob-service-operations] + Timeout *int32 + // Specify the transactional crc64 for the body, to be validated by the service. + TransactionalContentCRC64 []byte + // Specify the transactional md5 for the body, to be validated by the service. + TransactionalContentMD5 []byte +} + +// BlockBlobClientGetBlockListOptions contains the optional parameters for the BlockBlobClient.GetBlockList method. +type BlockBlobClientGetBlockListOptions struct { + // Provides a client-generated, opaque value with a 1 KB character limit that is recorded in the analytics logs when storage + // analytics logging is enabled. + RequestID *string + // The snapshot parameter is an opaque DateTime value that, when present, specifies the blob snapshot to retrieve. For more + // information on working with blob snapshots, see Creating a Snapshot of a Blob. + // [https://docs.microsoft.com/en-us/rest/api/storageservices/fileservices/creating-a-snapshot-of-a-blob] + Snapshot *string + // The timeout parameter is expressed in seconds. For more information, see Setting Timeouts for Blob Service Operations. + // [https://docs.microsoft.com/en-us/rest/api/storageservices/fileservices/setting-timeouts-for-blob-service-operations] + Timeout *int32 +} + +// BlockBlobClientPutBlobFromURLOptions contains the optional parameters for the BlockBlobClient.PutBlobFromURL method. +type BlockBlobClientPutBlobFromURLOptions struct { + // Optional. Used to set blob tags in various blob operations. + BlobTagsString *string + // Only Bearer type is supported. Credentials should be a valid OAuth access token to copy source. + CopySourceAuthorization *string + // Optional, default is true. Indicates if properties from the source blob should be copied. + CopySourcePathProperties *bool + // Optional. Specifies a user-defined name-value pair associated with the blob. If no name-value pairs are specified, the + // operation will copy the metadata from the source blob or file to the destination + // blob. If one or more name-value pairs are specified, the destination blob is created with the specified metadata, and metadata + // is not copied from the source blob or file. Note that beginning with + // version 2009-09-19, metadata names must adhere to the naming rules for C# identifiers. See Naming and Referencing Containers, + // Blobs, and Metadata for more information. + Metadata map[string]*string + // Provides a client-generated, opaque value with a 1 KB character limit that is recorded in the analytics logs when storage + // analytics logging is enabled. + RequestID *string + // Specify the md5 calculated for the range of bytes that must be read from the copy source. + SourceContentMD5 []byte + // Optional. Indicates the tier to be set on the blob. + Tier *AccessTier + // The timeout parameter is expressed in seconds. For more information, see Setting Timeouts for Blob Service Operations. + // [https://docs.microsoft.com/en-us/rest/api/storageservices/fileservices/setting-timeouts-for-blob-service-operations] + Timeout *int32 + // Specify the transactional md5 for the body, to be validated by the service. + TransactionalContentMD5 []byte +} + +// BlockBlobClientStageBlockFromURLOptions contains the optional parameters for the BlockBlobClient.StageBlockFromURL method. +type BlockBlobClientStageBlockFromURLOptions struct { + // Only Bearer type is supported. Credentials should be a valid OAuth access token to copy source. + CopySourceAuthorization *string + // Provides a client-generated, opaque value with a 1 KB character limit that is recorded in the analytics logs when storage + // analytics logging is enabled. + RequestID *string + // Specify the md5 calculated for the range of bytes that must be read from the copy source. + SourceContentMD5 []byte + // Specify the crc64 calculated for the range of bytes that must be read from the copy source. + SourceContentcrc64 []byte + // Bytes of source data in the specified range. + SourceRange *string + // The timeout parameter is expressed in seconds. For more information, see Setting Timeouts for Blob Service Operations. + // [https://docs.microsoft.com/en-us/rest/api/storageservices/fileservices/setting-timeouts-for-blob-service-operations] + Timeout *int32 +} + +// BlockBlobClientStageBlockOptions contains the optional parameters for the BlockBlobClient.StageBlock method. +type BlockBlobClientStageBlockOptions struct { + // Provides a client-generated, opaque value with a 1 KB character limit that is recorded in the analytics logs when storage + // analytics logging is enabled. + RequestID *string + // The timeout parameter is expressed in seconds. For more information, see Setting Timeouts for Blob Service Operations. + // [https://docs.microsoft.com/en-us/rest/api/storageservices/fileservices/setting-timeouts-for-blob-service-operations] + Timeout *int32 + // Specify the transactional crc64 for the body, to be validated by the service. + TransactionalContentCRC64 []byte + // Specify the transactional md5 for the body, to be validated by the service. + TransactionalContentMD5 []byte +} + +// BlockBlobClientUploadOptions contains the optional parameters for the BlockBlobClient.Upload method. +type BlockBlobClientUploadOptions struct { + // Optional. Used to set blob tags in various blob operations. + BlobTagsString *string + // Specifies the date time when the blobs immutability policy is set to expire. + ImmutabilityPolicyExpiry *time.Time + // Specifies the immutability policy mode to set on the blob. + ImmutabilityPolicyMode *ImmutabilityPolicySetting + // Specified if a legal hold should be set on the blob. + LegalHold *bool + // Optional. Specifies a user-defined name-value pair associated with the blob. If no name-value pairs are specified, the + // operation will copy the metadata from the source blob or file to the destination + // blob. If one or more name-value pairs are specified, the destination blob is created with the specified metadata, and metadata + // is not copied from the source blob or file. Note that beginning with + // version 2009-09-19, metadata names must adhere to the naming rules for C# identifiers. See Naming and Referencing Containers, + // Blobs, and Metadata for more information. + Metadata map[string]*string + // Provides a client-generated, opaque value with a 1 KB character limit that is recorded in the analytics logs when storage + // analytics logging is enabled. + RequestID *string + // Optional. Indicates the tier to be set on the blob. + Tier *AccessTier + // The timeout parameter is expressed in seconds. For more information, see Setting Timeouts for Blob Service Operations. + // [https://docs.microsoft.com/en-us/rest/api/storageservices/fileservices/setting-timeouts-for-blob-service-operations] + Timeout *int32 + // Specify the transactional md5 for the body, to be validated by the service. + TransactionalContentMD5 []byte +} + +type BlockList struct { + CommittedBlocks []*Block `xml:"CommittedBlocks>Block"` + UncommittedBlocks []*Block `xml:"UncommittedBlocks>Block"` +} + +type BlockLookupList struct { + Committed []*string `xml:"Committed"` + Latest []*string `xml:"Latest"` + Uncommitted []*string `xml:"Uncommitted"` +} + +type ClearRange struct { + // REQUIRED + End *int64 `xml:"End"` + + // REQUIRED + Start *int64 `xml:"Start"` +} + +// ContainerClientAcquireLeaseOptions contains the optional parameters for the ContainerClient.AcquireLease method. +type ContainerClientAcquireLeaseOptions struct { + // Proposed lease ID, in a GUID string format. The Blob service returns 400 (Invalid request) if the proposed lease ID is + // not in the correct format. See Guid Constructor (String) for a list of valid GUID + // string formats. + ProposedLeaseID *string + // Provides a client-generated, opaque value with a 1 KB character limit that is recorded in the analytics logs when storage + // analytics logging is enabled. + RequestID *string + // The timeout parameter is expressed in seconds. For more information, see Setting Timeouts for Blob Service Operations. + // [https://docs.microsoft.com/en-us/rest/api/storageservices/fileservices/setting-timeouts-for-blob-service-operations] + Timeout *int32 +} + +// ContainerClientBreakLeaseOptions contains the optional parameters for the ContainerClient.BreakLease method. +type ContainerClientBreakLeaseOptions struct { + // For a break operation, proposed duration the lease should continue before it is broken, in seconds, between 0 and 60. This + // break period is only used if it is shorter than the time remaining on the + // lease. If longer, the time remaining on the lease is used. A new lease will not be available before the break period has + // expired, but the lease may be held for longer than the break period. If this + // header does not appear with a break operation, a fixed-duration lease breaks after the remaining lease period elapses, + // and an infinite lease breaks immediately. + BreakPeriod *int32 + // Provides a client-generated, opaque value with a 1 KB character limit that is recorded in the analytics logs when storage + // analytics logging is enabled. + RequestID *string + // The timeout parameter is expressed in seconds. For more information, see Setting Timeouts for Blob Service Operations. + // [https://docs.microsoft.com/en-us/rest/api/storageservices/fileservices/setting-timeouts-for-blob-service-operations] + Timeout *int32 +} + +// ContainerClientChangeLeaseOptions contains the optional parameters for the ContainerClient.ChangeLease method. +type ContainerClientChangeLeaseOptions struct { + // Provides a client-generated, opaque value with a 1 KB character limit that is recorded in the analytics logs when storage + // analytics logging is enabled. + RequestID *string + // The timeout parameter is expressed in seconds. For more information, see Setting Timeouts for Blob Service Operations. + // [https://docs.microsoft.com/en-us/rest/api/storageservices/fileservices/setting-timeouts-for-blob-service-operations] + Timeout *int32 +} + +// ContainerClientCreateOptions contains the optional parameters for the ContainerClient.Create method. +type ContainerClientCreateOptions struct { + // Specifies whether data in the container may be accessed publicly and the level of access + Access *PublicAccessType + // Optional. Specifies a user-defined name-value pair associated with the blob. If no name-value pairs are specified, the + // operation will copy the metadata from the source blob or file to the destination + // blob. If one or more name-value pairs are specified, the destination blob is created with the specified metadata, and metadata + // is not copied from the source blob or file. Note that beginning with + // version 2009-09-19, metadata names must adhere to the naming rules for C# identifiers. See Naming and Referencing Containers, + // Blobs, and Metadata for more information. + Metadata map[string]*string + // Provides a client-generated, opaque value with a 1 KB character limit that is recorded in the analytics logs when storage + // analytics logging is enabled. + RequestID *string + // The timeout parameter is expressed in seconds. For more information, see Setting Timeouts for Blob Service Operations. + // [https://docs.microsoft.com/en-us/rest/api/storageservices/fileservices/setting-timeouts-for-blob-service-operations] + Timeout *int32 +} + +// ContainerClientDeleteOptions contains the optional parameters for the ContainerClient.Delete method. +type ContainerClientDeleteOptions struct { + // Provides a client-generated, opaque value with a 1 KB character limit that is recorded in the analytics logs when storage + // analytics logging is enabled. + RequestID *string + // The timeout parameter is expressed in seconds. For more information, see Setting Timeouts for Blob Service Operations. + // [https://docs.microsoft.com/en-us/rest/api/storageservices/fileservices/setting-timeouts-for-blob-service-operations] + Timeout *int32 +} + +// ContainerClientGetAccessPolicyOptions contains the optional parameters for the ContainerClient.GetAccessPolicy method. +type ContainerClientGetAccessPolicyOptions struct { + // Provides a client-generated, opaque value with a 1 KB character limit that is recorded in the analytics logs when storage + // analytics logging is enabled. + RequestID *string + // The timeout parameter is expressed in seconds. For more information, see Setting Timeouts for Blob Service Operations. + // [https://docs.microsoft.com/en-us/rest/api/storageservices/fileservices/setting-timeouts-for-blob-service-operations] + Timeout *int32 +} + +// ContainerClientGetAccountInfoOptions contains the optional parameters for the ContainerClient.GetAccountInfo method. +type ContainerClientGetAccountInfoOptions struct { + // placeholder for future optional parameters +} + +// ContainerClientGetPropertiesOptions contains the optional parameters for the ContainerClient.GetProperties method. +type ContainerClientGetPropertiesOptions struct { + // Provides a client-generated, opaque value with a 1 KB character limit that is recorded in the analytics logs when storage + // analytics logging is enabled. + RequestID *string + // The timeout parameter is expressed in seconds. For more information, see Setting Timeouts for Blob Service Operations. + // [https://docs.microsoft.com/en-us/rest/api/storageservices/fileservices/setting-timeouts-for-blob-service-operations] + Timeout *int32 +} + +// ContainerClientListBlobFlatSegmentOptions contains the optional parameters for the ContainerClient.NewListBlobFlatSegmentPager +// method. +type ContainerClientListBlobFlatSegmentOptions struct { + // Include this parameter to specify one or more datasets to include in the response. + Include []ListBlobsIncludeItem + // A string value that identifies the portion of the list of containers to be returned with the next listing operation. The + // operation returns the NextMarker value within the response body if the listing + // operation did not return all containers remaining to be listed with the current page. The NextMarker value can be used + // as the value for the marker parameter in a subsequent call to request the next + // page of list items. The marker value is opaque to the client. + Marker *string + // Specifies the maximum number of containers to return. If the request does not specify maxresults, or specifies a value + // greater than 5000, the server will return up to 5000 items. Note that if the + // listing operation crosses a partition boundary, then the service will return a continuation token for retrieving the remainder + // of the results. For this reason, it is possible that the service will + // return fewer results than specified by maxresults, or than the default of 5000. + Maxresults *int32 + // Filters the results to return only containers whose name begins with the specified prefix. + Prefix *string + // Provides a client-generated, opaque value with a 1 KB character limit that is recorded in the analytics logs when storage + // analytics logging is enabled. + RequestID *string + // The timeout parameter is expressed in seconds. For more information, see Setting Timeouts for Blob Service Operations. + // [https://docs.microsoft.com/en-us/rest/api/storageservices/fileservices/setting-timeouts-for-blob-service-operations] + Timeout *int32 +} + +// ContainerClientListBlobHierarchySegmentOptions contains the optional parameters for the ContainerClient.NewListBlobHierarchySegmentPager +// method. +type ContainerClientListBlobHierarchySegmentOptions struct { + // Include this parameter to specify one or more datasets to include in the response. + Include []ListBlobsIncludeItem + // A string value that identifies the portion of the list of containers to be returned with the next listing operation. The + // operation returns the NextMarker value within the response body if the listing + // operation did not return all containers remaining to be listed with the current page. The NextMarker value can be used + // as the value for the marker parameter in a subsequent call to request the next + // page of list items. The marker value is opaque to the client. + Marker *string + // Specifies the maximum number of containers to return. If the request does not specify maxresults, or specifies a value + // greater than 5000, the server will return up to 5000 items. Note that if the + // listing operation crosses a partition boundary, then the service will return a continuation token for retrieving the remainder + // of the results. For this reason, it is possible that the service will + // return fewer results than specified by maxresults, or than the default of 5000. + Maxresults *int32 + // Filters the results to return only containers whose name begins with the specified prefix. + Prefix *string + // Provides a client-generated, opaque value with a 1 KB character limit that is recorded in the analytics logs when storage + // analytics logging is enabled. + RequestID *string + // The timeout parameter is expressed in seconds. For more information, see Setting Timeouts for Blob Service Operations. + // [https://docs.microsoft.com/en-us/rest/api/storageservices/fileservices/setting-timeouts-for-blob-service-operations] + Timeout *int32 +} + +// ContainerClientReleaseLeaseOptions contains the optional parameters for the ContainerClient.ReleaseLease method. +type ContainerClientReleaseLeaseOptions struct { + // Provides a client-generated, opaque value with a 1 KB character limit that is recorded in the analytics logs when storage + // analytics logging is enabled. + RequestID *string + // The timeout parameter is expressed in seconds. For more information, see Setting Timeouts for Blob Service Operations. + // [https://docs.microsoft.com/en-us/rest/api/storageservices/fileservices/setting-timeouts-for-blob-service-operations] + Timeout *int32 +} + +// ContainerClientRenameOptions contains the optional parameters for the ContainerClient.Rename method. +type ContainerClientRenameOptions struct { + // Provides a client-generated, opaque value with a 1 KB character limit that is recorded in the analytics logs when storage + // analytics logging is enabled. + RequestID *string + // A lease ID for the source path. If specified, the source path must have an active lease and the lease ID must match. + SourceLeaseID *string + // The timeout parameter is expressed in seconds. For more information, see Setting Timeouts for Blob Service Operations. + // [https://docs.microsoft.com/en-us/rest/api/storageservices/fileservices/setting-timeouts-for-blob-service-operations] + Timeout *int32 +} + +// ContainerClientRenewLeaseOptions contains the optional parameters for the ContainerClient.RenewLease method. +type ContainerClientRenewLeaseOptions struct { + // Provides a client-generated, opaque value with a 1 KB character limit that is recorded in the analytics logs when storage + // analytics logging is enabled. + RequestID *string + // The timeout parameter is expressed in seconds. For more information, see Setting Timeouts for Blob Service Operations. + // [https://docs.microsoft.com/en-us/rest/api/storageservices/fileservices/setting-timeouts-for-blob-service-operations] + Timeout *int32 +} + +// ContainerClientRestoreOptions contains the optional parameters for the ContainerClient.Restore method. +type ContainerClientRestoreOptions struct { + // Optional. Version 2019-12-12 and later. Specifies the name of the deleted container to restore. + DeletedFilesystemName *string + // Optional. Version 2019-12-12 and later. Specifies the version of the deleted container to restore. + DeletedContainerVersion *string + // Provides a client-generated, opaque value with a 1 KB character limit that is recorded in the analytics logs when storage + // analytics logging is enabled. + RequestID *string + // The timeout parameter is expressed in seconds. For more information, see Setting Timeouts for Blob Service Operations. + // [https://docs.microsoft.com/en-us/rest/api/storageservices/fileservices/setting-timeouts-for-blob-service-operations] + Timeout *int32 +} + +// ContainerClientSetAccessPolicyOptions contains the optional parameters for the ContainerClient.SetAccessPolicy method. +type ContainerClientSetAccessPolicyOptions struct { + // Specifies whether data in the container may be accessed publicly and the level of access + Access *PublicAccessType + // Provides a client-generated, opaque value with a 1 KB character limit that is recorded in the analytics logs when storage + // analytics logging is enabled. + RequestID *string + // The timeout parameter is expressed in seconds. For more information, see Setting Timeouts for Blob Service Operations. + // [https://docs.microsoft.com/en-us/rest/api/storageservices/fileservices/setting-timeouts-for-blob-service-operations] + Timeout *int32 +} + +// ContainerClientSetMetadataOptions contains the optional parameters for the ContainerClient.SetMetadata method. +type ContainerClientSetMetadataOptions struct { + // Optional. Specifies a user-defined name-value pair associated with the blob. If no name-value pairs are specified, the + // operation will copy the metadata from the source blob or file to the destination + // blob. If one or more name-value pairs are specified, the destination blob is created with the specified metadata, and metadata + // is not copied from the source blob or file. Note that beginning with + // version 2009-09-19, metadata names must adhere to the naming rules for C# identifiers. See Naming and Referencing Containers, + // Blobs, and Metadata for more information. + Metadata map[string]*string + // Provides a client-generated, opaque value with a 1 KB character limit that is recorded in the analytics logs when storage + // analytics logging is enabled. + RequestID *string + // The timeout parameter is expressed in seconds. For more information, see Setting Timeouts for Blob Service Operations. + // [https://docs.microsoft.com/en-us/rest/api/storageservices/fileservices/setting-timeouts-for-blob-service-operations] + Timeout *int32 +} + +// ContainerClientSubmitBatchOptions contains the optional parameters for the ContainerClient.SubmitBatch method. +type ContainerClientSubmitBatchOptions struct { + // Provides a client-generated, opaque value with a 1 KB character limit that is recorded in the analytics logs when storage + // analytics logging is enabled. + RequestID *string + // The timeout parameter is expressed in seconds. For more information, see Setting Timeouts for Blob Service Operations. + // [https://docs.microsoft.com/en-us/rest/api/storageservices/fileservices/setting-timeouts-for-blob-service-operations] + Timeout *int32 +} + +// ContainerCPKScopeInfo contains a group of parameters for the ContainerClient.Create method. +type ContainerCPKScopeInfo struct { + // Optional. Version 2019-07-07 and later. Specifies the default encryption scope to set on the container and use for all + // future writes. + DefaultEncryptionScope *string + // Optional. Version 2019-07-07 and newer. If true, prevents any request from specifying a different encryption scope than + // the scope set on the container. + PreventEncryptionScopeOverride *bool +} + +// FileSystemItem - An Azure Storage container +type FileSystemItem struct { + // REQUIRED + Name *string `xml:"Name"` + + // REQUIRED; Properties of a container + Properties *FileSystemProperties `xml:"Properties"` + Deleted *bool `xml:"Deleted"` + + // Dictionary of + Metadata map[string]*string `xml:"Metadata"` + Version *string `xml:"Version"` +} + +// FileSystemProperties - Properties of a container +type FileSystemProperties struct { + // REQUIRED + ETag *azcore.ETag `xml:"Etag"` + + // REQUIRED + LastModified *time.Time `xml:"Last-Modified"` + DefaultEncryptionScope *string `xml:"DefaultEncryptionScope"` + DeletedTime *time.Time `xml:"DeletedTime"` + HasImmutabilityPolicy *bool `xml:"HasImmutabilityPolicy"` + HasLegalHold *bool `xml:"HasLegalHold"` + + // Indicates if version level worm is enabled on this container. + IsImmutableStorageWithVersioningEnabled *bool `xml:"ImmutableStorageWithVersioningEnabled"` + LeaseDuration *LeaseDurationType `xml:"LeaseDuration"` + LeaseState *LeaseStateType `xml:"LeaseState"` + LeaseStatus *LeaseStatusType `xml:"LeaseStatus"` + PreventEncryptionScopeOverride *bool `xml:"DenyEncryptionScopeOverride"` + PublicAccess *PublicAccessType `xml:"PublicAccess"` + RemainingRetentionDays *int32 `xml:"RemainingRetentionDays"` +} + +// CORSRule - CORS is an HTTP feature that enables a web application running under one domain to access resources in another +// domain. Web browsers implement a security restriction known as same-origin policy that +// prevents a web page from calling APIs in a different domain; CORS provides a secure way to allow one domain (the origin +// domain) to call APIs in another domain +type CORSRule struct { + // REQUIRED; the request headers that the origin domain may specify on the CORS request. + AllowedHeaders *string `xml:"AllowedHeaders"` + + // REQUIRED; The methods (HTTP request verbs) that the origin domain may use for a CORS request. (comma separated) + AllowedMethods *string `xml:"AllowedMethods"` + + // REQUIRED; The origin domains that are permitted to make a request against the storage service via CORS. The origin domain + // is the domain from which the request originates. Note that the origin must be an exact + // case-sensitive match with the origin that the user age sends to the service. You can also use the wildcard character '*' + // to allow all origin domains to make requests via CORS. + AllowedOrigins *string `xml:"AllowedOrigins"` + + // REQUIRED; The response headers that may be sent in the response to the CORS request and exposed by the browser to the request + // issuer + ExposedHeaders *string `xml:"ExposedHeaders"` + + // REQUIRED; The maximum amount time that a browser should cache the preflight OPTIONS request. + MaxAgeInSeconds *int32 `xml:"MaxAgeInSeconds"` +} + +// CPKInfo contains a group of parameters for the BlobClient.Download method. +type CPKInfo struct { + // The algorithm used to produce the encryption key hash. Currently, the only accepted value is "AES256". Must be provided + // if the x-ms-encryption-key header is provided. + EncryptionAlgorithm *EncryptionAlgorithmType + // Optional. Specifies the encryption key to use to encrypt the data provided in the request. If not specified, encryption + // is performed with the root account encryption key. For more information, see + // Encryption at Rest for Azure Storage Services. + EncryptionKey *string + // The SHA-256 hash of the provided encryption key. Must be provided if the x-ms-encryption-key header is provided. + EncryptionKeySHA256 *string +} + +// CPKScopeInfo contains a group of parameters for the BlobClient.SetMetadata method. +type CPKScopeInfo struct { + // Optional. Version 2019-07-07 and later. Specifies the name of the encryption scope to use to encrypt the data provided + // in the request. If not specified, encryption is performed with the default + // account encryption scope. For more information, see Encryption at Rest for Azure Storage Services. + EncryptionScope *string +} + +// DelimitedTextConfiguration - Groups the settings used for interpreting the blob data if the blob is delimited text formatted. +type DelimitedTextConfiguration struct { + // The string used to separate columns. + ColumnSeparator *string `xml:"ColumnSeparator"` + + // The string used as an escape character. + EscapeChar *string `xml:"EscapeChar"` + + // The string used to quote a specific field. + FieldQuote *string `xml:"FieldQuote"` + + // Represents whether the data has headers. + HeadersPresent *bool `xml:"HasHeaders"` + + // The string used to separate records. + RecordSeparator *string `xml:"RecordSeparator"` +} + +// FilterPathItem - Blob info from a Filter Blobs API call +type FilterPathItem struct { + // REQUIRED + FilesystemName *string `xml:"ContainerName"` + + // REQUIRED + Name *string `xml:"Name"` + + // Blob tags + Tags *BlobTags `xml:"Tags"` +} + +// FilterBlobSegment - The result of a Filter Blobs API call +type FilterBlobSegment struct { + // REQUIRED + Blobs []*FilterPathItem `xml:"Blobs>Blob"` + + // REQUIRED + ServiceEndpoint *string `xml:"ServiceEndpoint,attr"` + + // REQUIRED + Where *string `xml:"Where"` + NextMarker *string `xml:"NextMarker"` +} + +// GeoReplication - Geo-Replication information for the Secondary Storage Service +type GeoReplication struct { + // REQUIRED; A GMT date/time value, to the second. All primary writes preceding this value are guaranteed to be available + // for read operations at the secondary. Primary writes after this point in time may or may + // not be available for reads. + LastSyncTime *time.Time `xml:"LastSyncTime"` + + // REQUIRED; The status of the secondary location + Status *BlobGeoReplicationStatus `xml:"Status"` +} + +// JSONTextConfiguration - json text configuration +type JSONTextConfiguration struct { + // The string used to separate records. + RecordSeparator *string `xml:"RecordSeparator"` +} + +// KeyInfo - Key information +type KeyInfo struct { + // REQUIRED; The date-time the key expires in ISO 8601 UTC time + Expiry *string `xml:"Expiry"` + + // REQUIRED; The date-time the key is active in ISO 8601 UTC time + Start *string `xml:"Start"` +} + +// LeaseAccessConditions contains a group of parameters for the ContainerClient.GetProperties method. +type LeaseAccessConditions struct { + // If specified, the operation only succeeds if the resource's lease is active and matches this ID. + LeaseID *string +} + +// ListBlobsFlatSegmentResponse - An enumeration of blobs +type ListBlobsFlatSegmentResponse struct { + // REQUIRED + FilesystemName *string `xml:"ContainerName,attr"` + + // REQUIRED + Segment *BlobFlatListSegment `xml:"Blobs"` + + // REQUIRED + ServiceEndpoint *string `xml:"ServiceEndpoint,attr"` + Marker *string `xml:"Marker"` + MaxResults *int32 `xml:"MaxResults"` + NextMarker *string `xml:"NextMarker"` + Prefix *string `xml:"Prefix"` +} + +// ListPathsHierarchySegmentResponse - An enumeration of blobs +type ListPathsHierarchySegmentResponse struct { + // REQUIRED + FilesystemName *string `xml:"ContainerName,attr"` + + // REQUIRED + Segment *PathHierarchyListSegment `xml:"Blobs"` + + // REQUIRED + ServiceEndpoint *string `xml:"ServiceEndpoint,attr"` + Delimiter *string `xml:"Delimiter"` + Marker *string `xml:"Marker"` + MaxResults *int32 `xml:"MaxResults"` + NextMarker *string `xml:"NextMarker"` + Prefix *string `xml:"Prefix"` +} + +// ListFileSystemsSegmentResponse - An enumeration of containers +type ListFileSystemsSegmentResponse struct { + // REQUIRED + FileSystemItems []*FileSystemItem `xml:"Containers>Container"` + + // REQUIRED + ServiceEndpoint *string `xml:"ServiceEndpoint,attr"` + Marker *string `xml:"Marker"` + MaxResults *int32 `xml:"MaxResults"` + NextMarker *string `xml:"NextMarker"` + Prefix *string `xml:"Prefix"` +} + +// Logging - Azure Analytics Logging settings. +type Logging struct { + // REQUIRED; Indicates whether all delete requests should be logged. + Delete *bool `xml:"Delete"` + + // REQUIRED; Indicates whether all read requests should be logged. + Read *bool `xml:"Read"` + + // REQUIRED; the retention policy which determines how long the associated data should persist + RetentionPolicy *RetentionPolicy `xml:"RetentionPolicy"` + + // REQUIRED; The version of Storage Analytics to configure. + Version *string `xml:"Version"` + + // REQUIRED; Indicates whether all write requests should be logged. + Write *bool `xml:"Write"` +} + +// Metrics - a summary of request statistics grouped by API in hour or minute aggregates for blobs +type Metrics struct { + // REQUIRED; Indicates whether metrics are enabled for the Blob service. + Enabled *bool `xml:"Enabled"` + + // Indicates whether metrics should generate summary statistics for called API operations. + IncludeAPIs *bool `xml:"IncludeAPIs"` + + // the retention policy which determines how long the associated data should persist + RetentionPolicy *RetentionPolicy `xml:"RetentionPolicy"` + + // The version of Storage Analytics to configure. + Version *string `xml:"Version"` +} + +// ModifiedAccessConditions contains a group of parameters for the ContainerClient.Delete method. +type ModifiedAccessConditions struct { + // Specify an ETag value to operate only on blobs with a matching value. + IfMatch *azcore.ETag + // Specify this header value to operate only on a blob if it has been modified since the specified date/time. + IfModifiedSince *time.Time + // Specify an ETag value to operate only on blobs without a matching value. + IfNoneMatch *azcore.ETag + // Specify a SQL where clause on blob tags to operate only on blobs with a matching value. + IfTags *string + // Specify this header value to operate only on a blob if it has not been modified since the specified date/time. + IfUnmodifiedSince *time.Time +} + +// PageBlobClientClearPagesOptions contains the optional parameters for the PageBlobClient.ClearPages method. +type PageBlobClientClearPagesOptions struct { + // Return only the bytes of the blob in the specified range. + Range *string + // Provides a client-generated, opaque value with a 1 KB character limit that is recorded in the analytics logs when storage + // analytics logging is enabled. + RequestID *string + // The timeout parameter is expressed in seconds. For more information, see Setting Timeouts for Blob Service Operations. + // [https://docs.microsoft.com/en-us/rest/api/storageservices/fileservices/setting-timeouts-for-blob-service-operations] + Timeout *int32 +} + +// PageBlobClientCopyIncrementalOptions contains the optional parameters for the PageBlobClient.CopyIncremental method. +type PageBlobClientCopyIncrementalOptions struct { + // Provides a client-generated, opaque value with a 1 KB character limit that is recorded in the analytics logs when storage + // analytics logging is enabled. + RequestID *string + // The timeout parameter is expressed in seconds. For more information, see Setting Timeouts for Blob Service Operations. + // [https://docs.microsoft.com/en-us/rest/api/storageservices/fileservices/setting-timeouts-for-blob-service-operations] + Timeout *int32 +} + +// PageBlobClientCreateOptions contains the optional parameters for the PageBlobClient.Create method. +type PageBlobClientCreateOptions struct { + // Set for page blobs only. The sequence number is a user-controlled value that you can use to track requests. The value of + // the sequence number must be between 0 and 2^63 - 1. + BlobSequenceNumber *int64 + // Optional. Used to set blob tags in various blob operations. + BlobTagsString *string + // Specifies the date time when the blobs immutability policy is set to expire. + ImmutabilityPolicyExpiry *time.Time + // Specifies the immutability policy mode to set on the blob. + ImmutabilityPolicyMode *ImmutabilityPolicySetting + // Specified if a legal hold should be set on the blob. + LegalHold *bool + // Optional. Specifies a user-defined name-value pair associated with the blob. If no name-value pairs are specified, the + // operation will copy the metadata from the source blob or file to the destination + // blob. If one or more name-value pairs are specified, the destination blob is created with the specified metadata, and metadata + // is not copied from the source blob or file. Note that beginning with + // version 2009-09-19, metadata names must adhere to the naming rules for C# identifiers. See Naming and Referencing Containers, + // Blobs, and Metadata for more information. + Metadata map[string]*string + // Provides a client-generated, opaque value with a 1 KB character limit that is recorded in the analytics logs when storage + // analytics logging is enabled. + RequestID *string + // Optional. Indicates the tier to be set on the page blob. + Tier *PremiumPageBlobAccessTier + // The timeout parameter is expressed in seconds. For more information, see Setting Timeouts for Blob Service Operations. + // [https://docs.microsoft.com/en-us/rest/api/storageservices/fileservices/setting-timeouts-for-blob-service-operations] + Timeout *int32 +} + +// PageBlobClientGetPageRangesDiffOptions contains the optional parameters for the PageBlobClient.NewGetPageRangesDiffPager +// method. +type PageBlobClientGetPageRangesDiffOptions struct { + // A string value that identifies the portion of the list of containers to be returned with the next listing operation. The + // operation returns the NextMarker value within the response body if the listing + // operation did not return all containers remaining to be listed with the current page. The NextMarker value can be used + // as the value for the marker parameter in a subsequent call to request the next + // page of list items. The marker value is opaque to the client. + Marker *string + // Specifies the maximum number of containers to return. If the request does not specify maxresults, or specifies a value + // greater than 5000, the server will return up to 5000 items. Note that if the + // listing operation crosses a partition boundary, then the service will return a continuation token for retrieving the remainder + // of the results. For this reason, it is possible that the service will + // return fewer results than specified by maxresults, or than the default of 5000. + Maxresults *int32 + // Optional. This header is only supported in service versions 2019-04-19 and after and specifies the URL of a previous snapshot + // of the target blob. The response will only contain pages that were changed + // between the target blob and its previous snapshot. + PrevSnapshotURL *string + // Optional in version 2015-07-08 and newer. The prevsnapshot parameter is a DateTime value that specifies that the response + // will contain only pages that were changed between target blob and previous + // snapshot. Changed pages include both updated and cleared pages. The target blob may be a snapshot, as long as the snapshot + // specified by prevsnapshot is the older of the two. Note that incremental + // snapshots are currently supported only for blobs created on or after January 1, 2016. + Prevsnapshot *string + // Return only the bytes of the blob in the specified range. + Range *string + // Provides a client-generated, opaque value with a 1 KB character limit that is recorded in the analytics logs when storage + // analytics logging is enabled. + RequestID *string + // The snapshot parameter is an opaque DateTime value that, when present, specifies the blob snapshot to retrieve. For more + // information on working with blob snapshots, see Creating a Snapshot of a Blob. + // [https://docs.microsoft.com/en-us/rest/api/storageservices/fileservices/creating-a-snapshot-of-a-blob] + Snapshot *string + // The timeout parameter is expressed in seconds. For more information, see Setting Timeouts for Blob Service Operations. + // [https://docs.microsoft.com/en-us/rest/api/storageservices/fileservices/setting-timeouts-for-blob-service-operations] + Timeout *int32 +} + +// PageBlobClientGetPageRangesOptions contains the optional parameters for the PageBlobClient.NewGetPageRangesPager method. +type PageBlobClientGetPageRangesOptions struct { + // A string value that identifies the portion of the list of containers to be returned with the next listing operation. The + // operation returns the NextMarker value within the response body if the listing + // operation did not return all containers remaining to be listed with the current page. The NextMarker value can be used + // as the value for the marker parameter in a subsequent call to request the next + // page of list items. The marker value is opaque to the client. + Marker *string + // Specifies the maximum number of containers to return. If the request does not specify maxresults, or specifies a value + // greater than 5000, the server will return up to 5000 items. Note that if the + // listing operation crosses a partition boundary, then the service will return a continuation token for retrieving the remainder + // of the results. For this reason, it is possible that the service will + // return fewer results than specified by maxresults, or than the default of 5000. + Maxresults *int32 + // Return only the bytes of the blob in the specified range. + Range *string + // Provides a client-generated, opaque value with a 1 KB character limit that is recorded in the analytics logs when storage + // analytics logging is enabled. + RequestID *string + // The snapshot parameter is an opaque DateTime value that, when present, specifies the blob snapshot to retrieve. For more + // information on working with blob snapshots, see Creating a Snapshot of a Blob. + // [https://docs.microsoft.com/en-us/rest/api/storageservices/fileservices/creating-a-snapshot-of-a-blob] + Snapshot *string + // The timeout parameter is expressed in seconds. For more information, see Setting Timeouts for Blob Service Operations. + // [https://docs.microsoft.com/en-us/rest/api/storageservices/fileservices/setting-timeouts-for-blob-service-operations] + Timeout *int32 +} + +// PageBlobClientResizeOptions contains the optional parameters for the PageBlobClient.Resize method. +type PageBlobClientResizeOptions struct { + // Provides a client-generated, opaque value with a 1 KB character limit that is recorded in the analytics logs when storage + // analytics logging is enabled. + RequestID *string + // The timeout parameter is expressed in seconds. For more information, see Setting Timeouts for Blob Service Operations. + // [https://docs.microsoft.com/en-us/rest/api/storageservices/fileservices/setting-timeouts-for-blob-service-operations] + Timeout *int32 +} + +// PageBlobClientUpdateSequenceNumberOptions contains the optional parameters for the PageBlobClient.UpdateSequenceNumber +// method. +type PageBlobClientUpdateSequenceNumberOptions struct { + // Set for page blobs only. The sequence number is a user-controlled value that you can use to track requests. The value of + // the sequence number must be between 0 and 2^63 - 1. + BlobSequenceNumber *int64 + // Provides a client-generated, opaque value with a 1 KB character limit that is recorded in the analytics logs when storage + // analytics logging is enabled. + RequestID *string + // The timeout parameter is expressed in seconds. For more information, see Setting Timeouts for Blob Service Operations. + // [https://docs.microsoft.com/en-us/rest/api/storageservices/fileservices/setting-timeouts-for-blob-service-operations] + Timeout *int32 +} + +// PageBlobClientUploadPagesFromURLOptions contains the optional parameters for the PageBlobClient.UploadPagesFromURL method. +type PageBlobClientUploadPagesFromURLOptions struct { + // Only Bearer type is supported. Credentials should be a valid OAuth access token to copy source. + CopySourceAuthorization *string + // Provides a client-generated, opaque value with a 1 KB character limit that is recorded in the analytics logs when storage + // analytics logging is enabled. + RequestID *string + // Specify the md5 calculated for the range of bytes that must be read from the copy source. + SourceContentMD5 []byte + // Specify the crc64 calculated for the range of bytes that must be read from the copy source. + SourceContentcrc64 []byte + // The timeout parameter is expressed in seconds. For more information, see Setting Timeouts for Blob Service Operations. + // [https://docs.microsoft.com/en-us/rest/api/storageservices/fileservices/setting-timeouts-for-blob-service-operations] + Timeout *int32 +} + +// PageBlobClientUploadPagesOptions contains the optional parameters for the PageBlobClient.UploadPages method. +type PageBlobClientUploadPagesOptions struct { + // Return only the bytes of the blob in the specified range. + Range *string + // Provides a client-generated, opaque value with a 1 KB character limit that is recorded in the analytics logs when storage + // analytics logging is enabled. + RequestID *string + // The timeout parameter is expressed in seconds. For more information, see Setting Timeouts for Blob Service Operations. + // [https://docs.microsoft.com/en-us/rest/api/storageservices/fileservices/setting-timeouts-for-blob-service-operations] + Timeout *int32 + // Specify the transactional crc64 for the body, to be validated by the service. + TransactionalContentCRC64 []byte + // Specify the transactional md5 for the body, to be validated by the service. + TransactionalContentMD5 []byte +} + +// PageList - the list of pages +type PageList struct { + ClearRange []*ClearRange `xml:"ClearRange"` + NextMarker *string `xml:"NextMarker"` + PageRange []*PageRange `xml:"PageRange"` +} + +type PageRange struct { + // REQUIRED + End *int64 `xml:"End"` + + // REQUIRED + Start *int64 `xml:"Start"` +} + +type QueryFormat struct { + // REQUIRED; The quick query format type. + Type *QueryFormatType `xml:"Type"` + + // Groups the settings used for formatting the response if the response should be Arrow formatted. + ArrowConfiguration *ArrowConfiguration `xml:"ArrowConfiguration"` + + // Groups the settings used for interpreting the blob data if the blob is delimited text formatted. + DelimitedTextConfiguration *DelimitedTextConfiguration `xml:"DelimitedTextConfiguration"` + + // json text configuration + JSONTextConfiguration *JSONTextConfiguration `xml:"JsonTextConfiguration"` + + // parquet configuration + ParquetTextConfiguration any `xml:"ParquetTextConfiguration"` +} + +// QueryRequest - Groups the set of query request settings. +type QueryRequest struct { + // REQUIRED; The query expression in SQL. The maximum size of the query expression is 256KiB. + Expression *string `xml:"Expression"` + + // CONSTANT; Required. The type of the provided query expression. + // Field has constant value "SQL", any specified value is ignored. + QueryType *string `xml:"QueryType"` + InputSerialization *QuerySerialization `xml:"InputSerialization"` + OutputSerialization *QuerySerialization `xml:"OutputSerialization"` +} + +type QuerySerialization struct { + // REQUIRED + Format *QueryFormat `xml:"Format"` +} + +// RetentionPolicy - the retention policy which determines how long the associated data should persist +type RetentionPolicy struct { + // REQUIRED; Indicates whether a retention policy is enabled for the storage service + Enabled *bool `xml:"Enabled"` + + // Indicates whether permanent delete is allowed on this storage account. + AllowPermanentDelete *bool `xml:"AllowPermanentDelete"` + + // Indicates the number of days that metrics or logging or soft-deleted data should be retained. All data older than this + // value will be deleted + Days *int32 `xml:"Days"` +} + +// SequenceNumberAccessConditions contains a group of parameters for the PageBlobClient.UploadPages method. +type SequenceNumberAccessConditions struct { + // Specify this header value to operate only on a blob if it has the specified sequence number. + IfSequenceNumberEqualTo *int64 + // Specify this header value to operate only on a blob if it has a sequence number less than the specified. + IfSequenceNumberLessThan *int64 + // Specify this header value to operate only on a blob if it has a sequence number less than or equal to the specified. + IfSequenceNumberLessThanOrEqualTo *int64 +} + +// ServiceClientFilterBlobsOptions contains the optional parameters for the ServiceClient.FilterBlobs method. +type ServiceClientFilterBlobsOptions struct { + // A string value that identifies the portion of the list of containers to be returned with the next listing operation. The + // operation returns the NextMarker value within the response body if the listing + // operation did not return all containers remaining to be listed with the current page. The NextMarker value can be used + // as the value for the marker parameter in a subsequent call to request the next + // page of list items. The marker value is opaque to the client. + Marker *string + // Specifies the maximum number of containers to return. If the request does not specify maxresults, or specifies a value + // greater than 5000, the server will return up to 5000 items. Note that if the + // listing operation crosses a partition boundary, then the service will return a continuation token for retrieving the remainder + // of the results. For this reason, it is possible that the service will + // return fewer results than specified by maxresults, or than the default of 5000. + Maxresults *int32 + // Provides a client-generated, opaque value with a 1 KB character limit that is recorded in the analytics logs when storage + // analytics logging is enabled. + RequestID *string + // The timeout parameter is expressed in seconds. For more information, see Setting Timeouts for Blob Service Operations. + // [https://docs.microsoft.com/en-us/rest/api/storageservices/fileservices/setting-timeouts-for-blob-service-operations] + Timeout *int32 +} + +// ServiceClientGetAccountInfoOptions contains the optional parameters for the ServiceClient.GetAccountInfo method. +type ServiceClientGetAccountInfoOptions struct { + // placeholder for future optional parameters +} + +// ServiceClientGetPropertiesOptions contains the optional parameters for the ServiceClient.GetProperties method. +type ServiceClientGetPropertiesOptions struct { + // Provides a client-generated, opaque value with a 1 KB character limit that is recorded in the analytics logs when storage + // analytics logging is enabled. + RequestID *string + // The timeout parameter is expressed in seconds. For more information, see Setting Timeouts for Blob Service Operations. + // [https://docs.microsoft.com/en-us/rest/api/storageservices/fileservices/setting-timeouts-for-blob-service-operations] + Timeout *int32 +} + +// ServiceClientGetStatisticsOptions contains the optional parameters for the ServiceClient.GetStatistics method. +type ServiceClientGetStatisticsOptions struct { + // Provides a client-generated, opaque value with a 1 KB character limit that is recorded in the analytics logs when storage + // analytics logging is enabled. + RequestID *string + // The timeout parameter is expressed in seconds. For more information, see Setting Timeouts for Blob Service Operations. + // [https://docs.microsoft.com/en-us/rest/api/storageservices/fileservices/setting-timeouts-for-blob-service-operations] + Timeout *int32 +} + +// ServiceClientGetUserDelegationKeyOptions contains the optional parameters for the ServiceClient.GetUserDelegationKey method. +type ServiceClientGetUserDelegationKeyOptions struct { + // Provides a client-generated, opaque value with a 1 KB character limit that is recorded in the analytics logs when storage + // analytics logging is enabled. + RequestID *string + // The timeout parameter is expressed in seconds. For more information, see Setting Timeouts for Blob Service Operations. + // [https://docs.microsoft.com/en-us/rest/api/storageservices/fileservices/setting-timeouts-for-blob-service-operations] + Timeout *int32 +} + +// ServiceClientListContainersSegmentOptions contains the optional parameters for the ServiceClient.NewListContainersSegmentPager +// method. +type ServiceClientListContainersSegmentOptions struct { + // Include this parameter to specify that the container's metadata be returned as part of the response body. + Include []ListContainersIncludeType + // A string value that identifies the portion of the list of containers to be returned with the next listing operation. The + // operation returns the NextMarker value within the response body if the listing + // operation did not return all containers remaining to be listed with the current page. The NextMarker value can be used + // as the value for the marker parameter in a subsequent call to request the next + // page of list items. The marker value is opaque to the client. + Marker *string + // Specifies the maximum number of containers to return. If the request does not specify maxresults, or specifies a value + // greater than 5000, the server will return up to 5000 items. Note that if the + // listing operation crosses a partition boundary, then the service will return a continuation token for retrieving the remainder + // of the results. For this reason, it is possible that the service will + // return fewer results than specified by maxresults, or than the default of 5000. + Maxresults *int32 + // Filters the results to return only containers whose name begins with the specified prefix. + Prefix *string + // Provides a client-generated, opaque value with a 1 KB character limit that is recorded in the analytics logs when storage + // analytics logging is enabled. + RequestID *string + // The timeout parameter is expressed in seconds. For more information, see Setting Timeouts for Blob Service Operations. + // [https://docs.microsoft.com/en-us/rest/api/storageservices/fileservices/setting-timeouts-for-blob-service-operations] + Timeout *int32 +} + +// ServiceClientSetPropertiesOptions contains the optional parameters for the ServiceClient.SetProperties method. +type ServiceClientSetPropertiesOptions struct { + // Provides a client-generated, opaque value with a 1 KB character limit that is recorded in the analytics logs when storage + // analytics logging is enabled. + RequestID *string + // The timeout parameter is expressed in seconds. For more information, see Setting Timeouts for Blob Service Operations. + // [https://docs.microsoft.com/en-us/rest/api/storageservices/fileservices/setting-timeouts-for-blob-service-operations] + Timeout *int32 +} + +// ServiceClientSubmitBatchOptions contains the optional parameters for the ServiceClient.SubmitBatch method. +type ServiceClientSubmitBatchOptions struct { + // Provides a client-generated, opaque value with a 1 KB character limit that is recorded in the analytics logs when storage + // analytics logging is enabled. + RequestID *string + // The timeout parameter is expressed in seconds. For more information, see Setting Timeouts for Blob Service Operations. + // [https://docs.microsoft.com/en-us/rest/api/storageservices/fileservices/setting-timeouts-for-blob-service-operations] + Timeout *int32 +} + +// SignedIdentifier - signed identifier +type SignedIdentifier struct { + // REQUIRED; An Access policy + AccessPolicy *AccessPolicy `xml:"AccessPolicy"` + + // REQUIRED; a unique id + ID *string `xml:"Id"` +} + +// SourceModifiedAccessConditions contains a group of parameters for the BlobClient.StartCopyFromURL method. +type SourceModifiedAccessConditions struct { + // Specify an ETag value to operate only on blobs with a matching value. + SourceIfMatch *azcore.ETag + // Specify this header value to operate only on a blob if it has been modified since the specified date/time. + SourceIfModifiedSince *time.Time + // Specify an ETag value to operate only on blobs without a matching value. + SourceIfNoneMatch *azcore.ETag + // Specify a SQL where clause on blob tags to operate only on blobs with a matching value. + SourceIfTags *string + // Specify this header value to operate only on a blob if it has not been modified since the specified date/time. + SourceIfUnmodifiedSince *time.Time +} + +// StaticWebsite - The properties that enable an account to host a static website +type StaticWebsite struct { + // REQUIRED; Indicates whether this account is hosting a static website + Enabled *bool `xml:"Enabled"` + + // Absolute path of the default index page + DefaultIndexDocumentPath *string `xml:"DefaultIndexDocumentPath"` + + // The absolute path of the custom 404 page + ErrorDocument404Path *string `xml:"ErrorDocument404Path"` + + // The default name of the index page under each directory + IndexDocument *string `xml:"IndexDocument"` +} + +type StorageError struct { + Message *string +} + +// StorageServiceProperties - Storage Service Properties. +type StorageServiceProperties struct { + // The set of CORS rules. + CORS []*CORSRule `xml:"Cors>CorsRule"` + + // The default version to use for requests to the Blob service if an incoming request's version is not specified. Possible + // values include version 2008-10-27 and all more recent versions + DefaultServiceVersion *string `xml:"DefaultServiceVersion"` + + // the retention policy which determines how long the associated data should persist + DeleteRetentionPolicy *RetentionPolicy `xml:"DeleteRetentionPolicy"` + + // a summary of request statistics grouped by API in hour or minute aggregates for blobs + HourMetrics *Metrics `xml:"HourMetrics"` + + // Azure Analytics Logging settings. + Logging *Logging `xml:"Logging"` + + // a summary of request statistics grouped by API in hour or minute aggregates for blobs + MinuteMetrics *Metrics `xml:"MinuteMetrics"` + + // The properties that enable an account to host a static website + StaticWebsite *StaticWebsite `xml:"StaticWebsite"` +} + +// StorageServiceStats - Stats for the storage service. +type StorageServiceStats struct { + // Geo-Replication information for the Secondary Storage Service + GeoReplication *GeoReplication `xml:"GeoReplication"` +} + +// UserDelegationKey - A user delegation key +type UserDelegationKey struct { + // REQUIRED; The date-time the key expires + SignedExpiry *time.Time `xml:"SignedExpiry"` + + // REQUIRED; The Azure Active Directory object ID in GUID format. + SignedOID *string `xml:"SignedOid"` + + // REQUIRED; Abbreviation of the Azure Storage service that accepts the key + SignedService *string `xml:"SignedService"` + + // REQUIRED; The date-time the key is active + SignedStart *time.Time `xml:"SignedStart"` + + // REQUIRED; The Azure Active Directory tenant ID in GUID format + SignedTID *string `xml:"SignedTid"` + + // REQUIRED; The service version that created the key + SignedVersion *string `xml:"SignedVersion"` + + // REQUIRED; The key as a base64 string + Value *string `xml:"Value"` +} diff --git a/sdk/storage/azdatalake/internal/generated_blob/zz_models_serde.go b/sdk/storage/azdatalake/internal/generated_blob/zz_models_serde.go new file mode 100644 index 000000000000..bc5a3d6ec6ad --- /dev/null +++ b/sdk/storage/azdatalake/internal/generated_blob/zz_models_serde.go @@ -0,0 +1,473 @@ +//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. +// Code generated by Microsoft (R) AutoRest Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. +// DO NOT EDIT. + +package generated_blob + +import ( + "encoding/json" + "encoding/xml" + "fmt" + "github.com/Azure/azure-sdk-for-go/sdk/azcore" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime" + "reflect" + "time" +) + +// MarshalXML implements the xml.Marshaller interface for type AccessPolicy. +func (a AccessPolicy) MarshalXML(enc *xml.Encoder, start xml.StartElement) error { + type alias AccessPolicy + aux := &struct { + *alias + Expiry *timeRFC3339 `xml:"Expiry"` + Start *timeRFC3339 `xml:"Start"` + }{ + alias: (*alias)(&a), + Expiry: (*timeRFC3339)(a.Expiry), + Start: (*timeRFC3339)(a.Start), + } + return enc.EncodeElement(aux, start) +} + +// UnmarshalXML implements the xml.Unmarshaller interface for type AccessPolicy. +func (a *AccessPolicy) UnmarshalXML(dec *xml.Decoder, start xml.StartElement) error { + type alias AccessPolicy + aux := &struct { + *alias + Expiry *timeRFC3339 `xml:"Expiry"` + Start *timeRFC3339 `xml:"Start"` + }{ + alias: (*alias)(a), + } + if err := dec.DecodeElement(aux, &start); err != nil { + return err + } + a.Expiry = (*time.Time)(aux.Expiry) + a.Start = (*time.Time)(aux.Start) + return nil +} + +// MarshalXML implements the xml.Marshaller interface for type ArrowConfiguration. +func (a ArrowConfiguration) MarshalXML(enc *xml.Encoder, start xml.StartElement) error { + type alias ArrowConfiguration + aux := &struct { + *alias + Schema *[]*ArrowField `xml:"Schema>Field"` + }{ + alias: (*alias)(&a), + } + if a.Schema != nil { + aux.Schema = &a.Schema + } + return enc.EncodeElement(aux, start) +} + +// MarshalXML implements the xml.Marshaller interface for type BlobFlatListSegment. +func (b BlobFlatListSegment) MarshalXML(enc *xml.Encoder, start xml.StartElement) error { + type alias BlobFlatListSegment + aux := &struct { + *alias + PathItems *[]*PathItem `xml:"Blob"` + }{ + alias: (*alias)(&b), + } + if b.PathItems != nil { + aux.PathItems = &b.PathItems + } + return enc.EncodeElement(aux, start) +} + +// MarshalXML implements the xml.Marshaller interface for type PathHierarchyListSegment. +func (b PathHierarchyListSegment) MarshalXML(enc *xml.Encoder, start xml.StartElement) error { + type alias PathHierarchyListSegment + aux := &struct { + *alias + PathItems *[]*PathItem `xml:"Blob"` + PathPrefixes *[]*PathPrefix `xml:"PathPrefix"` + }{ + alias: (*alias)(&b), + } + if b.PathItems != nil { + aux.PathItems = &b.PathItems + } + if b.PathPrefixes != nil { + aux.PathPrefixes = &b.PathPrefixes + } + return enc.EncodeElement(aux, start) +} + +// MarshalXML implements the xml.Marshaller interface for type PathProperties. +func (b PathProperties) MarshalXML(enc *xml.Encoder, start xml.StartElement) error { + type alias PathProperties + aux := &struct { + *alias + AccessTierChangeTime *timeRFC1123 `xml:"AccessTierChangeTime"` + ContentMD5 *string `xml:"Content-MD5"` + CopyCompletionTime *timeRFC1123 `xml:"CopyCompletionTime"` + CreationTime *timeRFC1123 `xml:"Creation-Time"` + DeletedTime *timeRFC1123 `xml:"DeletedTime"` + ExpiresOn *timeRFC1123 `xml:"Expiry-Time"` + ImmutabilityPolicyExpiresOn *timeRFC1123 `xml:"ImmutabilityPolicyUntilDate"` + LastAccessedOn *timeRFC1123 `xml:"LastAccessTime"` + LastModified *timeRFC1123 `xml:"Last-Modified"` + }{ + alias: (*alias)(&b), + AccessTierChangeTime: (*timeRFC1123)(b.AccessTierChangeTime), + CopyCompletionTime: (*timeRFC1123)(b.CopyCompletionTime), + CreationTime: (*timeRFC1123)(b.CreationTime), + DeletedTime: (*timeRFC1123)(b.DeletedTime), + ExpiresOn: (*timeRFC1123)(b.ExpiresOn), + ImmutabilityPolicyExpiresOn: (*timeRFC1123)(b.ImmutabilityPolicyExpiresOn), + LastAccessedOn: (*timeRFC1123)(b.LastAccessedOn), + LastModified: (*timeRFC1123)(b.LastModified), + } + if b.ContentMD5 != nil { + encodedContentMD5 := runtime.EncodeByteArray(b.ContentMD5, runtime.Base64StdFormat) + aux.ContentMD5 = &encodedContentMD5 + } + return enc.EncodeElement(aux, start) +} + +// UnmarshalXML implements the xml.Unmarshaller interface for type PathProperties. +func (b *PathProperties) UnmarshalXML(dec *xml.Decoder, start xml.StartElement) error { + type alias PathProperties + aux := &struct { + *alias + AccessTierChangeTime *timeRFC1123 `xml:"AccessTierChangeTime"` + ContentMD5 *string `xml:"Content-MD5"` + CopyCompletionTime *timeRFC1123 `xml:"CopyCompletionTime"` + CreationTime *timeRFC1123 `xml:"Creation-Time"` + DeletedTime *timeRFC1123 `xml:"DeletedTime"` + ExpiresOn *timeRFC1123 `xml:"Expiry-Time"` + ImmutabilityPolicyExpiresOn *timeRFC1123 `xml:"ImmutabilityPolicyUntilDate"` + LastAccessedOn *timeRFC1123 `xml:"LastAccessTime"` + LastModified *timeRFC1123 `xml:"Last-Modified"` + }{ + alias: (*alias)(b), + } + if err := dec.DecodeElement(aux, &start); err != nil { + return err + } + b.AccessTierChangeTime = (*time.Time)(aux.AccessTierChangeTime) + if aux.ContentMD5 != nil { + if err := runtime.DecodeByteArray(*aux.ContentMD5, &b.ContentMD5, runtime.Base64StdFormat); err != nil { + return err + } + } + b.CopyCompletionTime = (*time.Time)(aux.CopyCompletionTime) + b.CreationTime = (*time.Time)(aux.CreationTime) + b.DeletedTime = (*time.Time)(aux.DeletedTime) + b.ExpiresOn = (*time.Time)(aux.ExpiresOn) + b.ImmutabilityPolicyExpiresOn = (*time.Time)(aux.ImmutabilityPolicyExpiresOn) + b.LastAccessedOn = (*time.Time)(aux.LastAccessedOn) + b.LastModified = (*time.Time)(aux.LastModified) + return nil +} + +// MarshalXML implements the xml.Marshaller interface for type BlobTags. +func (b BlobTags) MarshalXML(enc *xml.Encoder, start xml.StartElement) error { + start.Name.Local = "Tags" + type alias BlobTags + aux := &struct { + *alias + BlobTagSet *[]*BlobTag `xml:"TagSet>Tag"` + }{ + alias: (*alias)(&b), + } + if b.BlobTagSet != nil { + aux.BlobTagSet = &b.BlobTagSet + } + return enc.EncodeElement(aux, start) +} + +// MarshalXML implements the xml.Marshaller interface for type BlockList. +func (b BlockList) MarshalXML(enc *xml.Encoder, start xml.StartElement) error { + type alias BlockList + aux := &struct { + *alias + CommittedBlocks *[]*Block `xml:"CommittedBlocks>Block"` + UncommittedBlocks *[]*Block `xml:"UncommittedBlocks>Block"` + }{ + alias: (*alias)(&b), + } + if b.CommittedBlocks != nil { + aux.CommittedBlocks = &b.CommittedBlocks + } + if b.UncommittedBlocks != nil { + aux.UncommittedBlocks = &b.UncommittedBlocks + } + return enc.EncodeElement(aux, start) +} + +// MarshalXML implements the xml.Marshaller interface for type BlockLookupList. +func (b BlockLookupList) MarshalXML(enc *xml.Encoder, start xml.StartElement) error { + start.Name.Local = "BlockList" + type alias BlockLookupList + aux := &struct { + *alias + Committed *[]*string `xml:"Committed"` + Latest *[]*string `xml:"Latest"` + Uncommitted *[]*string `xml:"Uncommitted"` + }{ + alias: (*alias)(&b), + } + if b.Committed != nil { + aux.Committed = &b.Committed + } + if b.Latest != nil { + aux.Latest = &b.Latest + } + if b.Uncommitted != nil { + aux.Uncommitted = &b.Uncommitted + } + return enc.EncodeElement(aux, start) +} + +// UnmarshalXML implements the xml.Unmarshaller interface for type FileSystemItem. +func (c *FileSystemItem) UnmarshalXML(dec *xml.Decoder, start xml.StartElement) error { + type alias FileSystemItem + aux := &struct { + *alias + Metadata additionalProperties `xml:"Metadata"` + }{ + alias: (*alias)(c), + } + if err := dec.DecodeElement(aux, &start); err != nil { + return err + } + c.Metadata = (map[string]*string)(aux.Metadata) + return nil +} + +// MarshalXML implements the xml.Marshaller interface for type FileSystemProperties. +func (c FileSystemProperties) MarshalXML(enc *xml.Encoder, start xml.StartElement) error { + type alias FileSystemProperties + aux := &struct { + *alias + DeletedTime *timeRFC1123 `xml:"DeletedTime"` + LastModified *timeRFC1123 `xml:"Last-Modified"` + }{ + alias: (*alias)(&c), + DeletedTime: (*timeRFC1123)(c.DeletedTime), + LastModified: (*timeRFC1123)(c.LastModified), + } + return enc.EncodeElement(aux, start) +} + +// UnmarshalXML implements the xml.Unmarshaller interface for type FileSystemProperties. +func (c *FileSystemProperties) UnmarshalXML(dec *xml.Decoder, start xml.StartElement) error { + type alias FileSystemProperties + aux := &struct { + *alias + DeletedTime *timeRFC1123 `xml:"DeletedTime"` + LastModified *timeRFC1123 `xml:"Last-Modified"` + }{ + alias: (*alias)(c), + } + if err := dec.DecodeElement(aux, &start); err != nil { + return err + } + c.DeletedTime = (*time.Time)(aux.DeletedTime) + c.LastModified = (*time.Time)(aux.LastModified) + return nil +} + +// MarshalXML implements the xml.Marshaller interface for type FilterBlobSegment. +func (f FilterBlobSegment) MarshalXML(enc *xml.Encoder, start xml.StartElement) error { + type alias FilterBlobSegment + aux := &struct { + *alias + Blobs *[]*FilterPathItem `xml:"Blobs>Blob"` + }{ + alias: (*alias)(&f), + } + if f.Blobs != nil { + aux.Blobs = &f.Blobs + } + return enc.EncodeElement(aux, start) +} + +// MarshalXML implements the xml.Marshaller interface for type GeoReplication. +func (g GeoReplication) MarshalXML(enc *xml.Encoder, start xml.StartElement) error { + type alias GeoReplication + aux := &struct { + *alias + LastSyncTime *timeRFC1123 `xml:"LastSyncTime"` + }{ + alias: (*alias)(&g), + LastSyncTime: (*timeRFC1123)(g.LastSyncTime), + } + return enc.EncodeElement(aux, start) +} + +// UnmarshalXML implements the xml.Unmarshaller interface for type GeoReplication. +func (g *GeoReplication) UnmarshalXML(dec *xml.Decoder, start xml.StartElement) error { + type alias GeoReplication + aux := &struct { + *alias + LastSyncTime *timeRFC1123 `xml:"LastSyncTime"` + }{ + alias: (*alias)(g), + } + if err := dec.DecodeElement(aux, &start); err != nil { + return err + } + g.LastSyncTime = (*time.Time)(aux.LastSyncTime) + return nil +} + +// MarshalXML implements the xml.Marshaller interface for type ListFileSystemsSegmentResponse. +func (l ListFileSystemsSegmentResponse) MarshalXML(enc *xml.Encoder, start xml.StartElement) error { + type alias ListFileSystemsSegmentResponse + aux := &struct { + *alias + FileSystemItems *[]*FileSystemItem `xml:"Containers>Container"` + }{ + alias: (*alias)(&l), + } + if l.FileSystemItems != nil { + aux.FileSystemItems = &l.FileSystemItems + } + return enc.EncodeElement(aux, start) +} + +// MarshalXML implements the xml.Marshaller interface for type PageList. +func (p PageList) MarshalXML(enc *xml.Encoder, start xml.StartElement) error { + type alias PageList + aux := &struct { + *alias + ClearRange *[]*ClearRange `xml:"ClearRange"` + PageRange *[]*PageRange `xml:"PageRange"` + }{ + alias: (*alias)(&p), + } + if p.ClearRange != nil { + aux.ClearRange = &p.ClearRange + } + if p.PageRange != nil { + aux.PageRange = &p.PageRange + } + return enc.EncodeElement(aux, start) +} + +// MarshalXML implements the xml.Marshaller interface for type QueryRequest. +func (q QueryRequest) MarshalXML(enc *xml.Encoder, start xml.StartElement) error { + start.Name.Local = "QueryRequest" + type alias QueryRequest + aux := &struct { + *alias + }{ + alias: (*alias)(&q), + } + return enc.EncodeElement(aux, start) +} + +// MarshalJSON implements the json.Marshaller interface for type StorageError. +func (s StorageError) MarshalJSON() ([]byte, error) { + objectMap := make(map[string]any) + populate(objectMap, "Message", s.Message) + return json.Marshal(objectMap) +} + +// UnmarshalJSON implements the json.Unmarshaller interface for type StorageError. +func (s *StorageError) UnmarshalJSON(data []byte) error { + var rawMsg map[string]json.RawMessage + if err := json.Unmarshal(data, &rawMsg); err != nil { + return fmt.Errorf("unmarshalling type %T: %v", s, err) + } + for key, val := range rawMsg { + var err error + switch key { + case "Message": + err = unpopulate(val, "Message", &s.Message) + delete(rawMsg, key) + } + if err != nil { + return fmt.Errorf("unmarshalling type %T: %v", s, err) + } + } + return nil +} + +// MarshalXML implements the xml.Marshaller interface for type StorageServiceProperties. +func (s StorageServiceProperties) MarshalXML(enc *xml.Encoder, start xml.StartElement) error { + type alias StorageServiceProperties + aux := &struct { + *alias + CORS *[]*CORSRule `xml:"Cors>CorsRule"` + }{ + alias: (*alias)(&s), + } + if s.CORS != nil { + aux.CORS = &s.CORS + } + return enc.EncodeElement(aux, start) +} + +// MarshalXML implements the xml.Marshaller interface for type UserDelegationKey. +func (u UserDelegationKey) MarshalXML(enc *xml.Encoder, start xml.StartElement) error { + type alias UserDelegationKey + aux := &struct { + *alias + SignedExpiry *timeRFC3339 `xml:"SignedExpiry"` + SignedStart *timeRFC3339 `xml:"SignedStart"` + }{ + alias: (*alias)(&u), + SignedExpiry: (*timeRFC3339)(u.SignedExpiry), + SignedStart: (*timeRFC3339)(u.SignedStart), + } + return enc.EncodeElement(aux, start) +} + +// UnmarshalXML implements the xml.Unmarshaller interface for type UserDelegationKey. +func (u *UserDelegationKey) UnmarshalXML(dec *xml.Decoder, start xml.StartElement) error { + type alias UserDelegationKey + aux := &struct { + *alias + SignedExpiry *timeRFC3339 `xml:"SignedExpiry"` + SignedStart *timeRFC3339 `xml:"SignedStart"` + }{ + alias: (*alias)(u), + } + if err := dec.DecodeElement(aux, &start); err != nil { + return err + } + u.SignedExpiry = (*time.Time)(aux.SignedExpiry) + u.SignedStart = (*time.Time)(aux.SignedStart) + return nil +} + +func populate(m map[string]any, k string, v any) { + if v == nil { + return + } else if azcore.IsNullValue(v) { + m[k] = nil + } else if !reflect.ValueOf(v).IsNil() { + m[k] = v + } +} + +func populateAny(m map[string]any, k string, v any) { + if v == nil { + return + } else if azcore.IsNullValue(v) { + m[k] = nil + } else { + m[k] = v + } +} + +func unpopulate(data json.RawMessage, fn string, v any) error { + if data == nil { + return nil + } + if err := json.Unmarshal(data, v); err != nil { + return fmt.Errorf("struct field %s: %v", fn, err) + } + return nil +} diff --git a/sdk/storage/azdatalake/internal/generated_blob/zz_pageblob_client.go b/sdk/storage/azdatalake/internal/generated_blob/zz_pageblob_client.go new file mode 100644 index 000000000000..b4801102a15d --- /dev/null +++ b/sdk/storage/azdatalake/internal/generated_blob/zz_pageblob_client.go @@ -0,0 +1,1289 @@ +//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. +// Code generated by Microsoft (R) AutoRest Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. +// DO NOT EDIT. + +package generated_blob + +import ( + "context" + "encoding/base64" + "github.com/Azure/azure-sdk-for-go/sdk/azcore" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/policy" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime" + "io" + "net/http" + "strconv" + "time" +) + +// PageBlobClient contains the methods for the PageBlob group. +// Don't use this type directly, use a constructor function instead. +type PageBlobClient struct { + internal *azcore.Client + endpoint string +} + +// ClearPages - The Clear Pages operation clears a set of pages from a page blob +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2020-10-02 +// - contentLength - The length of the request. +// - options - PageBlobClientClearPagesOptions contains the optional parameters for the PageBlobClient.ClearPages method. +// - LeaseAccessConditions - LeaseAccessConditions contains a group of parameters for the ContainerClient.GetProperties method. +// - CPKInfo - CPKInfo contains a group of parameters for the BlobClient.Download method. +// - CPKScopeInfo - CPKScopeInfo contains a group of parameters for the BlobClient.SetMetadata method. +// - SequenceNumberAccessConditions - SequenceNumberAccessConditions contains a group of parameters for the PageBlobClient.UploadPages +// method. +// - ModifiedAccessConditions - ModifiedAccessConditions contains a group of parameters for the ContainerClient.Delete method. +func (client *PageBlobClient) ClearPages(ctx context.Context, contentLength int64, options *PageBlobClientClearPagesOptions, leaseAccessConditions *LeaseAccessConditions, cpkInfo *CPKInfo, cpkScopeInfo *CPKScopeInfo, sequenceNumberAccessConditions *SequenceNumberAccessConditions, modifiedAccessConditions *ModifiedAccessConditions) (PageBlobClientClearPagesResponse, error) { + req, err := client.clearPagesCreateRequest(ctx, contentLength, options, leaseAccessConditions, cpkInfo, cpkScopeInfo, sequenceNumberAccessConditions, modifiedAccessConditions) + if err != nil { + return PageBlobClientClearPagesResponse{}, err + } + resp, err := client.internal.Pipeline().Do(req) + if err != nil { + return PageBlobClientClearPagesResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusCreated) { + return PageBlobClientClearPagesResponse{}, runtime.NewResponseError(resp) + } + return client.clearPagesHandleResponse(resp) +} + +// clearPagesCreateRequest creates the ClearPages request. +func (client *PageBlobClient) clearPagesCreateRequest(ctx context.Context, contentLength int64, options *PageBlobClientClearPagesOptions, leaseAccessConditions *LeaseAccessConditions, cpkInfo *CPKInfo, cpkScopeInfo *CPKScopeInfo, sequenceNumberAccessConditions *SequenceNumberAccessConditions, modifiedAccessConditions *ModifiedAccessConditions) (*policy.Request, error) { + req, err := runtime.NewRequest(ctx, http.MethodPut, client.endpoint) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("comp", "page") + if options != nil && options.Timeout != nil { + reqQP.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + } + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["x-ms-page-write"] = []string{"clear"} + req.Raw().Header["Content-Length"] = []string{strconv.FormatInt(contentLength, 10)} + if options != nil && options.Range != nil { + req.Raw().Header["x-ms-range"] = []string{*options.Range} + } + if leaseAccessConditions != nil && leaseAccessConditions.LeaseID != nil { + req.Raw().Header["x-ms-lease-id"] = []string{*leaseAccessConditions.LeaseID} + } + if cpkInfo != nil && cpkInfo.EncryptionKey != nil { + req.Raw().Header["x-ms-encryption-key"] = []string{*cpkInfo.EncryptionKey} + } + if cpkInfo != nil && cpkInfo.EncryptionKeySHA256 != nil { + req.Raw().Header["x-ms-encryption-key-sha256"] = []string{*cpkInfo.EncryptionKeySHA256} + } + if cpkInfo != nil && cpkInfo.EncryptionAlgorithm != nil { + req.Raw().Header["x-ms-encryption-algorithm"] = []string{string(*cpkInfo.EncryptionAlgorithm)} + } + if cpkScopeInfo != nil && cpkScopeInfo.EncryptionScope != nil { + req.Raw().Header["x-ms-encryption-scope"] = []string{*cpkScopeInfo.EncryptionScope} + } + if sequenceNumberAccessConditions != nil && sequenceNumberAccessConditions.IfSequenceNumberLessThanOrEqualTo != nil { + req.Raw().Header["x-ms-if-sequence-number-le"] = []string{strconv.FormatInt(*sequenceNumberAccessConditions.IfSequenceNumberLessThanOrEqualTo, 10)} + } + if sequenceNumberAccessConditions != nil && sequenceNumberAccessConditions.IfSequenceNumberLessThan != nil { + req.Raw().Header["x-ms-if-sequence-number-lt"] = []string{strconv.FormatInt(*sequenceNumberAccessConditions.IfSequenceNumberLessThan, 10)} + } + if sequenceNumberAccessConditions != nil && sequenceNumberAccessConditions.IfSequenceNumberEqualTo != nil { + req.Raw().Header["x-ms-if-sequence-number-eq"] = []string{strconv.FormatInt(*sequenceNumberAccessConditions.IfSequenceNumberEqualTo, 10)} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfModifiedSince != nil { + req.Raw().Header["If-Modified-Since"] = []string{(*modifiedAccessConditions.IfModifiedSince).In(gmt).Format(time.RFC1123)} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfUnmodifiedSince != nil { + req.Raw().Header["If-Unmodified-Since"] = []string{(*modifiedAccessConditions.IfUnmodifiedSince).In(gmt).Format(time.RFC1123)} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfMatch != nil { + req.Raw().Header["If-Match"] = []string{string(*modifiedAccessConditions.IfMatch)} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfNoneMatch != nil { + req.Raw().Header["If-None-Match"] = []string{string(*modifiedAccessConditions.IfNoneMatch)} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfTags != nil { + req.Raw().Header["x-ms-if-tags"] = []string{*modifiedAccessConditions.IfTags} + } + req.Raw().Header["x-ms-version"] = []string{"2020-10-02"} + if options != nil && options.RequestID != nil { + req.Raw().Header["x-ms-client-request-id"] = []string{*options.RequestID} + } + req.Raw().Header["Accept"] = []string{"application/xml"} + return req, nil +} + +// clearPagesHandleResponse handles the ClearPages response. +func (client *PageBlobClient) clearPagesHandleResponse(resp *http.Response) (PageBlobClientClearPagesResponse, error) { + result := PageBlobClientClearPagesResponse{} + if val := resp.Header.Get("ETag"); val != "" { + result.ETag = (*azcore.ETag)(&val) + } + if val := resp.Header.Get("Last-Modified"); val != "" { + lastModified, err := time.Parse(time.RFC1123, val) + if err != nil { + return PageBlobClientClearPagesResponse{}, err + } + result.LastModified = &lastModified + } + if val := resp.Header.Get("Content-MD5"); val != "" { + contentMD5, err := base64.StdEncoding.DecodeString(val) + if err != nil { + return PageBlobClientClearPagesResponse{}, err + } + result.ContentMD5 = contentMD5 + } + if val := resp.Header.Get("x-ms-content-crc64"); val != "" { + contentCRC64, err := base64.StdEncoding.DecodeString(val) + if err != nil { + return PageBlobClientClearPagesResponse{}, err + } + result.ContentCRC64 = contentCRC64 + } + if val := resp.Header.Get("x-ms-blob-sequence-number"); val != "" { + blobSequenceNumber, err := strconv.ParseInt(val, 10, 64) + if err != nil { + return PageBlobClientClearPagesResponse{}, err + } + result.BlobSequenceNumber = &blobSequenceNumber + } + if val := resp.Header.Get("x-ms-client-request-id"); val != "" { + result.ClientRequestID = &val + } + if val := resp.Header.Get("x-ms-request-id"); val != "" { + result.RequestID = &val + } + if val := resp.Header.Get("x-ms-version"); val != "" { + result.Version = &val + } + if val := resp.Header.Get("Date"); val != "" { + date, err := time.Parse(time.RFC1123, val) + if err != nil { + return PageBlobClientClearPagesResponse{}, err + } + result.Date = &date + } + return result, nil +} + +// CopyIncremental - The Copy Incremental operation copies a snapshot of the source page blob to a destination page blob. +// The snapshot is copied such that only the differential changes between the previously copied +// snapshot are transferred to the destination. The copied snapshots are complete copies of the original snapshot and can +// be read or copied from as usual. This API is supported since REST version +// 2016-05-31. +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2020-10-02 +// - copySource - Specifies the name of the source page blob snapshot. This value is a URL of up to 2 KB in length that specifies +// a page blob snapshot. The value should be URL-encoded as it would appear in a request +// URI. The source blob must either be public or must be authenticated via a shared access signature. +// - options - PageBlobClientCopyIncrementalOptions contains the optional parameters for the PageBlobClient.CopyIncremental +// method. +// - ModifiedAccessConditions - ModifiedAccessConditions contains a group of parameters for the ContainerClient.Delete method. +func (client *PageBlobClient) CopyIncremental(ctx context.Context, copySource string, options *PageBlobClientCopyIncrementalOptions, modifiedAccessConditions *ModifiedAccessConditions) (PageBlobClientCopyIncrementalResponse, error) { + req, err := client.copyIncrementalCreateRequest(ctx, copySource, options, modifiedAccessConditions) + if err != nil { + return PageBlobClientCopyIncrementalResponse{}, err + } + resp, err := client.internal.Pipeline().Do(req) + if err != nil { + return PageBlobClientCopyIncrementalResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusAccepted) { + return PageBlobClientCopyIncrementalResponse{}, runtime.NewResponseError(resp) + } + return client.copyIncrementalHandleResponse(resp) +} + +// copyIncrementalCreateRequest creates the CopyIncremental request. +func (client *PageBlobClient) copyIncrementalCreateRequest(ctx context.Context, copySource string, options *PageBlobClientCopyIncrementalOptions, modifiedAccessConditions *ModifiedAccessConditions) (*policy.Request, error) { + req, err := runtime.NewRequest(ctx, http.MethodPut, client.endpoint) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("comp", "incrementalcopy") + if options != nil && options.Timeout != nil { + reqQP.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + } + req.Raw().URL.RawQuery = reqQP.Encode() + if modifiedAccessConditions != nil && modifiedAccessConditions.IfModifiedSince != nil { + req.Raw().Header["If-Modified-Since"] = []string{(*modifiedAccessConditions.IfModifiedSince).In(gmt).Format(time.RFC1123)} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfUnmodifiedSince != nil { + req.Raw().Header["If-Unmodified-Since"] = []string{(*modifiedAccessConditions.IfUnmodifiedSince).In(gmt).Format(time.RFC1123)} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfMatch != nil { + req.Raw().Header["If-Match"] = []string{string(*modifiedAccessConditions.IfMatch)} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfNoneMatch != nil { + req.Raw().Header["If-None-Match"] = []string{string(*modifiedAccessConditions.IfNoneMatch)} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfTags != nil { + req.Raw().Header["x-ms-if-tags"] = []string{*modifiedAccessConditions.IfTags} + } + req.Raw().Header["x-ms-copy-source"] = []string{copySource} + req.Raw().Header["x-ms-version"] = []string{"2020-10-02"} + if options != nil && options.RequestID != nil { + req.Raw().Header["x-ms-client-request-id"] = []string{*options.RequestID} + } + req.Raw().Header["Accept"] = []string{"application/xml"} + return req, nil +} + +// copyIncrementalHandleResponse handles the CopyIncremental response. +func (client *PageBlobClient) copyIncrementalHandleResponse(resp *http.Response) (PageBlobClientCopyIncrementalResponse, error) { + result := PageBlobClientCopyIncrementalResponse{} + if val := resp.Header.Get("ETag"); val != "" { + result.ETag = (*azcore.ETag)(&val) + } + if val := resp.Header.Get("Last-Modified"); val != "" { + lastModified, err := time.Parse(time.RFC1123, val) + if err != nil { + return PageBlobClientCopyIncrementalResponse{}, err + } + result.LastModified = &lastModified + } + if val := resp.Header.Get("x-ms-client-request-id"); val != "" { + result.ClientRequestID = &val + } + if val := resp.Header.Get("x-ms-request-id"); val != "" { + result.RequestID = &val + } + if val := resp.Header.Get("x-ms-version"); val != "" { + result.Version = &val + } + if val := resp.Header.Get("Date"); val != "" { + date, err := time.Parse(time.RFC1123, val) + if err != nil { + return PageBlobClientCopyIncrementalResponse{}, err + } + result.Date = &date + } + if val := resp.Header.Get("x-ms-copy-id"); val != "" { + result.CopyID = &val + } + if val := resp.Header.Get("x-ms-copy-status"); val != "" { + result.CopyStatus = (*CopyStatusType)(&val) + } + return result, nil +} + +// Create - The Create operation creates a new page blob. +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2020-10-02 +// - contentLength - The length of the request. +// - blobContentLength - This header specifies the maximum size for the page blob, up to 1 TB. The page blob size must be aligned +// to a 512-byte boundary. +// - options - PageBlobClientCreateOptions contains the optional parameters for the PageBlobClient.Create method. +// - BlobHTTPHeaders - BlobHTTPHeaders contains a group of parameters for the BlobClient.SetHTTPHeaders method. +// - LeaseAccessConditions - LeaseAccessConditions contains a group of parameters for the ContainerClient.GetProperties method. +// - CPKInfo - CPKInfo contains a group of parameters for the BlobClient.Download method. +// - CPKScopeInfo - CPKScopeInfo contains a group of parameters for the BlobClient.SetMetadata method. +// - ModifiedAccessConditions - ModifiedAccessConditions contains a group of parameters for the ContainerClient.Delete method. +func (client *PageBlobClient) Create(ctx context.Context, contentLength int64, blobContentLength int64, options *PageBlobClientCreateOptions, blobHTTPHeaders *BlobHTTPHeaders, leaseAccessConditions *LeaseAccessConditions, cpkInfo *CPKInfo, cpkScopeInfo *CPKScopeInfo, modifiedAccessConditions *ModifiedAccessConditions) (PageBlobClientCreateResponse, error) { + req, err := client.createCreateRequest(ctx, contentLength, blobContentLength, options, blobHTTPHeaders, leaseAccessConditions, cpkInfo, cpkScopeInfo, modifiedAccessConditions) + if err != nil { + return PageBlobClientCreateResponse{}, err + } + resp, err := client.internal.Pipeline().Do(req) + if err != nil { + return PageBlobClientCreateResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusCreated) { + return PageBlobClientCreateResponse{}, runtime.NewResponseError(resp) + } + return client.createHandleResponse(resp) +} + +// createCreateRequest creates the Create request. +func (client *PageBlobClient) createCreateRequest(ctx context.Context, contentLength int64, blobContentLength int64, options *PageBlobClientCreateOptions, blobHTTPHeaders *BlobHTTPHeaders, leaseAccessConditions *LeaseAccessConditions, cpkInfo *CPKInfo, cpkScopeInfo *CPKScopeInfo, modifiedAccessConditions *ModifiedAccessConditions) (*policy.Request, error) { + req, err := runtime.NewRequest(ctx, http.MethodPut, client.endpoint) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + if options != nil && options.Timeout != nil { + reqQP.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + } + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["x-ms-blob-type"] = []string{"PageBlob"} + req.Raw().Header["Content-Length"] = []string{strconv.FormatInt(contentLength, 10)} + if options != nil && options.Tier != nil { + req.Raw().Header["x-ms-access-tier"] = []string{string(*options.Tier)} + } + if blobHTTPHeaders != nil && blobHTTPHeaders.BlobContentType != nil { + req.Raw().Header["x-ms-blob-content-type"] = []string{*blobHTTPHeaders.BlobContentType} + } + if blobHTTPHeaders != nil && blobHTTPHeaders.BlobContentEncoding != nil { + req.Raw().Header["x-ms-blob-content-encoding"] = []string{*blobHTTPHeaders.BlobContentEncoding} + } + if blobHTTPHeaders != nil && blobHTTPHeaders.BlobContentLanguage != nil { + req.Raw().Header["x-ms-blob-content-language"] = []string{*blobHTTPHeaders.BlobContentLanguage} + } + if blobHTTPHeaders != nil && blobHTTPHeaders.BlobContentMD5 != nil { + req.Raw().Header["x-ms-blob-content-md5"] = []string{base64.StdEncoding.EncodeToString(blobHTTPHeaders.BlobContentMD5)} + } + if blobHTTPHeaders != nil && blobHTTPHeaders.BlobCacheControl != nil { + req.Raw().Header["x-ms-blob-cache-control"] = []string{*blobHTTPHeaders.BlobCacheControl} + } + if options != nil && options.Metadata != nil { + for k, v := range options.Metadata { + if v != nil { + req.Raw().Header["x-ms-meta-"+k] = []string{*v} + } + } + } + if leaseAccessConditions != nil && leaseAccessConditions.LeaseID != nil { + req.Raw().Header["x-ms-lease-id"] = []string{*leaseAccessConditions.LeaseID} + } + if blobHTTPHeaders != nil && blobHTTPHeaders.BlobContentDisposition != nil { + req.Raw().Header["x-ms-blob-content-disposition"] = []string{*blobHTTPHeaders.BlobContentDisposition} + } + if cpkInfo != nil && cpkInfo.EncryptionKey != nil { + req.Raw().Header["x-ms-encryption-key"] = []string{*cpkInfo.EncryptionKey} + } + if cpkInfo != nil && cpkInfo.EncryptionKeySHA256 != nil { + req.Raw().Header["x-ms-encryption-key-sha256"] = []string{*cpkInfo.EncryptionKeySHA256} + } + if cpkInfo != nil && cpkInfo.EncryptionAlgorithm != nil { + req.Raw().Header["x-ms-encryption-algorithm"] = []string{string(*cpkInfo.EncryptionAlgorithm)} + } + if cpkScopeInfo != nil && cpkScopeInfo.EncryptionScope != nil { + req.Raw().Header["x-ms-encryption-scope"] = []string{*cpkScopeInfo.EncryptionScope} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfModifiedSince != nil { + req.Raw().Header["If-Modified-Since"] = []string{(*modifiedAccessConditions.IfModifiedSince).In(gmt).Format(time.RFC1123)} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfUnmodifiedSince != nil { + req.Raw().Header["If-Unmodified-Since"] = []string{(*modifiedAccessConditions.IfUnmodifiedSince).In(gmt).Format(time.RFC1123)} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfMatch != nil { + req.Raw().Header["If-Match"] = []string{string(*modifiedAccessConditions.IfMatch)} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfNoneMatch != nil { + req.Raw().Header["If-None-Match"] = []string{string(*modifiedAccessConditions.IfNoneMatch)} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfTags != nil { + req.Raw().Header["x-ms-if-tags"] = []string{*modifiedAccessConditions.IfTags} + } + req.Raw().Header["x-ms-blob-content-length"] = []string{strconv.FormatInt(blobContentLength, 10)} + if options != nil && options.BlobSequenceNumber != nil { + req.Raw().Header["x-ms-blob-sequence-number"] = []string{strconv.FormatInt(*options.BlobSequenceNumber, 10)} + } + req.Raw().Header["x-ms-version"] = []string{"2020-10-02"} + if options != nil && options.RequestID != nil { + req.Raw().Header["x-ms-client-request-id"] = []string{*options.RequestID} + } + if options != nil && options.BlobTagsString != nil { + req.Raw().Header["x-ms-tags"] = []string{*options.BlobTagsString} + } + if options != nil && options.ImmutabilityPolicyExpiry != nil { + req.Raw().Header["x-ms-immutability-policy-until-date"] = []string{(*options.ImmutabilityPolicyExpiry).In(gmt).Format(time.RFC1123)} + } + if options != nil && options.ImmutabilityPolicyMode != nil { + req.Raw().Header["x-ms-immutability-policy-mode"] = []string{string(*options.ImmutabilityPolicyMode)} + } + if options != nil && options.LegalHold != nil { + req.Raw().Header["x-ms-legal-hold"] = []string{strconv.FormatBool(*options.LegalHold)} + } + req.Raw().Header["Accept"] = []string{"application/xml"} + return req, nil +} + +// createHandleResponse handles the Create response. +func (client *PageBlobClient) createHandleResponse(resp *http.Response) (PageBlobClientCreateResponse, error) { + result := PageBlobClientCreateResponse{} + if val := resp.Header.Get("ETag"); val != "" { + result.ETag = (*azcore.ETag)(&val) + } + if val := resp.Header.Get("Last-Modified"); val != "" { + lastModified, err := time.Parse(time.RFC1123, val) + if err != nil { + return PageBlobClientCreateResponse{}, err + } + result.LastModified = &lastModified + } + if val := resp.Header.Get("Content-MD5"); val != "" { + contentMD5, err := base64.StdEncoding.DecodeString(val) + if err != nil { + return PageBlobClientCreateResponse{}, err + } + result.ContentMD5 = contentMD5 + } + if val := resp.Header.Get("x-ms-client-request-id"); val != "" { + result.ClientRequestID = &val + } + if val := resp.Header.Get("x-ms-request-id"); val != "" { + result.RequestID = &val + } + if val := resp.Header.Get("x-ms-version"); val != "" { + result.Version = &val + } + if val := resp.Header.Get("x-ms-version-id"); val != "" { + result.VersionID = &val + } + if val := resp.Header.Get("Date"); val != "" { + date, err := time.Parse(time.RFC1123, val) + if err != nil { + return PageBlobClientCreateResponse{}, err + } + result.Date = &date + } + if val := resp.Header.Get("x-ms-request-server-encrypted"); val != "" { + isServerEncrypted, err := strconv.ParseBool(val) + if err != nil { + return PageBlobClientCreateResponse{}, err + } + result.IsServerEncrypted = &isServerEncrypted + } + if val := resp.Header.Get("x-ms-encryption-key-sha256"); val != "" { + result.EncryptionKeySHA256 = &val + } + if val := resp.Header.Get("x-ms-encryption-scope"); val != "" { + result.EncryptionScope = &val + } + return result, nil +} + +// NewGetPageRangesPager - The Get Page Ranges operation returns the list of valid page ranges for a page blob or snapshot +// of a page blob +// +// Generated from API version 2020-10-02 +// - options - PageBlobClientGetPageRangesOptions contains the optional parameters for the PageBlobClient.NewGetPageRangesPager +// method. +// - LeaseAccessConditions - LeaseAccessConditions contains a group of parameters for the ContainerClient.GetProperties method. +// - ModifiedAccessConditions - ModifiedAccessConditions contains a group of parameters for the ContainerClient.Delete method. +func (client *PageBlobClient) NewGetPageRangesPager(options *PageBlobClientGetPageRangesOptions, leaseAccessConditions *LeaseAccessConditions, modifiedAccessConditions *ModifiedAccessConditions) *runtime.Pager[PageBlobClientGetPageRangesResponse] { + return runtime.NewPager(runtime.PagingHandler[PageBlobClientGetPageRangesResponse]{ + More: func(page PageBlobClientGetPageRangesResponse) bool { + return page.NextMarker != nil && len(*page.NextMarker) > 0 + }, + Fetcher: func(ctx context.Context, page *PageBlobClientGetPageRangesResponse) (PageBlobClientGetPageRangesResponse, error) { + var req *policy.Request + var err error + if page == nil { + req, err = client.GetPageRangesCreateRequest(ctx, options, leaseAccessConditions, modifiedAccessConditions) + } else { + req, err = runtime.NewRequest(ctx, http.MethodGet, *page.NextMarker) + } + if err != nil { + return PageBlobClientGetPageRangesResponse{}, err + } + resp, err := client.internal.Pipeline().Do(req) + if err != nil { + return PageBlobClientGetPageRangesResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusOK) { + return PageBlobClientGetPageRangesResponse{}, runtime.NewResponseError(resp) + } + return client.GetPageRangesHandleResponse(resp) + }, + }) +} + +// GetPageRangesCreateRequest creates the GetPageRanges request. +func (client *PageBlobClient) GetPageRangesCreateRequest(ctx context.Context, options *PageBlobClientGetPageRangesOptions, leaseAccessConditions *LeaseAccessConditions, modifiedAccessConditions *ModifiedAccessConditions) (*policy.Request, error) { + req, err := runtime.NewRequest(ctx, http.MethodGet, client.endpoint) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("comp", "pagelist") + if options != nil && options.Snapshot != nil { + reqQP.Set("snapshot", *options.Snapshot) + } + if options != nil && options.Timeout != nil { + reqQP.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + } + if options != nil && options.Marker != nil { + reqQP.Set("marker", *options.Marker) + } + if options != nil && options.Maxresults != nil { + reqQP.Set("maxresults", strconv.FormatInt(int64(*options.Maxresults), 10)) + } + req.Raw().URL.RawQuery = reqQP.Encode() + if options != nil && options.Range != nil { + req.Raw().Header["x-ms-range"] = []string{*options.Range} + } + if leaseAccessConditions != nil && leaseAccessConditions.LeaseID != nil { + req.Raw().Header["x-ms-lease-id"] = []string{*leaseAccessConditions.LeaseID} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfModifiedSince != nil { + req.Raw().Header["If-Modified-Since"] = []string{(*modifiedAccessConditions.IfModifiedSince).In(gmt).Format(time.RFC1123)} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfUnmodifiedSince != nil { + req.Raw().Header["If-Unmodified-Since"] = []string{(*modifiedAccessConditions.IfUnmodifiedSince).In(gmt).Format(time.RFC1123)} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfMatch != nil { + req.Raw().Header["If-Match"] = []string{string(*modifiedAccessConditions.IfMatch)} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfNoneMatch != nil { + req.Raw().Header["If-None-Match"] = []string{string(*modifiedAccessConditions.IfNoneMatch)} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfTags != nil { + req.Raw().Header["x-ms-if-tags"] = []string{*modifiedAccessConditions.IfTags} + } + req.Raw().Header["x-ms-version"] = []string{"2020-10-02"} + if options != nil && options.RequestID != nil { + req.Raw().Header["x-ms-client-request-id"] = []string{*options.RequestID} + } + req.Raw().Header["Accept"] = []string{"application/xml"} + return req, nil +} + +// GetPageRangesHandleResponse handles the GetPageRanges response. +func (client *PageBlobClient) GetPageRangesHandleResponse(resp *http.Response) (PageBlobClientGetPageRangesResponse, error) { + result := PageBlobClientGetPageRangesResponse{} + if val := resp.Header.Get("Last-Modified"); val != "" { + lastModified, err := time.Parse(time.RFC1123, val) + if err != nil { + return PageBlobClientGetPageRangesResponse{}, err + } + result.LastModified = &lastModified + } + if val := resp.Header.Get("ETag"); val != "" { + result.ETag = (*azcore.ETag)(&val) + } + if val := resp.Header.Get("x-ms-blob-content-length"); val != "" { + blobContentLength, err := strconv.ParseInt(val, 10, 64) + if err != nil { + return PageBlobClientGetPageRangesResponse{}, err + } + result.BlobContentLength = &blobContentLength + } + if val := resp.Header.Get("x-ms-client-request-id"); val != "" { + result.ClientRequestID = &val + } + if val := resp.Header.Get("x-ms-request-id"); val != "" { + result.RequestID = &val + } + if val := resp.Header.Get("x-ms-version"); val != "" { + result.Version = &val + } + if val := resp.Header.Get("Date"); val != "" { + date, err := time.Parse(time.RFC1123, val) + if err != nil { + return PageBlobClientGetPageRangesResponse{}, err + } + result.Date = &date + } + if err := runtime.UnmarshalAsXML(resp, &result.PageList); err != nil { + return PageBlobClientGetPageRangesResponse{}, err + } + return result, nil +} + +// NewGetPageRangesDiffPager - The Get Page Ranges Diff operation returns the list of valid page ranges for a page blob that +// were changed between target blob and previous snapshot. +// +// Generated from API version 2020-10-02 +// - options - PageBlobClientGetPageRangesDiffOptions contains the optional parameters for the PageBlobClient.NewGetPageRangesDiffPager +// method. +// - LeaseAccessConditions - LeaseAccessConditions contains a group of parameters for the ContainerClient.GetProperties method. +// - ModifiedAccessConditions - ModifiedAccessConditions contains a group of parameters for the ContainerClient.Delete method. +func (client *PageBlobClient) NewGetPageRangesDiffPager(options *PageBlobClientGetPageRangesDiffOptions, leaseAccessConditions *LeaseAccessConditions, modifiedAccessConditions *ModifiedAccessConditions) *runtime.Pager[PageBlobClientGetPageRangesDiffResponse] { + return runtime.NewPager(runtime.PagingHandler[PageBlobClientGetPageRangesDiffResponse]{ + More: func(page PageBlobClientGetPageRangesDiffResponse) bool { + return page.NextMarker != nil && len(*page.NextMarker) > 0 + }, + Fetcher: func(ctx context.Context, page *PageBlobClientGetPageRangesDiffResponse) (PageBlobClientGetPageRangesDiffResponse, error) { + var req *policy.Request + var err error + if page == nil { + req, err = client.GetPageRangesDiffCreateRequest(ctx, options, leaseAccessConditions, modifiedAccessConditions) + } else { + req, err = runtime.NewRequest(ctx, http.MethodGet, *page.NextMarker) + } + if err != nil { + return PageBlobClientGetPageRangesDiffResponse{}, err + } + resp, err := client.internal.Pipeline().Do(req) + if err != nil { + return PageBlobClientGetPageRangesDiffResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusOK) { + return PageBlobClientGetPageRangesDiffResponse{}, runtime.NewResponseError(resp) + } + return client.GetPageRangesDiffHandleResponse(resp) + }, + }) +} + +// GetPageRangesDiffCreateRequest creates the GetPageRangesDiff request. +func (client *PageBlobClient) GetPageRangesDiffCreateRequest(ctx context.Context, options *PageBlobClientGetPageRangesDiffOptions, leaseAccessConditions *LeaseAccessConditions, modifiedAccessConditions *ModifiedAccessConditions) (*policy.Request, error) { + req, err := runtime.NewRequest(ctx, http.MethodGet, client.endpoint) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("comp", "pagelist") + if options != nil && options.Snapshot != nil { + reqQP.Set("snapshot", *options.Snapshot) + } + if options != nil && options.Timeout != nil { + reqQP.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + } + if options != nil && options.Prevsnapshot != nil { + reqQP.Set("prevsnapshot", *options.Prevsnapshot) + } + if options != nil && options.Marker != nil { + reqQP.Set("marker", *options.Marker) + } + if options != nil && options.Maxresults != nil { + reqQP.Set("maxresults", strconv.FormatInt(int64(*options.Maxresults), 10)) + } + req.Raw().URL.RawQuery = reqQP.Encode() + if options != nil && options.PrevSnapshotURL != nil { + req.Raw().Header["x-ms-previous-snapshot-url"] = []string{*options.PrevSnapshotURL} + } + if options != nil && options.Range != nil { + req.Raw().Header["x-ms-range"] = []string{*options.Range} + } + if leaseAccessConditions != nil && leaseAccessConditions.LeaseID != nil { + req.Raw().Header["x-ms-lease-id"] = []string{*leaseAccessConditions.LeaseID} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfModifiedSince != nil { + req.Raw().Header["If-Modified-Since"] = []string{(*modifiedAccessConditions.IfModifiedSince).In(gmt).Format(time.RFC1123)} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfUnmodifiedSince != nil { + req.Raw().Header["If-Unmodified-Since"] = []string{(*modifiedAccessConditions.IfUnmodifiedSince).In(gmt).Format(time.RFC1123)} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfMatch != nil { + req.Raw().Header["If-Match"] = []string{string(*modifiedAccessConditions.IfMatch)} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfNoneMatch != nil { + req.Raw().Header["If-None-Match"] = []string{string(*modifiedAccessConditions.IfNoneMatch)} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfTags != nil { + req.Raw().Header["x-ms-if-tags"] = []string{*modifiedAccessConditions.IfTags} + } + req.Raw().Header["x-ms-version"] = []string{"2020-10-02"} + if options != nil && options.RequestID != nil { + req.Raw().Header["x-ms-client-request-id"] = []string{*options.RequestID} + } + req.Raw().Header["Accept"] = []string{"application/xml"} + return req, nil +} + +// GetPageRangesDiffHandleResponse handles the GetPageRangesDiff response. +func (client *PageBlobClient) GetPageRangesDiffHandleResponse(resp *http.Response) (PageBlobClientGetPageRangesDiffResponse, error) { + result := PageBlobClientGetPageRangesDiffResponse{} + if val := resp.Header.Get("Last-Modified"); val != "" { + lastModified, err := time.Parse(time.RFC1123, val) + if err != nil { + return PageBlobClientGetPageRangesDiffResponse{}, err + } + result.LastModified = &lastModified + } + if val := resp.Header.Get("ETag"); val != "" { + result.ETag = (*azcore.ETag)(&val) + } + if val := resp.Header.Get("x-ms-blob-content-length"); val != "" { + blobContentLength, err := strconv.ParseInt(val, 10, 64) + if err != nil { + return PageBlobClientGetPageRangesDiffResponse{}, err + } + result.BlobContentLength = &blobContentLength + } + if val := resp.Header.Get("x-ms-client-request-id"); val != "" { + result.ClientRequestID = &val + } + if val := resp.Header.Get("x-ms-request-id"); val != "" { + result.RequestID = &val + } + if val := resp.Header.Get("x-ms-version"); val != "" { + result.Version = &val + } + if val := resp.Header.Get("Date"); val != "" { + date, err := time.Parse(time.RFC1123, val) + if err != nil { + return PageBlobClientGetPageRangesDiffResponse{}, err + } + result.Date = &date + } + if err := runtime.UnmarshalAsXML(resp, &result.PageList); err != nil { + return PageBlobClientGetPageRangesDiffResponse{}, err + } + return result, nil +} + +// Resize - Resize the Blob +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2020-10-02 +// - blobContentLength - This header specifies the maximum size for the page blob, up to 1 TB. The page blob size must be aligned +// to a 512-byte boundary. +// - options - PageBlobClientResizeOptions contains the optional parameters for the PageBlobClient.Resize method. +// - LeaseAccessConditions - LeaseAccessConditions contains a group of parameters for the ContainerClient.GetProperties method. +// - CPKInfo - CPKInfo contains a group of parameters for the BlobClient.Download method. +// - CPKScopeInfo - CPKScopeInfo contains a group of parameters for the BlobClient.SetMetadata method. +// - ModifiedAccessConditions - ModifiedAccessConditions contains a group of parameters for the ContainerClient.Delete method. +func (client *PageBlobClient) Resize(ctx context.Context, blobContentLength int64, options *PageBlobClientResizeOptions, leaseAccessConditions *LeaseAccessConditions, cpkInfo *CPKInfo, cpkScopeInfo *CPKScopeInfo, modifiedAccessConditions *ModifiedAccessConditions) (PageBlobClientResizeResponse, error) { + req, err := client.resizeCreateRequest(ctx, blobContentLength, options, leaseAccessConditions, cpkInfo, cpkScopeInfo, modifiedAccessConditions) + if err != nil { + return PageBlobClientResizeResponse{}, err + } + resp, err := client.internal.Pipeline().Do(req) + if err != nil { + return PageBlobClientResizeResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusOK) { + return PageBlobClientResizeResponse{}, runtime.NewResponseError(resp) + } + return client.resizeHandleResponse(resp) +} + +// resizeCreateRequest creates the Resize request. +func (client *PageBlobClient) resizeCreateRequest(ctx context.Context, blobContentLength int64, options *PageBlobClientResizeOptions, leaseAccessConditions *LeaseAccessConditions, cpkInfo *CPKInfo, cpkScopeInfo *CPKScopeInfo, modifiedAccessConditions *ModifiedAccessConditions) (*policy.Request, error) { + req, err := runtime.NewRequest(ctx, http.MethodPut, client.endpoint) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("comp", "properties") + if options != nil && options.Timeout != nil { + reqQP.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + } + req.Raw().URL.RawQuery = reqQP.Encode() + if leaseAccessConditions != nil && leaseAccessConditions.LeaseID != nil { + req.Raw().Header["x-ms-lease-id"] = []string{*leaseAccessConditions.LeaseID} + } + if cpkInfo != nil && cpkInfo.EncryptionKey != nil { + req.Raw().Header["x-ms-encryption-key"] = []string{*cpkInfo.EncryptionKey} + } + if cpkInfo != nil && cpkInfo.EncryptionKeySHA256 != nil { + req.Raw().Header["x-ms-encryption-key-sha256"] = []string{*cpkInfo.EncryptionKeySHA256} + } + if cpkInfo != nil && cpkInfo.EncryptionAlgorithm != nil { + req.Raw().Header["x-ms-encryption-algorithm"] = []string{string(*cpkInfo.EncryptionAlgorithm)} + } + if cpkScopeInfo != nil && cpkScopeInfo.EncryptionScope != nil { + req.Raw().Header["x-ms-encryption-scope"] = []string{*cpkScopeInfo.EncryptionScope} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfModifiedSince != nil { + req.Raw().Header["If-Modified-Since"] = []string{(*modifiedAccessConditions.IfModifiedSince).In(gmt).Format(time.RFC1123)} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfUnmodifiedSince != nil { + req.Raw().Header["If-Unmodified-Since"] = []string{(*modifiedAccessConditions.IfUnmodifiedSince).In(gmt).Format(time.RFC1123)} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfMatch != nil { + req.Raw().Header["If-Match"] = []string{string(*modifiedAccessConditions.IfMatch)} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfNoneMatch != nil { + req.Raw().Header["If-None-Match"] = []string{string(*modifiedAccessConditions.IfNoneMatch)} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfTags != nil { + req.Raw().Header["x-ms-if-tags"] = []string{*modifiedAccessConditions.IfTags} + } + req.Raw().Header["x-ms-blob-content-length"] = []string{strconv.FormatInt(blobContentLength, 10)} + req.Raw().Header["x-ms-version"] = []string{"2020-10-02"} + if options != nil && options.RequestID != nil { + req.Raw().Header["x-ms-client-request-id"] = []string{*options.RequestID} + } + req.Raw().Header["Accept"] = []string{"application/xml"} + return req, nil +} + +// resizeHandleResponse handles the Resize response. +func (client *PageBlobClient) resizeHandleResponse(resp *http.Response) (PageBlobClientResizeResponse, error) { + result := PageBlobClientResizeResponse{} + if val := resp.Header.Get("ETag"); val != "" { + result.ETag = (*azcore.ETag)(&val) + } + if val := resp.Header.Get("Last-Modified"); val != "" { + lastModified, err := time.Parse(time.RFC1123, val) + if err != nil { + return PageBlobClientResizeResponse{}, err + } + result.LastModified = &lastModified + } + if val := resp.Header.Get("x-ms-blob-sequence-number"); val != "" { + blobSequenceNumber, err := strconv.ParseInt(val, 10, 64) + if err != nil { + return PageBlobClientResizeResponse{}, err + } + result.BlobSequenceNumber = &blobSequenceNumber + } + if val := resp.Header.Get("x-ms-client-request-id"); val != "" { + result.ClientRequestID = &val + } + if val := resp.Header.Get("x-ms-request-id"); val != "" { + result.RequestID = &val + } + if val := resp.Header.Get("x-ms-version"); val != "" { + result.Version = &val + } + if val := resp.Header.Get("Date"); val != "" { + date, err := time.Parse(time.RFC1123, val) + if err != nil { + return PageBlobClientResizeResponse{}, err + } + result.Date = &date + } + return result, nil +} + +// UpdateSequenceNumber - Update the sequence number of the blob +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2020-10-02 +// - sequenceNumberAction - Required if the x-ms-blob-sequence-number header is set for the request. This property applies to +// page blobs only. This property indicates how the service should modify the blob's sequence number +// - options - PageBlobClientUpdateSequenceNumberOptions contains the optional parameters for the PageBlobClient.UpdateSequenceNumber +// method. +// - LeaseAccessConditions - LeaseAccessConditions contains a group of parameters for the ContainerClient.GetProperties method. +// - ModifiedAccessConditions - ModifiedAccessConditions contains a group of parameters for the ContainerClient.Delete method. +func (client *PageBlobClient) UpdateSequenceNumber(ctx context.Context, sequenceNumberAction SequenceNumberActionType, options *PageBlobClientUpdateSequenceNumberOptions, leaseAccessConditions *LeaseAccessConditions, modifiedAccessConditions *ModifiedAccessConditions) (PageBlobClientUpdateSequenceNumberResponse, error) { + req, err := client.updateSequenceNumberCreateRequest(ctx, sequenceNumberAction, options, leaseAccessConditions, modifiedAccessConditions) + if err != nil { + return PageBlobClientUpdateSequenceNumberResponse{}, err + } + resp, err := client.internal.Pipeline().Do(req) + if err != nil { + return PageBlobClientUpdateSequenceNumberResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusOK) { + return PageBlobClientUpdateSequenceNumberResponse{}, runtime.NewResponseError(resp) + } + return client.updateSequenceNumberHandleResponse(resp) +} + +// updateSequenceNumberCreateRequest creates the UpdateSequenceNumber request. +func (client *PageBlobClient) updateSequenceNumberCreateRequest(ctx context.Context, sequenceNumberAction SequenceNumberActionType, options *PageBlobClientUpdateSequenceNumberOptions, leaseAccessConditions *LeaseAccessConditions, modifiedAccessConditions *ModifiedAccessConditions) (*policy.Request, error) { + req, err := runtime.NewRequest(ctx, http.MethodPut, client.endpoint) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("comp", "properties") + if options != nil && options.Timeout != nil { + reqQP.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + } + req.Raw().URL.RawQuery = reqQP.Encode() + if leaseAccessConditions != nil && leaseAccessConditions.LeaseID != nil { + req.Raw().Header["x-ms-lease-id"] = []string{*leaseAccessConditions.LeaseID} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfModifiedSince != nil { + req.Raw().Header["If-Modified-Since"] = []string{(*modifiedAccessConditions.IfModifiedSince).In(gmt).Format(time.RFC1123)} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfUnmodifiedSince != nil { + req.Raw().Header["If-Unmodified-Since"] = []string{(*modifiedAccessConditions.IfUnmodifiedSince).In(gmt).Format(time.RFC1123)} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfMatch != nil { + req.Raw().Header["If-Match"] = []string{string(*modifiedAccessConditions.IfMatch)} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfNoneMatch != nil { + req.Raw().Header["If-None-Match"] = []string{string(*modifiedAccessConditions.IfNoneMatch)} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfTags != nil { + req.Raw().Header["x-ms-if-tags"] = []string{*modifiedAccessConditions.IfTags} + } + req.Raw().Header["x-ms-sequence-number-action"] = []string{string(sequenceNumberAction)} + if options != nil && options.BlobSequenceNumber != nil { + req.Raw().Header["x-ms-blob-sequence-number"] = []string{strconv.FormatInt(*options.BlobSequenceNumber, 10)} + } + req.Raw().Header["x-ms-version"] = []string{"2020-10-02"} + if options != nil && options.RequestID != nil { + req.Raw().Header["x-ms-client-request-id"] = []string{*options.RequestID} + } + req.Raw().Header["Accept"] = []string{"application/xml"} + return req, nil +} + +// updateSequenceNumberHandleResponse handles the UpdateSequenceNumber response. +func (client *PageBlobClient) updateSequenceNumberHandleResponse(resp *http.Response) (PageBlobClientUpdateSequenceNumberResponse, error) { + result := PageBlobClientUpdateSequenceNumberResponse{} + if val := resp.Header.Get("ETag"); val != "" { + result.ETag = (*azcore.ETag)(&val) + } + if val := resp.Header.Get("Last-Modified"); val != "" { + lastModified, err := time.Parse(time.RFC1123, val) + if err != nil { + return PageBlobClientUpdateSequenceNumberResponse{}, err + } + result.LastModified = &lastModified + } + if val := resp.Header.Get("x-ms-blob-sequence-number"); val != "" { + blobSequenceNumber, err := strconv.ParseInt(val, 10, 64) + if err != nil { + return PageBlobClientUpdateSequenceNumberResponse{}, err + } + result.BlobSequenceNumber = &blobSequenceNumber + } + if val := resp.Header.Get("x-ms-client-request-id"); val != "" { + result.ClientRequestID = &val + } + if val := resp.Header.Get("x-ms-request-id"); val != "" { + result.RequestID = &val + } + if val := resp.Header.Get("x-ms-version"); val != "" { + result.Version = &val + } + if val := resp.Header.Get("Date"); val != "" { + date, err := time.Parse(time.RFC1123, val) + if err != nil { + return PageBlobClientUpdateSequenceNumberResponse{}, err + } + result.Date = &date + } + return result, nil +} + +// UploadPages - The Upload Pages operation writes a range of pages to a page blob +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2020-10-02 +// - contentLength - The length of the request. +// - body - Initial data +// - options - PageBlobClientUploadPagesOptions contains the optional parameters for the PageBlobClient.UploadPages method. +// - LeaseAccessConditions - LeaseAccessConditions contains a group of parameters for the ContainerClient.GetProperties method. +// - CPKInfo - CPKInfo contains a group of parameters for the BlobClient.Download method. +// - CPKScopeInfo - CPKScopeInfo contains a group of parameters for the BlobClient.SetMetadata method. +// - SequenceNumberAccessConditions - SequenceNumberAccessConditions contains a group of parameters for the PageBlobClient.UploadPages +// method. +// - ModifiedAccessConditions - ModifiedAccessConditions contains a group of parameters for the ContainerClient.Delete method. +func (client *PageBlobClient) UploadPages(ctx context.Context, contentLength int64, body io.ReadSeekCloser, options *PageBlobClientUploadPagesOptions, leaseAccessConditions *LeaseAccessConditions, cpkInfo *CPKInfo, cpkScopeInfo *CPKScopeInfo, sequenceNumberAccessConditions *SequenceNumberAccessConditions, modifiedAccessConditions *ModifiedAccessConditions) (PageBlobClientUploadPagesResponse, error) { + req, err := client.uploadPagesCreateRequest(ctx, contentLength, body, options, leaseAccessConditions, cpkInfo, cpkScopeInfo, sequenceNumberAccessConditions, modifiedAccessConditions) + if err != nil { + return PageBlobClientUploadPagesResponse{}, err + } + resp, err := client.internal.Pipeline().Do(req) + if err != nil { + return PageBlobClientUploadPagesResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusCreated) { + return PageBlobClientUploadPagesResponse{}, runtime.NewResponseError(resp) + } + return client.uploadPagesHandleResponse(resp) +} + +// uploadPagesCreateRequest creates the UploadPages request. +func (client *PageBlobClient) uploadPagesCreateRequest(ctx context.Context, contentLength int64, body io.ReadSeekCloser, options *PageBlobClientUploadPagesOptions, leaseAccessConditions *LeaseAccessConditions, cpkInfo *CPKInfo, cpkScopeInfo *CPKScopeInfo, sequenceNumberAccessConditions *SequenceNumberAccessConditions, modifiedAccessConditions *ModifiedAccessConditions) (*policy.Request, error) { + req, err := runtime.NewRequest(ctx, http.MethodPut, client.endpoint) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("comp", "page") + if options != nil && options.Timeout != nil { + reqQP.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + } + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["x-ms-page-write"] = []string{"update"} + req.Raw().Header["Content-Length"] = []string{strconv.FormatInt(contentLength, 10)} + if options != nil && options.TransactionalContentMD5 != nil { + req.Raw().Header["Content-MD5"] = []string{base64.StdEncoding.EncodeToString(options.TransactionalContentMD5)} + } + if options != nil && options.TransactionalContentCRC64 != nil { + req.Raw().Header["x-ms-content-crc64"] = []string{base64.StdEncoding.EncodeToString(options.TransactionalContentCRC64)} + } + if options != nil && options.Range != nil { + req.Raw().Header["x-ms-range"] = []string{*options.Range} + } + if leaseAccessConditions != nil && leaseAccessConditions.LeaseID != nil { + req.Raw().Header["x-ms-lease-id"] = []string{*leaseAccessConditions.LeaseID} + } + if cpkInfo != nil && cpkInfo.EncryptionKey != nil { + req.Raw().Header["x-ms-encryption-key"] = []string{*cpkInfo.EncryptionKey} + } + if cpkInfo != nil && cpkInfo.EncryptionKeySHA256 != nil { + req.Raw().Header["x-ms-encryption-key-sha256"] = []string{*cpkInfo.EncryptionKeySHA256} + } + if cpkInfo != nil && cpkInfo.EncryptionAlgorithm != nil { + req.Raw().Header["x-ms-encryption-algorithm"] = []string{string(*cpkInfo.EncryptionAlgorithm)} + } + if cpkScopeInfo != nil && cpkScopeInfo.EncryptionScope != nil { + req.Raw().Header["x-ms-encryption-scope"] = []string{*cpkScopeInfo.EncryptionScope} + } + if sequenceNumberAccessConditions != nil && sequenceNumberAccessConditions.IfSequenceNumberLessThanOrEqualTo != nil { + req.Raw().Header["x-ms-if-sequence-number-le"] = []string{strconv.FormatInt(*sequenceNumberAccessConditions.IfSequenceNumberLessThanOrEqualTo, 10)} + } + if sequenceNumberAccessConditions != nil && sequenceNumberAccessConditions.IfSequenceNumberLessThan != nil { + req.Raw().Header["x-ms-if-sequence-number-lt"] = []string{strconv.FormatInt(*sequenceNumberAccessConditions.IfSequenceNumberLessThan, 10)} + } + if sequenceNumberAccessConditions != nil && sequenceNumberAccessConditions.IfSequenceNumberEqualTo != nil { + req.Raw().Header["x-ms-if-sequence-number-eq"] = []string{strconv.FormatInt(*sequenceNumberAccessConditions.IfSequenceNumberEqualTo, 10)} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfModifiedSince != nil { + req.Raw().Header["If-Modified-Since"] = []string{(*modifiedAccessConditions.IfModifiedSince).In(gmt).Format(time.RFC1123)} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfUnmodifiedSince != nil { + req.Raw().Header["If-Unmodified-Since"] = []string{(*modifiedAccessConditions.IfUnmodifiedSince).In(gmt).Format(time.RFC1123)} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfMatch != nil { + req.Raw().Header["If-Match"] = []string{string(*modifiedAccessConditions.IfMatch)} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfNoneMatch != nil { + req.Raw().Header["If-None-Match"] = []string{string(*modifiedAccessConditions.IfNoneMatch)} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfTags != nil { + req.Raw().Header["x-ms-if-tags"] = []string{*modifiedAccessConditions.IfTags} + } + req.Raw().Header["x-ms-version"] = []string{"2020-10-02"} + if options != nil && options.RequestID != nil { + req.Raw().Header["x-ms-client-request-id"] = []string{*options.RequestID} + } + req.Raw().Header["Accept"] = []string{"application/xml"} + if err := req.SetBody(body, "application/octet-stream"); err != nil { + return nil, err + } + return req, nil +} + +// uploadPagesHandleResponse handles the UploadPages response. +func (client *PageBlobClient) uploadPagesHandleResponse(resp *http.Response) (PageBlobClientUploadPagesResponse, error) { + result := PageBlobClientUploadPagesResponse{} + if val := resp.Header.Get("ETag"); val != "" { + result.ETag = (*azcore.ETag)(&val) + } + if val := resp.Header.Get("Last-Modified"); val != "" { + lastModified, err := time.Parse(time.RFC1123, val) + if err != nil { + return PageBlobClientUploadPagesResponse{}, err + } + result.LastModified = &lastModified + } + if val := resp.Header.Get("Content-MD5"); val != "" { + contentMD5, err := base64.StdEncoding.DecodeString(val) + if err != nil { + return PageBlobClientUploadPagesResponse{}, err + } + result.ContentMD5 = contentMD5 + } + if val := resp.Header.Get("x-ms-content-crc64"); val != "" { + contentCRC64, err := base64.StdEncoding.DecodeString(val) + if err != nil { + return PageBlobClientUploadPagesResponse{}, err + } + result.ContentCRC64 = contentCRC64 + } + if val := resp.Header.Get("x-ms-blob-sequence-number"); val != "" { + blobSequenceNumber, err := strconv.ParseInt(val, 10, 64) + if err != nil { + return PageBlobClientUploadPagesResponse{}, err + } + result.BlobSequenceNumber = &blobSequenceNumber + } + if val := resp.Header.Get("x-ms-client-request-id"); val != "" { + result.ClientRequestID = &val + } + if val := resp.Header.Get("x-ms-request-id"); val != "" { + result.RequestID = &val + } + if val := resp.Header.Get("x-ms-version"); val != "" { + result.Version = &val + } + if val := resp.Header.Get("Date"); val != "" { + date, err := time.Parse(time.RFC1123, val) + if err != nil { + return PageBlobClientUploadPagesResponse{}, err + } + result.Date = &date + } + if val := resp.Header.Get("x-ms-request-server-encrypted"); val != "" { + isServerEncrypted, err := strconv.ParseBool(val) + if err != nil { + return PageBlobClientUploadPagesResponse{}, err + } + result.IsServerEncrypted = &isServerEncrypted + } + if val := resp.Header.Get("x-ms-encryption-key-sha256"); val != "" { + result.EncryptionKeySHA256 = &val + } + if val := resp.Header.Get("x-ms-encryption-scope"); val != "" { + result.EncryptionScope = &val + } + return result, nil +} + +// UploadPagesFromURL - The Upload Pages operation writes a range of pages to a page blob where the contents are read from +// a URL +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2020-10-02 +// - sourceURL - Specify a URL to the copy source. +// - sourceRange - Bytes of source data in the specified range. The length of this range should match the ContentLength header +// and x-ms-range/Range destination range header. +// - contentLength - The length of the request. +// - rangeParam - The range of bytes to which the source range would be written. The range should be 512 aligned and range-end +// is required. +// - options - PageBlobClientUploadPagesFromURLOptions contains the optional parameters for the PageBlobClient.UploadPagesFromURL +// method. +// - CPKInfo - CPKInfo contains a group of parameters for the BlobClient.Download method. +// - CPKScopeInfo - CPKScopeInfo contains a group of parameters for the BlobClient.SetMetadata method. +// - LeaseAccessConditions - LeaseAccessConditions contains a group of parameters for the ContainerClient.GetProperties method. +// - SequenceNumberAccessConditions - SequenceNumberAccessConditions contains a group of parameters for the PageBlobClient.UploadPages +// method. +// - ModifiedAccessConditions - ModifiedAccessConditions contains a group of parameters for the ContainerClient.Delete method. +// - SourceModifiedAccessConditions - SourceModifiedAccessConditions contains a group of parameters for the BlobClient.StartCopyFromURL +// method. +func (client *PageBlobClient) UploadPagesFromURL(ctx context.Context, sourceURL string, sourceRange string, contentLength int64, rangeParam string, options *PageBlobClientUploadPagesFromURLOptions, cpkInfo *CPKInfo, cpkScopeInfo *CPKScopeInfo, leaseAccessConditions *LeaseAccessConditions, sequenceNumberAccessConditions *SequenceNumberAccessConditions, modifiedAccessConditions *ModifiedAccessConditions, sourceModifiedAccessConditions *SourceModifiedAccessConditions) (PageBlobClientUploadPagesFromURLResponse, error) { + req, err := client.uploadPagesFromURLCreateRequest(ctx, sourceURL, sourceRange, contentLength, rangeParam, options, cpkInfo, cpkScopeInfo, leaseAccessConditions, sequenceNumberAccessConditions, modifiedAccessConditions, sourceModifiedAccessConditions) + if err != nil { + return PageBlobClientUploadPagesFromURLResponse{}, err + } + resp, err := client.internal.Pipeline().Do(req) + if err != nil { + return PageBlobClientUploadPagesFromURLResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusCreated) { + return PageBlobClientUploadPagesFromURLResponse{}, runtime.NewResponseError(resp) + } + return client.uploadPagesFromURLHandleResponse(resp) +} + +// uploadPagesFromURLCreateRequest creates the UploadPagesFromURL request. +func (client *PageBlobClient) uploadPagesFromURLCreateRequest(ctx context.Context, sourceURL string, sourceRange string, contentLength int64, rangeParam string, options *PageBlobClientUploadPagesFromURLOptions, cpkInfo *CPKInfo, cpkScopeInfo *CPKScopeInfo, leaseAccessConditions *LeaseAccessConditions, sequenceNumberAccessConditions *SequenceNumberAccessConditions, modifiedAccessConditions *ModifiedAccessConditions, sourceModifiedAccessConditions *SourceModifiedAccessConditions) (*policy.Request, error) { + req, err := runtime.NewRequest(ctx, http.MethodPut, client.endpoint) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("comp", "page") + if options != nil && options.Timeout != nil { + reqQP.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + } + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["x-ms-page-write"] = []string{"update"} + req.Raw().Header["x-ms-copy-source"] = []string{sourceURL} + req.Raw().Header["x-ms-source-range"] = []string{sourceRange} + if options != nil && options.SourceContentMD5 != nil { + req.Raw().Header["x-ms-source-content-md5"] = []string{base64.StdEncoding.EncodeToString(options.SourceContentMD5)} + } + if options != nil && options.SourceContentcrc64 != nil { + req.Raw().Header["x-ms-source-content-crc64"] = []string{base64.StdEncoding.EncodeToString(options.SourceContentcrc64)} + } + req.Raw().Header["Content-Length"] = []string{strconv.FormatInt(contentLength, 10)} + req.Raw().Header["x-ms-range"] = []string{rangeParam} + if cpkInfo != nil && cpkInfo.EncryptionKey != nil { + req.Raw().Header["x-ms-encryption-key"] = []string{*cpkInfo.EncryptionKey} + } + if cpkInfo != nil && cpkInfo.EncryptionKeySHA256 != nil { + req.Raw().Header["x-ms-encryption-key-sha256"] = []string{*cpkInfo.EncryptionKeySHA256} + } + if cpkInfo != nil && cpkInfo.EncryptionAlgorithm != nil { + req.Raw().Header["x-ms-encryption-algorithm"] = []string{string(*cpkInfo.EncryptionAlgorithm)} + } + if cpkScopeInfo != nil && cpkScopeInfo.EncryptionScope != nil { + req.Raw().Header["x-ms-encryption-scope"] = []string{*cpkScopeInfo.EncryptionScope} + } + if leaseAccessConditions != nil && leaseAccessConditions.LeaseID != nil { + req.Raw().Header["x-ms-lease-id"] = []string{*leaseAccessConditions.LeaseID} + } + if sequenceNumberAccessConditions != nil && sequenceNumberAccessConditions.IfSequenceNumberLessThanOrEqualTo != nil { + req.Raw().Header["x-ms-if-sequence-number-le"] = []string{strconv.FormatInt(*sequenceNumberAccessConditions.IfSequenceNumberLessThanOrEqualTo, 10)} + } + if sequenceNumberAccessConditions != nil && sequenceNumberAccessConditions.IfSequenceNumberLessThan != nil { + req.Raw().Header["x-ms-if-sequence-number-lt"] = []string{strconv.FormatInt(*sequenceNumberAccessConditions.IfSequenceNumberLessThan, 10)} + } + if sequenceNumberAccessConditions != nil && sequenceNumberAccessConditions.IfSequenceNumberEqualTo != nil { + req.Raw().Header["x-ms-if-sequence-number-eq"] = []string{strconv.FormatInt(*sequenceNumberAccessConditions.IfSequenceNumberEqualTo, 10)} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfModifiedSince != nil { + req.Raw().Header["If-Modified-Since"] = []string{(*modifiedAccessConditions.IfModifiedSince).In(gmt).Format(time.RFC1123)} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfUnmodifiedSince != nil { + req.Raw().Header["If-Unmodified-Since"] = []string{(*modifiedAccessConditions.IfUnmodifiedSince).In(gmt).Format(time.RFC1123)} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfMatch != nil { + req.Raw().Header["If-Match"] = []string{string(*modifiedAccessConditions.IfMatch)} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfNoneMatch != nil { + req.Raw().Header["If-None-Match"] = []string{string(*modifiedAccessConditions.IfNoneMatch)} + } + if modifiedAccessConditions != nil && modifiedAccessConditions.IfTags != nil { + req.Raw().Header["x-ms-if-tags"] = []string{*modifiedAccessConditions.IfTags} + } + if sourceModifiedAccessConditions != nil && sourceModifiedAccessConditions.SourceIfModifiedSince != nil { + req.Raw().Header["x-ms-source-if-modified-since"] = []string{(*sourceModifiedAccessConditions.SourceIfModifiedSince).In(gmt).Format(time.RFC1123)} + } + if sourceModifiedAccessConditions != nil && sourceModifiedAccessConditions.SourceIfUnmodifiedSince != nil { + req.Raw().Header["x-ms-source-if-unmodified-since"] = []string{(*sourceModifiedAccessConditions.SourceIfUnmodifiedSince).In(gmt).Format(time.RFC1123)} + } + if sourceModifiedAccessConditions != nil && sourceModifiedAccessConditions.SourceIfMatch != nil { + req.Raw().Header["x-ms-source-if-match"] = []string{string(*sourceModifiedAccessConditions.SourceIfMatch)} + } + if sourceModifiedAccessConditions != nil && sourceModifiedAccessConditions.SourceIfNoneMatch != nil { + req.Raw().Header["x-ms-source-if-none-match"] = []string{string(*sourceModifiedAccessConditions.SourceIfNoneMatch)} + } + req.Raw().Header["x-ms-version"] = []string{"2020-10-02"} + if options != nil && options.RequestID != nil { + req.Raw().Header["x-ms-client-request-id"] = []string{*options.RequestID} + } + if options != nil && options.CopySourceAuthorization != nil { + req.Raw().Header["x-ms-copy-source-authorization"] = []string{*options.CopySourceAuthorization} + } + req.Raw().Header["Accept"] = []string{"application/xml"} + return req, nil +} + +// uploadPagesFromURLHandleResponse handles the UploadPagesFromURL response. +func (client *PageBlobClient) uploadPagesFromURLHandleResponse(resp *http.Response) (PageBlobClientUploadPagesFromURLResponse, error) { + result := PageBlobClientUploadPagesFromURLResponse{} + if val := resp.Header.Get("ETag"); val != "" { + result.ETag = (*azcore.ETag)(&val) + } + if val := resp.Header.Get("Last-Modified"); val != "" { + lastModified, err := time.Parse(time.RFC1123, val) + if err != nil { + return PageBlobClientUploadPagesFromURLResponse{}, err + } + result.LastModified = &lastModified + } + if val := resp.Header.Get("Content-MD5"); val != "" { + contentMD5, err := base64.StdEncoding.DecodeString(val) + if err != nil { + return PageBlobClientUploadPagesFromURLResponse{}, err + } + result.ContentMD5 = contentMD5 + } + if val := resp.Header.Get("x-ms-content-crc64"); val != "" { + contentCRC64, err := base64.StdEncoding.DecodeString(val) + if err != nil { + return PageBlobClientUploadPagesFromURLResponse{}, err + } + result.ContentCRC64 = contentCRC64 + } + if val := resp.Header.Get("x-ms-blob-sequence-number"); val != "" { + blobSequenceNumber, err := strconv.ParseInt(val, 10, 64) + if err != nil { + return PageBlobClientUploadPagesFromURLResponse{}, err + } + result.BlobSequenceNumber = &blobSequenceNumber + } + if val := resp.Header.Get("x-ms-request-id"); val != "" { + result.RequestID = &val + } + if val := resp.Header.Get("x-ms-version"); val != "" { + result.Version = &val + } + if val := resp.Header.Get("Date"); val != "" { + date, err := time.Parse(time.RFC1123, val) + if err != nil { + return PageBlobClientUploadPagesFromURLResponse{}, err + } + result.Date = &date + } + if val := resp.Header.Get("x-ms-request-server-encrypted"); val != "" { + isServerEncrypted, err := strconv.ParseBool(val) + if err != nil { + return PageBlobClientUploadPagesFromURLResponse{}, err + } + result.IsServerEncrypted = &isServerEncrypted + } + if val := resp.Header.Get("x-ms-encryption-key-sha256"); val != "" { + result.EncryptionKeySHA256 = &val + } + if val := resp.Header.Get("x-ms-encryption-scope"); val != "" { + result.EncryptionScope = &val + } + return result, nil +} diff --git a/sdk/storage/azdatalake/internal/generated_blob/zz_response_types.go b/sdk/storage/azdatalake/internal/generated_blob/zz_response_types.go new file mode 100644 index 000000000000..44e0bb9131df --- /dev/null +++ b/sdk/storage/azdatalake/internal/generated_blob/zz_response_types.go @@ -0,0 +1,1972 @@ +//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. +// Code generated by Microsoft (R) AutoRest Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. +// DO NOT EDIT. + +package generated_blob + +import ( + "github.com/Azure/azure-sdk-for-go/sdk/azcore" + "io" + "time" +) + +// AppendBlobClientAppendBlockFromURLResponse contains the response from method AppendBlobClient.AppendBlockFromURL. +type AppendBlobClientAppendBlockFromURLResponse struct { + // BlobAppendOffset contains the information returned from the x-ms-blob-append-offset header response. + BlobAppendOffset *string + + // BlobCommittedBlockCount contains the information returned from the x-ms-blob-committed-block-count header response. + BlobCommittedBlockCount *int32 + + // ContentCRC64 contains the information returned from the x-ms-content-crc64 header response. + ContentCRC64 []byte + + // ContentMD5 contains the information returned from the Content-MD5 header response. + ContentMD5 []byte + + // Date contains the information returned from the Date header response. + Date *time.Time + + // ETag contains the information returned from the ETag header response. + ETag *azcore.ETag + + // EncryptionKeySHA256 contains the information returned from the x-ms-encryption-key-sha256 header response. + EncryptionKeySHA256 *string + + // EncryptionScope contains the information returned from the x-ms-encryption-scope header response. + EncryptionScope *string + + // IsServerEncrypted contains the information returned from the x-ms-request-server-encrypted header response. + IsServerEncrypted *bool + + // LastModified contains the information returned from the Last-Modified header response. + LastModified *time.Time + + // RequestID contains the information returned from the x-ms-request-id header response. + RequestID *string + + // Version contains the information returned from the x-ms-version header response. + Version *string +} + +// AppendBlobClientAppendBlockResponse contains the response from method AppendBlobClient.AppendBlock. +type AppendBlobClientAppendBlockResponse struct { + // BlobAppendOffset contains the information returned from the x-ms-blob-append-offset header response. + BlobAppendOffset *string + + // BlobCommittedBlockCount contains the information returned from the x-ms-blob-committed-block-count header response. + BlobCommittedBlockCount *int32 + + // ClientRequestID contains the information returned from the x-ms-client-request-id header response. + ClientRequestID *string + + // ContentCRC64 contains the information returned from the x-ms-content-crc64 header response. + ContentCRC64 []byte + + // ContentMD5 contains the information returned from the Content-MD5 header response. + ContentMD5 []byte + + // Date contains the information returned from the Date header response. + Date *time.Time + + // ETag contains the information returned from the ETag header response. + ETag *azcore.ETag + + // EncryptionKeySHA256 contains the information returned from the x-ms-encryption-key-sha256 header response. + EncryptionKeySHA256 *string + + // EncryptionScope contains the information returned from the x-ms-encryption-scope header response. + EncryptionScope *string + + // IsServerEncrypted contains the information returned from the x-ms-request-server-encrypted header response. + IsServerEncrypted *bool + + // LastModified contains the information returned from the Last-Modified header response. + LastModified *time.Time + + // RequestID contains the information returned from the x-ms-request-id header response. + RequestID *string + + // Version contains the information returned from the x-ms-version header response. + Version *string +} + +// AppendBlobClientCreateResponse contains the response from method AppendBlobClient.Create. +type AppendBlobClientCreateResponse struct { + // ClientRequestID contains the information returned from the x-ms-client-request-id header response. + ClientRequestID *string + + // ContentMD5 contains the information returned from the Content-MD5 header response. + ContentMD5 []byte + + // Date contains the information returned from the Date header response. + Date *time.Time + + // ETag contains the information returned from the ETag header response. + ETag *azcore.ETag + + // EncryptionKeySHA256 contains the information returned from the x-ms-encryption-key-sha256 header response. + EncryptionKeySHA256 *string + + // EncryptionScope contains the information returned from the x-ms-encryption-scope header response. + EncryptionScope *string + + // IsServerEncrypted contains the information returned from the x-ms-request-server-encrypted header response. + IsServerEncrypted *bool + + // LastModified contains the information returned from the Last-Modified header response. + LastModified *time.Time + + // RequestID contains the information returned from the x-ms-request-id header response. + RequestID *string + + // Version contains the information returned from the x-ms-version header response. + Version *string + + // VersionID contains the information returned from the x-ms-version-id header response. + VersionID *string +} + +// AppendBlobClientSealResponse contains the response from method AppendBlobClient.Seal. +type AppendBlobClientSealResponse struct { + // ClientRequestID contains the information returned from the x-ms-client-request-id header response. + ClientRequestID *string + + // Date contains the information returned from the Date header response. + Date *time.Time + + // ETag contains the information returned from the ETag header response. + ETag *azcore.ETag + + // IsSealed contains the information returned from the x-ms-blob-sealed header response. + IsSealed *bool + + // LastModified contains the information returned from the Last-Modified header response. + LastModified *time.Time + + // RequestID contains the information returned from the x-ms-request-id header response. + RequestID *string + + // Version contains the information returned from the x-ms-version header response. + Version *string +} + +// BlobClientAbortCopyFromURLResponse contains the response from method BlobClient.AbortCopyFromURL. +type BlobClientAbortCopyFromURLResponse struct { + // ClientRequestID contains the information returned from the x-ms-client-request-id header response. + ClientRequestID *string + + // Date contains the information returned from the Date header response. + Date *time.Time + + // RequestID contains the information returned from the x-ms-request-id header response. + RequestID *string + + // Version contains the information returned from the x-ms-version header response. + Version *string +} + +// BlobClientAcquireLeaseResponse contains the response from method BlobClient.AcquireLease. +type BlobClientAcquireLeaseResponse struct { + // ClientRequestID contains the information returned from the x-ms-client-request-id header response. + ClientRequestID *string + + // Date contains the information returned from the Date header response. + Date *time.Time + + // ETag contains the information returned from the ETag header response. + ETag *azcore.ETag + + // LastModified contains the information returned from the Last-Modified header response. + LastModified *time.Time + + // LeaseID contains the information returned from the x-ms-lease-id header response. + LeaseID *string + + // RequestID contains the information returned from the x-ms-request-id header response. + RequestID *string + + // Version contains the information returned from the x-ms-version header response. + Version *string +} + +// BlobClientBreakLeaseResponse contains the response from method BlobClient.BreakLease. +type BlobClientBreakLeaseResponse struct { + // ClientRequestID contains the information returned from the x-ms-client-request-id header response. + ClientRequestID *string + + // Date contains the information returned from the Date header response. + Date *time.Time + + // ETag contains the information returned from the ETag header response. + ETag *azcore.ETag + + // LastModified contains the information returned from the Last-Modified header response. + LastModified *time.Time + + // LeaseTime contains the information returned from the x-ms-lease-time header response. + LeaseTime *int32 + + // RequestID contains the information returned from the x-ms-request-id header response. + RequestID *string + + // Version contains the information returned from the x-ms-version header response. + Version *string +} + +// BlobClientChangeLeaseResponse contains the response from method BlobClient.ChangeLease. +type BlobClientChangeLeaseResponse struct { + // ClientRequestID contains the information returned from the x-ms-client-request-id header response. + ClientRequestID *string + + // Date contains the information returned from the Date header response. + Date *time.Time + + // ETag contains the information returned from the ETag header response. + ETag *azcore.ETag + + // LastModified contains the information returned from the Last-Modified header response. + LastModified *time.Time + + // LeaseID contains the information returned from the x-ms-lease-id header response. + LeaseID *string + + // RequestID contains the information returned from the x-ms-request-id header response. + RequestID *string + + // Version contains the information returned from the x-ms-version header response. + Version *string +} + +// BlobClientCopyFromURLResponse contains the response from method BlobClient.CopyFromURL. +type BlobClientCopyFromURLResponse struct { + // ClientRequestID contains the information returned from the x-ms-client-request-id header response. + ClientRequestID *string + + // ContentCRC64 contains the information returned from the x-ms-content-crc64 header response. + ContentCRC64 []byte + + // ContentMD5 contains the information returned from the Content-MD5 header response. + ContentMD5 []byte + + // CopyID contains the information returned from the x-ms-copy-id header response. + CopyID *string + + // CopyStatus contains the information returned from the x-ms-copy-status header response. + CopyStatus *string + + // Date contains the information returned from the Date header response. + Date *time.Time + + // ETag contains the information returned from the ETag header response. + ETag *azcore.ETag + + // LastModified contains the information returned from the Last-Modified header response. + LastModified *time.Time + + // RequestID contains the information returned from the x-ms-request-id header response. + RequestID *string + + // Version contains the information returned from the x-ms-version header response. + Version *string + + // VersionID contains the information returned from the x-ms-version-id header response. + VersionID *string +} + +// BlobClientCreateSnapshotResponse contains the response from method BlobClient.CreateSnapshot. +type BlobClientCreateSnapshotResponse struct { + // ClientRequestID contains the information returned from the x-ms-client-request-id header response. + ClientRequestID *string + + // Date contains the information returned from the Date header response. + Date *time.Time + + // ETag contains the information returned from the ETag header response. + ETag *azcore.ETag + + // IsServerEncrypted contains the information returned from the x-ms-request-server-encrypted header response. + IsServerEncrypted *bool + + // LastModified contains the information returned from the Last-Modified header response. + LastModified *time.Time + + // RequestID contains the information returned from the x-ms-request-id header response. + RequestID *string + + // Snapshot contains the information returned from the x-ms-snapshot header response. + Snapshot *string + + // Version contains the information returned from the x-ms-version header response. + Version *string + + // VersionID contains the information returned from the x-ms-version-id header response. + VersionID *string +} + +// BlobClientDeleteImmutabilityPolicyResponse contains the response from method BlobClient.DeleteImmutabilityPolicy. +type BlobClientDeleteImmutabilityPolicyResponse struct { + // ClientRequestID contains the information returned from the x-ms-client-request-id header response. + ClientRequestID *string + + // Date contains the information returned from the Date header response. + Date *time.Time + + // RequestID contains the information returned from the x-ms-request-id header response. + RequestID *string + + // Version contains the information returned from the x-ms-version header response. + Version *string +} + +// BlobClientDeleteResponse contains the response from method BlobClient.Delete. +type BlobClientDeleteResponse struct { + // ClientRequestID contains the information returned from the x-ms-client-request-id header response. + ClientRequestID *string + + // Date contains the information returned from the Date header response. + Date *time.Time + + // RequestID contains the information returned from the x-ms-request-id header response. + RequestID *string + + // Version contains the information returned from the x-ms-version header response. + Version *string +} + +// BlobClientDownloadResponse contains the response from method BlobClient.Download. +type BlobClientDownloadResponse struct { + // AcceptRanges contains the information returned from the Accept-Ranges header response. + AcceptRanges *string + + // BlobCommittedBlockCount contains the information returned from the x-ms-blob-committed-block-count header response. + BlobCommittedBlockCount *int32 + + // BlobContentMD5 contains the information returned from the x-ms-blob-content-md5 header response. + BlobContentMD5 []byte + + // BlobSequenceNumber contains the information returned from the x-ms-blob-sequence-number header response. + BlobSequenceNumber *int64 + + // BlobType contains the information returned from the x-ms-blob-type header response. + BlobType *BlobType + + // Body contains the streaming response. + Body io.ReadCloser + + // CacheControl contains the information returned from the Cache-Control header response. + CacheControl *string + + // ClientRequestID contains the information returned from the x-ms-client-request-id header response. + ClientRequestID *string + + // ContentCRC64 contains the information returned from the x-ms-content-crc64 header response. + ContentCRC64 []byte + + // ContentDisposition contains the information returned from the Content-Disposition header response. + ContentDisposition *string + + // ContentEncoding contains the information returned from the Content-Encoding header response. + ContentEncoding *string + + // ContentLanguage contains the information returned from the Content-Language header response. + ContentLanguage *string + + // ContentLength contains the information returned from the Content-Length header response. + ContentLength *int64 + + // ContentMD5 contains the information returned from the Content-MD5 header response. + ContentMD5 []byte + + // ContentRange contains the information returned from the Content-Range header response. + ContentRange *string + + // ContentType contains the information returned from the Content-Type header response. + ContentType *string + + // CopyCompletionTime contains the information returned from the x-ms-copy-completion-time header response. + CopyCompletionTime *time.Time + + // CopyID contains the information returned from the x-ms-copy-id header response. + CopyID *string + + // CopyProgress contains the information returned from the x-ms-copy-progress header response. + CopyProgress *string + + // CopySource contains the information returned from the x-ms-copy-source header response. + CopySource *string + + // CopyStatus contains the information returned from the x-ms-copy-status header response. + CopyStatus *CopyStatusType + + // CopyStatusDescription contains the information returned from the x-ms-copy-status-description header response. + CopyStatusDescription *string + + // Date contains the information returned from the Date header response. + Date *time.Time + + // ETag contains the information returned from the ETag header response. + ETag *azcore.ETag + + // EncryptionKeySHA256 contains the information returned from the x-ms-encryption-key-sha256 header response. + EncryptionKeySHA256 *string + + // EncryptionScope contains the information returned from the x-ms-encryption-scope header response. + EncryptionScope *string + + // ErrorCode contains the information returned from the x-ms-error-code header response. + ErrorCode *string + + // ImmutabilityPolicyExpiresOn contains the information returned from the x-ms-immutability-policy-until-date header response. + ImmutabilityPolicyExpiresOn *time.Time + + // ImmutabilityPolicyMode contains the information returned from the x-ms-immutability-policy-mode header response. + ImmutabilityPolicyMode *ImmutabilityPolicyMode + + // IsCurrentVersion contains the information returned from the x-ms-is-current-version header response. + IsCurrentVersion *bool + + // IsSealed contains the information returned from the x-ms-blob-sealed header response. + IsSealed *bool + + // IsServerEncrypted contains the information returned from the x-ms-server-encrypted header response. + IsServerEncrypted *bool + + // LastAccessed contains the information returned from the x-ms-last-access-time header response. + LastAccessed *time.Time + + // LastModified contains the information returned from the Last-Modified header response. + LastModified *time.Time + + // LeaseDuration contains the information returned from the x-ms-lease-duration header response. + LeaseDuration *LeaseDurationType + + // LeaseState contains the information returned from the x-ms-lease-state header response. + LeaseState *LeaseStateType + + // LeaseStatus contains the information returned from the x-ms-lease-status header response. + LeaseStatus *LeaseStatusType + + // LegalHold contains the information returned from the x-ms-legal-hold header response. + LegalHold *bool + + // Metadata contains the information returned from the x-ms-meta header response. + Metadata map[string]*string + + // ObjectReplicationPolicyID contains the information returned from the x-ms-or-policy-id header response. + ObjectReplicationPolicyID *string + + // ObjectReplicationRules contains the information returned from the x-ms-or header response. + ObjectReplicationRules map[string]*string + + // RequestID contains the information returned from the x-ms-request-id header response. + RequestID *string + + // TagCount contains the information returned from the x-ms-tag-count header response. + TagCount *int64 + + // Version contains the information returned from the x-ms-version header response. + Version *string + + // VersionID contains the information returned from the x-ms-version-id header response. + VersionID *string +} + +// BlobClientGetAccountInfoResponse contains the response from method BlobClient.GetAccountInfo. +type BlobClientGetAccountInfoResponse struct { + // AccountKind contains the information returned from the x-ms-account-kind header response. + AccountKind *AccountKind + + // ClientRequestID contains the information returned from the x-ms-client-request-id header response. + ClientRequestID *string + + // Date contains the information returned from the Date header response. + Date *time.Time + + // RequestID contains the information returned from the x-ms-request-id header response. + RequestID *string + + // SKUName contains the information returned from the x-ms-sku-name header response. + SKUName *SKUName + + // Version contains the information returned from the x-ms-version header response. + Version *string +} + +// BlobClientGetPropertiesResponse contains the response from method BlobClient.GetProperties. +type BlobClientGetPropertiesResponse struct { + // AcceptRanges contains the information returned from the Accept-Ranges header response. + AcceptRanges *string + + // AccessTier contains the information returned from the x-ms-access-tier header response. + AccessTier *string + + // AccessTierChangeTime contains the information returned from the x-ms-access-tier-change-time header response. + AccessTierChangeTime *time.Time + + // AccessTierInferred contains the information returned from the x-ms-access-tier-inferred header response. + AccessTierInferred *bool + + // ArchiveStatus contains the information returned from the x-ms-archive-status header response. + ArchiveStatus *string + + // BlobCommittedBlockCount contains the information returned from the x-ms-blob-committed-block-count header response. + BlobCommittedBlockCount *int32 + + // BlobSequenceNumber contains the information returned from the x-ms-blob-sequence-number header response. + BlobSequenceNumber *int64 + + // BlobType contains the information returned from the x-ms-blob-type header response. + BlobType *BlobType + + // CacheControl contains the information returned from the Cache-Control header response. + CacheControl *string + + // ClientRequestID contains the information returned from the x-ms-client-request-id header response. + ClientRequestID *string + + // ContentDisposition contains the information returned from the Content-Disposition header response. + ContentDisposition *string + + // ContentEncoding contains the information returned from the Content-Encoding header response. + ContentEncoding *string + + // ContentLanguage contains the information returned from the Content-Language header response. + ContentLanguage *string + + // ContentLength contains the information returned from the Content-Length header response. + ContentLength *int64 + + // ContentMD5 contains the information returned from the Content-MD5 header response. + ContentMD5 []byte + + // ContentType contains the information returned from the Content-Type header response. + ContentType *string + + // CopyCompletionTime contains the information returned from the x-ms-copy-completion-time header response. + CopyCompletionTime *time.Time + + // CopyID contains the information returned from the x-ms-copy-id header response. + CopyID *string + + // CopyProgress contains the information returned from the x-ms-copy-progress header response. + CopyProgress *string + + // CopySource contains the information returned from the x-ms-copy-source header response. + CopySource *string + + // CopyStatus contains the information returned from the x-ms-copy-status header response. + CopyStatus *CopyStatusType + + // CopyStatusDescription contains the information returned from the x-ms-copy-status-description header response. + CopyStatusDescription *string + + // CreationTime contains the information returned from the x-ms-creation-time header response. + CreationTime *time.Time + + // Date contains the information returned from the Date header response. + Date *time.Time + + // DestinationSnapshot contains the information returned from the x-ms-copy-destination-snapshot header response. + DestinationSnapshot *string + + // ETag contains the information returned from the ETag header response. + ETag *azcore.ETag + + // EncryptionKeySHA256 contains the information returned from the x-ms-encryption-key-sha256 header response. + EncryptionKeySHA256 *string + + // EncryptionScope contains the information returned from the x-ms-encryption-scope header response. + EncryptionScope *string + + // ExpiresOn contains the information returned from the x-ms-expiry-time header response. + ExpiresOn *time.Time + + // ImmutabilityPolicyExpiresOn contains the information returned from the x-ms-immutability-policy-until-date header response. + ImmutabilityPolicyExpiresOn *time.Time + + // ImmutabilityPolicyMode contains the information returned from the x-ms-immutability-policy-mode header response. + ImmutabilityPolicyMode *ImmutabilityPolicyMode + + // IsCurrentVersion contains the information returned from the x-ms-is-current-version header response. + IsCurrentVersion *bool + + // IsIncrementalCopy contains the information returned from the x-ms-incremental-copy header response. + IsIncrementalCopy *bool + + // IsSealed contains the information returned from the x-ms-blob-sealed header response. + IsSealed *bool + + // IsServerEncrypted contains the information returned from the x-ms-server-encrypted header response. + IsServerEncrypted *bool + + // LastAccessed contains the information returned from the x-ms-last-access-time header response. + LastAccessed *time.Time + + // LastModified contains the information returned from the Last-Modified header response. + LastModified *time.Time + + // LeaseDuration contains the information returned from the x-ms-lease-duration header response. + LeaseDuration *LeaseDurationType + + // LeaseState contains the information returned from the x-ms-lease-state header response. + LeaseState *LeaseStateType + + // LeaseStatus contains the information returned from the x-ms-lease-status header response. + LeaseStatus *LeaseStatusType + + // LegalHold contains the information returned from the x-ms-legal-hold header response. + LegalHold *bool + + // Metadata contains the information returned from the x-ms-meta header response. + Metadata map[string]*string + + // ObjectReplicationPolicyID contains the information returned from the x-ms-or-policy-id header response. + ObjectReplicationPolicyID *string + + // ObjectReplicationRules contains the information returned from the x-ms-or header response. + ObjectReplicationRules map[string]*string + + // RehydratePriority contains the information returned from the x-ms-rehydrate-priority header response. + RehydratePriority *string + + // RequestID contains the information returned from the x-ms-request-id header response. + RequestID *string + + // TagCount contains the information returned from the x-ms-tag-count header response. + TagCount *int64 + + // Version contains the information returned from the x-ms-version header response. + Version *string + + // VersionID contains the information returned from the x-ms-version-id header response. + VersionID *string +} + +// BlobClientGetTagsResponse contains the response from method BlobClient.GetTags. +type BlobClientGetTagsResponse struct { + BlobTags + // ClientRequestID contains the information returned from the x-ms-client-request-id header response. + ClientRequestID *string `xml:"ClientRequestID"` + + // Date contains the information returned from the Date header response. + Date *time.Time `xml:"Date"` + + // RequestID contains the information returned from the x-ms-request-id header response. + RequestID *string `xml:"RequestID"` + + // Version contains the information returned from the x-ms-version header response. + Version *string `xml:"Version"` +} + +// BlobClientQueryResponse contains the response from method BlobClient.Query. +type BlobClientQueryResponse struct { + // AcceptRanges contains the information returned from the Accept-Ranges header response. + AcceptRanges *string + + // BlobCommittedBlockCount contains the information returned from the x-ms-blob-committed-block-count header response. + BlobCommittedBlockCount *int32 + + // BlobContentMD5 contains the information returned from the x-ms-blob-content-md5 header response. + BlobContentMD5 []byte + + // BlobSequenceNumber contains the information returned from the x-ms-blob-sequence-number header response. + BlobSequenceNumber *int64 + + // BlobType contains the information returned from the x-ms-blob-type header response. + BlobType *BlobType + + // Body contains the streaming response. + Body io.ReadCloser + + // CacheControl contains the information returned from the Cache-Control header response. + CacheControl *string + + // ClientRequestID contains the information returned from the x-ms-client-request-id header response. + ClientRequestID *string + + // ContentCRC64 contains the information returned from the x-ms-content-crc64 header response. + ContentCRC64 []byte + + // ContentDisposition contains the information returned from the Content-Disposition header response. + ContentDisposition *string + + // ContentEncoding contains the information returned from the Content-Encoding header response. + ContentEncoding *string + + // ContentLanguage contains the information returned from the Content-Language header response. + ContentLanguage *string + + // ContentLength contains the information returned from the Content-Length header response. + ContentLength *int64 + + // ContentMD5 contains the information returned from the Content-MD5 header response. + ContentMD5 []byte + + // ContentRange contains the information returned from the Content-Range header response. + ContentRange *string + + // ContentType contains the information returned from the Content-Type header response. + ContentType *string + + // CopyCompletionTime contains the information returned from the x-ms-copy-completion-time header response. + CopyCompletionTime *time.Time + + // CopyID contains the information returned from the x-ms-copy-id header response. + CopyID *string + + // CopyProgress contains the information returned from the x-ms-copy-progress header response. + CopyProgress *string + + // CopySource contains the information returned from the x-ms-copy-source header response. + CopySource *string + + // CopyStatus contains the information returned from the x-ms-copy-status header response. + CopyStatus *CopyStatusType + + // CopyStatusDescription contains the information returned from the x-ms-copy-status-description header response. + CopyStatusDescription *string + + // Date contains the information returned from the Date header response. + Date *time.Time + + // ETag contains the information returned from the ETag header response. + ETag *azcore.ETag + + // EncryptionKeySHA256 contains the information returned from the x-ms-encryption-key-sha256 header response. + EncryptionKeySHA256 *string + + // EncryptionScope contains the information returned from the x-ms-encryption-scope header response. + EncryptionScope *string + + // IsServerEncrypted contains the information returned from the x-ms-server-encrypted header response. + IsServerEncrypted *bool + + // LastModified contains the information returned from the Last-Modified header response. + LastModified *time.Time + + // LeaseDuration contains the information returned from the x-ms-lease-duration header response. + LeaseDuration *LeaseDurationType + + // LeaseState contains the information returned from the x-ms-lease-state header response. + LeaseState *LeaseStateType + + // LeaseStatus contains the information returned from the x-ms-lease-status header response. + LeaseStatus *LeaseStatusType + + // Metadata contains the information returned from the x-ms-meta header response. + Metadata map[string]*string + + // RequestID contains the information returned from the x-ms-request-id header response. + RequestID *string + + // Version contains the information returned from the x-ms-version header response. + Version *string +} + +// BlobClientReleaseLeaseResponse contains the response from method BlobClient.ReleaseLease. +type BlobClientReleaseLeaseResponse struct { + // ClientRequestID contains the information returned from the x-ms-client-request-id header response. + ClientRequestID *string + + // Date contains the information returned from the Date header response. + Date *time.Time + + // ETag contains the information returned from the ETag header response. + ETag *azcore.ETag + + // LastModified contains the information returned from the Last-Modified header response. + LastModified *time.Time + + // RequestID contains the information returned from the x-ms-request-id header response. + RequestID *string + + // Version contains the information returned from the x-ms-version header response. + Version *string +} + +// BlobClientRenewLeaseResponse contains the response from method BlobClient.RenewLease. +type BlobClientRenewLeaseResponse struct { + // ClientRequestID contains the information returned from the x-ms-client-request-id header response. + ClientRequestID *string + + // Date contains the information returned from the Date header response. + Date *time.Time + + // ETag contains the information returned from the ETag header response. + ETag *azcore.ETag + + // LastModified contains the information returned from the Last-Modified header response. + LastModified *time.Time + + // LeaseID contains the information returned from the x-ms-lease-id header response. + LeaseID *string + + // RequestID contains the information returned from the x-ms-request-id header response. + RequestID *string + + // Version contains the information returned from the x-ms-version header response. + Version *string +} + +// BlobClientSetExpiryResponse contains the response from method BlobClient.SetExpiry. +type BlobClientSetExpiryResponse struct { + // ClientRequestID contains the information returned from the x-ms-client-request-id header response. + ClientRequestID *string + + // Date contains the information returned from the Date header response. + Date *time.Time + + // ETag contains the information returned from the ETag header response. + ETag *azcore.ETag + + // LastModified contains the information returned from the Last-Modified header response. + LastModified *time.Time + + // RequestID contains the information returned from the x-ms-request-id header response. + RequestID *string + + // Version contains the information returned from the x-ms-version header response. + Version *string +} + +// BlobClientSetHTTPHeadersResponse contains the response from method BlobClient.SetHTTPHeaders. +type BlobClientSetHTTPHeadersResponse struct { + // BlobSequenceNumber contains the information returned from the x-ms-blob-sequence-number header response. + BlobSequenceNumber *int64 + + // ClientRequestID contains the information returned from the x-ms-client-request-id header response. + ClientRequestID *string + + // Date contains the information returned from the Date header response. + Date *time.Time + + // ETag contains the information returned from the ETag header response. + ETag *azcore.ETag + + // LastModified contains the information returned from the Last-Modified header response. + LastModified *time.Time + + // RequestID contains the information returned from the x-ms-request-id header response. + RequestID *string + + // Version contains the information returned from the x-ms-version header response. + Version *string +} + +// BlobClientSetImmutabilityPolicyResponse contains the response from method BlobClient.SetImmutabilityPolicy. +type BlobClientSetImmutabilityPolicyResponse struct { + // ClientRequestID contains the information returned from the x-ms-client-request-id header response. + ClientRequestID *string + + // Date contains the information returned from the Date header response. + Date *time.Time + + // ImmutabilityPolicyExpiry contains the information returned from the x-ms-immutability-policy-until-date header response. + ImmutabilityPolicyExpiry *time.Time + + // ImmutabilityPolicyMode contains the information returned from the x-ms-immutability-policy-mode header response. + ImmutabilityPolicyMode *ImmutabilityPolicyMode + + // RequestID contains the information returned from the x-ms-request-id header response. + RequestID *string + + // Version contains the information returned from the x-ms-version header response. + Version *string +} + +// BlobClientSetLegalHoldResponse contains the response from method BlobClient.SetLegalHold. +type BlobClientSetLegalHoldResponse struct { + // ClientRequestID contains the information returned from the x-ms-client-request-id header response. + ClientRequestID *string + + // Date contains the information returned from the Date header response. + Date *time.Time + + // LegalHold contains the information returned from the x-ms-legal-hold header response. + LegalHold *bool + + // RequestID contains the information returned from the x-ms-request-id header response. + RequestID *string + + // Version contains the information returned from the x-ms-version header response. + Version *string +} + +// BlobClientSetMetadataResponse contains the response from method BlobClient.SetMetadata. +type BlobClientSetMetadataResponse struct { + // ClientRequestID contains the information returned from the x-ms-client-request-id header response. + ClientRequestID *string + + // Date contains the information returned from the Date header response. + Date *time.Time + + // ETag contains the information returned from the ETag header response. + ETag *azcore.ETag + + // EncryptionKeySHA256 contains the information returned from the x-ms-encryption-key-sha256 header response. + EncryptionKeySHA256 *string + + // EncryptionScope contains the information returned from the x-ms-encryption-scope header response. + EncryptionScope *string + + // IsServerEncrypted contains the information returned from the x-ms-request-server-encrypted header response. + IsServerEncrypted *bool + + // LastModified contains the information returned from the Last-Modified header response. + LastModified *time.Time + + // RequestID contains the information returned from the x-ms-request-id header response. + RequestID *string + + // Version contains the information returned from the x-ms-version header response. + Version *string + + // VersionID contains the information returned from the x-ms-version-id header response. + VersionID *string +} + +// BlobClientSetTagsResponse contains the response from method BlobClient.SetTags. +type BlobClientSetTagsResponse struct { + // ClientRequestID contains the information returned from the x-ms-client-request-id header response. + ClientRequestID *string + + // Date contains the information returned from the Date header response. + Date *time.Time + + // RequestID contains the information returned from the x-ms-request-id header response. + RequestID *string + + // Version contains the information returned from the x-ms-version header response. + Version *string +} + +// BlobClientSetTierResponse contains the response from method BlobClient.SetTier. +type BlobClientSetTierResponse struct { + // ClientRequestID contains the information returned from the x-ms-client-request-id header response. + ClientRequestID *string + + // RequestID contains the information returned from the x-ms-request-id header response. + RequestID *string + + // Version contains the information returned from the x-ms-version header response. + Version *string +} + +// BlobClientStartCopyFromURLResponse contains the response from method BlobClient.StartCopyFromURL. +type BlobClientStartCopyFromURLResponse struct { + // ClientRequestID contains the information returned from the x-ms-client-request-id header response. + ClientRequestID *string + + // CopyID contains the information returned from the x-ms-copy-id header response. + CopyID *string + + // CopyStatus contains the information returned from the x-ms-copy-status header response. + CopyStatus *CopyStatusType + + // Date contains the information returned from the Date header response. + Date *time.Time + + // ETag contains the information returned from the ETag header response. + ETag *azcore.ETag + + // LastModified contains the information returned from the Last-Modified header response. + LastModified *time.Time + + // RequestID contains the information returned from the x-ms-request-id header response. + RequestID *string + + // Version contains the information returned from the x-ms-version header response. + Version *string + + // VersionID contains the information returned from the x-ms-version-id header response. + VersionID *string +} + +// BlobClientUndeleteResponse contains the response from method BlobClient.Undelete. +type BlobClientUndeleteResponse struct { + // ClientRequestID contains the information returned from the x-ms-client-request-id header response. + ClientRequestID *string + + // Date contains the information returned from the Date header response. + Date *time.Time + + // RequestID contains the information returned from the x-ms-request-id header response. + RequestID *string + + // Version contains the information returned from the x-ms-version header response. + Version *string +} + +// BlockBlobClientCommitBlockListResponse contains the response from method BlockBlobClient.CommitBlockList. +type BlockBlobClientCommitBlockListResponse struct { + // ClientRequestID contains the information returned from the x-ms-client-request-id header response. + ClientRequestID *string + + // ContentCRC64 contains the information returned from the x-ms-content-crc64 header response. + ContentCRC64 []byte + + // ContentMD5 contains the information returned from the Content-MD5 header response. + ContentMD5 []byte + + // Date contains the information returned from the Date header response. + Date *time.Time + + // ETag contains the information returned from the ETag header response. + ETag *azcore.ETag + + // EncryptionKeySHA256 contains the information returned from the x-ms-encryption-key-sha256 header response. + EncryptionKeySHA256 *string + + // EncryptionScope contains the information returned from the x-ms-encryption-scope header response. + EncryptionScope *string + + // IsServerEncrypted contains the information returned from the x-ms-request-server-encrypted header response. + IsServerEncrypted *bool + + // LastModified contains the information returned from the Last-Modified header response. + LastModified *time.Time + + // RequestID contains the information returned from the x-ms-request-id header response. + RequestID *string + + // Version contains the information returned from the x-ms-version header response. + Version *string + + // VersionID contains the information returned from the x-ms-version-id header response. + VersionID *string +} + +// BlockBlobClientGetBlockListResponse contains the response from method BlockBlobClient.GetBlockList. +type BlockBlobClientGetBlockListResponse struct { + BlockList + // BlobContentLength contains the information returned from the x-ms-blob-content-length header response. + BlobContentLength *int64 `xml:"BlobContentLength"` + + // ClientRequestID contains the information returned from the x-ms-client-request-id header response. + ClientRequestID *string `xml:"ClientRequestID"` + + // ContentType contains the information returned from the Content-Type header response. + ContentType *string `xml:"ContentType"` + + // Date contains the information returned from the Date header response. + Date *time.Time `xml:"Date"` + + // ETag contains the information returned from the ETag header response. + ETag *azcore.ETag `xml:"ETag"` + + // LastModified contains the information returned from the Last-Modified header response. + LastModified *time.Time `xml:"LastModified"` + + // RequestID contains the information returned from the x-ms-request-id header response. + RequestID *string `xml:"RequestID"` + + // Version contains the information returned from the x-ms-version header response. + Version *string `xml:"Version"` +} + +// BlockBlobClientPutBlobFromURLResponse contains the response from method BlockBlobClient.PutBlobFromURL. +type BlockBlobClientPutBlobFromURLResponse struct { + // ClientRequestID contains the information returned from the x-ms-client-request-id header response. + ClientRequestID *string + + // ContentMD5 contains the information returned from the Content-MD5 header response. + ContentMD5 []byte + + // Date contains the information returned from the Date header response. + Date *time.Time + + // ETag contains the information returned from the ETag header response. + ETag *azcore.ETag + + // EncryptionKeySHA256 contains the information returned from the x-ms-encryption-key-sha256 header response. + EncryptionKeySHA256 *string + + // EncryptionScope contains the information returned from the x-ms-encryption-scope header response. + EncryptionScope *string + + // IsServerEncrypted contains the information returned from the x-ms-request-server-encrypted header response. + IsServerEncrypted *bool + + // LastModified contains the information returned from the Last-Modified header response. + LastModified *time.Time + + // RequestID contains the information returned from the x-ms-request-id header response. + RequestID *string + + // Version contains the information returned from the x-ms-version header response. + Version *string + + // VersionID contains the information returned from the x-ms-version-id header response. + VersionID *string +} + +// BlockBlobClientStageBlockFromURLResponse contains the response from method BlockBlobClient.StageBlockFromURL. +type BlockBlobClientStageBlockFromURLResponse struct { + // ClientRequestID contains the information returned from the x-ms-client-request-id header response. + ClientRequestID *string + + // ContentCRC64 contains the information returned from the x-ms-content-crc64 header response. + ContentCRC64 []byte + + // ContentMD5 contains the information returned from the Content-MD5 header response. + ContentMD5 []byte + + // Date contains the information returned from the Date header response. + Date *time.Time + + // EncryptionKeySHA256 contains the information returned from the x-ms-encryption-key-sha256 header response. + EncryptionKeySHA256 *string + + // EncryptionScope contains the information returned from the x-ms-encryption-scope header response. + EncryptionScope *string + + // IsServerEncrypted contains the information returned from the x-ms-request-server-encrypted header response. + IsServerEncrypted *bool + + // RequestID contains the information returned from the x-ms-request-id header response. + RequestID *string + + // Version contains the information returned from the x-ms-version header response. + Version *string +} + +// BlockBlobClientStageBlockResponse contains the response from method BlockBlobClient.StageBlock. +type BlockBlobClientStageBlockResponse struct { + // ClientRequestID contains the information returned from the x-ms-client-request-id header response. + ClientRequestID *string + + // ContentCRC64 contains the information returned from the x-ms-content-crc64 header response. + ContentCRC64 []byte + + // ContentMD5 contains the information returned from the Content-MD5 header response. + ContentMD5 []byte + + // Date contains the information returned from the Date header response. + Date *time.Time + + // EncryptionKeySHA256 contains the information returned from the x-ms-encryption-key-sha256 header response. + EncryptionKeySHA256 *string + + // EncryptionScope contains the information returned from the x-ms-encryption-scope header response. + EncryptionScope *string + + // IsServerEncrypted contains the information returned from the x-ms-request-server-encrypted header response. + IsServerEncrypted *bool + + // RequestID contains the information returned from the x-ms-request-id header response. + RequestID *string + + // Version contains the information returned from the x-ms-version header response. + Version *string +} + +// BlockBlobClientUploadResponse contains the response from method BlockBlobClient.Upload. +type BlockBlobClientUploadResponse struct { + // ClientRequestID contains the information returned from the x-ms-client-request-id header response. + ClientRequestID *string + + // ContentMD5 contains the information returned from the Content-MD5 header response. + ContentMD5 []byte + + // Date contains the information returned from the Date header response. + Date *time.Time + + // ETag contains the information returned from the ETag header response. + ETag *azcore.ETag + + // EncryptionKeySHA256 contains the information returned from the x-ms-encryption-key-sha256 header response. + EncryptionKeySHA256 *string + + // EncryptionScope contains the information returned from the x-ms-encryption-scope header response. + EncryptionScope *string + + // IsServerEncrypted contains the information returned from the x-ms-request-server-encrypted header response. + IsServerEncrypted *bool + + // LastModified contains the information returned from the Last-Modified header response. + LastModified *time.Time + + // RequestID contains the information returned from the x-ms-request-id header response. + RequestID *string + + // Version contains the information returned from the x-ms-version header response. + Version *string + + // VersionID contains the information returned from the x-ms-version-id header response. + VersionID *string +} + +// ContainerClientAcquireLeaseResponse contains the response from method ContainerClient.AcquireLease. +type ContainerClientAcquireLeaseResponse struct { + // ClientRequestID contains the information returned from the x-ms-client-request-id header response. + ClientRequestID *string + + // Date contains the information returned from the Date header response. + Date *time.Time + + // ETag contains the information returned from the ETag header response. + ETag *azcore.ETag + + // LastModified contains the information returned from the Last-Modified header response. + LastModified *time.Time + + // LeaseID contains the information returned from the x-ms-lease-id header response. + LeaseID *string + + // RequestID contains the information returned from the x-ms-request-id header response. + RequestID *string + + // Version contains the information returned from the x-ms-version header response. + Version *string +} + +// ContainerClientBreakLeaseResponse contains the response from method ContainerClient.BreakLease. +type ContainerClientBreakLeaseResponse struct { + // ClientRequestID contains the information returned from the x-ms-client-request-id header response. + ClientRequestID *string + + // Date contains the information returned from the Date header response. + Date *time.Time + + // ETag contains the information returned from the ETag header response. + ETag *azcore.ETag + + // LastModified contains the information returned from the Last-Modified header response. + LastModified *time.Time + + // LeaseTime contains the information returned from the x-ms-lease-time header response. + LeaseTime *int32 + + // RequestID contains the information returned from the x-ms-request-id header response. + RequestID *string + + // Version contains the information returned from the x-ms-version header response. + Version *string +} + +// ContainerClientChangeLeaseResponse contains the response from method ContainerClient.ChangeLease. +type ContainerClientChangeLeaseResponse struct { + // ClientRequestID contains the information returned from the x-ms-client-request-id header response. + ClientRequestID *string + + // Date contains the information returned from the Date header response. + Date *time.Time + + // ETag contains the information returned from the ETag header response. + ETag *azcore.ETag + + // LastModified contains the information returned from the Last-Modified header response. + LastModified *time.Time + + // LeaseID contains the information returned from the x-ms-lease-id header response. + LeaseID *string + + // RequestID contains the information returned from the x-ms-request-id header response. + RequestID *string + + // Version contains the information returned from the x-ms-version header response. + Version *string +} + +// ContainerClientCreateResponse contains the response from method ContainerClient.Create. +type ContainerClientCreateResponse struct { + // ClientRequestID contains the information returned from the x-ms-client-request-id header response. + ClientRequestID *string + + // Date contains the information returned from the Date header response. + Date *time.Time + + // ETag contains the information returned from the ETag header response. + ETag *azcore.ETag + + // LastModified contains the information returned from the Last-Modified header response. + LastModified *time.Time + + // RequestID contains the information returned from the x-ms-request-id header response. + RequestID *string + + // Version contains the information returned from the x-ms-version header response. + Version *string +} + +// ContainerClientDeleteResponse contains the response from method ContainerClient.Delete. +type ContainerClientDeleteResponse struct { + // ClientRequestID contains the information returned from the x-ms-client-request-id header response. + ClientRequestID *string + + // Date contains the information returned from the Date header response. + Date *time.Time + + // RequestID contains the information returned from the x-ms-request-id header response. + RequestID *string + + // Version contains the information returned from the x-ms-version header response. + Version *string +} + +// ContainerClientGetAccessPolicyResponse contains the response from method ContainerClient.GetAccessPolicy. +type ContainerClientGetAccessPolicyResponse struct { + // BlobPublicAccess contains the information returned from the x-ms-blob-public-access header response. + BlobPublicAccess *PublicAccessType `xml:"BlobPublicAccess"` + + // ClientRequestID contains the information returned from the x-ms-client-request-id header response. + ClientRequestID *string `xml:"ClientRequestID"` + + // Date contains the information returned from the Date header response. + Date *time.Time `xml:"Date"` + + // ETag contains the information returned from the ETag header response. + ETag *azcore.ETag `xml:"ETag"` + + // LastModified contains the information returned from the Last-Modified header response. + LastModified *time.Time `xml:"LastModified"` + + // RequestID contains the information returned from the x-ms-request-id header response. + RequestID *string `xml:"RequestID"` + + // a collection of signed identifiers + SignedIdentifiers []*SignedIdentifier `xml:"SignedIdentifier"` + + // Version contains the information returned from the x-ms-version header response. + Version *string `xml:"Version"` +} + +// ContainerClientGetAccountInfoResponse contains the response from method ContainerClient.GetAccountInfo. +type ContainerClientGetAccountInfoResponse struct { + // AccountKind contains the information returned from the x-ms-account-kind header response. + AccountKind *AccountKind + + // ClientRequestID contains the information returned from the x-ms-client-request-id header response. + ClientRequestID *string + + // Date contains the information returned from the Date header response. + Date *time.Time + + // RequestID contains the information returned from the x-ms-request-id header response. + RequestID *string + + // SKUName contains the information returned from the x-ms-sku-name header response. + SKUName *SKUName + + // Version contains the information returned from the x-ms-version header response. + Version *string +} + +// ContainerClientGetPropertiesResponse contains the response from method ContainerClient.GetProperties. +type ContainerClientGetPropertiesResponse struct { + // BlobPublicAccess contains the information returned from the x-ms-blob-public-access header response. + BlobPublicAccess *PublicAccessType + + // ClientRequestID contains the information returned from the x-ms-client-request-id header response. + ClientRequestID *string + + // Date contains the information returned from the Date header response. + Date *time.Time + + // DefaultEncryptionScope contains the information returned from the x-ms-default-encryption-scope header response. + DefaultEncryptionScope *string + + // DenyEncryptionScopeOverride contains the information returned from the x-ms-deny-encryption-scope-override header response. + DenyEncryptionScopeOverride *bool + + // ETag contains the information returned from the ETag header response. + ETag *azcore.ETag + + // HasImmutabilityPolicy contains the information returned from the x-ms-has-immutability-policy header response. + HasImmutabilityPolicy *bool + + // HasLegalHold contains the information returned from the x-ms-has-legal-hold header response. + HasLegalHold *bool + + // IsImmutableStorageWithVersioningEnabled contains the information returned from the x-ms-immutable-storage-with-versioning-enabled + // header response. + IsImmutableStorageWithVersioningEnabled *bool + + // LastModified contains the information returned from the Last-Modified header response. + LastModified *time.Time + + // LeaseDuration contains the information returned from the x-ms-lease-duration header response. + LeaseDuration *LeaseDurationType + + // LeaseState contains the information returned from the x-ms-lease-state header response. + LeaseState *LeaseStateType + + // LeaseStatus contains the information returned from the x-ms-lease-status header response. + LeaseStatus *LeaseStatusType + + // Metadata contains the information returned from the x-ms-meta header response. + Metadata map[string]*string + + // RequestID contains the information returned from the x-ms-request-id header response. + RequestID *string + + // Version contains the information returned from the x-ms-version header response. + Version *string +} + +// ContainerClientListBlobFlatSegmentResponse contains the response from method ContainerClient.NewListBlobFlatSegmentPager. +type ContainerClientListBlobFlatSegmentResponse struct { + ListBlobsFlatSegmentResponse + // ClientRequestID contains the information returned from the x-ms-client-request-id header response. + ClientRequestID *string `xml:"ClientRequestID"` + + // ContentType contains the information returned from the Content-Type header response. + ContentType *string `xml:"ContentType"` + + // Date contains the information returned from the Date header response. + Date *time.Time `xml:"Date"` + + // RequestID contains the information returned from the x-ms-request-id header response. + RequestID *string `xml:"RequestID"` + + // Version contains the information returned from the x-ms-version header response. + Version *string `xml:"Version"` +} + +// FileSystemClientListPathHierarchySegmentResponse contains the response from method ContainerClient.NewListBlobHierarchySegmentPager. +type FileSystemClientListPathHierarchySegmentResponse struct { + ListPathsHierarchySegmentResponse + // ClientRequestID contains the information returned from the x-ms-client-request-id header response. + ClientRequestID *string `xml:"ClientRequestID"` + + // ContentType contains the information returned from the Content-Type header response. + ContentType *string `xml:"ContentType"` + + // Date contains the information returned from the Date header response. + Date *time.Time `xml:"Date"` + + // RequestID contains the information returned from the x-ms-request-id header response. + RequestID *string `xml:"RequestID"` + + // Version contains the information returned from the x-ms-version header response. + Version *string `xml:"Version"` +} + +// ContainerClientReleaseLeaseResponse contains the response from method ContainerClient.ReleaseLease. +type ContainerClientReleaseLeaseResponse struct { + // ClientRequestID contains the information returned from the x-ms-client-request-id header response. + ClientRequestID *string + + // Date contains the information returned from the Date header response. + Date *time.Time + + // ETag contains the information returned from the ETag header response. + ETag *azcore.ETag + + // LastModified contains the information returned from the Last-Modified header response. + LastModified *time.Time + + // RequestID contains the information returned from the x-ms-request-id header response. + RequestID *string + + // Version contains the information returned from the x-ms-version header response. + Version *string +} + +// ContainerClientRenameResponse contains the response from method ContainerClient.Rename. +type ContainerClientRenameResponse struct { + // ClientRequestID contains the information returned from the x-ms-client-request-id header response. + ClientRequestID *string + + // Date contains the information returned from the Date header response. + Date *time.Time + + // RequestID contains the information returned from the x-ms-request-id header response. + RequestID *string + + // Version contains the information returned from the x-ms-version header response. + Version *string +} + +// ContainerClientRenewLeaseResponse contains the response from method ContainerClient.RenewLease. +type ContainerClientRenewLeaseResponse struct { + // ClientRequestID contains the information returned from the x-ms-client-request-id header response. + ClientRequestID *string + + // Date contains the information returned from the Date header response. + Date *time.Time + + // ETag contains the information returned from the ETag header response. + ETag *azcore.ETag + + // LastModified contains the information returned from the Last-Modified header response. + LastModified *time.Time + + // LeaseID contains the information returned from the x-ms-lease-id header response. + LeaseID *string + + // RequestID contains the information returned from the x-ms-request-id header response. + RequestID *string + + // Version contains the information returned from the x-ms-version header response. + Version *string +} + +// ContainerClientRestoreResponse contains the response from method ContainerClient.Restore. +type ContainerClientRestoreResponse struct { + // ClientRequestID contains the information returned from the x-ms-client-request-id header response. + ClientRequestID *string + + // Date contains the information returned from the Date header response. + Date *time.Time + + // RequestID contains the information returned from the x-ms-request-id header response. + RequestID *string + + // Version contains the information returned from the x-ms-version header response. + Version *string +} + +// ContainerClientSetAccessPolicyResponse contains the response from method ContainerClient.SetAccessPolicy. +type ContainerClientSetAccessPolicyResponse struct { + // ClientRequestID contains the information returned from the x-ms-client-request-id header response. + ClientRequestID *string + + // Date contains the information returned from the Date header response. + Date *time.Time + + // ETag contains the information returned from the ETag header response. + ETag *azcore.ETag + + // LastModified contains the information returned from the Last-Modified header response. + LastModified *time.Time + + // RequestID contains the information returned from the x-ms-request-id header response. + RequestID *string + + // Version contains the information returned from the x-ms-version header response. + Version *string +} + +// ContainerClientSetMetadataResponse contains the response from method ContainerClient.SetMetadata. +type ContainerClientSetMetadataResponse struct { + // ClientRequestID contains the information returned from the x-ms-client-request-id header response. + ClientRequestID *string + + // Date contains the information returned from the Date header response. + Date *time.Time + + // ETag contains the information returned from the ETag header response. + ETag *azcore.ETag + + // LastModified contains the information returned from the Last-Modified header response. + LastModified *time.Time + + // RequestID contains the information returned from the x-ms-request-id header response. + RequestID *string + + // Version contains the information returned from the x-ms-version header response. + Version *string +} + +// ContainerClientSubmitBatchResponse contains the response from method ContainerClient.SubmitBatch. +type ContainerClientSubmitBatchResponse struct { + // Body contains the streaming response. + Body io.ReadCloser + + // ContentType contains the information returned from the Content-Type header response. + ContentType *string + + // RequestID contains the information returned from the x-ms-request-id header response. + RequestID *string + + // Version contains the information returned from the x-ms-version header response. + Version *string +} + +// PageBlobClientClearPagesResponse contains the response from method PageBlobClient.ClearPages. +type PageBlobClientClearPagesResponse struct { + // BlobSequenceNumber contains the information returned from the x-ms-blob-sequence-number header response. + BlobSequenceNumber *int64 + + // ClientRequestID contains the information returned from the x-ms-client-request-id header response. + ClientRequestID *string + + // ContentCRC64 contains the information returned from the x-ms-content-crc64 header response. + ContentCRC64 []byte + + // ContentMD5 contains the information returned from the Content-MD5 header response. + ContentMD5 []byte + + // Date contains the information returned from the Date header response. + Date *time.Time + + // ETag contains the information returned from the ETag header response. + ETag *azcore.ETag + + // LastModified contains the information returned from the Last-Modified header response. + LastModified *time.Time + + // RequestID contains the information returned from the x-ms-request-id header response. + RequestID *string + + // Version contains the information returned from the x-ms-version header response. + Version *string +} + +// PageBlobClientCopyIncrementalResponse contains the response from method PageBlobClient.CopyIncremental. +type PageBlobClientCopyIncrementalResponse struct { + // ClientRequestID contains the information returned from the x-ms-client-request-id header response. + ClientRequestID *string + + // CopyID contains the information returned from the x-ms-copy-id header response. + CopyID *string + + // CopyStatus contains the information returned from the x-ms-copy-status header response. + CopyStatus *CopyStatusType + + // Date contains the information returned from the Date header response. + Date *time.Time + + // ETag contains the information returned from the ETag header response. + ETag *azcore.ETag + + // LastModified contains the information returned from the Last-Modified header response. + LastModified *time.Time + + // RequestID contains the information returned from the x-ms-request-id header response. + RequestID *string + + // Version contains the information returned from the x-ms-version header response. + Version *string +} + +// PageBlobClientCreateResponse contains the response from method PageBlobClient.Create. +type PageBlobClientCreateResponse struct { + // ClientRequestID contains the information returned from the x-ms-client-request-id header response. + ClientRequestID *string + + // ContentMD5 contains the information returned from the Content-MD5 header response. + ContentMD5 []byte + + // Date contains the information returned from the Date header response. + Date *time.Time + + // ETag contains the information returned from the ETag header response. + ETag *azcore.ETag + + // EncryptionKeySHA256 contains the information returned from the x-ms-encryption-key-sha256 header response. + EncryptionKeySHA256 *string + + // EncryptionScope contains the information returned from the x-ms-encryption-scope header response. + EncryptionScope *string + + // IsServerEncrypted contains the information returned from the x-ms-request-server-encrypted header response. + IsServerEncrypted *bool + + // LastModified contains the information returned from the Last-Modified header response. + LastModified *time.Time + + // RequestID contains the information returned from the x-ms-request-id header response. + RequestID *string + + // Version contains the information returned from the x-ms-version header response. + Version *string + + // VersionID contains the information returned from the x-ms-version-id header response. + VersionID *string +} + +// PageBlobClientGetPageRangesDiffResponse contains the response from method PageBlobClient.NewGetPageRangesDiffPager. +type PageBlobClientGetPageRangesDiffResponse struct { + PageList + // BlobContentLength contains the information returned from the x-ms-blob-content-length header response. + BlobContentLength *int64 `xml:"BlobContentLength"` + + // ClientRequestID contains the information returned from the x-ms-client-request-id header response. + ClientRequestID *string `xml:"ClientRequestID"` + + // Date contains the information returned from the Date header response. + Date *time.Time `xml:"Date"` + + // ETag contains the information returned from the ETag header response. + ETag *azcore.ETag `xml:"ETag"` + + // LastModified contains the information returned from the Last-Modified header response. + LastModified *time.Time `xml:"LastModified"` + + // RequestID contains the information returned from the x-ms-request-id header response. + RequestID *string `xml:"RequestID"` + + // Version contains the information returned from the x-ms-version header response. + Version *string `xml:"Version"` +} + +// PageBlobClientGetPageRangesResponse contains the response from method PageBlobClient.NewGetPageRangesPager. +type PageBlobClientGetPageRangesResponse struct { + PageList + // BlobContentLength contains the information returned from the x-ms-blob-content-length header response. + BlobContentLength *int64 `xml:"BlobContentLength"` + + // ClientRequestID contains the information returned from the x-ms-client-request-id header response. + ClientRequestID *string `xml:"ClientRequestID"` + + // Date contains the information returned from the Date header response. + Date *time.Time `xml:"Date"` + + // ETag contains the information returned from the ETag header response. + ETag *azcore.ETag `xml:"ETag"` + + // LastModified contains the information returned from the Last-Modified header response. + LastModified *time.Time `xml:"LastModified"` + + // RequestID contains the information returned from the x-ms-request-id header response. + RequestID *string `xml:"RequestID"` + + // Version contains the information returned from the x-ms-version header response. + Version *string `xml:"Version"` +} + +// PageBlobClientResizeResponse contains the response from method PageBlobClient.Resize. +type PageBlobClientResizeResponse struct { + // BlobSequenceNumber contains the information returned from the x-ms-blob-sequence-number header response. + BlobSequenceNumber *int64 + + // ClientRequestID contains the information returned from the x-ms-client-request-id header response. + ClientRequestID *string + + // Date contains the information returned from the Date header response. + Date *time.Time + + // ETag contains the information returned from the ETag header response. + ETag *azcore.ETag + + // LastModified contains the information returned from the Last-Modified header response. + LastModified *time.Time + + // RequestID contains the information returned from the x-ms-request-id header response. + RequestID *string + + // Version contains the information returned from the x-ms-version header response. + Version *string +} + +// PageBlobClientUpdateSequenceNumberResponse contains the response from method PageBlobClient.UpdateSequenceNumber. +type PageBlobClientUpdateSequenceNumberResponse struct { + // BlobSequenceNumber contains the information returned from the x-ms-blob-sequence-number header response. + BlobSequenceNumber *int64 + + // ClientRequestID contains the information returned from the x-ms-client-request-id header response. + ClientRequestID *string + + // Date contains the information returned from the Date header response. + Date *time.Time + + // ETag contains the information returned from the ETag header response. + ETag *azcore.ETag + + // LastModified contains the information returned from the Last-Modified header response. + LastModified *time.Time + + // RequestID contains the information returned from the x-ms-request-id header response. + RequestID *string + + // Version contains the information returned from the x-ms-version header response. + Version *string +} + +// PageBlobClientUploadPagesFromURLResponse contains the response from method PageBlobClient.UploadPagesFromURL. +type PageBlobClientUploadPagesFromURLResponse struct { + // BlobSequenceNumber contains the information returned from the x-ms-blob-sequence-number header response. + BlobSequenceNumber *int64 + + // ContentCRC64 contains the information returned from the x-ms-content-crc64 header response. + ContentCRC64 []byte + + // ContentMD5 contains the information returned from the Content-MD5 header response. + ContentMD5 []byte + + // Date contains the information returned from the Date header response. + Date *time.Time + + // ETag contains the information returned from the ETag header response. + ETag *azcore.ETag + + // EncryptionKeySHA256 contains the information returned from the x-ms-encryption-key-sha256 header response. + EncryptionKeySHA256 *string + + // EncryptionScope contains the information returned from the x-ms-encryption-scope header response. + EncryptionScope *string + + // IsServerEncrypted contains the information returned from the x-ms-request-server-encrypted header response. + IsServerEncrypted *bool + + // LastModified contains the information returned from the Last-Modified header response. + LastModified *time.Time + + // RequestID contains the information returned from the x-ms-request-id header response. + RequestID *string + + // Version contains the information returned from the x-ms-version header response. + Version *string +} + +// PageBlobClientUploadPagesResponse contains the response from method PageBlobClient.UploadPages. +type PageBlobClientUploadPagesResponse struct { + // BlobSequenceNumber contains the information returned from the x-ms-blob-sequence-number header response. + BlobSequenceNumber *int64 + + // ClientRequestID contains the information returned from the x-ms-client-request-id header response. + ClientRequestID *string + + // ContentCRC64 contains the information returned from the x-ms-content-crc64 header response. + ContentCRC64 []byte + + // ContentMD5 contains the information returned from the Content-MD5 header response. + ContentMD5 []byte + + // Date contains the information returned from the Date header response. + Date *time.Time + + // ETag contains the information returned from the ETag header response. + ETag *azcore.ETag + + // EncryptionKeySHA256 contains the information returned from the x-ms-encryption-key-sha256 header response. + EncryptionKeySHA256 *string + + // EncryptionScope contains the information returned from the x-ms-encryption-scope header response. + EncryptionScope *string + + // IsServerEncrypted contains the information returned from the x-ms-request-server-encrypted header response. + IsServerEncrypted *bool + + // LastModified contains the information returned from the Last-Modified header response. + LastModified *time.Time + + // RequestID contains the information returned from the x-ms-request-id header response. + RequestID *string + + // Version contains the information returned from the x-ms-version header response. + Version *string +} + +// ServiceClientFilterBlobsResponse contains the response from method ServiceClient.FilterBlobs. +type ServiceClientFilterBlobsResponse struct { + FilterBlobSegment + // ClientRequestID contains the information returned from the x-ms-client-request-id header response. + ClientRequestID *string `xml:"ClientRequestID"` + + // Date contains the information returned from the Date header response. + Date *time.Time `xml:"Date"` + + // RequestID contains the information returned from the x-ms-request-id header response. + RequestID *string `xml:"RequestID"` + + // Version contains the information returned from the x-ms-version header response. + Version *string `xml:"Version"` +} + +// ServiceClientGetAccountInfoResponse contains the response from method ServiceClient.GetAccountInfo. +type ServiceClientGetAccountInfoResponse struct { + // AccountKind contains the information returned from the x-ms-account-kind header response. + AccountKind *AccountKind + + // ClientRequestID contains the information returned from the x-ms-client-request-id header response. + ClientRequestID *string + + // Date contains the information returned from the Date header response. + Date *time.Time + + // IsHierarchicalNamespaceEnabled contains the information returned from the x-ms-is-hns-enabled header response. + IsHierarchicalNamespaceEnabled *bool + + // RequestID contains the information returned from the x-ms-request-id header response. + RequestID *string + + // SKUName contains the information returned from the x-ms-sku-name header response. + SKUName *SKUName + + // Version contains the information returned from the x-ms-version header response. + Version *string +} + +// ServiceClientGetPropertiesResponse contains the response from method ServiceClient.GetProperties. +type ServiceClientGetPropertiesResponse struct { + StorageServiceProperties + // ClientRequestID contains the information returned from the x-ms-client-request-id header response. + ClientRequestID *string `xml:"ClientRequestID"` + + // RequestID contains the information returned from the x-ms-request-id header response. + RequestID *string `xml:"RequestID"` + + // Version contains the information returned from the x-ms-version header response. + Version *string `xml:"Version"` +} + +// ServiceClientGetStatisticsResponse contains the response from method ServiceClient.GetStatistics. +type ServiceClientGetStatisticsResponse struct { + StorageServiceStats + // ClientRequestID contains the information returned from the x-ms-client-request-id header response. + ClientRequestID *string `xml:"ClientRequestID"` + + // Date contains the information returned from the Date header response. + Date *time.Time `xml:"Date"` + + // RequestID contains the information returned from the x-ms-request-id header response. + RequestID *string `xml:"RequestID"` + + // Version contains the information returned from the x-ms-version header response. + Version *string `xml:"Version"` +} + +// ServiceClientGetUserDelegationKeyResponse contains the response from method ServiceClient.GetUserDelegationKey. +type ServiceClientGetUserDelegationKeyResponse struct { + UserDelegationKey + // ClientRequestID contains the information returned from the x-ms-client-request-id header response. + ClientRequestID *string `xml:"ClientRequestID"` + + // Date contains the information returned from the Date header response. + Date *time.Time `xml:"Date"` + + // RequestID contains the information returned from the x-ms-request-id header response. + RequestID *string `xml:"RequestID"` + + // Version contains the information returned from the x-ms-version header response. + Version *string `xml:"Version"` +} + +// ServiceClientListFileSystemsSegmentResponse contains the response from method ServiceClient.NewListContainersSegmentPager. +type ServiceClientListFileSystemsSegmentResponse struct { + ListFileSystemsSegmentResponse + // ClientRequestID contains the information returned from the x-ms-client-request-id header response. + ClientRequestID *string `xml:"ClientRequestID"` + + // RequestID contains the information returned from the x-ms-request-id header response. + RequestID *string `xml:"RequestID"` + + // Version contains the information returned from the x-ms-version header response. + Version *string `xml:"Version"` +} + +// ServiceClientSetPropertiesResponse contains the response from method ServiceClient.SetProperties. +type ServiceClientSetPropertiesResponse struct { + // ClientRequestID contains the information returned from the x-ms-client-request-id header response. + ClientRequestID *string + + // RequestID contains the information returned from the x-ms-request-id header response. + RequestID *string + + // Version contains the information returned from the x-ms-version header response. + Version *string +} + +// ServiceClientSubmitBatchResponse contains the response from method ServiceClient.SubmitBatch. +type ServiceClientSubmitBatchResponse struct { + // Body contains the streaming response. + Body io.ReadCloser + + // ContentType contains the information returned from the Content-Type header response. + ContentType *string + + // RequestID contains the information returned from the x-ms-request-id header response. + RequestID *string + + // Version contains the information returned from the x-ms-version header response. + Version *string +} diff --git a/sdk/storage/azdatalake/internal/generated_blob/zz_service_client.go b/sdk/storage/azdatalake/internal/generated_blob/zz_service_client.go new file mode 100644 index 000000000000..e335a7e4c689 --- /dev/null +++ b/sdk/storage/azdatalake/internal/generated_blob/zz_service_client.go @@ -0,0 +1,557 @@ +//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. +// Code generated by Microsoft (R) AutoRest Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. +// DO NOT EDIT. + +package generated_blob + +import ( + "context" + "fmt" + "github.com/Azure/azure-sdk-for-go/sdk/azcore" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/policy" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime" + "io" + "net/http" + "strconv" + "strings" + "time" +) + +// ServiceClient contains the methods for the Service group. +// Don't use this type directly, use a constructor function instead. +type ServiceClient struct { + internal *azcore.Client + endpoint string +} + +// FilterBlobs - The Filter Blobs operation enables callers to list blobs across all containers whose tags match a given search +// expression. Filter blobs searches across all containers within a storage account but can +// be scoped within the expression to a single container. +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2020-10-02 +// - where - Filters the results to return only to return only blobs whose tags match the specified expression. +// - options - ServiceClientFilterBlobsOptions contains the optional parameters for the ServiceClient.FilterBlobs method. +func (client *ServiceClient) FilterBlobs(ctx context.Context, where string, options *ServiceClientFilterBlobsOptions) (ServiceClientFilterBlobsResponse, error) { + req, err := client.filterBlobsCreateRequest(ctx, where, options) + if err != nil { + return ServiceClientFilterBlobsResponse{}, err + } + resp, err := client.internal.Pipeline().Do(req) + if err != nil { + return ServiceClientFilterBlobsResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusOK) { + return ServiceClientFilterBlobsResponse{}, runtime.NewResponseError(resp) + } + return client.filterBlobsHandleResponse(resp) +} + +// filterBlobsCreateRequest creates the FilterBlobs request. +func (client *ServiceClient) filterBlobsCreateRequest(ctx context.Context, where string, options *ServiceClientFilterBlobsOptions) (*policy.Request, error) { + req, err := runtime.NewRequest(ctx, http.MethodGet, client.endpoint) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("comp", "blobs") + if options != nil && options.Timeout != nil { + reqQP.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + } + reqQP.Set("where", where) + if options != nil && options.Marker != nil { + reqQP.Set("marker", *options.Marker) + } + if options != nil && options.Maxresults != nil { + reqQP.Set("maxresults", strconv.FormatInt(int64(*options.Maxresults), 10)) + } + req.Raw().URL.RawQuery = strings.Replace(reqQP.Encode(), "+", "%20", -1) + req.Raw().Header["x-ms-version"] = []string{"2020-10-02"} + if options != nil && options.RequestID != nil { + req.Raw().Header["x-ms-client-request-id"] = []string{*options.RequestID} + } + req.Raw().Header["Accept"] = []string{"application/xml"} + return req, nil +} + +// filterBlobsHandleResponse handles the FilterBlobs response. +func (client *ServiceClient) filterBlobsHandleResponse(resp *http.Response) (ServiceClientFilterBlobsResponse, error) { + result := ServiceClientFilterBlobsResponse{} + if val := resp.Header.Get("x-ms-client-request-id"); val != "" { + result.ClientRequestID = &val + } + if val := resp.Header.Get("x-ms-request-id"); val != "" { + result.RequestID = &val + } + if val := resp.Header.Get("x-ms-version"); val != "" { + result.Version = &val + } + if val := resp.Header.Get("Date"); val != "" { + date, err := time.Parse(time.RFC1123, val) + if err != nil { + return ServiceClientFilterBlobsResponse{}, err + } + result.Date = &date + } + if err := runtime.UnmarshalAsXML(resp, &result.FilterBlobSegment); err != nil { + return ServiceClientFilterBlobsResponse{}, err + } + return result, nil +} + +// GetAccountInfo - Returns the sku name and account kind +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2020-10-02 +// - options - ServiceClientGetAccountInfoOptions contains the optional parameters for the ServiceClient.GetAccountInfo method. +func (client *ServiceClient) GetAccountInfo(ctx context.Context, options *ServiceClientGetAccountInfoOptions) (ServiceClientGetAccountInfoResponse, error) { + req, err := client.getAccountInfoCreateRequest(ctx, options) + if err != nil { + return ServiceClientGetAccountInfoResponse{}, err + } + resp, err := client.internal.Pipeline().Do(req) + if err != nil { + return ServiceClientGetAccountInfoResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusOK) { + return ServiceClientGetAccountInfoResponse{}, runtime.NewResponseError(resp) + } + return client.getAccountInfoHandleResponse(resp) +} + +// getAccountInfoCreateRequest creates the GetAccountInfo request. +func (client *ServiceClient) getAccountInfoCreateRequest(ctx context.Context, options *ServiceClientGetAccountInfoOptions) (*policy.Request, error) { + req, err := runtime.NewRequest(ctx, http.MethodGet, client.endpoint) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("restype", "account") + reqQP.Set("comp", "properties") + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["x-ms-version"] = []string{"2020-10-02"} + req.Raw().Header["Accept"] = []string{"application/xml"} + return req, nil +} + +// getAccountInfoHandleResponse handles the GetAccountInfo response. +func (client *ServiceClient) getAccountInfoHandleResponse(resp *http.Response) (ServiceClientGetAccountInfoResponse, error) { + result := ServiceClientGetAccountInfoResponse{} + if val := resp.Header.Get("x-ms-client-request-id"); val != "" { + result.ClientRequestID = &val + } + if val := resp.Header.Get("x-ms-request-id"); val != "" { + result.RequestID = &val + } + if val := resp.Header.Get("x-ms-version"); val != "" { + result.Version = &val + } + if val := resp.Header.Get("Date"); val != "" { + date, err := time.Parse(time.RFC1123, val) + if err != nil { + return ServiceClientGetAccountInfoResponse{}, err + } + result.Date = &date + } + if val := resp.Header.Get("x-ms-sku-name"); val != "" { + result.SKUName = (*SKUName)(&val) + } + if val := resp.Header.Get("x-ms-account-kind"); val != "" { + result.AccountKind = (*AccountKind)(&val) + } + if val := resp.Header.Get("x-ms-is-hns-enabled"); val != "" { + isHierarchicalNamespaceEnabled, err := strconv.ParseBool(val) + if err != nil { + return ServiceClientGetAccountInfoResponse{}, err + } + result.IsHierarchicalNamespaceEnabled = &isHierarchicalNamespaceEnabled + } + return result, nil +} + +// GetProperties - gets the properties of a storage account's Blob service, including properties for Storage Analytics and +// CORS (Cross-Origin Resource Sharing) rules. +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2020-10-02 +// - options - ServiceClientGetPropertiesOptions contains the optional parameters for the ServiceClient.GetProperties method. +func (client *ServiceClient) GetProperties(ctx context.Context, options *ServiceClientGetPropertiesOptions) (ServiceClientGetPropertiesResponse, error) { + req, err := client.getPropertiesCreateRequest(ctx, options) + if err != nil { + return ServiceClientGetPropertiesResponse{}, err + } + resp, err := client.internal.Pipeline().Do(req) + if err != nil { + return ServiceClientGetPropertiesResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusOK) { + return ServiceClientGetPropertiesResponse{}, runtime.NewResponseError(resp) + } + return client.getPropertiesHandleResponse(resp) +} + +// getPropertiesCreateRequest creates the GetProperties request. +func (client *ServiceClient) getPropertiesCreateRequest(ctx context.Context, options *ServiceClientGetPropertiesOptions) (*policy.Request, error) { + req, err := runtime.NewRequest(ctx, http.MethodGet, client.endpoint) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("restype", "service") + reqQP.Set("comp", "properties") + if options != nil && options.Timeout != nil { + reqQP.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + } + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["x-ms-version"] = []string{"2020-10-02"} + if options != nil && options.RequestID != nil { + req.Raw().Header["x-ms-client-request-id"] = []string{*options.RequestID} + } + req.Raw().Header["Accept"] = []string{"application/xml"} + return req, nil +} + +// getPropertiesHandleResponse handles the GetProperties response. +func (client *ServiceClient) getPropertiesHandleResponse(resp *http.Response) (ServiceClientGetPropertiesResponse, error) { + result := ServiceClientGetPropertiesResponse{} + if val := resp.Header.Get("x-ms-client-request-id"); val != "" { + result.ClientRequestID = &val + } + if val := resp.Header.Get("x-ms-request-id"); val != "" { + result.RequestID = &val + } + if val := resp.Header.Get("x-ms-version"); val != "" { + result.Version = &val + } + if err := runtime.UnmarshalAsXML(resp, &result.StorageServiceProperties); err != nil { + return ServiceClientGetPropertiesResponse{}, err + } + return result, nil +} + +// GetStatistics - Retrieves statistics related to replication for the Blob service. It is only available on the secondary +// location endpoint when read-access geo-redundant replication is enabled for the storage account. +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2020-10-02 +// - options - ServiceClientGetStatisticsOptions contains the optional parameters for the ServiceClient.GetStatistics method. +func (client *ServiceClient) GetStatistics(ctx context.Context, options *ServiceClientGetStatisticsOptions) (ServiceClientGetStatisticsResponse, error) { + req, err := client.getStatisticsCreateRequest(ctx, options) + if err != nil { + return ServiceClientGetStatisticsResponse{}, err + } + resp, err := client.internal.Pipeline().Do(req) + if err != nil { + return ServiceClientGetStatisticsResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusOK) { + return ServiceClientGetStatisticsResponse{}, runtime.NewResponseError(resp) + } + return client.getStatisticsHandleResponse(resp) +} + +// getStatisticsCreateRequest creates the GetStatistics request. +func (client *ServiceClient) getStatisticsCreateRequest(ctx context.Context, options *ServiceClientGetStatisticsOptions) (*policy.Request, error) { + req, err := runtime.NewRequest(ctx, http.MethodGet, client.endpoint) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("restype", "service") + reqQP.Set("comp", "stats") + if options != nil && options.Timeout != nil { + reqQP.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + } + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["x-ms-version"] = []string{"2020-10-02"} + if options != nil && options.RequestID != nil { + req.Raw().Header["x-ms-client-request-id"] = []string{*options.RequestID} + } + req.Raw().Header["Accept"] = []string{"application/xml"} + return req, nil +} + +// getStatisticsHandleResponse handles the GetStatistics response. +func (client *ServiceClient) getStatisticsHandleResponse(resp *http.Response) (ServiceClientGetStatisticsResponse, error) { + result := ServiceClientGetStatisticsResponse{} + if val := resp.Header.Get("x-ms-client-request-id"); val != "" { + result.ClientRequestID = &val + } + if val := resp.Header.Get("x-ms-request-id"); val != "" { + result.RequestID = &val + } + if val := resp.Header.Get("x-ms-version"); val != "" { + result.Version = &val + } + if val := resp.Header.Get("Date"); val != "" { + date, err := time.Parse(time.RFC1123, val) + if err != nil { + return ServiceClientGetStatisticsResponse{}, err + } + result.Date = &date + } + if err := runtime.UnmarshalAsXML(resp, &result.StorageServiceStats); err != nil { + return ServiceClientGetStatisticsResponse{}, err + } + return result, nil +} + +// GetUserDelegationKey - Retrieves a user delegation key for the Blob service. This is only a valid operation when using +// bearer token authentication. +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2020-10-02 +// - keyInfo - Key information +// - options - ServiceClientGetUserDelegationKeyOptions contains the optional parameters for the ServiceClient.GetUserDelegationKey +// method. +func (client *ServiceClient) GetUserDelegationKey(ctx context.Context, keyInfo KeyInfo, options *ServiceClientGetUserDelegationKeyOptions) (ServiceClientGetUserDelegationKeyResponse, error) { + req, err := client.getUserDelegationKeyCreateRequest(ctx, keyInfo, options) + if err != nil { + return ServiceClientGetUserDelegationKeyResponse{}, err + } + resp, err := client.internal.Pipeline().Do(req) + if err != nil { + return ServiceClientGetUserDelegationKeyResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusOK) { + return ServiceClientGetUserDelegationKeyResponse{}, runtime.NewResponseError(resp) + } + return client.getUserDelegationKeyHandleResponse(resp) +} + +// getUserDelegationKeyCreateRequest creates the GetUserDelegationKey request. +func (client *ServiceClient) getUserDelegationKeyCreateRequest(ctx context.Context, keyInfo KeyInfo, options *ServiceClientGetUserDelegationKeyOptions) (*policy.Request, error) { + req, err := runtime.NewRequest(ctx, http.MethodPost, client.endpoint) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("restype", "service") + reqQP.Set("comp", "userdelegationkey") + if options != nil && options.Timeout != nil { + reqQP.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + } + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["x-ms-version"] = []string{"2020-10-02"} + if options != nil && options.RequestID != nil { + req.Raw().Header["x-ms-client-request-id"] = []string{*options.RequestID} + } + req.Raw().Header["Accept"] = []string{"application/xml"} + if err := runtime.MarshalAsXML(req, keyInfo); err != nil { + return nil, err + } + return req, nil +} + +// getUserDelegationKeyHandleResponse handles the GetUserDelegationKey response. +func (client *ServiceClient) getUserDelegationKeyHandleResponse(resp *http.Response) (ServiceClientGetUserDelegationKeyResponse, error) { + result := ServiceClientGetUserDelegationKeyResponse{} + if val := resp.Header.Get("x-ms-client-request-id"); val != "" { + result.ClientRequestID = &val + } + if val := resp.Header.Get("x-ms-request-id"); val != "" { + result.RequestID = &val + } + if val := resp.Header.Get("x-ms-version"); val != "" { + result.Version = &val + } + if val := resp.Header.Get("Date"); val != "" { + date, err := time.Parse(time.RFC1123, val) + if err != nil { + return ServiceClientGetUserDelegationKeyResponse{}, err + } + result.Date = &date + } + if err := runtime.UnmarshalAsXML(resp, &result.UserDelegationKey); err != nil { + return ServiceClientGetUserDelegationKeyResponse{}, err + } + return result, nil +} + +// NewListContainersSegmentPager - The List Containers Segment operation returns a list of the containers under the specified +// account +// +// Generated from API version 2020-10-02 +// - options - ServiceClientListContainersSegmentOptions contains the optional parameters for the ServiceClient.NewListContainersSegmentPager +// method. +// +// listContainersSegmentCreateRequest creates the ListContainersSegment request. +func (client *ServiceClient) ListContainersSegmentCreateRequest(ctx context.Context, options *ServiceClientListContainersSegmentOptions) (*policy.Request, error) { + req, err := runtime.NewRequest(ctx, http.MethodGet, client.endpoint) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("comp", "list") + if options != nil && options.Prefix != nil { + reqQP.Set("prefix", *options.Prefix) + } + if options != nil && options.Marker != nil { + reqQP.Set("marker", *options.Marker) + } + if options != nil && options.Maxresults != nil { + reqQP.Set("maxresults", strconv.FormatInt(int64(*options.Maxresults), 10)) + } + if options != nil && options.Include != nil { + reqQP.Set("include", strings.Join(strings.Fields(strings.Trim(fmt.Sprint(options.Include), "[]")), ",")) + } + if options != nil && options.Timeout != nil { + reqQP.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + } + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["x-ms-version"] = []string{"2020-10-02"} + if options != nil && options.RequestID != nil { + req.Raw().Header["x-ms-client-request-id"] = []string{*options.RequestID} + } + req.Raw().Header["Accept"] = []string{"application/xml"} + return req, nil +} + +// listContainersSegmentHandleResponse handles the ListContainersSegment response. +func (client *ServiceClient) ListContainersSegmentHandleResponse(resp *http.Response) (ServiceClientListFileSystemsSegmentResponse, error) { + result := ServiceClientListFileSystemsSegmentResponse{} + if val := resp.Header.Get("x-ms-client-request-id"); val != "" { + result.ClientRequestID = &val + } + if val := resp.Header.Get("x-ms-request-id"); val != "" { + result.RequestID = &val + } + if val := resp.Header.Get("x-ms-version"); val != "" { + result.Version = &val + } + if err := runtime.UnmarshalAsXML(resp, &result.ListFileSystemsSegmentResponse); err != nil { + return ServiceClientListFileSystemsSegmentResponse{}, err + } + return result, nil +} + +// SetProperties - Sets properties for a storage account's Blob service endpoint, including properties for Storage Analytics +// and CORS (Cross-Origin Resource Sharing) rules +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2020-10-02 +// - storageServiceProperties - The StorageService properties. +// - options - ServiceClientSetPropertiesOptions contains the optional parameters for the ServiceClient.SetProperties method. +func (client *ServiceClient) SetProperties(ctx context.Context, storageServiceProperties StorageServiceProperties, options *ServiceClientSetPropertiesOptions) (ServiceClientSetPropertiesResponse, error) { + req, err := client.setPropertiesCreateRequest(ctx, storageServiceProperties, options) + if err != nil { + return ServiceClientSetPropertiesResponse{}, err + } + resp, err := client.internal.Pipeline().Do(req) + if err != nil { + return ServiceClientSetPropertiesResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusAccepted) { + return ServiceClientSetPropertiesResponse{}, runtime.NewResponseError(resp) + } + return client.setPropertiesHandleResponse(resp) +} + +// setPropertiesCreateRequest creates the SetProperties request. +func (client *ServiceClient) setPropertiesCreateRequest(ctx context.Context, storageServiceProperties StorageServiceProperties, options *ServiceClientSetPropertiesOptions) (*policy.Request, error) { + req, err := runtime.NewRequest(ctx, http.MethodPut, client.endpoint) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("restype", "service") + reqQP.Set("comp", "properties") + if options != nil && options.Timeout != nil { + reqQP.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + } + req.Raw().URL.RawQuery = reqQP.Encode() + req.Raw().Header["x-ms-version"] = []string{"2020-10-02"} + if options != nil && options.RequestID != nil { + req.Raw().Header["x-ms-client-request-id"] = []string{*options.RequestID} + } + req.Raw().Header["Accept"] = []string{"application/xml"} + if err := runtime.MarshalAsXML(req, storageServiceProperties); err != nil { + return nil, err + } + return req, nil +} + +// setPropertiesHandleResponse handles the SetProperties response. +func (client *ServiceClient) setPropertiesHandleResponse(resp *http.Response) (ServiceClientSetPropertiesResponse, error) { + result := ServiceClientSetPropertiesResponse{} + if val := resp.Header.Get("x-ms-client-request-id"); val != "" { + result.ClientRequestID = &val + } + if val := resp.Header.Get("x-ms-request-id"); val != "" { + result.RequestID = &val + } + if val := resp.Header.Get("x-ms-version"); val != "" { + result.Version = &val + } + return result, nil +} + +// SubmitBatch - The Batch operation allows multiple API calls to be embedded into a single HTTP request. +// If the operation fails it returns an *azcore.ResponseError type. +// +// Generated from API version 2020-10-02 +// - contentLength - The length of the request. +// - multipartContentType - Required. The value of this header must be multipart/mixed with a batch boundary. Example header +// value: multipart/mixed; boundary=batch_ +// - body - Initial data +// - options - ServiceClientSubmitBatchOptions contains the optional parameters for the ServiceClient.SubmitBatch method. +func (client *ServiceClient) SubmitBatch(ctx context.Context, contentLength int64, multipartContentType string, body io.ReadSeekCloser, options *ServiceClientSubmitBatchOptions) (ServiceClientSubmitBatchResponse, error) { + req, err := client.submitBatchCreateRequest(ctx, contentLength, multipartContentType, body, options) + if err != nil { + return ServiceClientSubmitBatchResponse{}, err + } + resp, err := client.internal.Pipeline().Do(req) + if err != nil { + return ServiceClientSubmitBatchResponse{}, err + } + if !runtime.HasStatusCode(resp, http.StatusAccepted) { + return ServiceClientSubmitBatchResponse{}, runtime.NewResponseError(resp) + } + return client.submitBatchHandleResponse(resp) +} + +// submitBatchCreateRequest creates the SubmitBatch request. +func (client *ServiceClient) submitBatchCreateRequest(ctx context.Context, contentLength int64, multipartContentType string, body io.ReadSeekCloser, options *ServiceClientSubmitBatchOptions) (*policy.Request, error) { + req, err := runtime.NewRequest(ctx, http.MethodPost, client.endpoint) + if err != nil { + return nil, err + } + reqQP := req.Raw().URL.Query() + reqQP.Set("comp", "batch") + if options != nil && options.Timeout != nil { + reqQP.Set("timeout", strconv.FormatInt(int64(*options.Timeout), 10)) + } + req.Raw().URL.RawQuery = reqQP.Encode() + runtime.SkipBodyDownload(req) + req.Raw().Header["Content-Length"] = []string{strconv.FormatInt(contentLength, 10)} + req.Raw().Header["Content-Type"] = []string{multipartContentType} + req.Raw().Header["x-ms-version"] = []string{"2020-10-02"} + if options != nil && options.RequestID != nil { + req.Raw().Header["x-ms-client-request-id"] = []string{*options.RequestID} + } + req.Raw().Header["Accept"] = []string{"application/xml"} + if err := req.SetBody(body, multipartContentType); err != nil { + return nil, err + } + return req, nil +} + +// submitBatchHandleResponse handles the SubmitBatch response. +func (client *ServiceClient) submitBatchHandleResponse(resp *http.Response) (ServiceClientSubmitBatchResponse, error) { + result := ServiceClientSubmitBatchResponse{Body: resp.Body} + if val := resp.Header.Get("Content-Type"); val != "" { + result.ContentType = &val + } + if val := resp.Header.Get("x-ms-request-id"); val != "" { + result.RequestID = &val + } + if val := resp.Header.Get("x-ms-version"); val != "" { + result.Version = &val + } + return result, nil +} diff --git a/sdk/storage/azdatalake/internal/generated_blob/zz_time_rfc1123.go b/sdk/storage/azdatalake/internal/generated_blob/zz_time_rfc1123.go new file mode 100644 index 000000000000..def276c50d08 --- /dev/null +++ b/sdk/storage/azdatalake/internal/generated_blob/zz_time_rfc1123.go @@ -0,0 +1,43 @@ +//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. +// Code generated by Microsoft (R) AutoRest Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. +// DO NOT EDIT. + +package generated_blob + +import ( + "strings" + "time" +) + +const ( + rfc1123JSON = `"` + time.RFC1123 + `"` +) + +type timeRFC1123 time.Time + +func (t timeRFC1123) MarshalJSON() ([]byte, error) { + b := []byte(time.Time(t).Format(rfc1123JSON)) + return b, nil +} + +func (t timeRFC1123) MarshalText() ([]byte, error) { + b := []byte(time.Time(t).Format(time.RFC1123)) + return b, nil +} + +func (t *timeRFC1123) UnmarshalJSON(data []byte) error { + p, err := time.Parse(rfc1123JSON, strings.ToUpper(string(data))) + *t = timeRFC1123(p) + return err +} + +func (t *timeRFC1123) UnmarshalText(data []byte) error { + p, err := time.Parse(time.RFC1123, string(data)) + *t = timeRFC1123(p) + return err +} diff --git a/sdk/storage/azdatalake/internal/generated_blob/zz_time_rfc3339.go b/sdk/storage/azdatalake/internal/generated_blob/zz_time_rfc3339.go new file mode 100644 index 000000000000..034d115920a9 --- /dev/null +++ b/sdk/storage/azdatalake/internal/generated_blob/zz_time_rfc3339.go @@ -0,0 +1,59 @@ +//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. +// Code generated by Microsoft (R) AutoRest Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. +// DO NOT EDIT. + +package generated_blob + +import ( + "regexp" + "strings" + "time" +) + +const ( + utcLayoutJSON = `"2006-01-02T15:04:05.999999999"` + utcLayout = "2006-01-02T15:04:05.999999999" + rfc3339JSON = `"` + time.RFC3339Nano + `"` +) + +// Azure reports time in UTC but it doesn't include the 'Z' time zone suffix in some cases. +var tzOffsetRegex = regexp.MustCompile(`(Z|z|\+|-)(\d+:\d+)*"*$`) + +type timeRFC3339 time.Time + +func (t timeRFC3339) MarshalJSON() (json []byte, err error) { + tt := time.Time(t) + return tt.MarshalJSON() +} + +func (t timeRFC3339) MarshalText() (text []byte, err error) { + tt := time.Time(t) + return tt.MarshalText() +} + +func (t *timeRFC3339) UnmarshalJSON(data []byte) error { + layout := utcLayoutJSON + if tzOffsetRegex.Match(data) { + layout = rfc3339JSON + } + return t.Parse(layout, string(data)) +} + +func (t *timeRFC3339) UnmarshalText(data []byte) (err error) { + layout := utcLayout + if tzOffsetRegex.Match(data) { + layout = time.RFC3339Nano + } + return t.Parse(layout, string(data)) +} + +func (t *timeRFC3339) Parse(layout, value string) error { + p, err := time.Parse(layout, strings.ToUpper(value)) + *t = timeRFC3339(p) + return err +} diff --git a/sdk/storage/azdatalake/internal/generated_blob/zz_xml_helper.go b/sdk/storage/azdatalake/internal/generated_blob/zz_xml_helper.go new file mode 100644 index 000000000000..be1f2b2d3ffd --- /dev/null +++ b/sdk/storage/azdatalake/internal/generated_blob/zz_xml_helper.go @@ -0,0 +1,41 @@ +//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. +// Code generated by Microsoft (R) AutoRest Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. +// DO NOT EDIT. + +package generated_blob + +import ( + "encoding/xml" + "strings" +) + +type additionalProperties map[string]*string + +// UnmarshalXML implements the xml.Unmarshaler interface for additionalProperties. +func (ap *additionalProperties) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error { + tokName := "" + for t, err := d.Token(); err == nil; t, err = d.Token() { + switch tt := t.(type) { + case xml.StartElement: + tokName = strings.ToLower(tt.Name.Local) + break + case xml.CharData: + if tokName == "" { + continue + } + if *ap == nil { + *ap = additionalProperties{} + } + s := string(tt) + (*ap)[tokName] = &s + tokName = "" + break + } + } + return nil +} diff --git a/sdk/storage/azdatalake/internal/path/constants.go b/sdk/storage/azdatalake/internal/path/constants.go index ce070f694d23..0744d15e9205 100644 --- a/sdk/storage/azdatalake/internal/path/constants.go +++ b/sdk/storage/azdatalake/internal/path/constants.go @@ -8,6 +8,7 @@ package path import ( "github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/blob" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake" "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/internal/generated" ) @@ -35,3 +36,40 @@ const ( CopyStatusTypeAborted CopyStatusType = blob.CopyStatusTypeAborted CopyStatusTypeFailed CopyStatusType = blob.CopyStatusTypeFailed ) + +// StatusType defines values for StatusType +type StatusType = azdatalake.StatusType + +const ( + StatusTypeLocked StatusType = azdatalake.StatusTypeLocked + StatusTypeUnlocked StatusType = azdatalake.StatusTypeUnlocked +) + +// PossibleStatusTypeValues returns the possible values for the StatusType const type. +func PossibleStatusTypeValues() []StatusType { + return azdatalake.PossibleStatusTypeValues() +} + +// DurationType defines values for DurationType +type DurationType = azdatalake.DurationType + +const ( + DurationTypeInfinite DurationType = azdatalake.DurationTypeInfinite + DurationTypeFixed DurationType = azdatalake.DurationTypeFixed +) + +// PossibleDurationTypeValues returns the possible values for the DurationType const type. +func PossibleDurationTypeValues() []DurationType { + return azdatalake.PossibleDurationTypeValues() +} + +// StateType defines values for StateType +type StateType = azdatalake.StateType + +const ( + StateTypeAvailable StateType = azdatalake.StateTypeAvailable + StateTypeLeased StateType = azdatalake.StateTypeLeased + StateTypeExpired StateType = azdatalake.StateTypeExpired + StateTypeBreaking StateType = azdatalake.StateTypeBreaking + StateTypeBroken StateType = azdatalake.StateTypeBroken +) diff --git a/sdk/storage/azdatalake/internal/path/models.go b/sdk/storage/azdatalake/internal/path/models.go index 112dda4c922c..a66c7bfc448c 100644 --- a/sdk/storage/azdatalake/internal/path/models.go +++ b/sdk/storage/azdatalake/internal/path/models.go @@ -79,6 +79,9 @@ func FormatGetPropertiesOptions(o *GetPropertiesOptions) *blob.GetPropertiesOpti return nil } accessConditions := exported.FormatBlobAccessConditions(o.AccessConditions) + if o.CPKInfo == nil { + o.CPKInfo = &CPKInfo{} + } return &blob.GetPropertiesOptions{ AccessConditions: accessConditions, CPKInfo: &blob.CPKInfo{ @@ -265,7 +268,7 @@ func FormatSetMetadataOptions(o *SetMetadataOptions) (*blob.SetMetadataOptions, } } if o.CPKScopeInfo != nil { - opts.CPKScopeInfo = (*blob.CPKScopeInfo)(o.CPKScopeInfo) + opts.CPKScopeInfo = o.CPKScopeInfo } return opts, o.Metadata } @@ -292,3 +295,6 @@ type SourceModifiedAccessConditions = exported.SourceModifiedAccessConditions // CPKScopeInfo contains a group of parameters for the Client.SetMetadata() method. type CPKScopeInfo = blob.CPKScopeInfo + +// ACLFailedEntry contains the failed ACL entry (response model). +type ACLFailedEntry = generated.ACLFailedEntry diff --git a/sdk/storage/azdatalake/internal/path/responses.go b/sdk/storage/azdatalake/internal/path/responses.go index 915d7b104374..1189ff02d693 100644 --- a/sdk/storage/azdatalake/internal/path/responses.go +++ b/sdk/storage/azdatalake/internal/path/responses.go @@ -9,7 +9,6 @@ package path import ( "github.com/Azure/azure-sdk-for-go/sdk/azcore" "github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/blob" - "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake" "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/internal/generated" "net/http" "time" @@ -21,7 +20,19 @@ type SetAccessControlResponse = generated.PathClientSetAccessControlResponse // GetAccessControlResponse contains the response fields for the GetAccessControl operation. type GetAccessControlResponse = generated.PathClientGetPropertiesResponse -// TODO: removed BlobSequenceNumber, BlobCommittedBlockCount and BlobType headers from the original response: +// UpdateAccessControlResponse contains the response fields for the UpdateAccessControlRecursive operation. +type UpdateAccessControlResponse = generated.PathClientSetAccessControlRecursiveResponse + +// RemoveAccessControlResponse contains the response fields for the RemoveAccessControlRecursive operation. +type RemoveAccessControlResponse = generated.PathClientSetAccessControlRecursiveResponse + +// CreateResponse contains the response fields for the Create operation. +type CreateResponse = generated.PathClientCreateResponse + +// DeleteResponse contains the response fields for the Delete operation. +type DeleteResponse = generated.PathClientDeleteResponse + +// removed BlobSequenceNumber, BlobCommittedBlockCount and BlobType headers from the original response: // GetPropertiesResponse contains the response fields for the GetProperties operation. type GetPropertiesResponse struct { @@ -128,13 +139,13 @@ type GetPropertiesResponse struct { LastModified *time.Time // LeaseDuration contains the information returned from the x-ms-lease-duration header response. - LeaseDuration *azdatalake.DurationType + LeaseDuration *DurationType // LeaseState contains the information returned from the x-ms-lease-state header response. - LeaseState *azdatalake.StateType + LeaseState *StateType // LeaseStatus contains the information returned from the x-ms-lease-status header response. - LeaseStatus *azdatalake.StatusType + LeaseStatus *StatusType // LegalHold contains the information returned from the x-ms-legal-hold header response. LegalHold *bool diff --git a/sdk/storage/azdatalake/internal/testcommon/clients_auth.go b/sdk/storage/azdatalake/internal/testcommon/clients_auth.go index 93a91257b1b8..6f93a8517585 100644 --- a/sdk/storage/azdatalake/internal/testcommon/clients_auth.go +++ b/sdk/storage/azdatalake/internal/testcommon/clients_auth.go @@ -1,3 +1,9 @@ +//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 testcommon import ( @@ -209,6 +215,7 @@ func CreateNewFilesystem(ctx context.Context, _require *require.Assertions, file // _require.Equal(cResp.RawResponse.StatusCode, 201) return fsClient } + func GetServiceClientFromConnectionString(t *testing.T, accountType TestAccountType, options *service.ClientOptions) (*service.Client, error) { if options == nil { options = &service.ClientOptions{} diff --git a/sdk/storage/azdatalake/internal/testcommon/common.go b/sdk/storage/azdatalake/internal/testcommon/common.go index e5451ba6a38b..4cc181b9b297 100644 --- a/sdk/storage/azdatalake/internal/testcommon/common.go +++ b/sdk/storage/azdatalake/internal/testcommon/common.go @@ -1,3 +1,9 @@ +//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 testcommon import ( diff --git a/sdk/storage/azdatalake/lease/path_client.go b/sdk/storage/azdatalake/lease/path_client.go index 97e785571c05..aab03d04a7fe 100644 --- a/sdk/storage/azdatalake/lease/path_client.go +++ b/sdk/storage/azdatalake/lease/path_client.go @@ -16,6 +16,7 @@ import ( "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/generated_blob" ) // PathClient provides lease functionality for the underlying path client. @@ -34,9 +35,9 @@ func NewPathClient[T directory.Client | file.Client](client *T, options *PathCli var blobClient *blockblob.Client switch t := any(client).(type) { case *directory.Client: - _, _, blobClient = base.InnerClients((*base.CompositeClient[generated.PathClient, generated.PathClient, blockblob.Client])(t)) + _, _, blobClient = base.InnerClients((*base.CompositeClient[generated.PathClient, generated_blob.BlobClient, blockblob.Client])(t)) case *file.Client: - _, _, blobClient = base.InnerClients((*base.CompositeClient[generated.PathClient, generated.PathClient, blockblob.Client])(t)) + _, _, blobClient = base.InnerClients((*base.CompositeClient[generated.PathClient, generated_blob.BlobClient, blockblob.Client])(t)) default: return nil, fmt.Errorf("unhandled client type %T", client) } diff --git a/sdk/storage/azdatalake/sas/service_test.go b/sdk/storage/azdatalake/sas/service_test.go index 218a6c116eac..186eb7e43a9f 100644 --- a/sdk/storage/azdatalake/sas/service_test.go +++ b/sdk/storage/azdatalake/sas/service_test.go @@ -97,22 +97,22 @@ func TestFilesystemPermissions_ParseNegative(t *testing.T) { require.Contains(t, err.Error(), "122") } -func TestPathPermissions_String(t *testing.T) { +func TestFilePermissions_String(t *testing.T) { testdata := []struct { - input PathPermissions + input FilePermissions expected string }{ - {input: PathPermissions{Read: true}, expected: "r"}, - {input: PathPermissions{Add: true}, expected: "a"}, - {input: PathPermissions{Create: true}, expected: "c"}, - {input: PathPermissions{Write: true}, expected: "w"}, - {input: PathPermissions{Delete: true}, expected: "d"}, - {input: PathPermissions{List: true}, expected: "l"}, - {input: PathPermissions{Move: true}, expected: "m"}, - {input: PathPermissions{Execute: true}, expected: "e"}, - {input: PathPermissions{Ownership: true}, expected: "o"}, - {input: PathPermissions{Permissions: true}, expected: "p"}, - {input: PathPermissions{ + {input: FilePermissions{Read: true}, expected: "r"}, + {input: FilePermissions{Add: true}, expected: "a"}, + {input: FilePermissions{Create: true}, expected: "c"}, + {input: FilePermissions{Write: true}, expected: "w"}, + {input: FilePermissions{Delete: true}, expected: "d"}, + {input: FilePermissions{List: true}, expected: "l"}, + {input: FilePermissions{Move: true}, expected: "m"}, + {input: FilePermissions{Execute: true}, expected: "e"}, + {input: FilePermissions{Ownership: true}, expected: "o"}, + {input: FilePermissions{Permissions: true}, expected: "p"}, + {input: FilePermissions{ Read: true, Add: true, Create: true, @@ -130,22 +130,22 @@ func TestPathPermissions_String(t *testing.T) { } } -func TestPathPermissions_Parse(t *testing.T) { +func TestFilePermissions_Parse(t *testing.T) { testdata := []struct { - expected PathPermissions + expected FilePermissions input string }{ - {expected: PathPermissions{Read: true}, input: "r"}, - {expected: PathPermissions{Add: true}, input: "a"}, - {expected: PathPermissions{Create: true}, input: "c"}, - {expected: PathPermissions{Write: true}, input: "w"}, - {expected: PathPermissions{Delete: true}, input: "d"}, - {expected: PathPermissions{List: true}, input: "l"}, - {expected: PathPermissions{Move: true}, input: "m"}, - {expected: PathPermissions{Execute: true}, input: "e"}, - {expected: PathPermissions{Ownership: true}, input: "o"}, - {expected: PathPermissions{Permissions: true}, input: "p"}, - {expected: PathPermissions{ + {expected: FilePermissions{Read: true}, input: "r"}, + {expected: FilePermissions{Add: true}, input: "a"}, + {expected: FilePermissions{Create: true}, input: "c"}, + {expected: FilePermissions{Write: true}, input: "w"}, + {expected: FilePermissions{Delete: true}, input: "d"}, + {expected: FilePermissions{List: true}, input: "l"}, + {expected: FilePermissions{Move: true}, input: "m"}, + {expected: FilePermissions{Execute: true}, input: "e"}, + {expected: FilePermissions{Ownership: true}, input: "o"}, + {expected: FilePermissions{Permissions: true}, input: "p"}, + {expected: FilePermissions{ Read: true, Add: true, Create: true, @@ -157,7 +157,7 @@ func TestPathPermissions_Parse(t *testing.T) { Ownership: true, Permissions: true, }, input: "racwdlmeop"}, - {expected: PathPermissions{ + {expected: FilePermissions{ Read: true, Add: true, Create: true, diff --git a/sdk/storage/azdatalake/sas/url_parts_test.go b/sdk/storage/azdatalake/sas/url_parts_test.go index 88b8d94f7a10..f4694b148056 100644 --- a/sdk/storage/azdatalake/sas/url_parts_test.go +++ b/sdk/storage/azdatalake/sas/url_parts_test.go @@ -45,10 +45,10 @@ func TestParseURL(t *testing.T) { testContainer := "fakecontainer" fileNames := []string{"/._.TESTT.txt", "/.gitignore/dummyfile1"} - const sasStr = "sv=2019-12-12&sr=b&st=2111-01-09T01:42:34.936Z&se=2222-03-09T01:42:34.936Z&sp=rw&sip=168.1.5.60-168.1.5.70&spr=https,http&si=myIdentifier&ss=bf&srt=s&sig=clNxbtnkKSHw7f3KMEVVc4agaszoRFdbZr%2FWBmPNsrw%3D" + const sasStr = "?sv=2019-12-12&sr=b&st=2111-01-09T01:42:34.936Z&se=2222-03-09T01:42:34.936Z&sp=rw&sip=168.1.5.60-168.1.5.70&spr=https,http&si=myIdentifier&ss=bf&srt=s&sig=clNxbtnkKSHw7f3KMEVVc4agaszoRFdbZr%2FWBmPNsrw%3D" for _, fileName := range fileNames { - urlWithVersion := fmt.Sprintf("https://%s.blob.core.windows.net/%s%s", testStorageAccount, testContainer, fileName) + urlWithVersion := fmt.Sprintf("https://%s.blob.core.windows.net/%s%s?%s", testStorageAccount, testContainer, fileName, sasStr) blobURLParts, err := ParseURL(urlWithVersion) require.NoError(t, err) @@ -60,7 +60,7 @@ func TestParseURL(t *testing.T) { } for _, fileName := range fileNames { - urlWithVersion := fmt.Sprintf("https://%s.blob.core.windows.net/%s%s", testStorageAccount, testContainer, fileName) + urlWithVersion := fmt.Sprintf("https://%s.blob.core.windows.net/%s%s?%s", testStorageAccount, testContainer, fileName, sasStr) blobURLParts, err := ParseURL(urlWithVersion) require.NoError(t, err) diff --git a/sdk/storage/azdatalake/service/client.go b/sdk/storage/azdatalake/service/client.go index 9a31c3f6a8ab..9a20d5fdf076 100644 --- a/sdk/storage/azdatalake/service/client.go +++ b/sdk/storage/azdatalake/service/client.go @@ -17,17 +17,21 @@ import ( "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/generated_blob" "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" "strings" "time" ) +// FOR SERVICE CLIENT WE STORE THE GENERATED BLOB LAYER IN ORDER TO USE FS LISTING AND THE TRANSFORMS IT HAS + // ClientOptions contains the optional parameters when creating a Client. type ClientOptions base.ClientOptions // Client represents a URL to the Azure Datalake Storage service. -type Client base.CompositeClient[generated.ServiceClient, generated.ServiceClient, service.Client] +type Client base.CompositeClient[generated.ServiceClient, generated_blob.ServiceClient, service.Client] // NewClient creates an instance of Client with the specified values. // - serviceURL - the URL of the blob e.g. https://.dfs.core.windows.net/ @@ -140,7 +144,7 @@ func NewClientFromConnectionString(connectionString string, options *ClientOptio } func (s *Client) getClientOptions() *base.ClientOptions { - return base.GetCompositeClientOptions((*base.CompositeClient[generated.ServiceClient, generated.ServiceClient, service.Client])(s)) + return base.GetCompositeClientOptions((*base.CompositeClient[generated.ServiceClient, generated_blob.ServiceClient, service.Client])(s)) } // NewFilesystemClient creates a new filesystem.Client object by concatenating filesystemName to the end of this Client's URL. @@ -169,26 +173,26 @@ func (s *Client) GetUserDelegationCredential(ctx context.Context, info KeyInfo, } func (s *Client) generatedServiceClientWithDFS() *generated.ServiceClient { - svcClientWithDFS, _, _ := base.InnerClients((*base.CompositeClient[generated.ServiceClient, generated.ServiceClient, service.Client])(s)) + svcClientWithDFS, _, _ := base.InnerClients((*base.CompositeClient[generated.ServiceClient, generated_blob.ServiceClient, service.Client])(s)) return svcClientWithDFS } -func (s *Client) generatedServiceClientWithBlob() *generated.ServiceClient { - _, svcClientWithBlob, _ := base.InnerClients((*base.CompositeClient[generated.ServiceClient, generated.ServiceClient, service.Client])(s)) +func (s *Client) generatedServiceClientWithBlob() *generated_blob.ServiceClient { + _, svcClientWithBlob, _ := base.InnerClients((*base.CompositeClient[generated.ServiceClient, generated_blob.ServiceClient, service.Client])(s)) return svcClientWithBlob } func (s *Client) serviceClient() *service.Client { - _, _, serviceClient := base.InnerClients((*base.CompositeClient[generated.ServiceClient, generated.ServiceClient, service.Client])(s)) + _, _, serviceClient := base.InnerClients((*base.CompositeClient[generated.ServiceClient, generated_blob.ServiceClient, service.Client])(s)) return serviceClient } func (s *Client) sharedKey() *exported.SharedKeyCredential { - return base.SharedKeyComposite((*base.CompositeClient[generated.ServiceClient, generated.ServiceClient, service.Client])(s)) + return base.SharedKeyComposite((*base.CompositeClient[generated.ServiceClient, generated_blob.ServiceClient, service.Client])(s)) } func (s *Client) identityCredential() *azcore.TokenCredential { - return base.IdentityCredentialComposite((*base.CompositeClient[generated.ServiceClient, generated.ServiceClient, service.Client])(s)) + return base.IdentityCredentialComposite((*base.CompositeClient[generated.ServiceClient, generated_blob.ServiceClient, service.Client])(s)) } // DFSURL returns the URL endpoint used by the Client object. @@ -236,32 +240,47 @@ func (s *Client) GetProperties(ctx context.Context, options *GetPropertiesOption // NewListFilesystemsPager operation returns a pager of the shares under the specified account. (blob3) // For more information, see https://learn.microsoft.com/en-us/rest/api/storageservices/list-shares -func (s *Client) NewListFilesystemsPager(options *ListFilesystemsOptions) *runtime.Pager[ListFilesystemsResponse] { +func (s *Client) NewListFilesystemsPager(o *ListFilesystemsOptions) *runtime.Pager[ListFilesystemsResponse] { + listOptions := generated_blob.ServiceClientListContainersSegmentOptions{} + if o != nil { + if o.Include.Deleted { + listOptions.Include = append(listOptions.Include, generated_blob.ListContainersIncludeTypeDeleted) + } + if o.Include.Metadata { + listOptions.Include = append(listOptions.Include, generated_blob.ListContainersIncludeTypeMetadata) + } + if o.Include.System { + listOptions.Include = append(listOptions.Include, generated_blob.ListContainersIncludeTypeSystem) + } + listOptions.Marker = o.Marker + listOptions.Maxresults = o.MaxResults + listOptions.Prefix = o.Prefix + } return runtime.NewPager(runtime.PagingHandler[ListFilesystemsResponse]{ More: func(page ListFilesystemsResponse) bool { return page.NextMarker != nil && len(*page.NextMarker) > 0 }, Fetcher: func(ctx context.Context, page *ListFilesystemsResponse) (ListFilesystemsResponse, error) { + var req *policy.Request + var err error if page == nil { - page = &ListFilesystemsResponse{} - opts := options.format() - page.blobPager = s.serviceClient().NewListContainersPager(opts) + req, err = s.generatedServiceClientWithBlob().ListContainersSegmentCreateRequest(ctx, &listOptions) + } else { + listOptions.Marker = page.NextMarker + req, err = s.generatedServiceClientWithBlob().ListContainersSegmentCreateRequest(ctx, &listOptions) + } + if err != nil { + return ListFilesystemsResponse{}, exported.ConvertToDFSError(err) } - newPage := ListFilesystemsResponse{} - currPage, err := page.blobPager.NextPage(context.TODO()) - err = exported.ConvertToDFSError(err) + resp, err := s.generatedServiceClientWithBlob().InternalClient().Pipeline().Do(req) if err != nil { - return newPage, err + return ListFilesystemsResponse{}, exported.ConvertToDFSError(err) + } + if !runtime.HasStatusCode(resp, http.StatusOK) { + return ListFilesystemsResponse{}, exported.ConvertToDFSError(runtime.NewResponseError(resp)) } - newPage.Prefix = currPage.Prefix - newPage.Marker = currPage.Marker - newPage.MaxResults = currPage.MaxResults - newPage.NextMarker = currPage.NextMarker - newPage.Filesystems = convertContainerItemsToFSItems(currPage.ContainerItems) - newPage.ServiceEndpoint = currPage.ServiceEndpoint - newPage.blobPager = page.blobPager - - return newPage, err + resp1, err := s.generatedServiceClientWithBlob().ListContainersSegmentHandleResponse(resp) + return resp1, exported.ConvertToDFSError(err) }, }) } diff --git a/sdk/storage/azdatalake/service/client_test.go b/sdk/storage/azdatalake/service/client_test.go index 53fd574b31a7..6d009463b140 100644 --- a/sdk/storage/azdatalake/service/client_test.go +++ b/sdk/storage/azdatalake/service/client_test.go @@ -62,7 +62,7 @@ type ServiceUnrecordedTestsSuite struct { suite.Suite } -func (s *ServiceRecordedTestsSuite) TestServiceClientFromConnectionString() { +func (s *ServiceUnrecordedTestsSuite) TestServiceClientFromConnectionString() { _require := require.New(s.T()) testName := s.T().Name() @@ -323,7 +323,7 @@ func (s *ServiceRecordedTestsSuite) TestAccountDeleteRetentionPolicyDaysOmitted( testcommon.ValidateErrorCode(_require, err, datalakeerror.InvalidXMLDocument) } -func (s *ServiceRecordedTestsSuite) TestSASServiceClient() { +func (s *ServiceUnrecordedTestsSuite) TestSASServiceClient() { _require := require.New(s.T()) testName := s.T().Name() cred, _ := testcommon.GetGenericSharedKeyCredential(testcommon.TestAccountDatalake) @@ -464,7 +464,7 @@ func (s *ServiceUnrecordedTestsSuite) TestNoSharedKeyCredError() { } -func (s *ServiceRecordedTestsSuite) TestGetFilesystemClient() { +func (s *ServiceUnrecordedTestsSuite) TestGetFilesystemClient() { _require := require.New(s.T()) testName := s.T().Name() accountName := os.Getenv("AZURE_STORAGE_ACCOUNT_NAME") @@ -486,7 +486,7 @@ func (s *ServiceRecordedTestsSuite) TestGetFilesystemClient() { _require.Nil(err) } -func (s *ServiceRecordedTestsSuite) TestSASFilesystemClient() { +func (s *ServiceUnrecordedTestsSuite) TestSASFilesystemClient() { _require := require.New(s.T()) testName := s.T().Name() accountName := os.Getenv("AZURE_STORAGE_ACCOUNT_NAME") @@ -519,7 +519,7 @@ func (s *ServiceRecordedTestsSuite) TestSASFilesystemClient() { testcommon.ValidateErrorCode(_require, err, datalakeerror.AuthorizationFailure) } -func (s *ServiceRecordedTestsSuite) TestSASFilesystem2() { +func (s *ServiceUnrecordedTestsSuite) TestSASFilesystem2() { _require := require.New(s.T()) testName := s.T().Name() accountName := os.Getenv("AZURE_STORAGE_ACCOUNT_NAME") @@ -592,15 +592,15 @@ func (s *ServiceRecordedTestsSuite) TestListFilesystemsBasic() { for pager.More() { resp, err := pager.NextPage(context.Background()) _require.Nil(err) - for _, ctnr := range resp.Filesystems { + for _, ctnr := range resp.FileSystemItems { _require.NotNil(ctnr.Name) if *ctnr.Name == fsName { _require.NotNil(ctnr.Properties) _require.NotNil(ctnr.Properties.LastModified) _require.NotNil(ctnr.Properties.ETag) - _require.Equal(*ctnr.Properties.LeaseStatus, azdatalake.StatusTypeUnlocked) - _require.Equal(*ctnr.Properties.LeaseState, azdatalake.StateTypeAvailable) + _require.Equal(*ctnr.Properties.LeaseStatus, service.StatusTypeUnlocked) + _require.Equal(*ctnr.Properties.LeaseState, service.StateTypeAvailable) _require.Nil(ctnr.Properties.LeaseDuration) _require.Nil(ctnr.Properties.PublicAccess) _require.NotNil(ctnr.Metadata) @@ -653,15 +653,15 @@ func (s *ServiceRecordedTestsSuite) TestListFilesystemsBasicUsingConnectionStrin resp, err := pager.NextPage(context.Background()) _require.Nil(err) - for _, ctnr := range resp.Filesystems { + for _, ctnr := range resp.FileSystemItems { _require.NotNil(ctnr.Name) if *ctnr.Name == fsName { _require.NotNil(ctnr.Properties) _require.NotNil(ctnr.Properties.LastModified) _require.NotNil(ctnr.Properties.ETag) - _require.Equal(*ctnr.Properties.LeaseStatus, azdatalake.StatusTypeUnlocked) - _require.Equal(*ctnr.Properties.LeaseState, azdatalake.StateTypeAvailable) + _require.Equal(*ctnr.Properties.LeaseStatus, service.StatusTypeUnlocked) + _require.Equal(*ctnr.Properties.LeaseState, service.StateTypeAvailable) _require.Nil(ctnr.Properties.LeaseDuration) _require.Nil(ctnr.Properties.PublicAccess) _require.NotNil(ctnr.Metadata) @@ -718,7 +718,7 @@ func (s *ServiceRecordedTestsSuite) TestListFilesystemsPaged() { for pager.More() { resp, err := pager.NextPage(context.Background()) _require.Nil(err) - for _, ctnr := range resp.Filesystems { + for _, ctnr := range resp.FileSystemItems { _require.NotNil(ctnr.Name) results = append(results, *ctnr) count += 1 @@ -760,7 +760,7 @@ func (s *ServiceRecordedTestsSuite) TestAccountListFilesystemsEmptyPrefix() { resp, err := pager.NextPage(context.Background()) _require.Nil(err) - for _, container := range resp.Filesystems { + for _, container := range resp.FileSystemItems { count++ _require.NotNil(container.Name) } diff --git a/sdk/storage/azdatalake/service/constants.go b/sdk/storage/azdatalake/service/constants.go new file mode 100644 index 000000000000..76069177867b --- /dev/null +++ b/sdk/storage/azdatalake/service/constants.go @@ -0,0 +1,57 @@ +//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 service + +import ( + "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/filesystem" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/internal/generated_blob" +) + +// PublicAccessType defines values for AccessType - private (default) or file or filesystem. +type PublicAccessType = filesystem.PublicAccessType + +const ( + File PublicAccessType = filesystem.File + Filesystem PublicAccessType = filesystem.Filesystem +) + +// StatusType defines values for StatusType +type StatusType = generated_blob.LeaseStatusType + +const ( + StatusTypeLocked StatusType = generated_blob.LeaseStatusTypeLocked + StatusTypeUnlocked StatusType = generated_blob.LeaseStatusTypeUnlocked +) + +// PossibleStatusTypeValues returns the possible values for the StatusType const type. +func PossibleStatusTypeValues() []StatusType { + return generated_blob.PossibleLeaseStatusTypeValues() +} + +// DurationType defines values for DurationType +type DurationType = generated_blob.LeaseDurationType + +const ( + DurationTypeInfinite DurationType = generated_blob.LeaseDurationTypeInfinite + DurationTypeFixed DurationType = generated_blob.LeaseDurationTypeFixed +) + +// PossibleDurationTypeValues returns the possible values for the DurationType const type. +func PossibleDurationTypeValues() []DurationType { + return generated_blob.PossibleLeaseDurationTypeValues() +} + +// StateType defines values for StateType +type StateType = generated_blob.LeaseStateType + +const ( + StateTypeAvailable StateType = generated_blob.LeaseStateTypeAvailable + StateTypeLeased StateType = generated_blob.LeaseStateTypeLeased + StateTypeExpired StateType = generated_blob.LeaseStateTypeExpired + StateTypeBreaking StateType = generated_blob.LeaseStateTypeBreaking + StateTypeBroken StateType = generated_blob.LeaseStateTypeBroken +) diff --git a/sdk/storage/azdatalake/service/models.go b/sdk/storage/azdatalake/service/models.go index 5efbd2b8c927..2c2c27af8d5e 100644 --- a/sdk/storage/azdatalake/service/models.go +++ b/sdk/storage/azdatalake/service/models.go @@ -10,61 +10,27 @@ import ( "github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/service" "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/filesystem" "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/generated_blob" "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/sas" "time" ) import blobSAS "github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/sas" -// KeyInfo contains KeyInfo struct. -type KeyInfo = generated.KeyInfo - +// CreateFilesystemOptions contains the optional parameters for the Filesystem Create method. type CreateFilesystemOptions = filesystem.CreateOptions +// DeleteFilesystemOptions contains the optional parameters for the Filesystem Delete method. type DeleteFilesystemOptions = filesystem.DeleteOptions -// CORSRule - CORS is an HTTP feature that enables a web application running under one domain to access resources in another -// domain. Web browsers implement a security restriction known as same-origin policy that -// prevents a web page from calling APIs in a different domain; CORS provides a secure way to allow one domain (the origin -// domain) to call APIs in another domain. -type CORSRule = service.CORSRule - -// StorageServiceProperties - Storage Service Properties. -type StorageServiceProperties = service.StorageServiceProperties - -// RetentionPolicy - the retention policy which determines how long the associated data should persist. -type RetentionPolicy = service.RetentionPolicy - -// Metrics - a summary of request statistics grouped by API in hour or minute aggregates -type Metrics = service.Metrics - -// Logging - Azure Analytics Logging settings. -type Logging = service.Logging - -// StaticWebsite - The properties that enable an account to host a static website. -type StaticWebsite = service.StaticWebsite - -// SharedKeyCredential contains an account's name and its primary or secondary key. -type SharedKeyCredential = exported.SharedKeyCredential - -// PublicAccessType defines values for AccessType - private (default) or file or filesystem. -type PublicAccessType = filesystem.PublicAccessType - // GetUserDelegationCredentialOptions contains optional parameters for Service.GetUserDelegationKey method. type GetUserDelegationCredentialOptions struct { // placeholder for future options } -func (o *GetUserDelegationCredentialOptions) format() *generated.ServiceClientGetUserDelegationKeyOptions { +func (o *GetUserDelegationCredentialOptions) format() *generated_blob.ServiceClientGetUserDelegationKeyOptions { return nil } -// UserDelegationCredential contains an account's name and its user delegation key. -type UserDelegationCredential = exported.UserDelegationCredential - -// UserDelegationKey contains UserDelegationKey. -type UserDelegationKey = exported.UserDelegationKey - // GetPropertiesOptions contains the optional parameters for the Client.GetProperties method. type GetPropertiesOptions struct { // placeholder for future options @@ -127,16 +93,8 @@ type ListFilesystemsInclude struct { // Tells the service whether to return soft-deleted filesystems. Deleted bool -} -func (o *ListFilesystemsInclude) format() service.ListContainersInclude { - if o == nil { - return service.ListContainersInclude{} - } - return service.ListContainersInclude{ - Metadata: o.Metadata, - Deleted: o.Deleted, - } + System bool } // ListFilesystemsOptions contains the optional parameters for the Client.List method. @@ -147,18 +105,6 @@ type ListFilesystemsOptions struct { Prefix *string } -func (o *ListFilesystemsOptions) format() *service.ListContainersOptions { - if o == nil { - return nil - } - return &service.ListContainersOptions{ - Include: o.Include.format(), - Marker: o.Marker, - MaxResults: o.MaxResults, - Prefix: o.Prefix, - } -} - // GetSASURLOptions contains the optional parameters for the Client.GetSASURL method. type GetSASURLOptions struct { StartTime *time.Time @@ -188,3 +134,57 @@ func (o *GetSASURLOptions) format(resources sas.AccountResourceTypes, permission StartTime: o.StartTime, } } + +// KeyInfo contains KeyInfo struct. +type KeyInfo = generated_blob.KeyInfo + +// CORSRule - CORS is an HTTP feature that enables a web application running under one domain to access resources in another +// domain. Web browsers implement a security restriction known as same-origin policy that +// prevents a web page from calling APIs in a different domain; CORS provides a secure way to allow one domain (the origin +// domain) to call APIs in another domain. +type CORSRule = service.CORSRule + +// RetentionPolicy - the retention policy which determines how long the associated data should persist. +type RetentionPolicy = service.RetentionPolicy + +// Metrics - a summary of request statistics grouped by API in hour or minute aggregates +type Metrics = service.Metrics + +// Logging - Azure Analytics Logging settings. +type Logging = service.Logging + +// StaticWebsite - The properties that enable an account to host a static website. +type StaticWebsite = service.StaticWebsite + +// SharedKeyCredential contains an account's name and its primary or secondary key. +type SharedKeyCredential = exported.SharedKeyCredential + +// UserDelegationCredential contains an account's name and its user delegation key. +type UserDelegationCredential = exported.UserDelegationCredential + +// UserDelegationKey contains UserDelegationKey. +type UserDelegationKey = exported.UserDelegationKey + +// AccessConditions identifies blob-specific access conditions which you optionally set. +type AccessConditions = exported.AccessConditions + +// LeaseAccessConditions contains optional parameters to access leased entity. +type LeaseAccessConditions = exported.LeaseAccessConditions + +// ModifiedAccessConditions contains a group of parameters for specifying access conditions. +type ModifiedAccessConditions = exported.ModifiedAccessConditions + +// CPKScopeInfo contains a group of parameters for the FilesystemClient.Create method. +type CPKScopeInfo = filesystem.CPKScopeInfo + +// StorageServiceProperties - Storage Service Properties. Returned in GetServiceProperties call. +type StorageServiceProperties = service.StorageServiceProperties + +// ListFilesystemsSegmentResponse contains fields from the ListFilesystems operation +type ListFilesystemsSegmentResponse = generated_blob.ListFileSystemsSegmentResponse + +// FilesystemItem contains fields from the ListFilesystems operation +type FilesystemItem = generated_blob.FileSystemItem + +// FilesystemProperties contains fields from the ListFilesystems operation +type FilesystemProperties = generated_blob.FileSystemProperties diff --git a/sdk/storage/azdatalake/service/responses.go b/sdk/storage/azdatalake/service/responses.go index 6a6cecd23b81..aa3581babdd7 100644 --- a/sdk/storage/azdatalake/service/responses.go +++ b/sdk/storage/azdatalake/service/responses.go @@ -10,12 +10,9 @@ package service import ( - "github.com/Azure/azure-sdk-for-go/sdk/azcore" - "github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime" "github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/service" - "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake" "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/filesystem" - "time" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/internal/generated_blob" ) // CreateFilesystemResponse contains the response fields for the CreateFilesystem operation. @@ -30,96 +27,5 @@ type SetPropertiesResponse = service.SetPropertiesResponse // GetPropertiesResponse contains the response fields for the GetProperties operation. type GetPropertiesResponse = service.GetPropertiesResponse -// TODO: use below after implementing listing - -type ListFilesystemsResponse struct { - ListFilesystemsSegmentResponse - // ClientRequestID contains the information returned from the x-ms-client-request-id header response. - ClientRequestID *string - - // RequestID contains the information returned from the x-ms-request-id header response. - RequestID *string - - // Version contains the information returned from the x-ms-version header response. - Version *string - - blobPager *runtime.Pager[service.ListContainersResponse] -} - -// ListFilesystemsSegmentResponse - An enumeration of containers -type ListFilesystemsSegmentResponse struct { - // REQUIRED - Filesystems []*FilesystemItem - - // REQUIRED - ServiceEndpoint *string - Marker *string - MaxResults *int32 - NextMarker *string - Prefix *string -} - -// FilesystemItem - An Azure Storage filesystem -type FilesystemItem struct { - // REQUIRED - Name *string - - // REQUIRED; Properties of a container - Properties *FilesystemProperties - Deleted *bool - - // Dictionary of - Metadata map[string]*string - Version *string -} - -// FilesystemProperties - Properties of a filesystem -type FilesystemProperties struct { - // REQUIRED - ETag *azcore.ETag - - // REQUIRED - LastModified *time.Time - DefaultEncryptionScope *string - DeletedTime *time.Time - HasImmutabilityPolicy *bool - HasLegalHold *bool - - // Indicates if version level worm is enabled on this container. - IsImmutableStorageWithVersioningEnabled *bool - LeaseDuration *azdatalake.DurationType - LeaseState *azdatalake.StateType - LeaseStatus *azdatalake.StatusType - PreventEncryptionScopeOverride *bool - PublicAccess *PublicAccessType - RemainingRetentionDays *int32 -} - -// converter from container items to filesystem items -func convertContainerItemsToFSItems(items []*service.ContainerItem) []*FilesystemItem { - var filesystemItems []*FilesystemItem - for _, item := range items { - filesystemItems = append(filesystemItems, &FilesystemItem{ - Name: item.Name, - Properties: &FilesystemProperties{ - LastModified: item.Properties.LastModified, - ETag: item.Properties.ETag, - DefaultEncryptionScope: item.Properties.DefaultEncryptionScope, - LeaseStatus: item.Properties.LeaseStatus, - LeaseState: item.Properties.LeaseState, - LeaseDuration: item.Properties.LeaseDuration, - PublicAccess: item.Properties.PublicAccess, - HasImmutabilityPolicy: item.Properties.HasImmutabilityPolicy, - HasLegalHold: item.Properties.HasLegalHold, - IsImmutableStorageWithVersioningEnabled: item.Properties.IsImmutableStorageWithVersioningEnabled, - PreventEncryptionScopeOverride: item.Properties.PreventEncryptionScopeOverride, - RemainingRetentionDays: item.Properties.RemainingRetentionDays, - DeletedTime: item.Properties.DeletedTime, - }, - Deleted: item.Deleted, - Metadata: item.Metadata, - Version: item.Version, - }) - } - return filesystemItems -} +// ListFilesystemsResponse contains the response fields for the ListFilesystems operation. +type ListFilesystemsResponse = generated_blob.ServiceClientListFileSystemsSegmentResponse diff --git a/sdk/storage/azdatalake/test-resources.json b/sdk/storage/azdatalake/test-resources.json new file mode 100644 index 000000000000..c6259f7ab02f --- /dev/null +++ b/sdk/storage/azdatalake/test-resources.json @@ -0,0 +1,579 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "baseName": { + "type": "String" + }, + "tenantId": { + "type": "string", + "defaultValue": "72f988bf-86f1-41af-91ab-2d7cd011db47", + "metadata": { + "description": "The tenant ID to which the application and resources belong." + } + }, + "testApplicationOid": { + "type": "string", + "metadata": { + "description": "The principal to assign the role to. This is application object id." + } + } + }, + "variables": { + "mgmtApiVersion": "2022-09-01", + "authorizationApiVersion": "2018-09-01-preview", + "blobDataContributorRoleId": "[concat('/subscriptions/', subscription().subscriptionId, '/providers/Microsoft.Authorization/roleDefinitions/ba92f5b4-2d11-453d-a403-e96b0029c9fe')]", + "contributorRoleId": "[concat('/subscriptions/', subscription().subscriptionId, '/providers/Microsoft.Authorization/roleDefinitions/b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "blobDataOwnerRoleId": "[concat('/subscriptions/', subscription().subscriptionId, '/providers/Microsoft.Authorization/roleDefinitions/b7e6dc6d-f1e8-4753-8033-0f276bb0955b')]", + "primaryAccountName": "[concat(parameters('baseName'), 'prim')]", + "immutableAccountName": "[concat(parameters('baseName'), 'imm')]", + "primaryEncryptionScopeName": "encryptionScope", + "primaryEncryptionScope": "[concat(parameters('baseName'), 'prim', concat('/', variables('primaryEncryptionScopeName')))]", + "secondaryAccountName": "[concat(parameters('baseName'), 'sec')]", + "premiumAccountName": "[concat(parameters('baseName'), 'prem')]", + "dataLakeAccountName": "[concat(parameters('baseName'), 'dtlk')]", + "softDeleteAccountName": "[concat(parameters('baseName'), 'sftdl')]", + "premiumFileAccountName": "[concat(parameters('baseName'), 'pfile')]", + "webjobsPrimaryAccountName": "[concat(parameters('baseName'), 'wjprim')]", + "webjobsSecondaryAccountName": "[concat(parameters('baseName'), 'wjsec')]", + "location": "[resourceGroup().location]", + "resourceGroupName": "[resourceGroup().name]", + "subscriptionId": "[subscription().subscriptionId]", + "encryption": { + "services": { + "file": { + "enabled": true + }, + "blob": { + "enabled": true + } + }, + "keySource": "Microsoft.Storage" + }, + "networkAcls": { + "bypass": "AzureServices", + "virtualNetworkRules": [], + "ipRules": [], + "defaultAction": "Allow" + } + }, + "resources": [ + { + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "[variables('authorizationApiVersion')]", + "name": "[guid(concat('dataContributorRoleId', resourceGroup().id))]", + "properties": { + "roleDefinitionId": "[variables('blobDataContributorRoleId')]", + "principalId": "[parameters('testApplicationOid')]" + } + }, + { + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "[variables('authorizationApiVersion')]", + "name": "[guid(concat('contributorRoleId', resourceGroup().id))]", + "properties": { + "roleDefinitionId": "[variables('contributorRoleId')]", + "principalId": "[parameters('testApplicationOid')]" + } + }, + { + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "[variables('authorizationApiVersion')]", + "name": "[guid(concat('blobDataOwnerRoleId', resourceGroup().id))]", + "properties": { + "roleDefinitionId": "[variables('blobDataOwnerRoleId')]", + "principalId": "[parameters('testApplicationOid')]" + } + }, + { + "type": "Microsoft.Storage/storageAccounts", + "apiVersion": "[variables('mgmtApiVersion')]", + "name": "[variables('primaryAccountName')]", + "location": "[variables('location')]", + "sku": { + "name": "Standard_RAGRS", + "tier": "Standard" + }, + "kind": "StorageV2", + "properties": { + "networkAcls": "[variables('networkAcls')]", + "supportsHttpsTrafficOnly": true, + "encryption": "[variables('encryption')]", + "accessTier": "Hot" + } + }, + { + "type": "Microsoft.Storage/storageAccounts/blobServices", + "apiVersion": "[variables('mgmtApiVersion')]", + "name": "[concat(variables('primaryAccountName'), '/default')]", + "properties": { + "isVersioningEnabled": true, + "lastAccessTimeTrackingPolicy": { + "enable": true, + "name": "AccessTimeTracking", + "trackingGranularityInDays": 1, + "blobType": [ + "blockBlob" + ] + } + }, + "dependsOn": [ + "[variables('primaryAccountName')]" + ] + }, + { + "type": "Microsoft.Storage/storageAccounts", + "apiVersion": "[variables('mgmtApiVersion')]", + "name": "[variables('immutableAccountName')]", + "location": "[variables('location')]", + "sku": { + "name": "Standard_RAGRS", + "tier": "Standard" + }, + "kind": "StorageV2", + "properties": { + "networkAcls": "[variables('networkAcls')]", + "supportsHttpsTrafficOnly": true, + "encryption": "[variables('encryption')]", + "accessTier": "Hot", + "immutableStorageWithVersioning": { + "enabled": true + } + } + }, + { + "type": "Microsoft.Storage/storageAccounts/blobServices", + "apiVersion": "[variables('mgmtApiVersion')]", + "name": "[concat(variables('immutableAccountName'), '/default')]", + "properties": { + "isVersioningEnabled": true, + "lastAccessTimeTrackingPolicy": { + "enable": true, + "name": "AccessTimeTracking", + "trackingGranularityInDays": 1, + "blobType": [ + "blockBlob" + ] + } + }, + "dependsOn": [ + "[variables('immutableAccountName')]" + ] + }, + { + "type": "Microsoft.Storage/storageAccounts/encryptionScopes", + "apiVersion": "[variables('mgmtApiVersion')]", + "name": "[variables('primaryEncryptionScope')]", + "properties": { + "source": "Microsoft.Storage", + "state": "Enabled" + }, + "dependsOn": [ + "[variables('primaryAccountName')]" + ] + }, + { + "type": "Microsoft.Storage/storageAccounts", + "apiVersion": "[variables('mgmtApiVersion')]", + "name": "[variables('secondaryAccountName')]", + "location": "[variables('location')]", + "sku": { + "name": "Standard_RAGRS", + "tier": "Standard" + }, + "kind": "StorageV2", + "properties": { + "networkAcls": "[variables('networkAcls')]", + "supportsHttpsTrafficOnly": true, + "encryption": "[variables('encryption')]", + "accessTier": "Hot" + } + }, + { + "type": "Microsoft.Storage/storageAccounts", + "apiVersion": "[variables('mgmtApiVersion')]", + "name": "[variables('premiumAccountName')]", + "location": "[variables('location')]", + "sku": { + "name": "Premium_LRS", + "tier": "Premium" + }, + "kind": "StorageV2", + "properties": { + "networkAcls": "[variables('networkAcls')]", + "supportsHttpsTrafficOnly": true, + "encryption": "[variables('encryption')]", + "accessTier": "Hot" + } + }, + { + "type": "Microsoft.Storage/storageAccounts", + "apiVersion": "[variables('mgmtApiVersion')]", + "name": "[variables('dataLakeAccountName')]", + "location": "[variables('location')]", + "sku": { + "name": "Standard_RAGRS", + "tier": "Standard" + }, + "kind": "StorageV2", + "properties": { + "isHnsEnabled": true, + "networkAcls": "[variables('networkAcls')]", + "supportsHttpsTrafficOnly": true, + "encryption": "[variables('encryption')]", + "accessTier": "Hot" + } + }, + { + "type": "Microsoft.Storage/storageAccounts/blobServices", + "apiVersion": "[variables('mgmtApiVersion')]", + "name": "[concat(variables('dataLakeAccountName'), '/default')]", + "properties": { + "containerDeleteRetentionPolicy": { + "enabled": true, + "days": 1 + } + }, + "dependsOn": [ + "[variables('dataLakeAccountName')]" + ] + }, + { + "type": "Microsoft.Storage/storageAccounts", + "apiVersion": "[variables('mgmtApiVersion')]", + "name": "[variables('softDeleteAccountName')]", + "location": "[variables('location')]", + "sku": { + "name": "Standard_RAGRS", + "tier": "Standard" + }, + "kind": "StorageV2", + "properties": { + "networkAcls": "[variables('networkAcls')]", + "supportsHttpsTrafficOnly": true, + "encryption": "[variables('encryption')]", + "accessTier": "Hot" + } + }, + { + "type": "Microsoft.Storage/storageAccounts/blobServices", + "apiVersion": "[variables('mgmtApiVersion')]", + "name": "[concat(variables('softDeleteAccountName'), '/default')]", + "properties": { + "isVersioningEnabled": true, + "deleteRetentionPolicy": { + "allowPermanentDelete": true, + "enabled": true, + "days": 1 + }, + "containerDeleteRetentionPolicy": { + "enabled": true, + "days": 1 + } + }, + "dependsOn": [ + "[variables('softDeleteAccountName')]" + ] + }, + { + "type": "Microsoft.Storage/storageAccounts/fileServices", + "apiVersion": "[variables('mgmtApiVersion')]", + "name": "[concat(variables('softDeleteAccountName'), '/default')]", + "properties": { + "shareDeleteRetentionPolicy": { + "enabled": true, + "days": 1 + } + }, + "dependsOn": [ + "[variables('softDeleteAccountName')]" + ] + }, + { + "type": "Microsoft.Storage/storageAccounts", + "apiVersion": "[variables('mgmtApiVersion')]", + "name": "[variables('premiumFileAccountName')]", + "location": "[variables('location')]", + "sku": { + "name": "Premium_LRS", + "tier": "Premium" + }, + "kind": "FileStorage", + "properties": { + "networkAcls": "[variables('networkAcls')]", + "supportsHttpsTrafficOnly": true, + "encryption": "[variables('encryption')]", + "accessTier": "Hot" + } + }, + { + "type": "Microsoft.Storage/storageAccounts", + "apiVersion": "[variables('mgmtApiVersion')]", + "name": "[variables('webjobsPrimaryAccountName')]", + "location": "[variables('location')]", + "sku": { + "name": "Standard_RAGRS", + "tier": "Standard" + }, + "kind": "StorageV2", + "properties": { + "networkAcls": "[variables('networkAcls')]", + "supportsHttpsTrafficOnly": true, + "encryption": "[variables('encryption')]", + "accessTier": "Hot" + } + }, + { + "type": "Microsoft.Storage/storageAccounts", + "apiVersion": "[variables('mgmtApiVersion')]", + "name": "[variables('webjobsSecondaryAccountName')]", + "location": "[variables('location')]", + "sku": { + "name": "Standard_RAGRS", + "tier": "Standard" + }, + "kind": "StorageV2", + "properties": { + "networkAcls": "[variables('networkAcls')]", + "supportsHttpsTrafficOnly": true, + "encryption": "[variables('encryption')]", + "accessTier": "Hot" + } + } + ], + "functions": [ + { + "namespace": "url", + "members": { + "serviceEndpointSuffix": { + "parameters": [ + { + "name": "endpoint", + "type": "string" + } + ], + "output": { + "type": "string", + "value": "[substring(parameters('endpoint'), add(indexOf(parameters('endpoint'), '.'),1), sub(length(parameters('endpoint')), add(indexOf(parameters('endpoint'), '.'),2)))]" + } + } + } + }, + { + "namespace": "connectionString", + "members": { + "create": { + "parameters": [ + { + "name": "accountName", + "type": "string" + }, + { + "name": "accountKey", + "type": "string" + }, + { + "name": "blobEndpoint", + "type": "string" + }, + { + "name": "queueEndpoint", + "type": "string" + }, + { + "name": "fileEndpoint", + "type": "string" + }, + { + "name": "tableEndpoint", + "type": "string" + } + ], + "output": { + "type": "string", + "value": "[concat('DefaultEndpointsProtocol=https;AccountName=', parameters('accountName'), ';AccountKey=', parameters('accountKey'), ';BlobEndpoint=', parameters('blobEndpoint'), ';QueueEndpoint=', parameters('queueEndpoint'), ';FileEndpoint=', parameters('fileEndpoint'), ';TableEndpoint=', parameters('tableEndpoint'))]" + } + } + } + } + ], + "outputs": { + "AZURE_STORAGE_ACCOUNT_NAME": { + "type": "string", + "value": "[variables('primaryAccountName')]" + }, + "AZURE_STORAGE_ACCOUNT_KEY": { + "type": "string", + "value": "[listKeys(resourceId('Microsoft.Storage/storageAccounts', variables('primaryAccountName')), variables('mgmtApiVersion')).keys[0].value]" + }, + "PRIMARY_STORAGE_ACCOUNT_BLOB_ENDPOINT_SUFFIX": { + "type": "string", + "value": "[url.serviceEndpointSuffix(reference(resourceId('Microsoft.Storage/storageAccounts', variables('primaryAccountName')), variables('mgmtApiVersion')).primaryEndpoints.blob)]" + }, + "PRIMARY_STORAGE_ACCOUNT_FILE_ENDPOINT_SUFFIX": { + "type": "string", + "value": "[url.serviceEndpointSuffix(reference(resourceId('Microsoft.Storage/storageAccounts', variables('primaryAccountName')), variables('mgmtApiVersion')).primaryEndpoints.file)]" + }, + "PRIMARY_STORAGE_ACCOUNT_QUEUE_ENDPOINT_SUFFIX": { + "type": "string", + "value": "[url.serviceEndpointSuffix(reference(resourceId('Microsoft.Storage/storageAccounts', variables('primaryAccountName')), variables('mgmtApiVersion')).primaryEndpoints.queue)]" + }, + "PRIMARY_STORAGE_ACCOUNT_TABLE_ENDPOINT_SUFFIX": { + "type": "string", + "value": "[url.serviceEndpointSuffix(reference(resourceId('Microsoft.Storage/storageAccounts', variables('primaryAccountName')), variables('mgmtApiVersion')).primaryEndpoints.table)]" + }, + "SECONDARY_AZURE_STORAGE_ACCOUNT_NAME": { + "type": "string", + "value": "[variables('secondaryAccountName')]" + }, + "SECONDARY_AZURE_STORAGE_ACCOUNT_KEY": { + "type": "string", + "value": "[listKeys(resourceId('Microsoft.Storage/storageAccounts', variables('secondaryAccountName')), variables('mgmtApiVersion')).keys[0].value]" + }, + "SECONDARY_STORAGE_ACCOUNT_BLOB_ENDPOINT_SUFFIX": { + "type": "string", + "value": "[url.serviceEndpointSuffix(reference(resourceId('Microsoft.Storage/storageAccounts', variables('secondaryAccountName')), variables('mgmtApiVersion')).primaryEndpoints.blob)]" + }, + "SECONDARY_STORAGE_ACCOUNT_FILE_ENDPOINT_SUFFIX": { + "type": "string", + "value": "[url.serviceEndpointSuffix(reference(resourceId('Microsoft.Storage/storageAccounts', variables('secondaryAccountName')), variables('mgmtApiVersion')).primaryEndpoints.file)]" + }, + "SECONDARY_STORAGE_ACCOUNT_QUEUE_ENDPOINT_SUFFIX": { + "type": "string", + "value": "[url.serviceEndpointSuffix(reference(resourceId('Microsoft.Storage/storageAccounts', variables('secondaryAccountName')), variables('mgmtApiVersion')).primaryEndpoints.queue)]" + }, + "SECONDARY_STORAGE_ACCOUNT_TABLE_ENDPOINT_SUFFIX": { + "type": "string", + "value": "[url.serviceEndpointSuffix(reference(resourceId('Microsoft.Storage/storageAccounts', variables('secondaryAccountName')), variables('mgmtApiVersion')).primaryEndpoints.table)]" + }, + "BLOB_STORAGE_ACCOUNT_NAME": { + "type": "string", + "value": "[variables('secondaryAccountName')]" + }, + "BLOB_STORAGE_ACCOUNT_KEY": { + "type": "string", + "value": "[listKeys(resourceId('Microsoft.Storage/storageAccounts', variables('secondaryAccountName')), variables('mgmtApiVersion')).keys[0].value]" + }, + "PREMIUM_AZURE_STORAGE_ACCOUNT_NAME": { + "type": "string", + "value": "[variables('premiumAccountName')]" + }, + "PREMIUM_AZURE_STORAGE_ACCOUNT_KEY": { + "type": "string", + "value": "[listKeys(resourceId('Microsoft.Storage/storageAccounts', variables('premiumAccountName')), variables('mgmtApiVersion')).keys[0].value]" + }, + "PREMIUM_STORAGE_ACCOUNT_BLOB_ENDPOINT_SUFFIX": { + "type": "string", + "value": "[url.serviceEndpointSuffix(reference(resourceId('Microsoft.Storage/storageAccounts', variables('premiumAccountName')), variables('mgmtApiVersion')).primaryEndpoints.blob)]" + }, + "DATALAKE_AZURE_STORAGE_ACCOUNT_NAME": { + "type": "string", + "value": "[variables('dataLakeAccountName')]" + }, + "DATALAKE_AZURE_STORAGE_ACCOUNT_KEY": { + "type": "string", + "value": "[listKeys(resourceId('Microsoft.Storage/storageAccounts', variables('dataLakeAccountName')), variables('mgmtApiVersion')).keys[0].value]" + }, + "DATALAKE_STORAGE_ACCOUNT_BLOB_ENDPOINT_SUFFIX": { + "type": "string", + "value": "[url.serviceEndpointSuffix(reference(resourceId('Microsoft.Storage/storageAccounts', variables('dataLakeAccountName')), variables('mgmtApiVersion')).primaryEndpoints.blob)]" + }, + "DATALAKE_STORAGE_ACCOUNT_FILE_ENDPOINT_SUFFIX": { + "type": "string", + "value": "[url.serviceEndpointSuffix(reference(resourceId('Microsoft.Storage/storageAccounts', variables('dataLakeAccountName')), variables('mgmtApiVersion')).primaryEndpoints.file)]" + }, + "DATALAKE_STORAGE_ACCOUNT_QUEUE_ENDPOINT_SUFFIX": { + "type": "string", + "value": "[url.serviceEndpointSuffix(reference(resourceId('Microsoft.Storage/storageAccounts', variables('dataLakeAccountName')), variables('mgmtApiVersion')).primaryEndpoints.queue)]" + }, + "DATALAKE_STORAGE_ACCOUNT_TABLE_ENDPOINT_SUFFIX": { + "type": "string", + "value": "[url.serviceEndpointSuffix(reference(resourceId('Microsoft.Storage/storageAccounts', variables('dataLakeAccountName')), variables('mgmtApiVersion')).primaryEndpoints.table)]" + }, + "IMMUTABLE_AZURE_STORAGE_ACCOUNT_NAME": { + "type": "string", + "value": "[variables('immutableAccountName')]" + }, + "IMMUTABLE_AZURE_STORAGE_ACCOUNT_KEY": { + "type": "string", + "value": "[listKeys(resourceId('Microsoft.Storage/storageAccounts', variables('immutableAccountName')), variables('mgmtApiVersion')).keys[0].value]" + }, + "IMMUTABLE_AZURE_STORAGE_ACCOUNT_BLOB_ENDPOINT_SUFFIX": { + "type": "string", + "value": "[url.serviceEndpointSuffix(reference(resourceId('Microsoft.Storage/storageAccounts', variables('immutableAccountName')), variables('mgmtApiVersion')).primaryEndpoints.blob)]" + }, + "IMMUTABLE_STORAGE_ACCOUNT_FILE_ENDPOINT_SUFFIX": { + "type": "string", + "value": "[url.serviceEndpointSuffix(reference(resourceId('Microsoft.Storage/storageAccounts', variables('immutableAccountName')), variables('mgmtApiVersion')).primaryEndpoints.file)]" + }, + "IMMUTABLE_AZURE_STORAGE_ACCOUNT_QUEUE_ENDPOINT_SUFFIX": { + "type": "string", + "value": "[url.serviceEndpointSuffix(reference(resourceId('Microsoft.Storage/storageAccounts', variables('immutableAccountName')), variables('mgmtApiVersion')).primaryEndpoints.queue)]" + }, + "IMMUTABLE_AZURE_STORAGE_ACCOUNT_TABLE_ENDPOINT_SUFFIX": { + "type": "string", + "value": "[url.serviceEndpointSuffix(reference(resourceId('Microsoft.Storage/storageAccounts', variables('immutableAccountName')), variables('mgmtApiVersion')).primaryEndpoints.table)]" + }, + "SOFT_DELETE_AZURE_STORAGE_ACCOUNT_NAME": { + "type": "string", + "value": "[variables('softDeleteAccountName')]" + }, + "SOFT_DELETE_AZURE_STORAGE_ACCOUNT_KEY": { + "type": "string", + "value": "[listKeys(resourceId('Microsoft.Storage/storageAccounts', variables('softDeleteAccountName')), variables('mgmtApiVersion')).keys[0].value]" + }, + "SOFT_DELETE_AZURE_STORAGE_ACCOUNT_BLOB_ENDPOINT_SUFFIX": { + "type": "string", + "value": "[url.serviceEndpointSuffix(reference(resourceId('Microsoft.Storage/storageAccounts', variables('softDeleteAccountName')), variables('mgmtApiVersion')).primaryEndpoints.blob)]" + }, + "SOFT_DELETE_AZURE_STORAGE_ACCOUNT_FILE_ENDPOINT_SUFFIX": { + "type": "string", + "value": "[url.serviceEndpointSuffix(reference(resourceId('Microsoft.Storage/storageAccounts', variables('softDeleteAccountName')), variables('mgmtApiVersion')).primaryEndpoints.file)]" + }, + "SOFT_DELETE_AZURE_STORAGE_ACCOUNT_QUEUE_ENDPOINT_SUFFIX": { + "type": "string", + "value": "[url.serviceEndpointSuffix(reference(resourceId('Microsoft.Storage/storageAccounts', variables('softDeleteAccountName')), variables('mgmtApiVersion')).primaryEndpoints.queue)]" + }, + "SOFT_DELETE_AZURE_STORAGE_ACCOUNT_TABLE_ENDPOINT_SUFFIX": { + "type": "string", + "value": "[url.serviceEndpointSuffix(reference(resourceId('Microsoft.Storage/storageAccounts', variables('softDeleteAccountName')), variables('mgmtApiVersion')).primaryEndpoints.table)]" + }, + "PREMIUM_FILE_STORAGE_ACCOUNT_NAME": { + "type": "string", + "value": "[variables('premiumFileAccountName')]" + }, + "PREMIUM_FILE_STORAGE_ACCOUNT_KEY": { + "type": "string", + "value": "[listKeys(resourceId('Microsoft.Storage/storageAccounts', variables('premiumFileAccountName')), variables('mgmtApiVersion')).keys[0].value]" + }, + "PREMIUM_FILE_STORAGE_ACCOUNT_FILE_ENDPOINT_SUFFIX": { + "type": "string", + "value": "[url.serviceEndpointSuffix(reference(resourceId('Microsoft.Storage/storageAccounts', variables('premiumFileAccountName')), variables('mgmtApiVersion')).primaryEndpoints.file)]" + }, + "AZUREWEBJOBSSTORAGE": { + "type": "string", + "value": "[connectionString.create(variables('webjobsPrimaryAccountName'), listKeys(resourceId('Microsoft.Storage/storageAccounts', variables('webjobsPrimaryAccountName')), variables('mgmtApiVersion')).keys[0].value, reference(resourceId('Microsoft.Storage/storageAccounts', variables('webjobsPrimaryAccountName')), variables('mgmtApiVersion')).primaryEndpoints.blob, reference(resourceId('Microsoft.Storage/storageAccounts', variables('webjobsPrimaryAccountName')), variables('mgmtApiVersion')).primaryEndpoints.queue, reference(resourceId('Microsoft.Storage/storageAccounts', variables('webjobsPrimaryAccountName')), variables('mgmtApiVersion')).primaryEndpoints.file, reference(resourceId('Microsoft.Storage/storageAccounts', variables('webjobsPrimaryAccountName')), variables('mgmtApiVersion')).primaryEndpoints.table)]" + }, + "AZUREWEBJOBSSECONDARYSTORAGE": { + "type": "string", + "value": "[connectionString.create(variables('webjobsSecondaryAccountName'), listKeys(resourceId('Microsoft.Storage/storageAccounts', variables('webjobsSecondaryAccountName')), variables('mgmtApiVersion')).keys[0].value, reference(resourceId('Microsoft.Storage/storageAccounts', variables('webjobsSecondaryAccountName')), variables('mgmtApiVersion')).primaryEndpoints.blob, reference(resourceId('Microsoft.Storage/storageAccounts', variables('webjobsSecondaryAccountName')), variables('mgmtApiVersion')).primaryEndpoints.queue, reference(resourceId('Microsoft.Storage/storageAccounts', variables('webjobsSecondaryAccountName')), variables('mgmtApiVersion')).primaryEndpoints.file, reference(resourceId('Microsoft.Storage/storageAccounts', variables('webjobsSecondaryAccountName')), variables('mgmtApiVersion')).primaryEndpoints.table)]" + }, + "RESOURCE_GROUP_NAME": { + "type": "string", + "value": "[variables('resourceGroupName')]" + }, + "SUBSCRIPTION_ID": { + "type": "string", + "value": "[variables('subscriptionId')]" + }, + "LOCATION": { + "type": "string", + "value": "[variables('location')]" + }, + "AZURE_STORAGE_ENCRYPTION_SCOPE": { + "type": "string", + "value": "[variables('primaryEncryptionScopeName')]" + } + } + } + \ No newline at end of file From 40f7a7fd7ee89ccd8db65c4013b7d5d7fbf12bcb Mon Sep 17 00:00:00 2001 From: Joel Hendrix Date: Wed, 16 Aug 2023 09:26:31 -0700 Subject: [PATCH 14/16] Refactor handling of setting file expiry policy (#21378) * Refactor handling of setting file expiry policy Switch to using a struct containing explicit fields instead of an interface to improve discovery and self-documentation. * fix lint * reverse order of fields --- sdk/storage/azdatalake/file/client.go | 28 ++++-- sdk/storage/azdatalake/file/client_test.go | 33 ++++--- sdk/storage/azdatalake/file/constants.go | 36 +++++++ sdk/storage/azdatalake/file/models.go | 95 +++++++------------ .../azdatalake/filesystem/client_test.go | 12 ++- .../internal/exported/set_expiry.go | 71 -------------- 6 files changed, 116 insertions(+), 159 deletions(-) delete mode 100644 sdk/storage/azdatalake/internal/exported/set_expiry.go diff --git a/sdk/storage/azdatalake/file/client.go b/sdk/storage/azdatalake/file/client.go index 101f580e06e7..0a84b5af7cba 100644 --- a/sdk/storage/azdatalake/file/client.go +++ b/sdk/storage/azdatalake/file/client.go @@ -10,6 +10,15 @@ import ( "bytes" "context" "errors" + "io" + "net/http" + "net/url" + "os" + "reflect" + "strings" + "sync" + "time" + "github.com/Azure/azure-sdk-for-go/sdk/azcore" "github.com/Azure/azure-sdk-for-go/sdk/azcore/policy" "github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime" @@ -25,13 +34,6 @@ import ( "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" - "io" - "net/http" - "net/url" - "os" - "strings" - "sync" - "time" ) // ClientOptions contains the optional parameters when creating a Client. @@ -259,9 +261,15 @@ func (f *Client) Rename(ctx context.Context, newName string, options *RenameOpti } // SetExpiry operation sets an expiry time on an existing file (blob2). -func (f *Client) SetExpiry(ctx context.Context, expiryType SetExpiryType, o *SetExpiryOptions) (SetExpiryResponse, error) { - expMode, opts := expiryType.Format(o) - resp, err := f.generatedFileClientWithBlob().SetExpiry(ctx, expMode, opts) +func (f *Client) SetExpiry(ctx context.Context, expiryValues SetExpiryValues, o *SetExpiryOptions) (SetExpiryResponse, error) { + if reflect.ValueOf(expiryValues).IsZero() { + expiryValues.ExpiryType = SetExpiryTypeNeverExpire + } + opts := &generated_blob.BlobClientSetExpiryOptions{} + if expiryValues.ExpiryType != SetExpiryTypeNeverExpire { + opts.ExpiresOn = &expiryValues.ExpiresOn + } + resp, err := f.generatedFileClientWithBlob().SetExpiry(ctx, expiryValues.ExpiryType, opts) err = exported.ConvertToDFSError(err) return resp, err } diff --git a/sdk/storage/azdatalake/file/client_test.go b/sdk/storage/azdatalake/file/client_test.go index a05807217188..8ab3897c6d9d 100644 --- a/sdk/storage/azdatalake/file/client_test.go +++ b/sdk/storage/azdatalake/file/client_test.go @@ -11,6 +11,15 @@ import ( "context" "crypto/md5" "encoding/binary" + "hash/crc64" + "io" + "math/rand" + "net/http" + "os" + "strconv" + "testing" + "time" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/streaming" "github.com/Azure/azure-sdk-for-go/sdk/azcore/to" "github.com/Azure/azure-sdk-for-go/sdk/internal/recording" @@ -21,13 +30,6 @@ import ( "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/sas" "github.com/stretchr/testify/require" "github.com/stretchr/testify/suite" - "hash/crc64" - "io" - "math/rand" - "net/http" - "os" - "testing" - "time" ) var proposedLeaseIDs = []*string{to.Ptr("c820a799-76d7-4ee2-6e15-546f19325c2c"), to.Ptr("326cc5e1-746e-4af8-4811-a50e6629a8ca")} @@ -472,9 +474,11 @@ func (s *UnrecordedTestSuite) TestCreateFileWithExpiryAbsolute() { defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) expiryTimeAbsolute := time.Now().Add(8 * time.Second) - expiry := file.CreationExpiryTypeAbsolute(expiryTimeAbsolute) createFileOpts := &file.CreateOptions{ - Expiry: expiry, + Expiry: file.CreateExpiryValues{ + ExpiryType: file.CreateExpiryTypeAbsolute, + ExpiresOn: time.Now().Add(8 * time.Second).UTC().Format(http.TimeFormat), + }, } _, err = fsClient.Create(context.Background(), nil) @@ -505,9 +509,11 @@ func (s *RecordedTestSuite) TestCreateFileWithExpiryRelativeToNow() { _require.NoError(err) defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) - expiry := file.CreationExpiryTypeRelativeToNow(8 * time.Second) createFileOpts := &file.CreateOptions{ - Expiry: expiry, + Expiry: file.CreateExpiryValues{ + ExpiryType: file.CreateExpiryTypeRelativeToNow, + ExpiresOn: strconv.FormatInt((8 * time.Second).Milliseconds(), 10), + }, } _, err = fsClient.Create(context.Background(), nil) @@ -540,7 +546,9 @@ func (s *RecordedTestSuite) TestCreateFileWithNeverExpire() { defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) createFileOpts := &file.CreateOptions{ - Expiry: file.CreationExpiryTypeNever{}, + Expiry: file.CreateExpiryValues{ + ExpiryType: file.CreateExpiryTypeNeverExpire, + }, } _, err = fsClient.Create(context.Background(), nil) @@ -2961,6 +2969,7 @@ func (s *RecordedTestSuite) TestFileAppendAndFlushAndDownloadDataWithLeasedFile( _require.Nil(err) _, err = rsc.Seek(0, io.SeekStart) + _require.NoError(err) _, err = srcFClient.AppendData(context.Background(), int64(contentSize), rsc, opts) _require.Nil(err) diff --git a/sdk/storage/azdatalake/file/constants.go b/sdk/storage/azdatalake/file/constants.go index 28032750ce15..da5ec3d2b065 100644 --- a/sdk/storage/azdatalake/file/constants.go +++ b/sdk/storage/azdatalake/file/constants.go @@ -9,6 +9,8 @@ package file import ( "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake" "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/generated_blob" "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/internal/path" ) @@ -50,6 +52,40 @@ func TransferValidationTypeComputeCRC64() TransferValidationType { return exported.TransferValidationTypeComputeCRC64() } +// SetExpiryType defines the values for modes of file expiration. +type SetExpiryType = generated_blob.ExpiryOptions + +const ( + // SetExpiryTypeAbsolute sets the expiration date as an absolute value expressed in RFC1123 format. + SetExpiryTypeAbsolute SetExpiryType = generated_blob.ExpiryOptionsAbsolute + + // SetExpiryTypeNeverExpire sets the file to never expire or removes the current expiration date. + SetExpiryTypeNeverExpire SetExpiryType = generated_blob.ExpiryOptionsNeverExpire + + // SetExpiryTypeRelativeToCreation sets the expiration date relative to the time of file creation. + // The value is expressed as the number of miliseconds to elapse from the time of creation. + SetExpiryTypeRelativeToCreation SetExpiryType = generated_blob.ExpiryOptionsRelativeToCreation + + // SetExpiryTypeRelativeToNow sets the expiration date relative to the current time. + // The value is expressed as the number of milliseconds to elapse from the present time. + SetExpiryTypeRelativeToNow SetExpiryType = generated_blob.ExpiryOptionsRelativeToNow +) + +// CreateExpiryType defines the values for modes of file expiration specified during creation. +type CreateExpiryType = generated.PathExpiryOptions + +const ( + // CreateExpiryTypeAbsolute sets the expiration date as an absolute value expressed in RFC1123 format. + CreateExpiryTypeAbsolute CreateExpiryType = generated.PathExpiryOptionsAbsolute + + // CreateExpiryTypeNeverExpire sets the file to never expire or removes the current expiration date. + CreateExpiryTypeNeverExpire CreateExpiryType = generated.PathExpiryOptionsNeverExpire + + // CreateExpiryTypeRelativeToNow sets the expiration date relative to the current time. + // The value is expressed as the number of milliseconds to elapse from the present time. + CreateExpiryTypeRelativeToNow CreateExpiryType = generated.PathExpiryOptionsRelativeToNow +) + // StatusType defines values for StatusType type StatusType = azdatalake.StatusType diff --git a/sdk/storage/azdatalake/file/models.go b/sdk/storage/azdatalake/file/models.go index a11818377e3f..928772d28e16 100644 --- a/sdk/storage/azdatalake/file/models.go +++ b/sdk/storage/azdatalake/file/models.go @@ -8,16 +8,14 @@ package file import ( "errors" - "github.com/Azure/azure-sdk-for-go/sdk/azcore/to" + "io" + "reflect" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/blob" "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" - "io" - "net/http" - "strconv" - "time" ) const ( @@ -42,7 +40,7 @@ type CreateOptions struct { // HTTPHeaders contains the HTTP headers for path operations. HTTPHeaders *HTTPHeaders // Expiry specifies the type and time of expiry for the file. - Expiry CreationExpiryType + Expiry CreateExpiryValues // 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. @@ -61,6 +59,18 @@ type CreateOptions struct { ACL *string } +// CreateExpiryValues describes when a newly created file should expire. +// A zero-value indicates the file has no expiration date. +type CreateExpiryValues struct { + // ExpiryType indicates how the value of ExpiresOn should be interpreted (absolute, relative to now, etc). + ExpiryType CreateExpiryType + + // ExpiresOn contains the time the file should expire. + // The value will either be an absolute UTC time in RFC1123 format or an integer expressing a number of milliseconds. + // NOTE: when ExpiryType is CreateExpiryTypeNeverExpire, this value is ignored. + ExpiresOn string +} + func (o *CreateOptions) format() (*generated.LeaseAccessConditions, *generated.ModifiedAccessConditions, *generated.PathHTTPHeaders, *generated.PathClientCreateOptions, *generated.CPKInfo) { resource := generated.PathResourceTypeFile createOpts := &generated.PathClientCreateOptions{ @@ -70,13 +80,11 @@ func (o *CreateOptions) format() (*generated.LeaseAccessConditions, *generated.M return nil, nil, nil, createOpts, nil } leaseAccessConditions, modifiedAccessConditions := exported.FormatPathAccessConditions(o.AccessConditions) - if o.Expiry == nil { - createOpts.ExpiryOptions = nil - createOpts.ExpiresOn = nil - } else { - expOpts, expiresOn := o.Expiry.Format() - createOpts.ExpiryOptions = (*generated.PathExpiryOptions)(&expOpts) - createOpts.ExpiresOn = expiresOn + if !reflect.ValueOf(o.Expiry).IsZero() { + createOpts.ExpiryOptions = &o.Expiry.ExpiryType + if o.Expiry.ExpiryType != CreateExpiryTypeNeverExpire { + createOpts.ExpiresOn = &o.Expiry.ExpiresOn + } } createOpts.ACL = o.ACL createOpts.Group = o.Group @@ -491,65 +499,28 @@ func (o *DownloadFileOptions) format() *blob.DownloadFileOptions { return downloadFileOptions } -// CreationExpiryType defines values for Create() ExpiryType -type CreationExpiryType interface { - Format() (generated.ExpiryOptions, *string) - notPubliclyImplementable() -} - -// CreationExpiryTypeAbsolute defines the absolute time for the blob expiry -type CreationExpiryTypeAbsolute time.Time - -// CreationExpiryTypeRelativeToNow defines the duration relative to now for the blob expiry -type CreationExpiryTypeRelativeToNow time.Duration - -// CreationExpiryTypeNever defines that the blob will be set to never expire -type CreationExpiryTypeNever struct { - // empty struct since NeverExpire expiry type does not require expiry time -} - -func (e CreationExpiryTypeAbsolute) Format() (generated.ExpiryOptions, *string) { - return generated.ExpiryOptionsAbsolute, to.Ptr(time.Time(e).UTC().Format(http.TimeFormat)) +// SetExpiryValues describes when a file should expire. +// A zero-value indicates the file has no expiration date. +type SetExpiryValues struct { + // ExpiryType indicates how the value of ExpiresOn should be interpreted (absolute, relative to now, etc). + ExpiryType SetExpiryType + // ExpiresOn contains the time the file should expire. + // The value will either be an absolute UTC time in RFC1123 format or an integer expressing a number of milliseconds. + // NOTE: when ExpiryType is SetExpiryTypeNeverExpire, this value is ignored. + ExpiresOn string } -func (e CreationExpiryTypeAbsolute) notPubliclyImplementable() {} - -func (e CreationExpiryTypeRelativeToNow) Format() (generated.ExpiryOptions, *string) { - return generated.ExpiryOptionsRelativeToNow, to.Ptr(strconv.FormatInt(time.Duration(e).Milliseconds(), 10)) -} - -func (e CreationExpiryTypeRelativeToNow) notPubliclyImplementable() {} - -func (e CreationExpiryTypeNever) Format() (generated.ExpiryOptions, *string) { - return generated.ExpiryOptionsNeverExpire, nil -} - -func (e CreationExpiryTypeNever) notPubliclyImplementable() {} - // ACLFailedEntry contains the failed ACL entry (response model). type ACLFailedEntry = path.ACLFailedEntry // SetAccessControlRecursiveResponse contains part of the response data returned by the []OP_AccessControl operations. type SetAccessControlRecursiveResponse = generated.SetAccessControlRecursiveResponse -// SetExpiryType defines values for ExpiryType. -type SetExpiryType = exported.SetExpiryType - -// SetExpiryTypeAbsolute defines the absolute time for the expiry. -type SetExpiryTypeAbsolute = exported.SetExpiryTypeAbsolute - -// SetExpiryTypeRelativeToNow defines the duration relative to now for the expiry. -type SetExpiryTypeRelativeToNow = exported.SetExpiryTypeRelativeToNow - -// SetExpiryTypeRelativeToCreation defines the duration relative to creation for the expiry. -type SetExpiryTypeRelativeToCreation = exported.SetExpiryTypeRelativeToCreation - -// SetExpiryTypeNever defines that will be set to never expire. -type SetExpiryTypeNever = exported.SetExpiryTypeNever - // SetExpiryOptions contains the optional parameters for the Client.SetExpiry method. -type SetExpiryOptions = exported.SetExpiryOptions +type SetExpiryOptions struct { + // placeholder for future options +} type HTTPRange = exported.HTTPRange diff --git a/sdk/storage/azdatalake/filesystem/client_test.go b/sdk/storage/azdatalake/filesystem/client_test.go index 1cbe0105d181..3cf5cae5ae0a 100644 --- a/sdk/storage/azdatalake/filesystem/client_test.go +++ b/sdk/storage/azdatalake/filesystem/client_test.go @@ -8,6 +8,11 @@ package filesystem_test import ( "context" + "strconv" + "strings" + "testing" + "time" + "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" @@ -17,10 +22,6 @@ import ( "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/sas" "github.com/stretchr/testify/require" "github.com/stretchr/testify/suite" - "strconv" - "strings" - "testing" - "time" ) func Test(t *testing.T) { @@ -100,6 +101,7 @@ func (s *RecordedTestSuite) TestCreateFilesystemWithOptions() { _require.Nil(err) props, err := fsClient.GetProperties(context.Background(), nil) + _require.NoError(err) _require.NotNil(props.Metadata) _require.Equal(*props.PublicAccess, filesystem.Filesystem) } @@ -123,6 +125,7 @@ func (s *RecordedTestSuite) TestCreateFilesystemWithFileAccess() { _, err = fsClient.Create(context.Background(), &opts) _require.Nil(err) props, err := fsClient.GetProperties(context.Background(), nil) + _require.NoError(err) _require.NotNil(props.Metadata) _require.Equal(*props.PublicAccess, filesystem.File) } @@ -146,6 +149,7 @@ func (s *RecordedTestSuite) TestCreateFilesystemEmptyMetadata() { _require.Nil(err) props, err := fsClient.GetProperties(context.Background(), nil) + _require.NoError(err) _require.Nil(props.Metadata) _require.Equal(*props.PublicAccess, filesystem.Filesystem) diff --git a/sdk/storage/azdatalake/internal/exported/set_expiry.go b/sdk/storage/azdatalake/internal/exported/set_expiry.go deleted file mode 100644 index 5938518bbdba..000000000000 --- a/sdk/storage/azdatalake/internal/exported/set_expiry.go +++ /dev/null @@ -1,71 +0,0 @@ -//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 exported - -import ( - "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/internal/generated_blob" - "net/http" - "strconv" - "time" - - "github.com/Azure/azure-sdk-for-go/sdk/azcore/to" -) - -// SetExpiryType defines values for ExpiryType -type SetExpiryType interface { - Format(o *SetExpiryOptions) (generated_blob.ExpiryOptions, *generated_blob.BlobClientSetExpiryOptions) - notPubliclyImplementable() -} - -// SetExpiryTypeAbsolute defines the absolute time for the blob expiry -type SetExpiryTypeAbsolute time.Time - -// SetExpiryTypeRelativeToNow defines the duration relative to now for the blob expiry -type SetExpiryTypeRelativeToNow time.Duration - -// SetExpiryTypeRelativeToCreation defines the duration relative to creation for the blob expiry -type SetExpiryTypeRelativeToCreation time.Duration - -// SetExpiryTypeNever defines that the blob will be set to never expire -type SetExpiryTypeNever struct { - // empty struct since NeverExpire expiry type does not require expiry time -} - -// SetExpiryOptions contains the optional parameters for the Client.SetExpiry method. -type SetExpiryOptions struct { - // placeholder for future options -} - -func (e SetExpiryTypeAbsolute) Format(o *SetExpiryOptions) (generated_blob.ExpiryOptions, *generated_blob.BlobClientSetExpiryOptions) { - return generated_blob.ExpiryOptionsAbsolute, &generated_blob.BlobClientSetExpiryOptions{ - ExpiresOn: to.Ptr(time.Time(e).UTC().Format(http.TimeFormat)), - } -} - -func (e SetExpiryTypeAbsolute) notPubliclyImplementable() {} - -func (e SetExpiryTypeRelativeToNow) Format(o *SetExpiryOptions) (generated_blob.ExpiryOptions, *generated_blob.BlobClientSetExpiryOptions) { - return generated_blob.ExpiryOptionsRelativeToNow, &generated_blob.BlobClientSetExpiryOptions{ - ExpiresOn: to.Ptr(strconv.FormatInt(time.Duration(e).Milliseconds(), 10)), - } -} - -func (e SetExpiryTypeRelativeToNow) notPubliclyImplementable() {} - -func (e SetExpiryTypeRelativeToCreation) Format(o *SetExpiryOptions) (generated_blob.ExpiryOptions, *generated_blob.BlobClientSetExpiryOptions) { - return generated_blob.ExpiryOptionsRelativeToCreation, &generated_blob.BlobClientSetExpiryOptions{ - ExpiresOn: to.Ptr(strconv.FormatInt(time.Duration(e).Milliseconds(), 10)), - } -} - -func (e SetExpiryTypeRelativeToCreation) notPubliclyImplementable() {} - -func (e SetExpiryTypeNever) Format(o *SetExpiryOptions) (generated_blob.ExpiryOptions, *generated_blob.BlobClientSetExpiryOptions) { - return generated_blob.ExpiryOptionsNeverExpire, &generated_blob.BlobClientSetExpiryOptions{} -} - -func (e SetExpiryTypeNever) notPubliclyImplementable() {} From d366659bfbd0bcff13d4dc0f03350ad0e0edb72b Mon Sep 17 00:00:00 2001 From: Tamer Sherif <69483382+tasherif-msft@users.noreply.github.com> Date: Wed, 16 Aug 2023 13:53:17 -0700 Subject: [PATCH 15/16] [AzDatalake] APIView Feedback + Samples + Doc + CI/Live issues cleanup (#21348) * Enable gocritic during linting (#20715) Enabled gocritic's evalOrder to catch dependencies on undefined behavior on return statements. Updated to latest version of golangci-lint. Fixed issue in azblob flagged by latest linter. * Cosmos DB: Enable merge support (#20716) * Adding header and value * Wiring and tests * format * Fixing value * change log * [azservicebus, azeventhubs] Stress test and logging improvement (#20710) Logging improvements: * Updating the logging to print more tracing information (per-link) in prep for the bigger release coming up. * Trimming out some of the verbose logging, seeing if I can get it a bit more reasonable. Stress tests: * Add a timestamp to the log name we generate and also default to append, not overwrite. * Use 0.5 cores, 0.5GB as our baseline. Some pods use more and I'll tune them more later. * update proxy version (#20712) Co-authored-by: Scott Beddall * Return an error when you try to send a message that's too large. (#20721) This now works just like the message batch - you'll get an ErrMessageTooLarge if you attempt to send a message that's too large for the link's configured size. NOTE: there's a patch to `internal/go-amqp/Sender.go` to match what's in go-amqp's main so it returns a programmatically useful error when the message is too large. Fixes #20647 * Changes in test that is failing in pipeline (#20693) * [azservicebus, azeventhubs] Treat 'entity full' as a fatal error (#20722) When the remote entity is full we get a resource-limit-exceeded condition. This isn't something we should keep retrying on and it's best to just abort and let the user know immediately, rather than hoping it might eventually clear out. This affected both Event Hubs and Service Bus. Fixes #20647 * [azservicebus/azeventhubs] Redirect stderr and stdout to tee (#20726) * Update changelog with latest features (#20730) * Update changelog with latest features Prepare for upcoming release. * bump minor version * pass along the artifact name so we can override it later (#20732) Co-authored-by: scbedd <45376673+scbedd@users.noreply.github.com> * [azeventhubs] Fixing checkpoint store race condition (#20727) The checkpoint store wasn't guarding against multiple owners claiming for the first time - fixing this by using IfNoneMatch Fixes #20717 * Fix azidentity troubleshooting guide link (#20736) * [Release] sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/0.1.0 (#20437) * [Release] sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/0.1.0 generation from spec commit: 85fb4ac6f8bfefd179e6c2632976a154b5c9ff04 * client factory * fix * fix * update * add sdk/resourcemanager/postgresql/armpostgresql live test (#20685) * add sdk/resourcemanager/postgresql/armpostgresql live test * update assets.json * set subscriptionId default value * format * add sdk/resourcemanager/eventhub/armeventhub live test (#20686) * add sdk/resourcemanager/eventhub/armeventhub live test * update assets * add sdk/resourcemanager/compute/armcompute live test (#20048) * add sdk/resourcemanager/compute/armcompute live test * skus filter * fix subscriptionId default value * fix * gofmt * update recording * sdk/resourcemanager/network/armnetwork live test (#20331) * sdk/resourcemanager/network/armnetwork live test * update subscriptionId default value * update recording * add sdk/resourcemanager/cosmos/armcosmos live test (#20705) * add sdk/resourcemanager/cosmos/armcosmos live test * update assets.json * update assets.json * update assets.json * update assets.json * Increment package version after release of azcore (#20740) * [azeventhubs] Improperly resetting etag in the checkpoint store (#20737) We shouldn't be resetting the etag to nil - it's what we use to enforce a "single winner" when doing ownership claims. The bug here was two-fold: I had bad logic in my previous claim ownership, which I fixed in a previous PR, but we need to reflect that same constraint properly in our in-memory checkpoint store for these tests. * Eng workflows sync and branch cleanup additions (#20743) Co-authored-by: James Suplizio * [azeventhubs] Latest start position can also be inclusive (ie, get the latest message) (#20744) * Update GitHubEventProcessor version and remove pull_request_review procesing (#20751) Co-authored-by: James Suplizio * Rename DisableAuthorityValidationAndInstanceDiscovery (#20746) * fix (#20707) * AzFile (#20739) * azfile: Fixing connection string parsing logic (#20798) * Fixing connection string parse logic * Update README * [azadmin] fix flaky test (#20758) * fix flaky test * charles suggestion * Prepare azidentity v1.3.0 for release (#20756) * Fix broken podman link (#20801) Co-authored-by: Wes Haggard * [azquery] update doc comments (#20755) * update doc comments * update statistics and visualization generation * prep-for-release * Fixed contribution section (#20752) Co-authored-by: Bob Tabor * [azeventhubs,azservicebus] Some API cleanup, renames (#20754) * Adding options to UpdateCheckpoint(), just for future potential expansion * Make Offset an int64, not a *int64 (it's not optional, it'll always come back with ReceivedEvents) * Adding more logging into the checkpoint store. * Point all imports at the production go-amqp * Add supporting features to enable distributed tracing (#20301) (#20708) * Add supporting features to enable distributed tracing This includes new internal pipeline policies and other supporting types. See the changelog for a full description. Added some missing doc comments. * fix linter issue * add net.peer.name trace attribute sequence custom HTTP header policy before logging policy. sequence logging policy after HTTP trace policy. keep body download policy at the end. * add span for iterating over pages * Restore ARM CAE support for azcore beta (#20657) This reverts commit 902097226ff3fe2fc6c3e7fc50d3478350253614. * Upgrade to stable azcore (#20808) * Increment package version after release of data/azcosmos (#20807) * Updating changelog (#20810) * Add fake package to azcore (#20711) * Add fake package to azcore This is the supporting infrastructure for the generated SDK fakes. * fix doc comment * Updating CHANGELOG.md (#20809) * changelog (#20811) * Increment package version after release of storage/azfile (#20813) * Update changelog (azblob) (#20815) * Updating CHANGELOG.md * Update the changelog with correct version * [azquery] migration guide (#20742) * migration guide * Charles feedback * Richard feedback --------- Co-authored-by: Charles Lowell <10964656+chlowell@users.noreply.github.com> * Increment package version after release of monitor/azquery (#20820) * [keyvault] prep for release (#20819) * prep for release * perf tests * update date * small cleanup * rename to FileSystem * regenrated * removed metadata option and fixed generated * fixed tests * fixed tests * fixed tests * fixed tests * added more tests * doc cleanup * doc failures * doc failures * doc failures * changelog * samples * mod tidy * removed client from rename response * fixed deserialize * cleanup * readme * live pipe fix * live pipe fix * live pipe fix * doc fix * doc fix * doc fix * model fix * model fix * doc fix * added doc.go * added file examples * apiview model fixes * version and changelog * changelog fix * fixed export --------- Co-authored-by: Joel Hendrix Co-authored-by: Matias Quaranta Co-authored-by: Richard Park <51494936+richardpark-msft@users.noreply.github.com> Co-authored-by: Azure SDK Bot <53356347+azure-sdk@users.noreply.github.com> Co-authored-by: Scott Beddall Co-authored-by: siminsavani-msft <77068571+siminsavani-msft@users.noreply.github.com> Co-authored-by: scbedd <45376673+scbedd@users.noreply.github.com> Co-authored-by: Charles Lowell <10964656+chlowell@users.noreply.github.com> Co-authored-by: Peng Jiahui <46921893+Alancere@users.noreply.github.com> Co-authored-by: James Suplizio Co-authored-by: Sourav Gupta <98318303+souravgupta-msft@users.noreply.github.com> Co-authored-by: gracewilcox <43627800+gracewilcox@users.noreply.github.com> Co-authored-by: Wes Haggard Co-authored-by: Bob Tabor Co-authored-by: Bob Tabor --- sdk/storage/azdatalake/CHANGELOG.md | 7 + sdk/storage/azdatalake/README.md | 280 +++++++ sdk/storage/azdatalake/assets.json | 2 +- .../azdatalake/datalakeerror/error_codes.go | 13 +- sdk/storage/azdatalake/directory/client.go | 78 +- .../azdatalake/directory/client_test.go | 582 ++++++-------- sdk/storage/azdatalake/directory/constants.go | 1 + .../azdatalake/directory/examples_test.go | 166 ++++ sdk/storage/azdatalake/directory/models.go | 28 +- sdk/storage/azdatalake/directory/responses.go | 7 +- sdk/storage/azdatalake/doc.go | 218 ++++++ sdk/storage/azdatalake/file/client.go | 65 +- sdk/storage/azdatalake/file/client_test.go | 721 ++++++++---------- sdk/storage/azdatalake/file/constants.go | 2 + sdk/storage/azdatalake/file/examples_test.go | 389 ++++++++++ sdk/storage/azdatalake/file/models.go | 79 +- sdk/storage/azdatalake/file/responses.go | 8 +- sdk/storage/azdatalake/file/retry_reader.go | 1 + .../azdatalake/file/retry_reader_test.go | 433 +++++++++++ sdk/storage/azdatalake/filesystem/client.go | 38 +- .../azdatalake/filesystem/client_test.go | 480 +++++++----- .../azdatalake/filesystem/constants.go | 2 +- .../azdatalake/filesystem/examples_test.go | 330 ++++++++ sdk/storage/azdatalake/filesystem/models.go | 65 +- .../azdatalake/filesystem/responses.go | 24 +- sdk/storage/azdatalake/go.mod | 8 + sdk/storage/azdatalake/go.sum | 11 + .../azdatalake/internal/base/clients.go | 6 +- .../internal/exported/access_conditions.go | 2 +- .../azdatalake/internal/exported/exported.go | 2 +- .../exported/shared_key_credential.go | 2 +- .../azdatalake/internal/exported/version.go | 2 +- .../azdatalake/internal/generated/autorest.md | 19 +- .../internal/generated/filesystem_client.go | 4 +- .../internal/generated/zz_models.go | 4 +- .../internal/generated/zz_models_serde.go | 11 +- .../internal/generated_blob/autorest.md | 2 +- .../generated_blob/zz_container_client.go | 14 +- .../internal/generated_blob/zz_models.go | 8 +- .../azdatalake/internal/path/models.go | 45 +- .../azdatalake/internal/path/responses.go | 45 ++ .../azdatalake/internal/shared/shared.go | 2 +- .../internal/testcommon/clients_auth.go | 12 +- .../azdatalake/internal/testcommon/common.go | 6 +- sdk/storage/azdatalake/lease/client.go | 26 +- sdk/storage/azdatalake/lease/client_test.go | 100 +-- sdk/storage/azdatalake/lease/examples_test.go | 92 +++ sdk/storage/azdatalake/lease/models.go | 46 +- sdk/storage/azdatalake/lease/responses.go | 20 +- sdk/storage/azdatalake/sas/query_params.go | 22 +- sdk/storage/azdatalake/sas/service.go | 26 +- sdk/storage/azdatalake/sas/service_test.go | 93 ++- sdk/storage/azdatalake/sas/url_parts.go | 10 +- sdk/storage/azdatalake/sas/url_parts_test.go | 8 +- sdk/storage/azdatalake/service/client.go | 47 +- sdk/storage/azdatalake/service/client_test.go | 96 +-- sdk/storage/azdatalake/service/constants.go | 2 +- .../azdatalake/service/examples_test.go | 335 ++++++++ sdk/storage/azdatalake/service/models.go | 76 +- sdk/storage/azdatalake/service/responses.go | 12 +- sdk/storage/azdatalake/test-resources.json | 9 +- 61 files changed, 3778 insertions(+), 1466 deletions(-) create mode 100644 sdk/storage/azdatalake/CHANGELOG.md create mode 100644 sdk/storage/azdatalake/README.md create mode 100644 sdk/storage/azdatalake/directory/examples_test.go create mode 100644 sdk/storage/azdatalake/doc.go create mode 100644 sdk/storage/azdatalake/file/examples_test.go create mode 100644 sdk/storage/azdatalake/file/retry_reader_test.go create mode 100644 sdk/storage/azdatalake/filesystem/examples_test.go create mode 100644 sdk/storage/azdatalake/lease/examples_test.go create mode 100644 sdk/storage/azdatalake/service/examples_test.go diff --git a/sdk/storage/azdatalake/CHANGELOG.md b/sdk/storage/azdatalake/CHANGELOG.md new file mode 100644 index 000000000000..5ed8f538c47e --- /dev/null +++ b/sdk/storage/azdatalake/CHANGELOG.md @@ -0,0 +1,7 @@ +# Release History + +## 0.1.0-beta.1 (2023-08-16) + +### Features Added + +* This is the initial preview release of the `azdatalake` library diff --git a/sdk/storage/azdatalake/README.md b/sdk/storage/azdatalake/README.md new file mode 100644 index 000000000000..cf1600dd706c --- /dev/null +++ b/sdk/storage/azdatalake/README.md @@ -0,0 +1,280 @@ +# ADLS Gen2 Storage SDK for Go + +> Service Version: 2020-10-02 + +Azure Data Lake Storage Gen2 (ADLS Gen2) is Microsoft's hierarchical object storage solution for the cloud with converged capabilities with Azure Blob Storage. +For example, Data Lake Storage Gen2 provides file system semantics, file-level security, and scale. +Because these capabilities are built on Blob storage, you also get low-cost, tiered storage, with high availability/disaster recovery capabilities. +ADLS Gen2 makes Azure Storage the foundation for building enterprise data lakes on Azure. +Designed from the start to service multiple petabytes of information while sustaining hundreds of gigabits of throughput, ADLS Gen2 allows you to easily manage massive amounts of data. + +[Source code][source] | [API reference documentation][docs] | [REST API documentation][rest_docs] + +## Getting started + +### Install the package + +Install the ADLS Gen2 Storage SDK for Go with [go get][goget]: + +```Powershell +go get github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake +``` + +If you're going to authenticate with Azure Active Directory (recommended), install the [azidentity][azidentity] module. +```Powershell +go get github.com/Azure/azure-sdk-for-go/sdk/azidentity +``` + +### Prerequisites + +A supported [Go][godevdl] version (the Azure SDK supports the two most recent Go releases). + +You need an [Azure subscription][azure_sub] and a +[Storage Account][storage_account_docs] to use this package. + +To create a new Storage Account, you can use the [Azure Portal][storage_account_create_portal], +[Azure PowerShell][storage_account_create_ps], or the [Azure CLI][storage_account_create_cli]. +Here's an example using the Azure CLI: + +```Powershell +az storage account create --name MyStorageAccount --resource-group MyResourceGroup --location westus --sku Standard_LRS +``` + +### Authenticate the client + +In order to interact with the ADLS Gen2 Storage service, you'll need to create an instance of the `Client` type. The [azidentity][azidentity] module makes it easy to add Azure Active Directory support for authenticating Azure SDK clients with their corresponding Azure services. + +```go +// create a credential for authenticating with Azure Active Directory +cred, err := azidentity.NewDefaultAzureCredential(nil) +// TODO: handle err + +// create a service.Client for the specified storage account that uses the above credential +client, err := service.NewClient("https://MYSTORAGEACCOUNT.dfs.core.windows.net/", cred, nil) +// TODO: handle err +// you can also create filesystem, file and directory clients +``` + +Learn more about enabling Azure Active Directory for authentication with Azure Storage in [our documentation][storage_ad] and [our samples](#next-steps). + +## Key concepts + +ADLS Gen2 provides: +- Hadoop-compatible access +- Hierarchical directory structure +- Optimized cost and performance +- Finer grain security model +- Massive scalability + +ADLS Gen2 storage is designed for: + +- Serving images or documents directly to a browser. +- Storing files for distributed access. +- Streaming video and audio. +- Writing to log files. +- Storing data for backup and restore, disaster recovery, and archiving. +- Storing data for analysis by an on-premises or Azure-hosted service. + +ADLS Gen2 storage offers three types of resources: + +- The _storage account_ +- One or more _filesystems_ in a storage account +- One or more _files_ or _directories_ in a filesystem + +Instances of the `Client` type provide methods for manipulating filesystems and paths within a storage account. +The storage account is specified when the `Client` is constructed. The clients available are referenced below. +Use the appropriate client constructor function for the authentication mechanism you wish to use. + +### Goroutine safety +We guarantee that all client instance methods are goroutine-safe and independent of each other ([guideline](https://azure.github.io/azure-sdk/golang_introduction.html#thread-safety)). This ensures that the recommendation of reusing client instances is always safe, even across goroutines. + +### About metadata +ADLS Gen2 metadata name/value pairs are valid HTTP headers and should adhere to all restrictions governing HTTP headers. Metadata names must be valid HTTP header names, may contain only ASCII characters, and should be treated as case-insensitive. Base64-encode or URL-encode metadata values containing non-ASCII characters. + +### Additional concepts + +[Client options](https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/azcore/policy#ClientOptions) | +[Accessing the response](https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime#WithCaptureResponse) | +[Handling failures](https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/azcore#ResponseError) | +[Logging](https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/azcore/log) + + +## Examples + +### Creating and uploading a file (assuming filesystem exists) + +```go +const ( + path = "https://MYSTORAGEACCOUNT.dfs.core.windows.net/sample-fs/sample-file" +) + +// authenticate with Azure Active Directory +cred, err := azidentity.NewDefaultAzureCredential(nil) +// TODO: handle error + +// create a client for the specified storage account +client, err := file.NewClient(path, cred, nil) +// TODO: handle error + +_, err = client.Create(context.TODO(), nil) +// TODO: handle error + +// open the file for reading +fh, err := os.OpenFile(sampleFile, os.O_RDONLY, 0) +// TODO: handle error +defer fh.Close() + +// upload the file to the specified filesystem with the specified file name +_, err = client.UploadFile(context.TODO(), fh, nil) +// TODO: handle error +``` + +### Downloading a file + +```go +const ( + path = "https://MYSTORAGEACCOUNT.dfs.core.windows.net/sample-fs/cloud.jpg" +) + +// authenticate with Azure Active Directory +cred, err := azidentity.NewDefaultAzureCredential(nil) +// TODO: handle error + +// create a client for the specified storage account +client, err := file.NewClient(path, cred, nil) +// TODO: handle error + +// create or open a local file where we can download the file +file, err := os.Create("cloud.jpg") +// TODO: handle error +defer file.Close() + +// download the file +_, err = client.DownloadFile(context.TODO(), file, nil) +// TODO: handle error +``` + +### Creating and deleting a filesystem + +```go +const ( + fs = "https://MYSTORAGEACCOUNT.dfs.core.windows.net/sample-fs" +) + +// authenticate with Azure Active Directory +cred, err := azidentity.NewDefaultAzureCredential(nil) +// TODO: handle error + +// create a client for the specified storage account +client, err := filesystem.NewClient(fs, cred, nil) +// TODO: handle error + +_, err = client.Create(context.TODO(), nil) +// TODO: handle error + +_, err = client.Delete(context.TODO(), nil) +// TODO: handle error +``` + +### Enumerating paths (assuming filesystem exists) + +```go +const ( + fs = "https://MYSTORAGEACCOUNT.dfs.core.windows.net/sample-fs" +) + +// authenticate with Azure Active Directory +cred, err := azidentity.NewDefaultAzureCredential(nil) +// TODO: handle error + +// create a filesystem client for the specified storage account +client, err := filesystem.NewClient(fs, cred, nil) +// TODO: handle error + +// path listings are returned across multiple pages +pager := client.NewListPathsPager(true, nil) + +// continue fetching pages until no more remain +for pager.More() { + // advance to the next page + page, err := pager.NextPage(context.TODO()) + // TODO: handle error + + // print the path names for this page + for _, path := range page.PathList.Paths { + fmt.Println(*path.Name) + fmt.Println(*path.IsDirectory) + } +} +``` + +## Troubleshooting + +All Datalake service operations will return an +[*azcore.ResponseError][azcore_response_error] on failure with a +populated `ErrorCode` field. Many of these errors are recoverable. +The [datalakeerror][datalake_error] package provides the possible Storage error codes +along with various helper facilities for error handling. + + +### Specialized clients + +The ADLS Gen2 Storage SDK for Go provides specialized clients in various subpackages. + +The [file][file] package contains APIs related to file path types. + +The [directory][directory] package contains APIs related to directory path types. + +The [lease][lease] package contains clients for managing leases on paths (paths represent both directory and file paths) and filesystems. Please see the [reference docs](https://docs.microsoft.com/rest/api/storageservices/lease-blob#remarks) for general information on leases. + +The [filesystem][filesystem] package contains APIs specific to filesystems. This includes APIs setting access policies or properties, and more. + +The [service][service] package contains APIs specific to Datalake service. This includes APIs for manipulating filesystems, retrieving account information, and more. + +The [sas][sas] package contains utilities to aid in the creation and manipulation of Shared Access Signature tokens. +See the package's documentation for more information. + + +You can find additional context and examples in our samples for each subpackage (named examples_test.go). + +## Contributing + +See the [Storage CONTRIBUTING.md][storage_contrib] for details on building, +testing, and contributing to this library. + +This project welcomes contributions and suggestions. Most contributions require +you to agree to a Contributor License Agreement (CLA) declaring that you have +the right to, and actually do, grant us the rights to use your contribution. For +details, visit [cla.microsoft.com][cla]. + +This project has adopted the [Microsoft Open Source Code of Conduct][coc]. +For more information see the [Code of Conduct FAQ][coc_faq] +or contact [opencode@microsoft.com][coc_contact] with any +additional questions or comments. + + +[source]: https://github.com/Azure/azure-sdk-for-go/tree/main/sdk/storage/azdatalake +[docs]: https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake +[rest_docs]: https://docs.microsoft.com/rest/api/storageservices/data-lake-storage-gen2 +[godevdl]: https://go.dev/dl/ +[goget]: https://pkg.go.dev/cmd/go#hdr-Add_dependencies_to_current_module_and_install_them +[storage_account_docs]: https://docs.microsoft.com/azure/storage/common/storage-account-overview +[storage_account_create_ps]: https://docs.microsoft.com/azure/storage/common/storage-quickstart-create-account?tabs=azure-powershell +[storage_account_create_cli]: https://docs.microsoft.com/azure/storage/common/storage-quickstart-create-account?tabs=azure-cli +[storage_account_create_portal]: https://docs.microsoft.com/azure/storage/common/storage-quickstart-create-account?tabs=azure-portal +[azure_sub]: https://azure.microsoft.com/free/ +[azidentity]: https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/azidentity +[storage_ad]: https://docs.microsoft.com/azure/storage/common/storage-auth-aad +[azcore_response_error]: https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/azcore#ResponseError +[datalake_error]: https://github.com/Azure/azure-sdk-for-go/tree/main/sdk/storage/azdatalake/datalakeerror/error_codes.go +[filesystem]: https://github.com/Azure/azure-sdk-for-go/tree/main/sdk/storage/azdatalake/filesystem/client.go +[lease]: https://github.com/Azure/azure-sdk-for-go/tree/main/sdk/storage/azdatalake/lease +[file]: https://github.com/Azure/azure-sdk-for-go/tree/main/sdk/storage/azdatalake/file/client.go +[directory]: https://github.com/Azure/azure-sdk-for-go/tree/main/sdk/storage/azdatalake/directory/client.go +[sas]: https://github.com/Azure/azure-sdk-for-go/tree/main/sdk/storage/azdatalake/sas +[service]: https://github.com/Azure/azure-sdk-for-go/tree/main/sdk/storage/azdatalake/service/client.go +[storage_contrib]: https://github.com/Azure/azure-sdk-for-go/blob/main/CONTRIBUTING.md +[cla]: https://cla.microsoft.com +[coc]: https://opensource.microsoft.com/codeofconduct/ +[coc_faq]: https://opensource.microsoft.com/codeofconduct/faq/ +[coc_contact]: mailto:opencode@microsoft.com diff --git a/sdk/storage/azdatalake/assets.json b/sdk/storage/azdatalake/assets.json index 3ec59c60cd99..6794bca42de8 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_ec80a91bf3" + "Tag": "go/storage/azdatalake_c3c16cffab" } \ No newline at end of file diff --git a/sdk/storage/azdatalake/datalakeerror/error_codes.go b/sdk/storage/azdatalake/datalakeerror/error_codes.go index b482c9b3f929..0c703a242606 100644 --- a/sdk/storage/azdatalake/datalakeerror/error_codes.go +++ b/sdk/storage/azdatalake/datalakeerror/error_codes.go @@ -30,6 +30,7 @@ func HasCode(err error, codes ...StorageErrorCode) bool { return false } +// StorageErrorCode - Error codes returned by the service type StorageErrorCode string // dfs errors @@ -79,10 +80,10 @@ const ( CannotVerifyCopySource StorageErrorCode = "CannotVerifyCopySource" ConditionHeadersNotSupported StorageErrorCode = "ConditionHeadersNotSupported" ConditionNotMet StorageErrorCode = "ConditionNotMet" - FilesystemAlreadyExists StorageErrorCode = "FilesystemAlreadyExists" - FilesystemBeingDeleted StorageErrorCode = "FilesystemBeingDeleted" - FilesystemDisabled StorageErrorCode = "FilesystemDisabled" - FilesystemNotFound StorageErrorCode = "FilesystemNotFound" + FileSystemAlreadyExists StorageErrorCode = "FileSystemAlreadyExists" + FileSystemBeingDeleted StorageErrorCode = "FileSystemBeingDeleted" + FileSystemDisabled StorageErrorCode = "FileSystemDisabled" + FileSystemNotFound StorageErrorCode = "FileSystemNotFound" ContentLengthLargerThanTierLimit StorageErrorCode = "ContentLengthLargerThanTierLimit" CopyAcrossAccountsNotSupported StorageErrorCode = "CopyAcrossAccountsNotSupported" CopyIDMismatch StorageErrorCode = "CopyIdMismatch" @@ -119,7 +120,7 @@ const ( LeaseAlreadyBroken StorageErrorCode = "LeaseAlreadyBroken" LeaseAlreadyPresent StorageErrorCode = "LeaseAlreadyPresent" LeaseIDMismatchWithPathOperation StorageErrorCode = "LeaseIdMismatchWithPathOperation" - LeaseIDMismatchWithFilesystemOperation StorageErrorCode = "LeaseIdMismatchWithFilesystemOperation" + LeaseIDMismatchWithFileSystemOperation StorageErrorCode = "LeaseIdMismatchWithFileSystemOperation" LeaseIDMismatchWithLeaseOperation StorageErrorCode = "LeaseIdMismatchWithLeaseOperation" LeaseIDMissing StorageErrorCode = "LeaseIdMissing" LeaseIsBreakingAndCannotBeAcquired StorageErrorCode = "LeaseIsBreakingAndCannotBeAcquired" @@ -127,7 +128,7 @@ const ( LeaseIsBrokenAndCannotBeRenewed StorageErrorCode = "LeaseIsBrokenAndCannotBeRenewed" LeaseLost StorageErrorCode = "LeaseLost" LeaseNotPresentWithPathOperation StorageErrorCode = "LeaseNotPresentWithPathOperation" - LeaseNotPresentWithFilesystemOperation StorageErrorCode = "LeaseNotPresentWithFilesystemOperation" + LeaseNotPresentWithFileSystemOperation StorageErrorCode = "LeaseNotPresentWithFileSystemOperation" LeaseNotPresentWithLeaseOperation StorageErrorCode = "LeaseNotPresentWithLeaseOperation" MD5Mismatch StorageErrorCode = "Md5Mismatch" CRC64Mismatch StorageErrorCode = "Crc64Mismatch" diff --git a/sdk/storage/azdatalake/directory/client.go b/sdk/storage/azdatalake/directory/client.go index dc7a6d0e63b6..45c9c21b6696 100644 --- a/sdk/storage/azdatalake/directory/client.go +++ b/sdk/storage/azdatalake/directory/client.go @@ -118,7 +118,7 @@ func NewClientWithSharedKeyCredential(directoryURL string, cred *SharedKeyCreden blobClientOpts := blockblob.ClientOptions{ ClientOptions: options.ClientOptions, } - blobSharedKey, err := cred.ConvertToBlobSharedKey() + blobSharedKey, err := exported.ConvertToBlobSharedKey(cred) if err != nil { return nil, err } @@ -188,8 +188,8 @@ func (d *Client) BlobURL() string { return d.generatedDirClientWithBlob().Endpoint() } -// NewFileClient creates a new file.Client object by concatenating fileName to the end of this Client's URL. -// The new file.Client uses the same request policy pipeline as the Client. +// NewFileClient creates a new directory.Client object by concatenating directoryName to the end of this Client's URL. +// The new directory.Client uses the same request policy pipeline as the Client. func (d *Client) NewFileClient(fileName string) (*file.Client, error) { fileName = url.PathEscape(fileName) fileURL := runtime.JoinPaths(d.DFSURL(), fileName) @@ -199,7 +199,7 @@ func (d *Client) NewFileClient(fileName string) (*file.Client, error) { if d.identityCredential() != nil { newBlobClient, err = blockblob.NewClient(newBlobURL, *d.identityCredential(), nil) } else if d.sharedKey() != nil { - blobSharedKey, _ := d.sharedKey().ConvertToBlobSharedKey() + blobSharedKey, _ := exported.ConvertToBlobSharedKey(d.sharedKey()) newBlobClient, err = blockblob.NewClientWithSharedKeyCredential(newBlobURL, blobSharedKey, nil) } else { newBlobClient, err = blockblob.NewClientWithNoCredential(newBlobURL, nil) @@ -210,7 +210,7 @@ func (d *Client) NewFileClient(fileName string) (*file.Client, error) { return (*file.Client)(base.NewPathClient(fileURL, newBlobURL, newBlobClient, d.generatedDirClientWithDFS().InternalClient().WithClientName(shared.FileClient), d.sharedKey(), d.identityCredential(), d.getClientOptions())), nil } -// Create creates a new directory (dfs1). +// Create creates a new directory. func (d *Client) Create(ctx context.Context, options *CreateOptions) (CreateResponse, error) { lac, mac, httpHeaders, createOpts, cpkOpts := options.format() resp, err := d.generatedDirClientWithDFS().Create(ctx, createOpts, httpHeaders, lac, mac, nil, cpkOpts) @@ -218,7 +218,7 @@ func (d *Client) Create(ctx context.Context, options *CreateOptions) (CreateResp return resp, err } -// Delete deletes directory and any path under it (dfs1). +// Delete deletes directory and any path under it. func (d *Client) Delete(ctx context.Context, options *DeleteOptions) (DeleteResponse, error) { lac, mac, deleteOpts := path.FormatDeleteOptions(options, true) resp, err := d.generatedDirClientWithDFS().Delete(ctx, deleteOpts, lac, mac) @@ -226,7 +226,7 @@ func (d *Client) Delete(ctx context.Context, options *DeleteOptions) (DeleteResp return resp, err } -// GetProperties gets the properties of a directory (blob3) +// GetProperties gets the properties of a directory. func (d *Client) GetProperties(ctx context.Context, options *GetPropertiesOptions) (GetPropertiesResponse, error) { opts := path.FormatGetPropertiesOptions(options) var respFromCtx *http.Response @@ -245,36 +245,37 @@ func (d *Client) renamePathInURL(newName string) (string, string, string) { // 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 newBlobURL, newPathURL := shared.GetURLs(runtime.JoinPaths(firstPart, newName)) - parsedNewURL, _ := url.Parse(d.DFSURL()) - return parsedNewURL.Path, newPathURL, newBlobURL + oldURL, _ := url.Parse(d.DFSURL()) + return oldURL.Path, newPathURL, newBlobURL } -// Rename renames a directory (dfs1) +// Rename renames a directory. The original directory will no longer exist and the client will be stale. func (d *Client) Rename(ctx context.Context, newName string, options *RenameOptions) (RenameResponse, error) { - newPathWithoutURL, newPathURL, newBlobURL := d.renamePathInURL(newName) - lac, mac, smac, createOpts := path.FormatRenameOptions(options, newPathWithoutURL) + oldURL, newPathURL, newBlobURL := d.renamePathInURL(newName) + lac, mac, smac, createOpts := path.FormatRenameOptions(options, oldURL) 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() + blobSharedKey, _ := exported.ConvertToBlobSharedKey(d.sharedKey()) newBlobClient, err = blockblob.NewClientWithSharedKeyCredential(newBlobURL, blobSharedKey, nil) } else { newBlobClient, err = blockblob.NewClientWithNoCredential(newBlobURL, nil) } if err != nil { - return RenameResponse{}, err + return RenameResponse{}, exported.ConvertToDFSError(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) + //return RenameResponse{ + // Response: resp, + // NewDirectoryClient: newDirClient, + //}, exported.ConvertToDFSError(err) + return path.FormatRenameResponse(&resp), exported.ConvertToDFSError(err) } -// SetAccessControl sets the owner, owning group, and permissions for a directory (dfs1). +// SetAccessControl sets the owner, owning group, and permissions for a directory. func (d *Client) SetAccessControl(ctx context.Context, options *SetAccessControlOptions) (SetAccessControlResponse, error) { opts, lac, mac, err := path.FormatSetAccessControlOptions(options) if err != nil { @@ -319,7 +320,7 @@ func (d *Client) setAccessControlPager(mode generated.PathSetAccessControlRecurs } -func (d *Client) setAccessControlRecursiveHelper(mode generated.PathSetAccessControlRecursiveMode, listOptions *generated.PathClientSetAccessControlRecursiveOptions, options *SetAccessControlRecursiveOptions) (SetAccessControlRecursiveResponse, error) { +func (d *Client) setAccessControlRecursiveHelper(ctx context.Context, mode generated.PathSetAccessControlRecursiveMode, listOptions *generated.PathClientSetAccessControlRecursiveOptions, options *SetAccessControlRecursiveOptions) (SetAccessControlRecursiveResponse, error) { pager := d.setAccessControlPager(mode, listOptions) counter := *options.MaxBatches continueOnFailure := listOptions.ForceFlag @@ -333,7 +334,7 @@ func (d *Client) setAccessControlRecursiveHelper(mode generated.PathSetAccessCon FailedEntries: []*ACLFailedEntry{}, } for pager.More() && counter != 0 { - resp, err := pager.NextPage(context.Background()) + resp, err := pager.NextPage(ctx) if err != nil { return finalResponse, exported.ConvertToDFSError(err) } @@ -349,34 +350,34 @@ func (d *Client) setAccessControlRecursiveHelper(mode generated.PathSetAccessCon return finalResponse, nil } -// SetAccessControlRecursive sets the owner, owning group, and permissions for a directory (dfs1). -func (d *Client) SetAccessControlRecursive(ACL string, options *SetAccessControlRecursiveOptions) (SetAccessControlRecursiveResponse, error) { +// SetAccessControlRecursive sets the owner, owning group, and permissions for a directory. +func (d *Client) SetAccessControlRecursive(ctx context.Context, ACL string, options *SetAccessControlRecursiveOptions) (SetAccessControlRecursiveResponse, error) { if options == nil { options = &SetAccessControlRecursiveOptions{} } mode, listOptions := options.format(ACL, "set") - return d.setAccessControlRecursiveHelper(mode, listOptions, options) + return d.setAccessControlRecursiveHelper(ctx, mode, listOptions, options) } -// UpdateAccessControlRecursive updates the owner, owning group, and permissions for a directory (dfs1). -func (d *Client) UpdateAccessControlRecursive(ACL string, options *UpdateAccessControlRecursiveOptions) (SetAccessControlRecursiveResponse, error) { +// UpdateAccessControlRecursive updates the owner, owning group, and permissions for a directory. +func (d *Client) UpdateAccessControlRecursive(ctx context.Context, ACL string, options *UpdateAccessControlRecursiveOptions) (SetAccessControlRecursiveResponse, error) { if options == nil { options = &UpdateAccessControlRecursiveOptions{} } mode, listOptions := options.format(ACL, "modify") - return d.setAccessControlRecursiveHelper(mode, listOptions, options) + return d.setAccessControlRecursiveHelper(ctx, mode, listOptions, options) } -// RemoveAccessControlRecursive removes the owner, owning group, and permissions for a directory (dfs1). -func (d *Client) RemoveAccessControlRecursive(ACL string, options *RemoveAccessControlRecursiveOptions) (SetAccessControlRecursiveResponse, error) { +// RemoveAccessControlRecursive removes the owner, owning group, and permissions for a directory. +func (d *Client) RemoveAccessControlRecursive(ctx context.Context, ACL string, options *RemoveAccessControlRecursiveOptions) (SetAccessControlRecursiveResponse, error) { if options == nil { options = &RemoveAccessControlRecursiveOptions{} } mode, listOptions := options.format(ACL, "remove") - return d.setAccessControlRecursiveHelper(mode, listOptions, options) + return d.setAccessControlRecursiveHelper(ctx, mode, listOptions, options) } -// GetAccessControl gets the owner, owning group, and permissions for a directory (dfs1). +// GetAccessControl gets the owner, owning group, and permissions for a directory. 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) @@ -384,15 +385,15 @@ func (d *Client) GetAccessControl(ctx context.Context, options *GetAccessControl return resp, err } -// SetMetadata sets the metadata for a directory (blob3). -func (d *Client) SetMetadata(ctx context.Context, options *SetMetadataOptions) (SetMetadataResponse, error) { - opts, metadata := path.FormatSetMetadataOptions(options) +// SetMetadata sets the metadata for a directory. +func (d *Client) SetMetadata(ctx context.Context, metadata map[string]*string, options *SetMetadataOptions) (SetMetadataResponse, error) { + opts := 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 directory (blob3). +// SetHTTPHeaders sets the HTTP headers for a directory. func (d *Client) SetHTTPHeaders(ctx context.Context, httpHeaders HTTPHeaders, options *SetHTTPHeadersOptions) (SetHTTPHeadersResponse, error) { opts, blobHTTPHeaders := path.FormatSetHTTPHeadersOptions(options, httpHeaders) resp, err := d.blobClient().SetHTTPHeaders(ctx, blobHTTPHeaders, opts) @@ -402,7 +403,7 @@ func (d *Client) SetHTTPHeaders(ctx context.Context, httpHeaders HTTPHeaders, op return newResp, err } -// GetSASURL is a convenience method for generating a SAS token for the currently pointed at blob. +// GetSASURL is a convenience method for generating a SAS token for the currently pointed at directory. // It can only be used if the credential supplied during creation was a SharedKeyCredential. func (d *Client) GetSASURL(permissions sas.DirectoryPermissions, expiry time.Time, o *GetSASURLOptions) (string, error) { if d.sharedKey() == nil { @@ -419,7 +420,7 @@ func (d *Client) GetSASURL(permissions sas.DirectoryPermissions, expiry time.Tim qps, err := sas.DatalakeSignatureValues{ DirectoryPath: urlParts.PathName, - FilesystemName: urlParts.FilesystemName, + FileSystemName: urlParts.FileSystemName, Version: sas.Version, Permissions: permissions.String(), StartTime: st, @@ -435,3 +436,6 @@ func (d *Client) GetSASURL(permissions sas.DirectoryPermissions, expiry time.Tim return endpoint, nil } + +// TODO: Undelete() +// TODO: ListPaths() diff --git a/sdk/storage/azdatalake/directory/client_test.go b/sdk/storage/azdatalake/directory/client_test.go index f9b0ea71f857..9ff90a56b9d4 100644 --- a/sdk/storage/azdatalake/directory/client_test.go +++ b/sdk/storage/azdatalake/directory/client_test.go @@ -66,10 +66,10 @@ func (s *UnrecordedTestSuite) TestCreateDirAndDeleteWithConnectionString() { connectionString, _ := testcommon.GetGenericConnectionString(testcommon.TestAccountDatalake) - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + filesystemName := testcommon.GenerateFileSystemName(testName) + fsClient, err := testcommon.GetFileSystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) - defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) _, err = fsClient.Create(context.Background(), nil) _require.Nil(err) @@ -90,10 +90,10 @@ func (s *RecordedTestSuite) TestBlobURLAndDFSURL() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + filesystemName := testcommon.GenerateFileSystemName(testName) + fsClient, err := testcommon.GetFileSystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) - defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) _, err = fsClient.Create(context.Background(), nil) _require.Nil(err) @@ -116,10 +116,10 @@ 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) + filesystemName := testcommon.GenerateFileSystemName(testName) + fsClient, err := testcommon.GetFileSystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) - defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) _, err = fsClient.Create(context.Background(), nil) _require.Nil(err) @@ -139,10 +139,10 @@ func (s *RecordedTestSuite) TestGetAndCreateFileClient() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + filesystemName := testcommon.GenerateFileSystemName(testName) + fsClient, err := testcommon.GetFileSystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) - defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) _, err = fsClient.Create(context.Background(), nil) _require.Nil(err) @@ -169,10 +169,10 @@ 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) + filesystemName := testcommon.GenerateFileSystemName(testName) + fsClient, err := testcommon.GetFileSystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) - defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) _, err = fsClient.Create(context.Background(), nil) _require.Nil(err) @@ -200,10 +200,10 @@ 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) + filesystemName := testcommon.GenerateFileSystemName(testName) + fsClient, err := testcommon.GetFileSystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) - defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) _, err = fsClient.Create(context.Background(), nil) _require.Nil(err) @@ -237,10 +237,10 @@ 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) + filesystemName := testcommon.GenerateFileSystemName(testName) + fsClient, err := testcommon.GetFileSystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) - defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) _, err = fsClient.Create(context.Background(), nil) _require.Nil(err) @@ -274,10 +274,10 @@ 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) + filesystemName := testcommon.GenerateFileSystemName(testName) + fsClient, err := testcommon.GetFileSystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) - defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) _, err = fsClient.Create(context.Background(), nil) _require.Nil(err) @@ -311,10 +311,10 @@ func (s *RecordedTestSuite) TestCreateDirIfUnmodifiedSinceFalse() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + filesystemName := testcommon.GenerateFileSystemName(testName) + fsClient, err := testcommon.GetFileSystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) - defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) _, err = fsClient.Create(context.Background(), nil) _require.Nil(err) @@ -349,10 +349,10 @@ func (s *RecordedTestSuite) TestCreateDirIfETagMatch() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + filesystemName := testcommon.GenerateFileSystemName(testName) + fsClient, err := testcommon.GetFileSystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) - defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) _, err = fsClient.Create(context.Background(), nil) _require.Nil(err) @@ -386,10 +386,10 @@ func (s *RecordedTestSuite) TestCreateDirIfETagMatchFalse() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + filesystemName := testcommon.GenerateFileSystemName(testName) + fsClient, err := testcommon.GetFileSystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) - defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) _, err = fsClient.Create(context.Background(), nil) _require.Nil(err) @@ -420,68 +420,14 @@ func (s *RecordedTestSuite) TestCreateDirIfETagMatchFalse() { testcommon.ValidateErrorCode(_require, err, datalakeerror.ConditionNotMet) } -func (s *RecordedTestSuite) TestCreateDirWithMetadataNotNil() { - _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) TestCreateDirWithEmptyMetadata() { - _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) TestCreateDirWithNilHTTPHeaders() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + filesystemName := testcommon.GenerateFileSystemName(testName) + fsClient, err := testcommon.GetFileSystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) - defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) createDirOpts := &directory.CreateOptions{ HTTPHeaders: nil, @@ -505,10 +451,10 @@ func (s *RecordedTestSuite) TestCreateDirWithHTTPHeaders() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + filesystemName := testcommon.GenerateFileSystemName(testName) + fsClient, err := testcommon.GetFileSystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) - defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) createDirOpts := &directory.CreateOptions{ HTTPHeaders: &testcommon.BasicHeaders, @@ -532,10 +478,10 @@ 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) + filesystemName := testcommon.GenerateFileSystemName(testName) + fsClient, err := testcommon.GetFileSystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) - defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) createFileOpts := &directory.CreateOptions{ ProposedLeaseID: proposedLeaseIDs[0], @@ -567,12 +513,12 @@ 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) + 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) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) createFileOpts := &directory.CreateOptions{ Permissions: &perms, @@ -600,14 +546,14 @@ 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) + 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) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) createFileOpts := &directory.CreateOptions{ Owner: &owner, @@ -633,10 +579,10 @@ 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) + filesystemName := testcommon.GenerateFileSystemName(testName) + fsClient, err := testcommon.GetFileSystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) - defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) _, err = fsClient.Create(context.Background(), nil) _require.Nil(err) @@ -661,10 +607,10 @@ 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) + filesystemName := testcommon.GenerateFileSystemName(testName) + fsClient, err := testcommon.GetFileSystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) - defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) _, err = fsClient.Create(context.Background(), nil) _require.Nil(err) @@ -695,10 +641,10 @@ 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) + filesystemName := testcommon.GenerateFileSystemName(testName) + fsClient, err := testcommon.GetFileSystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) - defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) _, err = fsClient.Create(context.Background(), nil) _require.Nil(err) @@ -730,10 +676,10 @@ 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) + filesystemName := testcommon.GenerateFileSystemName(testName) + fsClient, err := testcommon.GetFileSystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) - defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) _, err = fsClient.Create(context.Background(), nil) _require.Nil(err) @@ -765,10 +711,10 @@ 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) + filesystemName := testcommon.GenerateFileSystemName(testName) + fsClient, err := testcommon.GetFileSystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) - defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) _, err = fsClient.Create(context.Background(), nil) _require.Nil(err) @@ -801,10 +747,10 @@ 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) + filesystemName := testcommon.GenerateFileSystemName(testName) + fsClient, err := testcommon.GetFileSystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) - defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) _, err = fsClient.Create(context.Background(), nil) _require.Nil(err) @@ -836,10 +782,10 @@ 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) + filesystemName := testcommon.GenerateFileSystemName(testName) + fsClient, err := testcommon.GetFileSystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) - defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) _, err = fsClient.Create(context.Background(), nil) _require.Nil(err) @@ -872,10 +818,10 @@ func (s *RecordedTestSuite) TestDirSetAccessControlNil() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + filesystemName := testcommon.GenerateFileSystemName(testName) + fsClient, err := testcommon.GetFileSystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) - defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) _, err = fsClient.Create(context.Background(), nil) _require.Nil(err) @@ -899,13 +845,13 @@ func (s *RecordedTestSuite) TestDirSetAccessControl() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + 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) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) opts := &directory.SetAccessControlOptions{ Owner: &owner, @@ -932,13 +878,13 @@ func (s *RecordedTestSuite) TestDirSetAccessControlWithNilAccessConditions() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + 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) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) opts := &directory.SetAccessControlOptions{ Owner: &owner, @@ -966,13 +912,13 @@ func (s *RecordedTestSuite) TestDirSetAccessControlIfModifiedSinceTrue() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + 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) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) _, err = fsClient.Create(context.Background(), nil) _require.Nil(err) @@ -1005,13 +951,13 @@ func (s *RecordedTestSuite) TestDirSetAccessControlIfModifiedSinceFalse() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + 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) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) _, err = fsClient.Create(context.Background(), nil) _require.Nil(err) @@ -1045,13 +991,13 @@ func (s *RecordedTestSuite) TestDirSetAccessControlIfUnmodifiedSinceTrue() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + 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) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) _, err = fsClient.Create(context.Background(), nil) _require.Nil(err) @@ -1083,13 +1029,13 @@ func (s *RecordedTestSuite) TestDirSetAccessControlIfUnmodifiedSinceFalse() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + 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) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) _, err = fsClient.Create(context.Background(), nil) _require.Nil(err) @@ -1125,13 +1071,13 @@ func (s *RecordedTestSuite) TestDirSetAccessControlIfETagMatch() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + 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) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) _, err = fsClient.Create(context.Background(), nil) _require.Nil(err) @@ -1164,13 +1110,13 @@ func (s *RecordedTestSuite) TestDirSetAccessControlIfETagMatchFalse() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + 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) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) _, err = fsClient.Create(context.Background(), nil) _require.Nil(err) @@ -1203,11 +1149,11 @@ func (s *RecordedTestSuite) TestDirGetAccessControl() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + 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) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) createOpts := &directory.CreateOptions{ ACL: &acl, @@ -1232,11 +1178,11 @@ func (s *UnrecordedTestSuite) TestDirGetAccessControlWithSAS() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + 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) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) createOpts := &directory.CreateOptions{ ACL: &acl, @@ -1276,10 +1222,10 @@ func (s *UnrecordedTestSuite) TestDeleteWithSAS() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + filesystemName := testcommon.GenerateFileSystemName(testName) + fsClient, err := testcommon.GetFileSystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) - defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) _, err = fsClient.Create(context.Background(), nil) _require.Nil(err) @@ -1315,11 +1261,11 @@ func (s *RecordedTestSuite) TestDirGetAccessControlWithNilAccessConditions() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + 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) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) createOpts := &directory.CreateOptions{ ACL: &acl, @@ -1348,11 +1294,11 @@ func (s *RecordedTestSuite) TestDirGetAccessControlIfModifiedSinceTrue() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + 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) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) createOpts := &directory.CreateOptions{ ACL: &acl, @@ -1386,11 +1332,11 @@ func (s *RecordedTestSuite) TestDirGetAccessControlIfModifiedSinceFalse() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + 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) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) createOpts := &directory.CreateOptions{ ACL: &acl, @@ -1424,11 +1370,11 @@ func (s *RecordedTestSuite) TestDirGetAccessControlIfUnmodifiedSinceTrue() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + 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) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) createOpts := &directory.CreateOptions{ ACL: &acl, @@ -1461,11 +1407,11 @@ func (s *RecordedTestSuite) TestDirGetAccessControlIfUnmodifiedSinceFalse() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + 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) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) createOpts := &directory.CreateOptions{ ACL: &acl, @@ -1501,11 +1447,11 @@ func (s *RecordedTestSuite) TestDirGetAccessControlIfETagMatch() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + 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) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) createOpts := &directory.CreateOptions{ ACL: &acl, @@ -1539,11 +1485,11 @@ func (s *RecordedTestSuite) TestDirGetAccessControlIfETagMatchFalse() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + 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) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) createOpts := &directory.CreateOptions{ ACL: &acl, @@ -1578,11 +1524,11 @@ func (s *RecordedTestSuite) TestDirSetAccessControlRecursive() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + 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) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) _, err = fsClient.Create(context.Background(), nil) _require.Nil(err) @@ -1595,7 +1541,7 @@ func (s *RecordedTestSuite) TestDirSetAccessControlRecursive() { _require.Nil(err) _require.NotNil(resp) - resp1, err := dirClient.SetAccessControlRecursive(acl, nil) + resp1, err := dirClient.SetAccessControlRecursive(context.Background(), acl, nil) _require.Nil(err) _require.Equal(resp1.DirectoriesSuccessful, to.Ptr(int32(1))) @@ -1611,11 +1557,11 @@ func (s *RecordedTestSuite) TestDirSetAccessControlRecursiveWithBadContinuation( _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + 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) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) _, err = fsClient.Create(context.Background(), nil) _require.Nil(err) @@ -1629,7 +1575,7 @@ func (s *RecordedTestSuite) TestDirSetAccessControlRecursiveWithBadContinuation( _require.NotNil(resp) opts := &directory.SetAccessControlRecursiveOptions{Marker: to.Ptr("garbage")} - resp1, err := dirClient.SetAccessControlRecursive(acl, opts) + resp1, err := dirClient.SetAccessControlRecursive(context.Background(), acl, opts) _require.Nil(err) _require.Equal(resp1.DirectoriesSuccessful, to.Ptr(int32(0))) @@ -1641,11 +1587,11 @@ func (s *RecordedTestSuite) TestDirSetAccessControlRecursiveWithEmptyOpts() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + 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) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) _, err = fsClient.Create(context.Background(), nil) _require.Nil(err) @@ -1659,7 +1605,7 @@ func (s *RecordedTestSuite) TestDirSetAccessControlRecursiveWithEmptyOpts() { _require.NotNil(resp) opts := &directory.SetAccessControlRecursiveOptions{} - resp1, err := dirClient.SetAccessControlRecursive(acl, opts) + resp1, err := dirClient.SetAccessControlRecursive(context.Background(), acl, opts) _require.Nil(err) _require.Equal(resp1.DirectoriesSuccessful, to.Ptr(int32(1))) @@ -1675,11 +1621,11 @@ func (s *RecordedTestSuite) TestDirSetAccessControlRecursiveWithMaxResults() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + 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) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) _, err = fsClient.Create(context.Background(), nil) _require.Nil(err) @@ -1711,7 +1657,7 @@ func (s *RecordedTestSuite) TestDirSetAccessControlRecursiveWithMaxResults() { _require.Nil(err) opts := &directory.SetAccessControlRecursiveOptions{BatchSize: to.Ptr(int32(2)), MaxBatches: to.Ptr(int32(1)), ContinueOnFailure: to.Ptr(true), Marker: nil} - resp2, err := dirClient.SetAccessControlRecursive(acl, opts) + resp2, err := dirClient.SetAccessControlRecursive(context.Background(), acl, opts) _require.Nil(err) // we expect only one file to have been updated not both since our batch size is 2 and max batches is 1 @@ -1728,11 +1674,11 @@ func (s *RecordedTestSuite) TestDirSetAccessControlRecursiveWithMaxResults2() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + 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) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) _, err = fsClient.Create(context.Background(), nil) _require.Nil(err) @@ -1764,7 +1710,7 @@ func (s *RecordedTestSuite) TestDirSetAccessControlRecursiveWithMaxResults2() { _require.Nil(err) opts := &directory.SetAccessControlRecursiveOptions{ContinueOnFailure: to.Ptr(true), Marker: nil} - resp2, err := dirClient.SetAccessControlRecursive(acl, opts) + resp2, err := dirClient.SetAccessControlRecursive(context.Background(), acl, opts) _require.Nil(err) // we expect only one file to have been updated not both since our batch size is 2 and max batches is 1 @@ -1781,11 +1727,11 @@ func (s *RecordedTestSuite) TestDirSetAccessControlRecursiveWithMaxResults3() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + 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) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) _, err = fsClient.Create(context.Background(), nil) _require.Nil(err) @@ -1817,7 +1763,7 @@ func (s *RecordedTestSuite) TestDirSetAccessControlRecursiveWithMaxResults3() { _require.Nil(err) opts := &directory.SetAccessControlRecursiveOptions{BatchSize: to.Ptr(int32(1)), ContinueOnFailure: to.Ptr(true), Marker: nil} - resp2, err := dirClient.SetAccessControlRecursive(acl, opts) + resp2, err := dirClient.SetAccessControlRecursive(context.Background(), acl, opts) _require.Nil(err) // we expect only one file to have been updated not both since our batch size is 2 and max batches is 1 @@ -1834,12 +1780,12 @@ func (s *RecordedTestSuite) TestDirUpdateAccessControlRecursive() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + 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) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) createOpts := &directory.CreateOptions{ ACL: &acl, @@ -1855,7 +1801,7 @@ func (s *RecordedTestSuite) TestDirUpdateAccessControlRecursive() { _require.Nil(err) _require.NotNil(resp) - resp1, err := dirClient.UpdateAccessControlRecursive(acl1, nil) + resp1, err := dirClient.UpdateAccessControlRecursive(context.Background(), acl1, nil) _require.Nil(err) _require.Equal(resp1.DirectoriesSuccessful, to.Ptr(int32(1))) @@ -1869,13 +1815,13 @@ func (s *RecordedTestSuite) TestDirRemoveAccessControlRecursive() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + 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) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) _, err = fsClient.Create(context.Background(), nil) _require.Nil(err) @@ -1888,74 +1834,19 @@ func (s *RecordedTestSuite) TestDirRemoveAccessControlRecursive() { _require.Nil(err) _require.NotNil(resp) - resp1, err := dirClient.RemoveAccessControlRecursive(acl, nil) + resp1, err := dirClient.RemoveAccessControlRecursive(context.Background(), acl, nil) _require.Nil(err) _require.Equal(resp1.DirectoriesSuccessful, to.Ptr(int32(1))) } -func (s *RecordedTestSuite) TestDirSetMetadataNil() { - _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) TestDirSetMetadataWithEmptyOpts() { - _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) TestDirSetMetadataWithBasicMetadata() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + filesystemName := testcommon.GenerateFileSystemName(testName) + fsClient, err := testcommon.GetFileSystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) - defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) _, err = fsClient.Create(context.Background(), nil) _require.Nil(err) @@ -1970,10 +1861,7 @@ func (s *RecordedTestSuite) TestDirSetMetadataWithBasicMetadata() { _require.Nil(err) _require.NotNil(resp) - opts := &directory.SetMetadataOptions{ - Metadata: testcommon.BasicMetadata, - } - _, err = dirClient.SetMetadata(context.Background(), opts) + _, err = dirClient.SetMetadata(context.Background(), testcommon.BasicMetadata, nil) _require.Nil(err) } @@ -1981,10 +1869,10 @@ func (s *RecordedTestSuite) TestDirSetMetadataWithAccessConditions() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + filesystemName := testcommon.GenerateFileSystemName(testName) + fsClient, err := testcommon.GetFileSystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) - defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) _, err = fsClient.Create(context.Background(), nil) _require.Nil(err) @@ -2002,14 +1890,13 @@ func (s *RecordedTestSuite) TestDirSetMetadataWithAccessConditions() { 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) + _, err = dirClient.SetMetadata(context.Background(), testcommon.BasicMetadata, opts) _require.Nil(err) } @@ -2023,10 +1910,10 @@ func (s *RecordedTestSuite) TestDirSetHTTPHeaders() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + filesystemName := testcommon.GenerateFileSystemName(testName) + fsClient, err := testcommon.GetFileSystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) - defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) _, err = fsClient.Create(context.Background(), nil) _require.Nil(err) @@ -2048,10 +1935,10 @@ func (s *RecordedTestSuite) TestDirSetHTTPHeadersWithNilAccessConditions() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + filesystemName := testcommon.GenerateFileSystemName(testName) + fsClient, err := testcommon.GetFileSystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) - defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) _, err = fsClient.Create(context.Background(), nil) _require.Nil(err) @@ -2077,10 +1964,10 @@ func (s *RecordedTestSuite) TestDirSetHTTPHeadersIfModifiedSinceTrue() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + filesystemName := testcommon.GenerateFileSystemName(testName) + fsClient, err := testcommon.GetFileSystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) - defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) _, err = fsClient.Create(context.Background(), nil) _require.Nil(err) @@ -2111,10 +1998,10 @@ func (s *RecordedTestSuite) TestDirSetHTTPHeadersIfModifiedSinceFalse() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + filesystemName := testcommon.GenerateFileSystemName(testName) + fsClient, err := testcommon.GetFileSystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) - defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) _, err = fsClient.Create(context.Background(), nil) _require.Nil(err) @@ -2145,10 +2032,10 @@ func (s *RecordedTestSuite) TestDirSetHTTPHeadersIfUnmodifiedSinceTrue() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + filesystemName := testcommon.GenerateFileSystemName(testName) + fsClient, err := testcommon.GetFileSystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) - defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) _, err = fsClient.Create(context.Background(), nil) _require.Nil(err) @@ -2179,10 +2066,10 @@ func (s *RecordedTestSuite) TestDirSetHTTPHeadersIfUnmodifiedSinceFalse() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + filesystemName := testcommon.GenerateFileSystemName(testName) + fsClient, err := testcommon.GetFileSystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) - defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) _, err = fsClient.Create(context.Background(), nil) _require.Nil(err) @@ -2213,10 +2100,10 @@ func (s *RecordedTestSuite) TestDirSetHTTPHeadersIfETagMatch() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + filesystemName := testcommon.GenerateFileSystemName(testName) + fsClient, err := testcommon.GetFileSystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) - defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) _, err = fsClient.Create(context.Background(), nil) _require.Nil(err) @@ -2246,10 +2133,10 @@ func (s *RecordedTestSuite) TestDirSetHTTPHeadersIfETagMatchFalse() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + filesystemName := testcommon.GenerateFileSystemName(testName) + fsClient, err := testcommon.GetFileSystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) - defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) _, err = fsClient.Create(context.Background(), nil) _require.Nil(err) @@ -2280,10 +2167,10 @@ func (s *RecordedTestSuite) TestDirRenameNoOptions() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + filesystemName := testcommon.GenerateFileSystemName(testName) + fsClient, err := testcommon.GetFileSystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) - defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) _, err = fsClient.Create(context.Background(), nil) _require.Nil(err) @@ -2296,20 +2183,21 @@ func (s *RecordedTestSuite) TestDirRenameNoOptions() { _require.Nil(err) _require.NotNil(resp) - resp1, err := dirClient.Rename(context.Background(), "newName", nil) + //resp1, err := dirClient.Rename(context.Background(), "newName", renameFileOpts) + _, err = dirClient.Rename(context.Background(), "newName", nil) _require.Nil(err) - _require.NotNil(resp1) - _require.Contains(resp1.NewDirectoryClient.DFSURL(), "newName") + //_require.NotNil(resp1) + //_require.Contains(resp1.NewDirectoryClient.DFSURL(), "newName") } func (s *RecordedTestSuite) TestRenameDirWithNilAccessConditions() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + filesystemName := testcommon.GenerateFileSystemName(testName) + fsClient, err := testcommon.GetFileSystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) - defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) _, err = fsClient.Create(context.Background(), nil) _require.Nil(err) @@ -2326,20 +2214,21 @@ func (s *RecordedTestSuite) TestRenameDirWithNilAccessConditions() { AccessConditions: nil, } - resp1, err := dirClient.Rename(context.Background(), "newName", renameFileOpts) + //resp1, err := dirClient.Rename(context.Background(), "newName", renameFileOpts) + _, err = dirClient.Rename(context.Background(), "newName", renameFileOpts) _require.Nil(err) - _require.NotNil(resp1) - _require.Contains(resp1.NewDirectoryClient.DFSURL(), "newName") + //_require.NotNil(resp1) + //_require.Contains(resp1.NewDirectoryClient.DFSURL(), "newName") } func (s *RecordedTestSuite) TestRenameDirIfModifiedSinceTrue() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + filesystemName := testcommon.GenerateFileSystemName(testName) + fsClient, err := testcommon.GetFileSystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) - defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) _, err = fsClient.Create(context.Background(), nil) _require.Nil(err) @@ -2361,20 +2250,21 @@ func (s *RecordedTestSuite) TestRenameDirIfModifiedSinceTrue() { }, }, } - resp1, err := dirClient.Rename(context.Background(), "newName", renameFileOpts) + //resp1, err := dirClient.Rename(context.Background(), "newName", renameFileOpts) + _, err = dirClient.Rename(context.Background(), "newName", renameFileOpts) _require.Nil(err) - _require.NotNil(resp1) - _require.Contains(resp1.NewDirectoryClient.DFSURL(), "newName") + //_require.NotNil(resp1) + //_require.Contains(resp1.NewDirectoryClient.DFSURL(), "newName") } func (s *RecordedTestSuite) TestRenameDirIfModifiedSinceFalse() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + filesystemName := testcommon.GenerateFileSystemName(testName) + fsClient, err := testcommon.GetFileSystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) - defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) _, err = fsClient.Create(context.Background(), nil) _require.Nil(err) @@ -2397,7 +2287,9 @@ func (s *RecordedTestSuite) TestRenameDirIfModifiedSinceFalse() { }, } + //_, err = dirClient.Rename(context.Background(), "newName", renameFileOpts) _, err = dirClient.Rename(context.Background(), "newName", renameFileOpts) + _require.NotNil(err) testcommon.ValidateErrorCode(_require, err, datalakeerror.SourceConditionNotMet) } @@ -2406,10 +2298,10 @@ func (s *RecordedTestSuite) TestRenameDirIfUnmodifiedSinceTrue() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + filesystemName := testcommon.GenerateFileSystemName(testName) + fsClient, err := testcommon.GetFileSystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) - defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) _, err = fsClient.Create(context.Background(), nil) _require.Nil(err) @@ -2432,20 +2324,21 @@ func (s *RecordedTestSuite) TestRenameDirIfUnmodifiedSinceTrue() { }, } - resp1, err := dirClient.Rename(context.Background(), "newName", renameFileOpts) + //resp1, err := dirClient.Rename(context.Background(), "newName", renameFileOpts) + _, err = dirClient.Rename(context.Background(), "newName", renameFileOpts) _require.Nil(err) - _require.NotNil(resp1) - _require.Contains(resp1.NewDirectoryClient.DFSURL(), "newName") + //_require.NotNil(resp1) + //_require.Contains(resp1.NewDirectoryClient.DFSURL(), "newName") } func (s *RecordedTestSuite) TestRenameDirIfUnmodifiedSinceFalse() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + filesystemName := testcommon.GenerateFileSystemName(testName) + fsClient, err := testcommon.GetFileSystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) - defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) _, err = fsClient.Create(context.Background(), nil) _require.Nil(err) @@ -2468,7 +2361,9 @@ func (s *RecordedTestSuite) TestRenameDirIfUnmodifiedSinceFalse() { }, } + //_, err = dirClient.Rename(context.Background(), "newName", renameFileOpts) _, err = dirClient.Rename(context.Background(), "newName", renameFileOpts) + _require.NotNil(err) testcommon.ValidateErrorCode(_require, err, datalakeerror.SourceConditionNotMet) } @@ -2477,10 +2372,10 @@ func (s *RecordedTestSuite) TestRenameDirIfETagMatch() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + filesystemName := testcommon.GenerateFileSystemName(testName) + fsClient, err := testcommon.GetFileSystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) - defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) _, err = fsClient.Create(context.Background(), nil) _require.Nil(err) @@ -2503,20 +2398,21 @@ func (s *RecordedTestSuite) TestRenameDirIfETagMatch() { }, } - resp1, err := dirClient.Rename(context.Background(), "newName", renameFileOpts) + //resp1, err := dirClient.Rename(context.Background(), "newName", renameFileOpts) + _, err = dirClient.Rename(context.Background(), "newName", renameFileOpts) _require.Nil(err) - _require.NotNil(resp1) - _require.Contains(resp1.NewDirectoryClient.DFSURL(), "newName") + //_require.NotNil(resp1) + //_require.Contains(resp1.NewDirectoryClient.DFSURL(), "newName") } func (s *RecordedTestSuite) TestRenameDirIfETagMatchFalse() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + filesystemName := testcommon.GenerateFileSystemName(testName) + fsClient, err := testcommon.GetFileSystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) - defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) _, err = fsClient.Create(context.Background(), nil) _require.Nil(err) @@ -2539,7 +2435,9 @@ func (s *RecordedTestSuite) TestRenameDirIfETagMatchFalse() { }, } + //_, err = dirClient.Rename(context.Background(), "newName", renameFileOpts) _, err = dirClient.Rename(context.Background(), "newName", renameFileOpts) + _require.NotNil(err) testcommon.ValidateErrorCode(_require, err, datalakeerror.SourceConditionNotMet) } diff --git a/sdk/storage/azdatalake/directory/constants.go b/sdk/storage/azdatalake/directory/constants.go index 99aae6d16704..25bfba6e776d 100644 --- a/sdk/storage/azdatalake/directory/constants.go +++ b/sdk/storage/azdatalake/directory/constants.go @@ -10,6 +10,7 @@ import ( "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/internal/path" ) +// EncryptionAlgorithmType defines values for EncryptionAlgorithmType. type EncryptionAlgorithmType = path.EncryptionAlgorithmType const ( diff --git a/sdk/storage/azdatalake/directory/examples_test.go b/sdk/storage/azdatalake/directory/examples_test.go new file mode 100644 index 000000000000..627317f8a62f --- /dev/null +++ b/sdk/storage/azdatalake/directory/examples_test.go @@ -0,0 +1,166 @@ +//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" + "fmt" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/to" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/directory" + "log" + "os" + "time" +) + +func handleError(err error) { + if err != nil { + log.Fatal(err.Error()) + } +} + +// make sure you create the filesystem before running this example +func Example_directory_CreateAndDelete() { + accountName, accountKey := os.Getenv("AZURE_STORAGE_ACCOUNT_NAME"), os.Getenv("AZURE_STORAGE_ACCOUNT_KEY") + + // Create a directory client + u := fmt.Sprintf("https://%s.dfs.core.windows.net/fs/dir1", accountName) + credential, err := azdatalake.NewSharedKeyCredential(accountName, accountKey) + handleError(err) + dirClient, err := directory.NewClientWithSharedKeyCredential(u, credential, nil) + handleError(err) + + _, err = dirClient.Create(context.Background(), nil) + handleError(err) + + _, err = dirClient.Delete(context.Background(), nil) + handleError(err) +} + +// This examples shows how to set a directory HTTP Headers, how to read, and how to update the directory's HTTP headers. +func Example_directory_HTTPHeaders() { + // make sure you create the filesystem and directory before running this example + accountName, accountKey := os.Getenv("AZURE_STORAGE_ACCOUNT_NAME"), os.Getenv("AZURE_STORAGE_ACCOUNT_KEY") + + // Create a dir client + u := fmt.Sprintf("https://%s.dfs.core.windows.net/fs/dir1", accountName) + credential, err := azdatalake.NewSharedKeyCredential(accountName, accountKey) + handleError(err) + dirClient, err := directory.NewClientWithSharedKeyCredential(u, credential, nil) + handleError(err) + + // Create a directory with HTTP headers + _, err = dirClient.SetHTTPHeaders(context.TODO(), directory.HTTPHeaders{ + ContentType: to.Ptr("text/html; charset=utf-8"), + ContentDisposition: to.Ptr("attachment"), + }, nil) + handleError(err) + + get, err := dirClient.GetProperties(context.TODO(), nil) + handleError(err) + + fmt.Println(get.ContentType) + fmt.Println(get.ContentDisposition) +} + +// make sure you create the filesystem and directory before running this example +func Example_dir_Client_SetMetadata() { + accountName, accountKey := os.Getenv("AZURE_STORAGE_ACCOUNT_NAME"), os.Getenv("AZURE_STORAGE_ACCOUNT_KEY") + // Create a dir client + u := fmt.Sprintf("https://%s.dfs.core.windows.net/fs/dir1", accountName) + credential, err := azdatalake.NewSharedKeyCredential(accountName, accountKey) + handleError(err) + + dirClient, err := directory.NewClientWithSharedKeyCredential(u, credential, nil) + handleError(err) + + _, err = dirClient.SetMetadata(context.TODO(), map[string]*string{"author": to.Ptr("Tamer")}, nil) + handleError(err) + + // Query the directory's properties and metadata + get, err := dirClient.GetProperties(context.TODO(), nil) + handleError(err) + + // Show the directory's metadata + if get.Metadata == nil { + log.Fatal("No metadata returned") + } + + for k, v := range get.Metadata { + fmt.Print(k + "=" + *v + "\n") + } +} + +// make sure you create the filesystem before running this example +func Example_directory_Rename() { + accountName, accountKey := os.Getenv("AZURE_STORAGE_ACCOUNT_NAME"), os.Getenv("AZURE_STORAGE_ACCOUNT_KEY") + + // Create a directory client + u := fmt.Sprintf("https://%s.dfs.core.windows.net/fs/dir1", accountName) + credential, err := azdatalake.NewSharedKeyCredential(accountName, accountKey) + handleError(err) + dirClient, err := directory.NewClientWithSharedKeyCredential(u, credential, nil) + handleError(err) + + _, err = dirClient.Create(context.Background(), nil) + handleError(err) + + _, err = dirClient.Rename(context.Background(), "renameDir", nil) + handleError(err) +} + +// for this example make sure to create paths within the dir so you can recursively set the ACL on them +func Example_directory_SetACLRecursive() { + accountName, accountKey := os.Getenv("AZURE_STORAGE_ACCOUNT_NAME"), os.Getenv("AZURE_STORAGE_ACCOUNT_KEY") + + // Create a directory client + acl := "user::rwx,group::r-x,other::rwx" + u := fmt.Sprintf("https://%s.dfs.core.windows.net/fs/dir1", accountName) + credential, err := azdatalake.NewSharedKeyCredential(accountName, accountKey) + handleError(err) + dirClient, err := directory.NewClientWithSharedKeyCredential(u, credential, nil) + handleError(err) + + _, err = dirClient.SetAccessControlRecursive(context.Background(), acl, &directory.SetAccessControlRecursiveOptions{ + BatchSize: to.Ptr(int32(2)), MaxBatches: to.Ptr(int32(1)), ContinueOnFailure: to.Ptr(true), Marker: nil}) + handleError(err) +} + +func getRelativeTimeFromAnchor(anchorTime *time.Time, amount time.Duration) time.Time { + return anchorTime.Add(amount * time.Second) +} + +// make sure you create the filesystem before running this example +func Example_directory_SetAccessControlIfUnmodifiedSinceTrue() { + accountName, accountKey := os.Getenv("AZURE_STORAGE_ACCOUNT_NAME"), os.Getenv("AZURE_STORAGE_ACCOUNT_KEY") + + // Create a directory client + owner := "4cf4e284-f6a8-4540-b53e-c3469af032dc" + group := owner + acl := "user::rwx,group::r-x,other::rwx" + u := fmt.Sprintf("https://%s.dfs.core.windows.net/fs/dir1", accountName) + credential, err := azdatalake.NewSharedKeyCredential(accountName, accountKey) + handleError(err) + dirClient, err := directory.NewClientWithSharedKeyCredential(u, credential, nil) + handleError(err) + resp, err := dirClient.Create(context.Background(), nil) + handleError(err) + + currentTime := 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) + handleError(err) +} diff --git a/sdk/storage/azdatalake/directory/models.go b/sdk/storage/azdatalake/directory/models.go index 9e3016c05322..954ee67c481d 100644 --- a/sdk/storage/azdatalake/directory/models.go +++ b/sdk/storage/azdatalake/directory/models.go @@ -13,12 +13,10 @@ import ( "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/internal/path" ) -// CreateOptions contains the optional parameters when calling the Create operation. dfs endpoint. +// CreateOptions contains the optional parameters when calling the Create operation. type CreateOptions struct { // AccessConditions contains parameters for accessing the file. AccessConditions *AccessConditions - // Metadata is a map of name-value pairs to associate with the file storage object. - Metadata map[string]*string // CPKInfo contains a group of parameters for client provided encryption key. CPKInfo *CPKInfo // HTTPHeaders contains the HTTP headers for path operations. @@ -80,7 +78,7 @@ func (o *CreateOptions) format() (*generated.LeaseAccessConditions, *generated.M type accessControlRecursiveOptions struct { // Max batch size is 2000 paths BatchSize *int32 - // Number of recursive calls to be made to set access control + // Number of recursive calls to be made to set access control. MaxBatches *int32 // ContinueOnFailure indicates whether to continue on failure when the operation encounters an error. ContinueOnFailure *bool @@ -119,43 +117,43 @@ type RemoveAccessControlRecursiveOptions = accessControlRecursiveOptions // ================================= path imports ================================== -// DeleteOptions contains the optional parameters when calling the Delete operation. dfs endpoint +// DeleteOptions contains the optional parameters when calling the Delete operation. 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 +// GetPropertiesOptions contains the optional parameters for the GetProperties method. type GetPropertiesOptions = path.GetPropertiesOptions -// SetAccessControlOptions contains the optional parameters when calling the SetAccessControl operation. dfs endpoint +// SetAccessControlOptions contains the optional parameters when calling the SetAccessControl operation. type SetAccessControlOptions = path.SetAccessControlOptions // GetAccessControlOptions contains the optional parameters when calling the GetAccessControl operation. type GetAccessControlOptions = path.GetAccessControlOptions -// CPKInfo contains a group of parameters for the PathClient.Download method. +// CPKInfo contains a group of parameters for client provided encryption key. type CPKInfo = path.CPKInfo -// GetSASURLOptions contains the optional parameters for the Client.GetSASURL method. +// GetSASURLOptions contains the optional parameters for the GetSASURL method. type GetSASURLOptions = path.GetSASURLOptions -// SetHTTPHeadersOptions contains the optional parameters for the Client.SetHTTPHeaders method. +// SetHTTPHeadersOptions contains the optional parameters for the SetHTTPHeaders method. type SetHTTPHeadersOptions = path.SetHTTPHeadersOptions // HTTPHeaders contains the HTTP headers for path operations. type HTTPHeaders = path.HTTPHeaders -// SetMetadataOptions provides set of configurations for Set Metadata on path operation +// SetMetadataOptions provides set of configurations for SetMetadata. type SetMetadataOptions = path.SetMetadataOptions // SharedKeyCredential contains an account's name and its primary or secondary key. type SharedKeyCredential = path.SharedKeyCredential -// AccessConditions identifies blob-specific access conditions which you optionally set. +// AccessConditions identifies path-specific access conditions which you optionally set. type AccessConditions = path.AccessConditions -// SourceAccessConditions identifies blob-specific access conditions which you optionally set. +// SourceAccessConditions identifies source path-specific access conditions which you optionally set. type SourceAccessConditions = path.SourceAccessConditions // LeaseAccessConditions contains optional parameters to access leased entity. @@ -164,10 +162,10 @@ type LeaseAccessConditions = path.LeaseAccessConditions // ModifiedAccessConditions contains a group of parameters for specifying access conditions. type ModifiedAccessConditions = path.ModifiedAccessConditions -// SourceModifiedAccessConditions contains a group of parameters for specifying access conditions. +// SourceModifiedAccessConditions contains a group of parameters for specifying source access conditions. type SourceModifiedAccessConditions = path.SourceModifiedAccessConditions -// CPKScopeInfo contains a group of parameters for the PathClient.SetMetadata method. +// CPKScopeInfo contains a group of parameters for client provided encryption scope. type CPKScopeInfo path.CPKScopeInfo // ACLFailedEntry contains the failed ACL entry (response model). diff --git a/sdk/storage/azdatalake/directory/responses.go b/sdk/storage/azdatalake/directory/responses.go index ce5a222f298b..0a3cd654da49 100644 --- a/sdk/storage/azdatalake/directory/responses.go +++ b/sdk/storage/azdatalake/directory/responses.go @@ -10,11 +10,8 @@ import ( "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/internal/path" ) -// RenameResponse contains the response fields for the Create operation. -type RenameResponse struct { - Response CreateResponse - NewDirectoryClient *Client -} +// RenameResponse contains the response fields for the Rename operation. +type RenameResponse = path.RenameResponse type setAccessControlRecursiveResponse struct { DirectoriesSuccessful *int32 diff --git a/sdk/storage/azdatalake/doc.go b/sdk/storage/azdatalake/doc.go new file mode 100644 index 000000000000..50b93e555d49 --- /dev/null +++ b/sdk/storage/azdatalake/doc.go @@ -0,0 +1,218 @@ +//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 azdatalake can access an Azure Data Lake Service Gen2 (ADLS Gen2). + +The azdatalake package is capable of :- + - Creating, deleting, and querying filesystems in an account + - Creating, deleting, and querying files and directories in a filesystem + - Creating Shared Access Signature for authentication + +Types of Resources + +The azdatalake package allows you to interact with three types of resources :- + +* Azure storage accounts. +* filesystems within those storage accounts. +* files and directories within those filesystems. + +ADLS Gen2 client library for Go allows you to interact with each of these components through the use of a dedicated client object. +To create a client object, you will need the account's ADLS Gen2 service endpoint URL and a credential that allows you to access the account. + +Types of Credentials + +The clients support different forms of authentication. +The azdatalake library supports any of the `azcore.TokenCredential` interfaces, authorization via a Connection String, +or authorization with a Shared Access Signature token. + +Using a Shared Key + +To use an account shared key (aka account key or access key), provide the key as a string. +This can be found in your storage account in the Azure Portal under the "Access Keys" section. + +Use the key as the credential parameter to authenticate the client: + + accountName, ok := os.LookupEnv("AZURE_STORAGE_ACCOUNT_NAME") + if !ok { + panic("AZURE_STORAGE_ACCOUNT_NAME could not be found") + } + accountKey, ok := os.LookupEnv("AZURE_STORAGE_ACCOUNT_KEY") + if !ok { + panic("AZURE_STORAGE_ACCOUNT_KEY could not be found") + } + + serviceURL := fmt.Sprintf("https://%s.dfs.core.windows.net/", accountName) + + cred, err := azdatalake.NewSharedKeyCredential(accountName, accountKey) + handle(err) + + serviceClient, err := service.NewClientWithSharedKey(serviceURL, cred, nil) + handle(err) + + // get the underlying dfs endpoint + fmt.Println(serviceClient.DFSURL()) + + // get the underlying blob endpoint + fmt.Println(serviceClient.BlobURL()) + +Using a Connection String + +Depending on your use case and authorization method, you may prefer to initialize a client instance with a connection string instead of providing the account URL and credential separately. +To do this, pass the connection string to the service client's `NewClientFromConnectionString` method. +The connection string can be found in your storage account in the Azure Portal under the "Access Keys" section. + + connStr := "DefaultEndpointsProtocol=https;AccountName=;AccountKey=;EndpointSuffix=core.windows.net" + serviceClient, err := service.NewClientFromConnectionString(connStr, nil) + +Using a Shared Access Signature (SAS) Token + +To use a shared access signature (SAS) token, provide the token at the end of your service URL. +You can generate a SAS token from the Azure Portal under Shared Access Signature or use the ServiceClient.GetSASToken() functions. + + accountName, ok := os.LookupEnv("AZURE_STORAGE_ACCOUNT_NAME") + if !ok { + panic("AZURE_STORAGE_ACCOUNT_NAME could not be found") + } + accountKey, ok := os.LookupEnv("AZURE_STORAGE_ACCOUNT_KEY") + if !ok { + panic("AZURE_STORAGE_ACCOUNT_KEY could not be found") + } + serviceURL := fmt.Sprintf("https://%s.dfs.core.windows.net/", accountName) + + cred, err := azdatalake.NewSharedKeyCredential(accountName, accountKey) + handle(err) + serviceClient, err := service.NewClientWithSharedKey(serviceURL, cred, nil) + handle(err) + fmt.Println(serviceClient.DFSURL()) + + // Alternatively, you can create SAS on the fly + + resources := sas.AccountResourceTypes{Service: true} + permission := sas.AccountPermissions{Read: true} + start := time.Now() + expiry := start.AddDate(0, 0, 1) + serviceURLWithSAS, err := serviceClient.GetSASURL(resources, permission, start, expiry) + handle(err) + + serviceClientWithSAS, err := service.NewClientWithNoCredential(serviceURLWithSAS, nil) + handle(err) + + fmt.Println(serviceClientWithSAS.DFSURL()) + fmt.Println(serviceClientWithSAS.BlobURL()) + +Types of Clients + +There are three different clients provided to interact with the various components of the ADLS Gen2 Service: + +1. **`ServiceClient`** + * Get and set account settings. + * Query, create, list and delete filesystems within the account. + +2. **`FileSystemClient`** + * Get and set filesystem access settings, properties, and metadata. + * Create, delete, and query files/directories within the filesystem. + * `FileSystemLeaseClient` to support filesystem lease management. + +3. **`FileClient`** + * Get and set file properties. + * Perform CRUD operations on a given file. + * Set ACLs on a given file. + * `PathLeaseClient` to support file lease management. + +4. **`DirectoryClient`** + * Get and set directory properties. + * Perform CRUD operations on a given directory. + * Set ACLs on a given directory and recursively on all subdirectories and files. + * `PathLeaseClient` to support directory lease management. + +Examples + + // Your account name and key can be obtained from the Azure Portal. + accountName, ok := os.LookupEnv("AZURE_STORAGE_ACCOUNT_NAME") + if !ok { + panic("AZURE_STORAGE_ACCOUNT_NAME could not be found") + } + + accountKey, ok := os.LookupEnv("AZURE_STORAGE_ACCOUNT_KEY") + if !ok { + panic("AZURE_STORAGE_ACCOUNT_KEY could not be found") + } + cred, err := azdatalake.NewSharedKeyCredential(accountName, accountKey) + handle(err) + + // The service URL for dfs endpoints is usually in the form: http(s)://.dfs.core.windows.net/ + serviceClient, err := service.NewClientWithSharedKey(fmt.Sprintf("https://%s.dfs.core.windows.net/", accountName), cred, nil) + handle(err) + + // ===== 1. Create a filesystem ===== + + // First, create a filesystem client, and use the Create method to create a new filesystem in your account + fsClient, err := serviceClient.NewFileSystemClient("testfs") + handle(err) + + // All APIs have an options' bag struct as a parameter. + // The options' bag struct allows you to specify optional parameters such as metadata, public access types, etc. + // If you want to use the default options, pass in nil. + _, err = fsClient.Create(context.TODO(), nil) + handle(err) + + // ===== 2. Upload and Download a file ===== + uploadData := "Hello world!" + + // Create a new file from the fsClient + fileClient, err := fsClient.NewFileClient("HelloWorld.txt") + handle(err) + + + _, err = fileClient.UploadStream(context.TODO(), streaming.NopCloser(strings.NewReader(uploadData)), nil) + handle(err) + + // Download the file's contents and ensure that the download worked properly + fileDownloadResponse, err := fileClient.DownloadStream(context.TODO(), nil) + handle(err) + + // Use the bytes.Buffer object to read the downloaded data. + // RetryReaderOptions has a lot of in-depth tuning abilities, but for the sake of simplicity, we'll omit those here. + reader := fileDownloadResponse.Body(nil) + downloadData, err := io.ReadAll(reader) + handle(err) + if string(downloadData) != uploadData { + handle(errors.New("Uploaded data should be same as downloaded data")) + } + + if err = reader.Close(); err != nil { + handle(err) + return + } + + // ===== 3. List paths ===== + // List methods returns a pager object which can be used to iterate over the results of a paging operation. + // To iterate over a page use the NextPage(context.Context) to fetch the next page of results. + // PageResponse() can be used to iterate over the results of the specific page. + // Always check the Err() method after paging to see if an error was returned by the pager. A pager will return either an error or the page of results. + + pager := fsClient.NewListPathsPager(nil) + page, err := pager.NextPage(context.TODO()) + handle(err) + + // print the path names for this page + for _, path := range page.PathList.Paths { + fmt.Println(*path.Name) + fmt.Println(*path.IsDirectory) + } + + // Delete the file. + _, err = fileClient.Delete(context.TODO(), nil) + handle(err) + + // Delete the filesystem. + _, err = fsClient.Delete(context.TODO(), nil) + handle(err) +*/ + +package azdatalake diff --git a/sdk/storage/azdatalake/file/client.go b/sdk/storage/azdatalake/file/client.go index 0a84b5af7cba..113750ae05e9 100644 --- a/sdk/storage/azdatalake/file/client.go +++ b/sdk/storage/azdatalake/file/client.go @@ -125,7 +125,7 @@ func NewClientWithSharedKeyCredential(fileURL string, cred *SharedKeyCredential, blobClientOpts := blockblob.ClientOptions{ ClientOptions: options.ClientOptions, } - blobSharedKey, err := cred.ConvertToBlobSharedKey() + blobSharedKey, err := exported.ConvertToBlobSharedKey(cred) if err != nil { return nil, err } @@ -196,7 +196,7 @@ func (f *Client) BlobURL() string { return f.generatedFileClientWithBlob().Endpoint() } -// Create creates a new file (dfs1). +// Create creates a new file. func (f *Client) Create(ctx context.Context, options *CreateOptions) (CreateResponse, error) { lac, mac, httpHeaders, createOpts, cpkOpts := options.format() resp, err := f.generatedFileClientWithDFS().Create(ctx, createOpts, httpHeaders, lac, mac, nil, cpkOpts) @@ -204,7 +204,7 @@ func (f *Client) Create(ctx context.Context, options *CreateOptions) (CreateResp return resp, err } -// Delete deletes a file (dfs1). +// Delete deletes a file. func (f *Client) Delete(ctx context.Context, options *DeleteOptions) (DeleteResponse, error) { lac, mac, deleteOpts := path.FormatDeleteOptions(options, false) resp, err := f.generatedFileClientWithDFS().Delete(ctx, deleteOpts, lac, mac) @@ -212,7 +212,7 @@ func (f *Client) Delete(ctx context.Context, options *DeleteOptions) (DeleteResp return resp, err } -// GetProperties gets the properties of a file (blob3) +// GetProperties gets the properties of a file. func (f *Client) GetProperties(ctx context.Context, options *GetPropertiesOptions) (GetPropertiesResponse, error) { opts := path.FormatGetPropertiesOptions(options) var respFromCtx *http.Response @@ -231,33 +231,34 @@ func (f *Client) renamePathInURL(newName string) (string, string, string) { // 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 newBlobURL, newPathURL := shared.GetURLs(runtime.JoinPaths(firstPart, newName)) - parsedNewURL, _ := url.Parse(f.DFSURL()) - return parsedNewURL.Path, newPathURL, newBlobURL + oldURL, _ := url.Parse(f.DFSURL()) + return oldURL.Path, newPathURL, newBlobURL } -// Rename renames a file (dfs1) +// Rename renames a file. The original file will no longer exist and the client will be stale. func (f *Client) Rename(ctx context.Context, newName string, options *RenameOptions) (RenameResponse, error) { - newPathWithoutURL, newPathURL, newBlobURL := f.renamePathInURL(newName) - lac, mac, smac, createOpts := path.FormatRenameOptions(options, newPathWithoutURL) + oldPathWithoutURL, newPathURL, newBlobURL := f.renamePathInURL(newName) + lac, mac, smac, createOpts := path.FormatRenameOptions(options, oldPathWithoutURL) var newBlobClient *blockblob.Client var err error if f.identityCredential() != nil { newBlobClient, err = blockblob.NewClient(newBlobURL, *f.identityCredential(), nil) } else if f.sharedKey() != nil { - blobSharedKey, _ := f.sharedKey().ConvertToBlobSharedKey() + blobSharedKey, _ := exported.ConvertToBlobSharedKey(f.sharedKey()) newBlobClient, err = blockblob.NewClientWithSharedKeyCredential(newBlobURL, blobSharedKey, nil) } else { newBlobClient, err = blockblob.NewClientWithNoCredential(newBlobURL, nil) } if err != nil { - return RenameResponse{}, err + return RenameResponse{}, exported.ConvertToDFSError(err) } newFileClient := (*Client)(base.NewPathClient(newPathURL, newBlobURL, newBlobClient, f.generatedFileClientWithDFS().InternalClient().WithClientName(shared.FileClient), f.sharedKey(), f.identityCredential(), f.getClientOptions())) resp, err := newFileClient.generatedFileClientWithDFS().Create(ctx, createOpts, nil, lac, mac, smac, nil) - return RenameResponse{ - Response: resp, - NewFileClient: newFileClient, - }, exported.ConvertToDFSError(err) + //return RenameResponse{ + // Response: resp, + // NewFileClient: newFileClient, + //}, exported.ConvertToDFSError(err) + return path.FormatRenameResponse(&resp), exported.ConvertToDFSError(err) } // SetExpiry operation sets an expiry time on an existing file (blob2). @@ -274,7 +275,7 @@ func (f *Client) SetExpiry(ctx context.Context, expiryValues SetExpiryValues, o return resp, 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 file. func (f *Client) SetAccessControl(ctx context.Context, options *SetAccessControlOptions) (SetAccessControlResponse, error) { opts, lac, mac, err := path.FormatSetAccessControlOptions(options) if err != nil { @@ -285,7 +286,7 @@ func (f *Client) SetAccessControl(ctx context.Context, options *SetAccessControl return resp, err } -// UpdateAccessControl updates the owner, owning group, and permissions for a file or directory (dfs1). +// UpdateAccessControl updates the owner, owning group, and permissions for a file. func (f *Client) UpdateAccessControl(ctx context.Context, ACL string, options *UpdateAccessControlOptions) (UpdateAccessControlResponse, error) { opts, mode := options.format(ACL) resp, err := f.generatedFileClientWithDFS().SetAccessControlRecursive(ctx, mode, opts) @@ -293,7 +294,7 @@ func (f *Client) UpdateAccessControl(ctx context.Context, ACL string, options *U return resp, err } -// GetAccessControl gets the owner, owning group, and permissions for a file or directory (dfs1). +// GetAccessControl gets the owner, owning group, and permissions for a file. func (f *Client) GetAccessControl(ctx context.Context, options *GetAccessControlOptions) (GetAccessControlResponse, error) { opts, lac, mac := path.FormatGetAccessControlOptions(options) resp, err := f.generatedFileClientWithDFS().GetProperties(ctx, opts, lac, mac) @@ -301,7 +302,7 @@ func (f *Client) GetAccessControl(ctx context.Context, options *GetAccessControl return resp, err } -// RemoveAccessControl removes the owner, owning group, and permissions for a file or directory (dfs1). +// RemoveAccessControl removes the owner, owning group, and permissions for a file. func (f *Client) RemoveAccessControl(ctx context.Context, ACL string, options *RemoveAccessControlOptions) (RemoveAccessControlResponse, error) { opts, mode := options.format(ACL) resp, err := f.generatedFileClientWithDFS().SetAccessControlRecursive(ctx, mode, opts) @@ -309,15 +310,15 @@ func (f *Client) RemoveAccessControl(ctx context.Context, ACL string, options *R return resp, err } -// SetMetadata sets the metadata for a file or directory (blob3). -func (f *Client) SetMetadata(ctx context.Context, options *SetMetadataOptions) (SetMetadataResponse, error) { - opts, metadata := path.FormatSetMetadataOptions(options) +// SetMetadata sets the metadata for a file. +func (f *Client) SetMetadata(ctx context.Context, metadata map[string]*string, options *SetMetadataOptions) (SetMetadataResponse, error) { + opts := path.FormatSetMetadataOptions(options) resp, err := f.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 file. func (f *Client) SetHTTPHeaders(ctx context.Context, httpHeaders HTTPHeaders, options *SetHTTPHeadersOptions) (SetHTTPHeadersResponse, error) { opts, blobHTTPHeaders := path.FormatSetHTTPHeadersOptions(options, httpHeaders) resp, err := f.blobClient().SetHTTPHeaders(ctx, blobHTTPHeaders, opts) @@ -327,7 +328,7 @@ func (f *Client) SetHTTPHeaders(ctx context.Context, httpHeaders HTTPHeaders, op return newResp, err } -// GetSASURL is a convenience method for generating a SAS token for the currently pointed at blob. +// GetSASURL is a convenience method for generating a SAS token for the currently pointed at file. // It can only be used if the credential supplied during creation was a SharedKeyCredential. func (f *Client) GetSASURL(permissions sas.FilePermissions, expiry time.Time, o *GetSASURLOptions) (string, error) { if f.sharedKey() == nil { @@ -344,7 +345,7 @@ func (f *Client) GetSASURL(permissions sas.FilePermissions, expiry time.Time, o qps, err := sas.DatalakeSignatureValues{ FilePath: urlParts.PathName, - FilesystemName: urlParts.FilesystemName, + FileSystemName: urlParts.FileSystemName, Version: sas.Version, Permissions: permissions.String(), StartTime: st, @@ -361,6 +362,7 @@ func (f *Client) GetSASURL(permissions sas.FilePermissions, expiry time.Time, o return endpoint, nil } +// AppendData appends data to existing file with a given offset. func (f *Client) AppendData(ctx context.Context, offset int64, body io.ReadSeekCloser, options *AppendDataOptions) (AppendDataResponse, error) { appendDataOptions, leaseAccessConditions, cpkInfo, err := options.format(offset, body) if err != nil { @@ -377,6 +379,7 @@ func (f *Client) AppendData(ctx context.Context, offset int64, body io.ReadSeekC return resp, exported.ConvertToDFSError(err) } +// FlushData commits appended data to file func (f *Client) FlushData(ctx context.Context, offset int64, options *FlushDataOptions) (FlushDataResponse, error) { flushDataOpts, modifiedAccessConditions, leaseAccessConditions, httpHeaderOpts, cpkInfoOpts, err := options.format(offset) if err != nil { @@ -453,7 +456,7 @@ func (f *Client) uploadFromReader(ctx context.Context, reader io.ReaderAt, actua return exported.ConvertToDFSError(err) } -// UploadBuffer uploads a buffer in chunks to an Azure file. +// UploadBuffer uploads a buffer in chunks to a file. func (f *Client) UploadBuffer(ctx context.Context, buffer []byte, options *UploadBufferOptions) error { uploadOptions := uploadFromReaderOptions{} if options != nil { @@ -462,7 +465,7 @@ func (f *Client) UploadBuffer(ctx context.Context, buffer []byte, options *Uploa return exported.ConvertToDFSError(f.uploadFromReader(ctx, bytes.NewReader(buffer), int64(len(buffer)), &uploadOptions)) } -// UploadFile uploads a file in chunks to an Azure file. +// UploadFile uploads a file in chunks to a file. func (f *Client) UploadFile(ctx context.Context, file *os.File, options *UploadFileOptions) error { stat, err := file.Stat() if err != nil { @@ -486,7 +489,7 @@ func (f *Client) UploadStream(ctx context.Context, body io.Reader, options *Uplo return exported.ConvertToDFSError(err) } -// DownloadStream reads a range of bytes from a blob. The response also includes the blob's properties and metadata. +// DownloadStream reads a range of bytes from a file. The response also includes the file's properties and metadata. // For more information, see https://docs.microsoft.com/rest/api/storageservices/get-blob. func (f *Client) DownloadStream(ctx context.Context, o *DownloadStreamOptions) (DownloadStreamResponse, error) { if o == nil { @@ -506,14 +509,14 @@ func (f *Client) DownloadStream(ctx context.Context, o *DownloadStreamOptions) ( return fullResp, exported.ConvertToDFSError(err) } -// DownloadBuffer downloads an Azure blob to a buffer with parallel. +// DownloadBuffer downloads an Azure file to a buffer with parallel. func (f *Client) DownloadBuffer(ctx context.Context, buffer []byte, o *DownloadBufferOptions) (int64, error) { opts := o.format() val, err := f.blobClient().DownloadBuffer(ctx, shared.NewBytesWriter(buffer), opts) return val, exported.ConvertToDFSError(err) } -// DownloadFile downloads an Azure blob to a local file. +// DownloadFile downloads a datalake file to a local file. // The file would be truncated if the size doesn't match. func (f *Client) DownloadFile(ctx context.Context, file *os.File, o *DownloadFileOptions) (int64, error) { opts := o.format() @@ -521,4 +524,4 @@ func (f *Client) DownloadFile(ctx context.Context, file *os.File, o *DownloadFil return val, exported.ConvertToDFSError(err) } -// TODO: add undelete +// TODO: Undelete() diff --git a/sdk/storage/azdatalake/file/client_test.go b/sdk/storage/azdatalake/file/client_test.go index 8ab3897c6d9d..23a9f03d4c35 100644 --- a/sdk/storage/azdatalake/file/client_test.go +++ b/sdk/storage/azdatalake/file/client_test.go @@ -85,10 +85,10 @@ func (s *UnrecordedTestSuite) TestCreateFileAndDeleteWithConnectionString() { connectionString, _ := testcommon.GetGenericConnectionString(testcommon.TestAccountDatalake) - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + filesystemName := testcommon.GenerateFileSystemName(testName) + fsClient, err := testcommon.GetFileSystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) - defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) _, err = fsClient.Create(context.Background(), nil) _require.Nil(err) @@ -109,10 +109,10 @@ func (s *RecordedTestSuite) TestCreateFileAndDelete() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + filesystemName := testcommon.GenerateFileSystemName(testName) + fsClient, err := testcommon.GetFileSystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) - defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) _, err = fsClient.Create(context.Background(), nil) _require.Nil(err) @@ -132,10 +132,10 @@ func (s *RecordedTestSuite) TestCreateFileWithNilAccessConditions() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + filesystemName := testcommon.GenerateFileSystemName(testName) + fsClient, err := testcommon.GetFileSystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) - defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) _, err = fsClient.Create(context.Background(), nil) _require.Nil(err) @@ -163,10 +163,10 @@ func (s *RecordedTestSuite) TestCreateFileIfModifiedSinceTrue() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + filesystemName := testcommon.GenerateFileSystemName(testName) + fsClient, err := testcommon.GetFileSystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) - defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) _, err = fsClient.Create(context.Background(), nil) _require.Nil(err) @@ -200,10 +200,10 @@ func (s *RecordedTestSuite) TestCreateFileIfModifiedSinceFalse() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + filesystemName := testcommon.GenerateFileSystemName(testName) + fsClient, err := testcommon.GetFileSystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) - defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) _, err = fsClient.Create(context.Background(), nil) _require.Nil(err) @@ -237,10 +237,10 @@ func (s *RecordedTestSuite) TestCreateFileIfUnmodifiedSinceTrue() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + filesystemName := testcommon.GenerateFileSystemName(testName) + fsClient, err := testcommon.GetFileSystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) - defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) _, err = fsClient.Create(context.Background(), nil) _require.Nil(err) @@ -274,10 +274,10 @@ 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) + filesystemName := testcommon.GenerateFileSystemName(testName) + fsClient, err := testcommon.GetFileSystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) - defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) _, err = fsClient.Create(context.Background(), nil) _require.Nil(err) @@ -312,10 +312,10 @@ 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) + filesystemName := testcommon.GenerateFileSystemName(testName) + fsClient, err := testcommon.GetFileSystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) - defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) _, err = fsClient.Create(context.Background(), nil) _require.Nil(err) @@ -349,10 +349,10 @@ 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) + filesystemName := testcommon.GenerateFileSystemName(testName) + fsClient, err := testcommon.GetFileSystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) - defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) _, err = fsClient.Create(context.Background(), nil) _require.Nil(err) @@ -383,17 +383,17 @@ func (s *RecordedTestSuite) TestCreateFileIfETagMatchFalse() { testcommon.ValidateErrorCode(_require, err, datalakeerror.ConditionNotMet) } -func (s *RecordedTestSuite) TestCreateFileWithMetadataNotNil() { +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) + filesystemName := testcommon.GenerateFileSystemName(testName) + fsClient, err := testcommon.GetFileSystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) - defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) createFileOpts := &file.CreateOptions{ - Metadata: testcommon.BasicMetadata, + HTTPHeaders: nil, } _, err = fsClient.Create(context.Background(), nil) @@ -410,17 +410,21 @@ func (s *RecordedTestSuite) TestCreateFileWithMetadataNotNil() { _require.NotNil(resp) } -func (s *RecordedTestSuite) TestCreateFileWithEmptyMetadata() { +func (s *UnrecordedTestSuite) TestCreateFileWithExpiryAbsolute() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + filesystemName := testcommon.GenerateFileSystemName(testName) + fsClient, err := testcommon.GetFileSystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) - defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) + expiryTimeAbsolute := time.Now().Add(8 * time.Second) createFileOpts := &file.CreateOptions{ - Metadata: nil, + Expiry: file.CreateExpiryValues{ + ExpiryType: file.CreateExpiryTypeAbsolute, + ExpiresOn: time.Now().Add(8 * time.Second).UTC().Format(http.TimeFormat), + }, } _, err = fsClient.Create(context.Background(), nil) @@ -435,49 +439,25 @@ func (s *RecordedTestSuite) TestCreateFileWithEmptyMetadata() { resp, err := fClient.Create(context.Background(), createFileOpts) _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) - - createFileOpts := &file.CreateOptions{ - HTTPHeaders: nil, - } - - _, err = fsClient.Create(context.Background(), nil) - _require.Nil(err) - - fileName := testcommon.GenerateFileName(testName) - fClient, err := testcommon.GetFileClient(filesystemName, fileName, s.T(), testcommon.TestAccountDatalake, nil) - _require.NoError(err) - defer testcommon.DeleteFile(context.Background(), _require, fClient) - - resp, err := fClient.Create(context.Background(), createFileOpts) + resp1, err := fClient.GetProperties(context.Background(), nil) _require.Nil(err) - _require.NotNil(resp) + _require.NotNil(resp1.ExpiresOn) + _require.Equal(expiryTimeAbsolute.UTC().Format(http.TimeFormat), (*resp1.ExpiresOn).UTC().Format(http.TimeFormat)) } -func (s *UnrecordedTestSuite) TestCreateFileWithExpiryAbsolute() { +func (s *RecordedTestSuite) TestCreateFileWithExpiryNever() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + filesystemName := testcommon.GenerateFileSystemName(testName) + fsClient, err := testcommon.GetFileSystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) - defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) - expiryTimeAbsolute := time.Now().Add(8 * time.Second) createFileOpts := &file.CreateOptions{ Expiry: file.CreateExpiryValues{ - ExpiryType: file.CreateExpiryTypeAbsolute, - ExpiresOn: time.Now().Add(8 * time.Second).UTC().Format(http.TimeFormat), + ExpiryType: file.CreateExpiryTypeNeverExpire, }, } @@ -488,26 +468,23 @@ func (s *UnrecordedTestSuite) TestCreateFileWithExpiryAbsolute() { fClient, err := testcommon.GetFileClient(filesystemName, fileName, s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) - defer testcommon.DeleteFile(context.Background(), _require, fClient) - resp, err := fClient.Create(context.Background(), createFileOpts) _require.Nil(err) _require.NotNil(resp) - resp1, err := fClient.GetProperties(context.Background(), nil) + _, err = fClient.Delete(context.Background(), nil) _require.Nil(err) - _require.NotNil(resp1.ExpiresOn) - _require.Equal(expiryTimeAbsolute.UTC().Format(http.TimeFormat), (*resp1.ExpiresOn).UTC().Format(http.TimeFormat)) + } func (s *RecordedTestSuite) TestCreateFileWithExpiryRelativeToNow() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + filesystemName := testcommon.GenerateFileSystemName(testName) + fsClient, err := testcommon.GetFileSystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) - defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) createFileOpts := &file.CreateOptions{ Expiry: file.CreateExpiryValues{ @@ -540,10 +517,10 @@ func (s *RecordedTestSuite) TestCreateFileWithNeverExpire() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + filesystemName := testcommon.GenerateFileSystemName(testName) + fsClient, err := testcommon.GetFileSystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) - defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) createFileOpts := &file.CreateOptions{ Expiry: file.CreateExpiryValues{ @@ -571,10 +548,10 @@ func (s *RecordedTestSuite) TestCreateFileWithLease() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + filesystemName := testcommon.GenerateFileSystemName(testName) + fsClient, err := testcommon.GetFileSystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) - defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) createFileOpts := &file.CreateOptions{ ProposedLeaseID: proposedLeaseIDs[0], @@ -606,12 +583,12 @@ func (s *RecordedTestSuite) TestCreateFileWithPermissions() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + 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) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) createFileOpts := &file.CreateOptions{ Permissions: &perms, @@ -639,14 +616,14 @@ func (s *RecordedTestSuite) TestCreateFileWithOwnerGroupACLUmask() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + 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) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) createFileOpts := &file.CreateOptions{ Owner: &owner, @@ -672,10 +649,10 @@ func (s *RecordedTestSuite) TestDeleteFileWithNilAccessConditions() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + filesystemName := testcommon.GenerateFileSystemName(testName) + fsClient, err := testcommon.GetFileSystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) - defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) _, err = fsClient.Create(context.Background(), nil) _require.Nil(err) @@ -700,10 +677,10 @@ func (s *RecordedTestSuite) TestDeleteFileIfModifiedSinceTrue() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + filesystemName := testcommon.GenerateFileSystemName(testName) + fsClient, err := testcommon.GetFileSystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) - defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) _, err = fsClient.Create(context.Background(), nil) _require.Nil(err) @@ -734,10 +711,10 @@ func (s *RecordedTestSuite) TestDeleteFileIfModifiedSinceFalse() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + filesystemName := testcommon.GenerateFileSystemName(testName) + fsClient, err := testcommon.GetFileSystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) - defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) _, err = fsClient.Create(context.Background(), nil) _require.Nil(err) @@ -769,10 +746,10 @@ func (s *RecordedTestSuite) TestDeleteFileIfUnmodifiedSinceTrue() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + filesystemName := testcommon.GenerateFileSystemName(testName) + fsClient, err := testcommon.GetFileSystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) - defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) _, err = fsClient.Create(context.Background(), nil) _require.Nil(err) @@ -804,10 +781,10 @@ func (s *RecordedTestSuite) TestDeleteFileIfUnmodifiedSinceFalse() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + filesystemName := testcommon.GenerateFileSystemName(testName) + fsClient, err := testcommon.GetFileSystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) - defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) _, err = fsClient.Create(context.Background(), nil) _require.Nil(err) @@ -840,10 +817,10 @@ func (s *RecordedTestSuite) TestDeleteFileIfETagMatch() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + filesystemName := testcommon.GenerateFileSystemName(testName) + fsClient, err := testcommon.GetFileSystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) - defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) _, err = fsClient.Create(context.Background(), nil) _require.Nil(err) @@ -875,10 +852,10 @@ func (s *RecordedTestSuite) TestDeleteFileIfETagMatchFalse() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + filesystemName := testcommon.GenerateFileSystemName(testName) + fsClient, err := testcommon.GetFileSystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) - defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) _, err = fsClient.Create(context.Background(), nil) _require.Nil(err) @@ -911,10 +888,10 @@ func (s *RecordedTestSuite) TestFileSetAccessControlNil() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + filesystemName := testcommon.GenerateFileSystemName(testName) + fsClient, err := testcommon.GetFileSystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) - defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) _, err = fsClient.Create(context.Background(), nil) _require.Nil(err) @@ -938,13 +915,13 @@ func (s *RecordedTestSuite) TestFileSetAccessControl() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + 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) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) opts := &file.SetAccessControlOptions{ Owner: &owner, @@ -971,13 +948,13 @@ func (s *RecordedTestSuite) TestFileSetAccessControlWithNilAccessConditions() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + 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) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) opts := &file.SetAccessControlOptions{ Owner: &owner, @@ -1005,13 +982,13 @@ func (s *RecordedTestSuite) TestFileSetAccessControlIfModifiedSinceTrue() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + 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) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) _, err = fsClient.Create(context.Background(), nil) _require.Nil(err) @@ -1044,13 +1021,13 @@ func (s *RecordedTestSuite) TestFileSetAccessControlIfModifiedSinceFalse() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + 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) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) _, err = fsClient.Create(context.Background(), nil) _require.Nil(err) @@ -1084,13 +1061,13 @@ func (s *RecordedTestSuite) TestFileSetAccessControlIfUnmodifiedSinceTrue() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + 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) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) _, err = fsClient.Create(context.Background(), nil) _require.Nil(err) @@ -1122,13 +1099,13 @@ func (s *RecordedTestSuite) TestFileSetAccessControlIfUnmodifiedSinceFalse() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + 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) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) _, err = fsClient.Create(context.Background(), nil) _require.Nil(err) @@ -1164,13 +1141,13 @@ func (s *RecordedTestSuite) TestFileSetAccessControlIfETagMatch() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + 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) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) _, err = fsClient.Create(context.Background(), nil) _require.Nil(err) @@ -1203,13 +1180,13 @@ func (s *RecordedTestSuite) TestFileSetAccessControlIfETagMatchFalse() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + 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) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) _, err = fsClient.Create(context.Background(), nil) _require.Nil(err) @@ -1242,11 +1219,11 @@ func (s *RecordedTestSuite) TestFileGetAccessControl() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + 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) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) createOpts := &file.CreateOptions{ ACL: &acl, @@ -1271,11 +1248,11 @@ func (s *UnrecordedTestSuite) TestFileGetAccessControlWithSAS() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + 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) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) createOpts := &file.CreateOptions{ ACL: &acl, @@ -1315,10 +1292,10 @@ func (s *UnrecordedTestSuite) TestFileDeleteWithSAS() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + filesystemName := testcommon.GenerateFileSystemName(testName) + fsClient, err := testcommon.GetFileSystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) - defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) _, err = fsClient.Create(context.Background(), nil) _require.Nil(err) @@ -1354,11 +1331,11 @@ func (s *RecordedTestSuite) TestFileGetAccessControlWithNilAccessConditions() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + 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) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) createOpts := &file.CreateOptions{ ACL: &acl, @@ -1387,11 +1364,11 @@ func (s *RecordedTestSuite) TestFileGetAccessControlIfModifiedSinceTrue() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + 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) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) createOpts := &file.CreateOptions{ ACL: &acl, @@ -1425,11 +1402,11 @@ func (s *RecordedTestSuite) TestFileGetAccessControlIfModifiedSinceFalse() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + 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) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) createOpts := &file.CreateOptions{ ACL: &acl, @@ -1463,11 +1440,11 @@ func (s *RecordedTestSuite) TestFileGetAccessControlIfUnmodifiedSinceTrue() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + 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) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) createOpts := &file.CreateOptions{ ACL: &acl, @@ -1500,11 +1477,11 @@ func (s *RecordedTestSuite) TestFileGetAccessControlIfUnmodifiedSinceFalse() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + 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) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) createOpts := &file.CreateOptions{ ACL: &acl, @@ -1540,11 +1517,11 @@ func (s *RecordedTestSuite) TestFileGetAccessControlIfETagMatch() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + 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) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) createOpts := &file.CreateOptions{ ACL: &acl, @@ -1578,11 +1555,11 @@ func (s *RecordedTestSuite) TestFileGetAccessControlIfETagMatchFalse() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + 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) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) createOpts := &file.CreateOptions{ ACL: &acl, @@ -1615,12 +1592,12 @@ func (s *RecordedTestSuite) TestFileUpdateAccessControl() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + 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) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) createOpts := &file.CreateOptions{ ACL: &acl, @@ -1648,13 +1625,13 @@ func (s *RecordedTestSuite) TestFileRemoveAccessControl() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + 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) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) _, err = fsClient.Create(context.Background(), nil) _require.Nil(err) @@ -1671,69 +1648,14 @@ func (s *RecordedTestSuite) TestFileRemoveAccessControl() { _require.Nil(err) } -func (s *RecordedTestSuite) TestFileSetMetadataNil() { - _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) - - fileName := testcommon.GenerateFileName(testName) - fClient, err := testcommon.GetFileClient(filesystemName, fileName, s.T(), testcommon.TestAccountDatalake, nil) - _require.NoError(err) - - defer testcommon.DeleteFile(context.Background(), _require, fClient) - - resp, err := fClient.Create(context.Background(), nil) - _require.Nil(err) - _require.NotNil(resp) - - _, err = fClient.SetMetadata(context.Background(), nil) - _require.Nil(err) -} - -func (s *RecordedTestSuite) TestFileSetMetadataWithEmptyOpts() { - _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) - - fileName := testcommon.GenerateFileName(testName) - fClient, err := testcommon.GetFileClient(filesystemName, fileName, s.T(), testcommon.TestAccountDatalake, nil) - _require.NoError(err) - - defer testcommon.DeleteFile(context.Background(), _require, fClient) - - resp, err := fClient.Create(context.Background(), nil) - _require.Nil(err) - _require.NotNil(resp) - - opts := &file.SetMetadataOptions{ - Metadata: nil, - } - _, err = fClient.SetMetadata(context.Background(), opts) - _require.Nil(err) -} - func (s *RecordedTestSuite) TestFileSetMetadataWithBasicMetadata() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + filesystemName := testcommon.GenerateFileSystemName(testName) + fsClient, err := testcommon.GetFileSystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) - defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) _, err = fsClient.Create(context.Background(), nil) _require.Nil(err) @@ -1748,10 +1670,7 @@ func (s *RecordedTestSuite) TestFileSetMetadataWithBasicMetadata() { _require.Nil(err) _require.NotNil(resp) - opts := &file.SetMetadataOptions{ - Metadata: testcommon.BasicMetadata, - } - _, err = fClient.SetMetadata(context.Background(), opts) + _, err = fClient.SetMetadata(context.Background(), testcommon.BasicMetadata, nil) _require.Nil(err) } @@ -1759,10 +1678,10 @@ func (s *RecordedTestSuite) TestFileSetMetadataWithAccessConditions() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + filesystemName := testcommon.GenerateFileSystemName(testName) + fsClient, err := testcommon.GetFileSystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) - defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) _, err = fsClient.Create(context.Background(), nil) _require.Nil(err) @@ -1780,14 +1699,13 @@ func (s *RecordedTestSuite) TestFileSetMetadataWithAccessConditions() { currentTime := testcommon.GetRelativeTimeFromAnchor(resp.Date, -10) opts := &file.SetMetadataOptions{ - Metadata: testcommon.BasicMetadata, AccessConditions: &file.AccessConditions{ ModifiedAccessConditions: &file.ModifiedAccessConditions{ IfModifiedSince: ¤tTime, }, }, } - _, err = fClient.SetMetadata(context.Background(), opts) + _, err = fClient.SetMetadata(context.Background(), testcommon.BasicMetadata, opts) _require.Nil(err) } @@ -1801,10 +1719,10 @@ func (s *RecordedTestSuite) TestFileSetHTTPHeaders() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + filesystemName := testcommon.GenerateFileSystemName(testName) + fsClient, err := testcommon.GetFileSystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) - defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) _, err = fsClient.Create(context.Background(), nil) _require.Nil(err) @@ -1826,10 +1744,10 @@ func (s *RecordedTestSuite) TestFileSetHTTPHeadersWithNilAccessConditions() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + filesystemName := testcommon.GenerateFileSystemName(testName) + fsClient, err := testcommon.GetFileSystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) - defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) _, err = fsClient.Create(context.Background(), nil) _require.Nil(err) @@ -1855,10 +1773,10 @@ func (s *RecordedTestSuite) TestFileSetHTTPHeadersIfModifiedSinceTrue() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + filesystemName := testcommon.GenerateFileSystemName(testName) + fsClient, err := testcommon.GetFileSystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) - defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) _, err = fsClient.Create(context.Background(), nil) _require.Nil(err) @@ -1889,10 +1807,10 @@ func (s *RecordedTestSuite) TestFileSetHTTPHeadersIfModifiedSinceFalse() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + filesystemName := testcommon.GenerateFileSystemName(testName) + fsClient, err := testcommon.GetFileSystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) - defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) _, err = fsClient.Create(context.Background(), nil) _require.Nil(err) @@ -1923,10 +1841,10 @@ func (s *RecordedTestSuite) TestFileSetHTTPHeadersIfUnmodifiedSinceTrue() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + filesystemName := testcommon.GenerateFileSystemName(testName) + fsClient, err := testcommon.GetFileSystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) - defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) _, err = fsClient.Create(context.Background(), nil) _require.Nil(err) @@ -1957,10 +1875,10 @@ func (s *RecordedTestSuite) TestFileSetHTTPHeadersIfUnmodifiedSinceFalse() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + filesystemName := testcommon.GenerateFileSystemName(testName) + fsClient, err := testcommon.GetFileSystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) - defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) _, err = fsClient.Create(context.Background(), nil) _require.Nil(err) @@ -1991,10 +1909,10 @@ func (s *RecordedTestSuite) TestFileSetHTTPHeadersIfETagMatch() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + filesystemName := testcommon.GenerateFileSystemName(testName) + fsClient, err := testcommon.GetFileSystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) - defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) _, err = fsClient.Create(context.Background(), nil) _require.Nil(err) @@ -2024,10 +1942,10 @@ func (s *RecordedTestSuite) TestFileSetHTTPHeadersIfETagMatchFalse() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + filesystemName := testcommon.GenerateFileSystemName(testName) + fsClient, err := testcommon.GetFileSystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) - defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) _, err = fsClient.Create(context.Background(), nil) _require.Nil(err) @@ -2058,10 +1976,10 @@ 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) + filesystemName := testcommon.GenerateFileSystemName(testName) + fsClient, err := testcommon.GetFileSystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) - defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) _, err = fsClient.Create(context.Background(), nil) _require.Nil(err) @@ -2074,20 +1992,21 @@ func (s *RecordedTestSuite) TestRenameNoOptions() { _require.Nil(err) _require.NotNil(resp) - resp1, err := fClient.Rename(context.Background(), "newName", nil) + //resp1, err := fClient.Rename(context.Background(), "newName", renameFileOpts) + _, err = fClient.Rename(context.Background(), "newName", nil) _require.Nil(err) - _require.NotNil(resp1) - _require.Contains(resp1.NewFileClient.DFSURL(), "newName") + //_require.NotNil(resp1) + //_require.Contains(resp1.NewFileClient.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) + filesystemName := testcommon.GenerateFileSystemName(testName) + fsClient, err := testcommon.GetFileSystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) - defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) _, err = fsClient.Create(context.Background(), nil) _require.Nil(err) @@ -2104,20 +2023,21 @@ func (s *RecordedTestSuite) TestRenameFileWithNilAccessConditions() { AccessConditions: nil, } - resp1, err := fClient.Rename(context.Background(), "newName", renameFileOpts) + //resp1, err := fClient.Rename(context.Background(), "newName", renameFileOpts) + _, err = fClient.Rename(context.Background(), "newName", renameFileOpts) _require.Nil(err) - _require.NotNil(resp1) - _require.Contains(resp1.NewFileClient.DFSURL(), "newName") + //_require.NotNil(resp1) + //_require.Contains(resp1.NewFileClient.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) + filesystemName := testcommon.GenerateFileSystemName(testName) + fsClient, err := testcommon.GetFileSystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) - defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) _, err = fsClient.Create(context.Background(), nil) _require.Nil(err) @@ -2139,20 +2059,21 @@ func (s *RecordedTestSuite) TestRenameFileIfModifiedSinceTrue() { }, }, } - resp1, err := fClient.Rename(context.Background(), "newName", renameFileOpts) + //resp1, err := fClient.Rename(context.Background(), "newName", renameFileOpts) + _, err = fClient.Rename(context.Background(), "newName", renameFileOpts) _require.Nil(err) - _require.NotNil(resp1) - _require.Contains(resp1.NewFileClient.DFSURL(), "newName") + //_require.NotNil(resp1) + //_require.Contains(resp1.NewFileClient.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) + filesystemName := testcommon.GenerateFileSystemName(testName) + fsClient, err := testcommon.GetFileSystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) - defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) _, err = fsClient.Create(context.Background(), nil) _require.Nil(err) @@ -2175,7 +2096,9 @@ func (s *RecordedTestSuite) TestRenameFileIfModifiedSinceFalse() { }, } + //_, err = fClient.Rename(context.Background(), "newName", renameFileOpts) _, err = fClient.Rename(context.Background(), "newName", renameFileOpts) + _require.NotNil(err) testcommon.ValidateErrorCode(_require, err, datalakeerror.SourceConditionNotMet) } @@ -2184,10 +2107,10 @@ 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) + filesystemName := testcommon.GenerateFileSystemName(testName) + fsClient, err := testcommon.GetFileSystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) - defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) _, err = fsClient.Create(context.Background(), nil) _require.Nil(err) @@ -2210,20 +2133,21 @@ func (s *RecordedTestSuite) TestRenameFileIfUnmodifiedSinceTrue() { }, } - resp1, err := fClient.Rename(context.Background(), "newName", renameFileOpts) + //resp1, err := fClient.Rename(context.Background(), "newName", renameFileOpts) + _, err = fClient.Rename(context.Background(), "newName", renameFileOpts) _require.Nil(err) - _require.NotNil(resp1) - _require.Contains(resp1.NewFileClient.DFSURL(), "newName") + //_require.NotNil(resp1) + //_require.Contains(resp1.NewFileClient.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) + filesystemName := testcommon.GenerateFileSystemName(testName) + fsClient, err := testcommon.GetFileSystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) - defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) _, err = fsClient.Create(context.Background(), nil) _require.Nil(err) @@ -2246,7 +2170,9 @@ func (s *RecordedTestSuite) TestRenameFileIfUnmodifiedSinceFalse() { }, } + //_, err = fClient.Rename(context.Background(), "newName", renameFileOpts) _, err = fClient.Rename(context.Background(), "newName", renameFileOpts) + _require.NotNil(err) testcommon.ValidateErrorCode(_require, err, datalakeerror.SourceConditionNotMet) } @@ -2255,10 +2181,10 @@ 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) + filesystemName := testcommon.GenerateFileSystemName(testName) + fsClient, err := testcommon.GetFileSystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) - defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) _, err = fsClient.Create(context.Background(), nil) _require.Nil(err) @@ -2281,20 +2207,21 @@ func (s *RecordedTestSuite) TestRenameFileIfETagMatch() { }, } - resp1, err := fClient.Rename(context.Background(), "newName", renameFileOpts) + //resp1, err := fClient.Rename(context.Background(), "newName", renameFileOpts) + _, err = fClient.Rename(context.Background(), "newName", renameFileOpts) _require.Nil(err) - _require.NotNil(resp1) - _require.Contains(resp1.NewFileClient.DFSURL(), "newName") + //_require.NotNil(resp1) + //_require.Contains(resp1.NewFileClient.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) + filesystemName := testcommon.GenerateFileSystemName(testName) + fsClient, err := testcommon.GetFileSystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) - defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) _, err = fsClient.Create(context.Background(), nil) _require.Nil(err) @@ -2317,7 +2244,9 @@ func (s *RecordedTestSuite) TestRenameFileIfETagMatchFalse() { }, } + //_, err = fClient.Rename(context.Background(), "newName", renameFileOpts) _, err = fClient.Rename(context.Background(), "newName", renameFileOpts) + _require.NotNil(err) testcommon.ValidateErrorCode(_require, err, datalakeerror.SourceConditionNotMet) } @@ -2326,10 +2255,10 @@ func (s *UnrecordedTestSuite) TestFileUploadDownloadStream() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + filesystemName := testcommon.GenerateFileSystemName(testName) + fsClient, err := testcommon.GetFileSystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) - defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) _, err = fsClient.Create(context.Background(), nil) _require.Nil(err) @@ -2376,10 +2305,10 @@ func (s *RecordedTestSuite) TestFileUploadDownloadSmallStream() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + filesystemName := testcommon.GenerateFileSystemName(testName) + fsClient, err := testcommon.GetFileSystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) - defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) _, err = fsClient.Create(context.Background(), nil) _require.Nil(err) @@ -2423,10 +2352,10 @@ func (s *RecordedTestSuite) TestFileUploadTinyStream() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + filesystemName := testcommon.GenerateFileSystemName(testName) + fsClient, err := testcommon.GetFileSystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) - defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) _, err = fsClient.Create(context.Background(), nil) _require.Nil(err) @@ -2470,10 +2399,10 @@ func (s *UnrecordedTestSuite) TestFileUploadFile() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + filesystemName := testcommon.GenerateFileSystemName(testName) + fsClient, err := testcommon.GetFileSystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) - defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) _, err = fsClient.Create(context.Background(), nil) _require.Nil(err) @@ -2538,10 +2467,10 @@ func (s *RecordedTestSuite) TestSmallFileUploadFile() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + filesystemName := testcommon.GenerateFileSystemName(testName) + fsClient, err := testcommon.GetFileSystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) - defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) _, err = fsClient.Create(context.Background(), nil) _require.Nil(err) @@ -2605,10 +2534,10 @@ func (s *RecordedTestSuite) TestTinyFileUploadFile() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + filesystemName := testcommon.GenerateFileSystemName(testName) + fsClient, err := testcommon.GetFileSystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) - defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) _, err = fsClient.Create(context.Background(), nil) _require.Nil(err) @@ -2671,10 +2600,10 @@ func (s *UnrecordedTestSuite) TestFileUploadBuffer() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + filesystemName := testcommon.GenerateFileSystemName(testName) + fsClient, err := testcommon.GetFileSystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) - defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) _, err = fsClient.Create(context.Background(), nil) _require.Nil(err) @@ -2719,10 +2648,10 @@ func (s *RecordedTestSuite) TestFileUploadSmallBuffer() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + filesystemName := testcommon.GenerateFileSystemName(testName) + fsClient, err := testcommon.GetFileSystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) - defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) _, err = fsClient.Create(context.Background(), nil) _require.Nil(err) @@ -2765,10 +2694,10 @@ func (s *RecordedTestSuite) TestFileAppendAndFlushData() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + filesystemName := testcommon.GenerateFileSystemName(testName) + fsClient, err := testcommon.GetFileSystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) - defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) _, err = fsClient.Create(context.Background(), nil) _require.Nil(err) @@ -2800,10 +2729,10 @@ func (s *UnrecordedTestSuite) TestFileAppendAndFlushDataWithValidation() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + filesystemName := testcommon.GenerateFileSystemName(testName) + fsClient, err := testcommon.GetFileSystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) - defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) _, err = fsClient.Create(context.Background(), nil) _require.Nil(err) @@ -2844,10 +2773,10 @@ func (s *RecordedTestSuite) TestFileAppendAndFlushDataWithEmptyOpts() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + filesystemName := testcommon.GenerateFileSystemName(testName) + fsClient, err := testcommon.GetFileSystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) - defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) _, err = fsClient.Create(context.Background(), nil) _require.Nil(err) @@ -2882,10 +2811,10 @@ func (s *RecordedTestSuite) TestFileAppendAndFlushDataWithLeasedFile() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + filesystemName := testcommon.GenerateFileSystemName(testName) + fsClient, err := testcommon.GetFileSystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) - defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) _, err = fsClient.Create(context.Background(), nil) _require.Nil(err) @@ -2937,10 +2866,10 @@ func (s *RecordedTestSuite) TestFileAppendAndFlushAndDownloadDataWithLeasedFile( _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + filesystemName := testcommon.GenerateFileSystemName(testName) + fsClient, err := testcommon.GetFileSystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) - defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) _, err = fsClient.Create(context.Background(), nil) _require.Nil(err) @@ -3000,10 +2929,10 @@ func (s *RecordedTestSuite) TestAppendAndFlushFileWithHTTPHeaders() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + filesystemName := testcommon.GenerateFileSystemName(testName) + fsClient, err := testcommon.GetFileSystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) - defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) _, err = fsClient.Create(context.Background(), nil) _require.Nil(err) @@ -3038,10 +2967,10 @@ func (s *RecordedTestSuite) TestFlushWithNilAccessConditions() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + filesystemName := testcommon.GenerateFileSystemName(testName) + fsClient, err := testcommon.GetFileSystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) - defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) _, err = fsClient.Create(context.Background(), nil) _require.Nil(err) @@ -3076,10 +3005,10 @@ func (s *RecordedTestSuite) TestFlushWithEmptyAccessConditions() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + filesystemName := testcommon.GenerateFileSystemName(testName) + fsClient, err := testcommon.GetFileSystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) - defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) _, err = fsClient.Create(context.Background(), nil) _require.Nil(err) @@ -3116,10 +3045,10 @@ func (s *RecordedTestSuite) TestFlushIfModifiedSinceTrue() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + filesystemName := testcommon.GenerateFileSystemName(testName) + fsClient, err := testcommon.GetFileSystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) - defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) _, err = fsClient.Create(context.Background(), nil) _require.Nil(err) @@ -3159,10 +3088,10 @@ func (s *RecordedTestSuite) TestFlushIfModifiedSinceFalse() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + filesystemName := testcommon.GenerateFileSystemName(testName) + fsClient, err := testcommon.GetFileSystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) - defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) _, err = fsClient.Create(context.Background(), nil) _require.Nil(err) @@ -3199,10 +3128,10 @@ func (s *RecordedTestSuite) TestFlushIfUnmodifiedSinceTrue() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + filesystemName := testcommon.GenerateFileSystemName(testName) + fsClient, err := testcommon.GetFileSystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) - defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) _, err = fsClient.Create(context.Background(), nil) _require.Nil(err) @@ -3243,10 +3172,10 @@ func (s *RecordedTestSuite) TestFlushIfUnmodifiedSinceFalse() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + filesystemName := testcommon.GenerateFileSystemName(testName) + fsClient, err := testcommon.GetFileSystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) - defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) _, err = fsClient.Create(context.Background(), nil) _require.Nil(err) @@ -3283,10 +3212,10 @@ func (s *RecordedTestSuite) TestFlushIfEtagMatch() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + filesystemName := testcommon.GenerateFileSystemName(testName) + fsClient, err := testcommon.GetFileSystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) - defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) _, err = fsClient.Create(context.Background(), nil) _require.Nil(err) @@ -3326,10 +3255,10 @@ func (s *RecordedTestSuite) TestFlushIfEtagMatchFalse() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + filesystemName := testcommon.GenerateFileSystemName(testName) + fsClient, err := testcommon.GetFileSystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) - defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) _, err = fsClient.Create(context.Background(), nil) _require.Nil(err) @@ -3371,10 +3300,10 @@ func (s *UnrecordedTestSuite) TestFileDownloadFile() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + filesystemName := testcommon.GenerateFileSystemName(testName) + fsClient, err := testcommon.GetFileSystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) - defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) _, err = fsClient.Create(context.Background(), nil) _require.Nil(err) @@ -3435,10 +3364,10 @@ func (s *RecordedTestSuite) TestFileUploadDownloadSmallFile() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + filesystemName := testcommon.GenerateFileSystemName(testName) + fsClient, err := testcommon.GetFileSystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) - defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) _, err = fsClient.Create(context.Background(), nil) _require.Nil(err) @@ -3514,10 +3443,10 @@ func (s *RecordedTestSuite) TestFileUploadDownloadSmallFileWithRange() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + filesystemName := testcommon.GenerateFileSystemName(testName) + fsClient, err := testcommon.GetFileSystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) - defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) _, err = fsClient.Create(context.Background(), nil) _require.Nil(err) @@ -3597,10 +3526,10 @@ func (s *RecordedTestSuite) TestFileUploadDownloadSmallFileWithAccessConditions( _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + filesystemName := testcommon.GenerateFileSystemName(testName) + fsClient, err := testcommon.GetFileSystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) - defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) _, err = fsClient.Create(context.Background(), nil) _require.Nil(err) @@ -3686,10 +3615,10 @@ func (s *RecordedTestSuite) TestFileUploadDownloadWithProgress() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + filesystemName := testcommon.GenerateFileSystemName(testName) + fsClient, err := testcommon.GetFileSystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) - defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) _, err = fsClient.Create(context.Background(), nil) _require.Nil(err) @@ -3747,10 +3676,10 @@ func (s *UnrecordedTestSuite) TestFileDownloadBuffer() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + filesystemName := testcommon.GenerateFileSystemName(testName) + fsClient, err := testcommon.GetFileSystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) - defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) _, err = fsClient.Create(context.Background(), nil) _require.Nil(err) @@ -3798,10 +3727,10 @@ func (s *RecordedTestSuite) TestFileDownloadSmallBuffer() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + filesystemName := testcommon.GenerateFileSystemName(testName) + fsClient, err := testcommon.GetFileSystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) - defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) _, err = fsClient.Create(context.Background(), nil) _require.Nil(err) @@ -3847,10 +3776,10 @@ func (s *RecordedTestSuite) TestFileDownloadSmallBufferWithHTTPRange() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + filesystemName := testcommon.GenerateFileSystemName(testName) + fsClient, err := testcommon.GetFileSystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) - defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) _, err = fsClient.Create(context.Background(), nil) _require.Nil(err) @@ -3900,10 +3829,10 @@ func (s *RecordedTestSuite) TestFileDownloadSmallBufferWithAccessConditions() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + filesystemName := testcommon.GenerateFileSystemName(testName) + fsClient, err := testcommon.GetFileSystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) - defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) _, err = fsClient.Create(context.Background(), nil) _require.Nil(err) diff --git a/sdk/storage/azdatalake/file/constants.go b/sdk/storage/azdatalake/file/constants.go index da5ec3d2b065..77729179d3d4 100644 --- a/sdk/storage/azdatalake/file/constants.go +++ b/sdk/storage/azdatalake/file/constants.go @@ -14,6 +14,7 @@ import ( "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/internal/path" ) +// EncryptionAlgorithmType defines values for EncryptionAlgorithmType. type EncryptionAlgorithmType = path.EncryptionAlgorithmType const ( @@ -23,6 +24,7 @@ const ( // response models: +// ImmutabilityPolicyMode Specifies the immutability policy mode to set on the file. type ImmutabilityPolicyMode = path.ImmutabilityPolicyMode const ( diff --git a/sdk/storage/azdatalake/file/examples_test.go b/sdk/storage/azdatalake/file/examples_test.go new file mode 100644 index 000000000000..213adfb3f173 --- /dev/null +++ b/sdk/storage/azdatalake/file/examples_test.go @@ -0,0 +1,389 @@ +//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 file_test + +import ( + "bytes" + "context" + "crypto/md5" + "encoding/binary" + "fmt" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/streaming" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/to" + "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/internal/shared" + "hash/crc64" + "io" + "log" + "os" + "strconv" + "strings" + "time" +) + +func handleError(err error) { + if err != nil { + log.Fatal(err.Error()) + } +} + +// make sure you create the filesystem before running this example +func Example_file_CreateAndDelete() { + accountName, accountKey := os.Getenv("AZURE_STORAGE_ACCOUNT_NAME"), os.Getenv("AZURE_STORAGE_ACCOUNT_KEY") + + // Create a file client + u := fmt.Sprintf("https://%s.dfs.core.windows.net/fs/file.txt", accountName) + credential, err := azdatalake.NewSharedKeyCredential(accountName, accountKey) + handleError(err) + fileClient, err := file.NewClientWithSharedKeyCredential(u, credential, nil) + handleError(err) + + _, err = fileClient.Create(context.Background(), nil) + handleError(err) + + _, err = fileClient.Delete(context.Background(), nil) + handleError(err) +} + +// This examples shows how to create a file with HTTP Headers, how to read, and how to update the file's HTTP headers. +// make sure you create the filesystem and file before running this example. +func Example_file_HTTPHeaders() { + accountName, accountKey := os.Getenv("AZURE_STORAGE_ACCOUNT_NAME"), os.Getenv("AZURE_STORAGE_ACCOUNT_KEY") + + // Create a file client + u := fmt.Sprintf("https://%s.dfs.core.windows.net/fs/file.txt", accountName) + credential, err := azdatalake.NewSharedKeyCredential(accountName, accountKey) + handleError(err) + fileClient, err := file.NewClientWithSharedKeyCredential(u, credential, nil) + handleError(err) + + // Create a directory with HTTP headers + _, err = fileClient.SetHTTPHeaders(context.TODO(), file.HTTPHeaders{ + ContentType: to.Ptr("text/html; charset=utf-8"), + ContentDisposition: to.Ptr("attachment"), + }, nil) + handleError(err) + + get, err := fileClient.GetProperties(context.TODO(), nil) + handleError(err) + + fmt.Println(get.ContentType) + fmt.Println(get.ContentDisposition) +} + +// make sure you create the filesystem before running this example +func Example_file_CreateFileWithExpiryRelativeToNow() { + accountName, accountKey := os.Getenv("AZURE_STORAGE_ACCOUNT_NAME"), os.Getenv("AZURE_STORAGE_ACCOUNT_KEY") + + // Create a file client + u := fmt.Sprintf("https://%s.dfs.core.windows.net/fs/file.txt", accountName) + credential, err := azdatalake.NewSharedKeyCredential(accountName, accountKey) + handleError(err) + fClient, err := file.NewClientWithSharedKeyCredential(u, credential, nil) + handleError(err) + + createFileOpts := &file.CreateOptions{ + Expiry: file.CreateExpiryValues{ + ExpiryType: file.CreateExpiryTypeRelativeToNow, + ExpiresOn: strconv.FormatInt((8 * time.Second).Milliseconds(), 10), + }, + } + + _, err = fClient.Create(context.Background(), createFileOpts) + handleError(err) + + resp, err := fClient.GetProperties(context.Background(), nil) + handleError(err) + fmt.Println(*resp.ExpiresOn) + + time.Sleep(time.Second * 10) + _, err = fClient.GetProperties(context.Background(), nil) + // we expect datalakeerror.PathNotFound + handleError(err) +} + +// make sure you create the filesystem before running this example +func Example_file_CreateFileWithNeverExpire() { + accountName, accountKey := os.Getenv("AZURE_STORAGE_ACCOUNT_NAME"), os.Getenv("AZURE_STORAGE_ACCOUNT_KEY") + + // Create a file client + u := fmt.Sprintf("https://%s.dfs.core.windows.net/fs/file.txt", accountName) + credential, err := azdatalake.NewSharedKeyCredential(accountName, accountKey) + handleError(err) + fClient, err := file.NewClientWithSharedKeyCredential(u, credential, nil) + handleError(err) + + createFileOpts := &file.CreateOptions{ + Expiry: file.CreateExpiryValues{ + ExpiryType: file.CreateExpiryTypeNeverExpire, + }, + } + + _, err = fClient.Create(context.Background(), createFileOpts) + handleError(err) + + resp, err := fClient.GetProperties(context.Background(), nil) + handleError(err) + // should be empty since we never expire + fmt.Println(*resp.ExpiresOn) +} + +// make sure you create the filesystem and file before running this example +func Example_file_Client_SetMetadata() { + accountName, accountKey := os.Getenv("AZURE_STORAGE_ACCOUNT_NAME"), os.Getenv("AZURE_STORAGE_ACCOUNT_KEY") + + // Create a file client + u := fmt.Sprintf("https://%s.dfs.core.windows.net/fs/file.txt", accountName) + credential, err := azdatalake.NewSharedKeyCredential(accountName, accountKey) + handleError(err) + + fileClient, err := file.NewClientWithSharedKeyCredential(u, credential, nil) + handleError(err) + + _, err = fileClient.SetMetadata(context.TODO(), map[string]*string{"author": to.Ptr("Tamer")}, nil) + handleError(err) + + // Query the directory's properties and metadata + get, err := fileClient.GetProperties(context.TODO(), nil) + handleError(err) + + // Show the directory's metadata + if get.Metadata == nil { + log.Fatal("No metadata returned") + } + + for k, v := range get.Metadata { + fmt.Print(k + "=" + *v + "\n") + } +} + +// make sure you create the filesystem before running this example +func Example_file_Rename() { + accountName, accountKey := os.Getenv("AZURE_STORAGE_ACCOUNT_NAME"), os.Getenv("AZURE_STORAGE_ACCOUNT_KEY") + + // Create a file client + u := fmt.Sprintf("https://%s.dfs.core.windows.net/fs/file.txt", accountName) + credential, err := azdatalake.NewSharedKeyCredential(accountName, accountKey) + handleError(err) + fileClient, err := file.NewClientWithSharedKeyCredential(u, credential, nil) + handleError(err) + + _, err = fileClient.Create(context.Background(), nil) + handleError(err) + + _, err = fileClient.Rename(context.Background(), "renameFile", nil) + handleError(err) +} + +// set acl on a file +// make sure you create the filesystem and file before running this example +func Example_file_SetACL() { + accountName, accountKey := os.Getenv("AZURE_STORAGE_ACCOUNT_NAME"), os.Getenv("AZURE_STORAGE_ACCOUNT_KEY") + + // Create a file client + acl := "user::rwx,group::r-x,other::rwx" + u := fmt.Sprintf("https://%s.dfs.core.windows.net/fs/file.txt", accountName) + credential, err := azdatalake.NewSharedKeyCredential(accountName, accountKey) + handleError(err) + fileClient, err := file.NewClientWithSharedKeyCredential(u, credential, nil) + handleError(err) + + _, err = fileClient.SetAccessControl(context.Background(), &file.SetAccessControlOptions{ + ACL: &acl, + }) + handleError(err) +} + +func getRelativeTimeFromAnchor(anchorTime *time.Time, amount time.Duration) time.Time { + return anchorTime.Add(amount * time.Second) +} + +// make sure you create the filesystem before running this example +func Example_file_SetAccessControlIfUnmodifiedSinceTrue() { + accountName, accountKey := os.Getenv("AZURE_STORAGE_ACCOUNT_NAME"), os.Getenv("AZURE_STORAGE_ACCOUNT_KEY") + + // Create a directory client + owner := "4cf4e284-f6a8-4540-b53e-c3469af032dc" + group := owner + acl := "user::rwx,group::r-x,other::rwx" + u := fmt.Sprintf("https://%s.dfs.core.windows.net/fs/file.txt", accountName) + credential, err := azdatalake.NewSharedKeyCredential(accountName, accountKey) + handleError(err) + fileClient, err := directory.NewClientWithSharedKeyCredential(u, credential, nil) + handleError(err) + resp, err := fileClient.Create(context.Background(), nil) + handleError(err) + + currentTime := getRelativeTimeFromAnchor(resp.Date, 10) + opts := &directory.SetAccessControlOptions{ + Owner: &owner, + Group: &group, + ACL: &acl, + AccessConditions: &directory.AccessConditions{ + ModifiedAccessConditions: &directory.ModifiedAccessConditions{ + IfUnmodifiedSince: ¤tTime, + }, + }} + + _, err = fileClient.SetAccessControl(context.Background(), opts) + handleError(err) +} + +const random64BString string = "2SDgZj6RkKYzJpu04sweQek4uWHO8ndPnYlZ0tnFS61hjnFZ5IkvIGGY44eKABov" + +func generateData(sizeInBytes int) (io.ReadSeekCloser, []byte) { + data := make([]byte, sizeInBytes) + _len := len(random64BString) + if sizeInBytes > _len { + count := sizeInBytes / _len + if sizeInBytes%_len != 0 { + count = count + 1 + } + copy(data[:], strings.Repeat(random64BString, count)) + } else { + copy(data[:], random64BString) + } + return streaming.NopCloser(bytes.NewReader(data)), data +} + +// make sure you create the filesystem before running this example +func Example_file_UploadFileAndDownloadStream() { + accountName, accountKey := os.Getenv("AZURE_STORAGE_ACCOUNT_NAME"), os.Getenv("AZURE_STORAGE_ACCOUNT_KEY") + + // Create a file client + u := fmt.Sprintf("https://%s.dfs.core.windows.net/fs/file.txt", accountName) + credential, err := azdatalake.NewSharedKeyCredential(accountName, accountKey) + handleError(err) + fClient, err := file.NewClientWithSharedKeyCredential(u, credential, nil) + handleError(err) + var fileSize int64 = 10 * 1024 + + _, err = fClient.Create(context.Background(), nil) + handleError(err) + + // create local file + _, content := generateData(int(fileSize)) + err = os.WriteFile("testFile", content, 0644) + handleError(err) + + defer func() { + err = os.Remove("testFile") + handleError(err) + }() + + fh, err := os.Open("testFile") + handleError(err) + + defer func(fh *os.File) { + err := fh.Close() + handleError(err) + }(fh) + + // get md5 hash to compare against after download + hash := md5.New() + _, err = io.Copy(hash, fh) + handleError(err) + contentMD5 := hash.Sum(nil) + + // upload the file + err = fClient.UploadFile(context.Background(), fh, &file.UploadFileOptions{ + Concurrency: 5, + ChunkSize: 2 * 1024, + }) + handleError(err) + + gResp2, err := fClient.GetProperties(context.Background(), nil) + handleError(err) + fmt.Println(*gResp2.ContentLength, fileSize) + + dResp, err := fClient.DownloadStream(context.Background(), nil) + handleError(err) + + data, err := io.ReadAll(dResp.Body) + handleError(err) + + downloadedMD5Value := md5.Sum(data) + downloadedContentMD5 := downloadedMD5Value[:] + + // compare the hashes + fmt.Println(downloadedContentMD5, contentMD5) +} + +// make sure you create the filesystem before running this example +func Example_file_UploadBufferAndDownloadStream() { + accountName, accountKey := os.Getenv("AZURE_STORAGE_ACCOUNT_NAME"), os.Getenv("AZURE_STORAGE_ACCOUNT_KEY") + + // Create a file client + u := fmt.Sprintf("https://%s.dfs.core.windows.net/fs/file.txt", accountName) + credential, err := azdatalake.NewSharedKeyCredential(accountName, accountKey) + handleError(err) + fClient, err := file.NewClientWithSharedKeyCredential(u, credential, nil) + handleError(err) + var fileSize int64 = 10 * 1024 + + _, content := generateData(int(fileSize)) + md5Value := md5.Sum(content) + contentMD5 := md5Value[:] + + err = fClient.UploadBuffer(context.Background(), content, &file.UploadBufferOptions{ + Concurrency: 5, + ChunkSize: 2 * 1024, + }) + handleError(err) + gResp2, err := fClient.GetProperties(context.Background(), nil) + handleError(err) + fmt.Println(*gResp2.ContentLength, fileSize) + + dResp, err := fClient.DownloadStream(context.Background(), nil) + handleError(err) + + data, err := io.ReadAll(dResp.Body) + handleError(err) + + downloadedMD5Value := md5.Sum(data) + downloadedContentMD5 := downloadedMD5Value[:] + + fmt.Println(downloadedContentMD5, contentMD5) +} + +// make sure you create the filesystem before running this example +func Example_file_AppendAndFlushDataWithValidation() { + accountName, accountKey := os.Getenv("AZURE_STORAGE_ACCOUNT_NAME"), os.Getenv("AZURE_STORAGE_ACCOUNT_KEY") + + // Create a file client + u := fmt.Sprintf("https://%s.dfs.core.windows.net/fs/file.txt", accountName) + credential, err := azdatalake.NewSharedKeyCredential(accountName, accountKey) + handleError(err) + fClient, err := file.NewClientWithSharedKeyCredential(u, credential, nil) + handleError(err) + + contentSize := 1024 * 8 // 8KB + content := make([]byte, contentSize) + body := bytes.NewReader(content) + rsc := streaming.NopCloser(body) + contentCRC64 := crc64.Checksum(content, shared.CRC64Table) + + // validate data using crc64 + opts := &file.AppendDataOptions{ + TransactionalValidation: file.TransferValidationTypeComputeCRC64(), + } + putResp, err := fClient.AppendData(context.Background(), 0, rsc, opts) + handleError(err) + fmt.Println(putResp.ContentCRC64) + fmt.Println(binary.LittleEndian.Uint64(putResp.ContentCRC64), contentCRC64) + + // after appending data, flush it + _, err = fClient.FlushData(context.Background(), int64(contentSize), nil) + handleError(err) + + // compare content length as well + gResp2, err := fClient.GetProperties(context.Background(), nil) + handleError(err) + fmt.Println(*gResp2.ContentLength, int64(contentSize)) +} diff --git a/sdk/storage/azdatalake/file/models.go b/sdk/storage/azdatalake/file/models.go index 928772d28e16..aa4852e7c9e8 100644 --- a/sdk/storage/azdatalake/file/models.go +++ b/sdk/storage/azdatalake/file/models.go @@ -22,19 +22,17 @@ const ( _1MiB = 1024 * 1024 CountToEnd = 0 - // MaxAppendBytes indicates the maximum number of bytes that can be updated in a call to Client.UploadRange. + // MaxAppendBytes indicates the maximum number of bytes that can be updated in a call to Client.AppendData. MaxAppendBytes = 100 * 1024 * 1024 // 100iB // MaxFileSize indicates the maximum size of the file allowed. MaxFileSize = 4 * 1024 * 1024 * 1024 * 1024 // 4 TiB ) -// CreateOptions contains the optional parameters when calling the Create operation. dfs endpoint. +// CreateOptions contains the optional parameters when calling the Create operation. type CreateOptions struct { // AccessConditions contains parameters for accessing the file. AccessConditions *AccessConditions - // Metadata is a map of name-value pairs to associate with the file storage object. - Metadata map[string]*string // CPKInfo contains a group of parameters for client provided encryption key. CPKInfo *CPKInfo // HTTPHeaders contains the HTTP headers for path operations. @@ -175,12 +173,17 @@ type UploadFileOptions = uploadFromReaderOptions // FlushDataOptions contains the optional parameters for the Client.FlushData method. type FlushDataOptions struct { + // AccessConditions contains parameters for accessing the file. AccessConditions *AccessConditions - // HTTPHeaders contains the optional path HTTP headers to set when the file is created. // CPKInfo contains optional parameters to perform encryption using customer-provided key. - CPKInfo *CPKInfo - HTTPHeaders *HTTPHeaders - Close *bool + CPKInfo *CPKInfo + // HTTPHeaders contains the HTTP headers for path operations. + HTTPHeaders *HTTPHeaders + // Close This event has a property indicating whether this is the final change to distinguish the + // difference between an intermediate flush to a file stream and the final close of a file stream. + Close *bool + // RetainUncommittedData if "true", uncommitted data is retained after the flush operation + // completes, otherwise, the uncommitted data is deleted after the flush operation. RetainUncommittedData *bool } @@ -231,7 +234,7 @@ func (o *FlushDataOptions) format(offset int64) (*generated.PathClientFlushDataO return flushDataOpts, modifiedAccessConditions, leaseAccessConditions, httpHeaderOpts, cpkInfoOpts, nil } -// AppendDataOptions contains the optional parameters for the Client.UploadRange method. +// AppendDataOptions contains the optional parameters for the Client.AppendData method. type AppendDataOptions struct { // TransactionalValidation specifies the transfer validation type to use. // The default is nil (no transfer validation). @@ -342,18 +345,19 @@ func (u *UploadStreamOptions) getFlushDataOptions() *FlushDataOptions { } } -// DownloadStreamOptions contains the optional parameters for the Client.Download method. +// DownloadStreamOptions contains the optional parameters for the Client.DownloadStream method. type DownloadStreamOptions struct { // When set to true and specified together with the Range, the service returns the MD5 hash for the range, as long as the // range is less than or equal to 4 MB in size. RangeGetContentMD5 *bool - // Range specifies a range of bytes. The default value is all bytes. Range *HTTPRange - + // AccessConditions contains parameters for accessing the file. AccessConditions *AccessConditions - CPKInfo *CPKInfo - CPKScopeInfo *CPKScopeInfo + // CPKInfo contains optional parameters to perform encryption using customer-provided key. + CPKInfo *CPKInfo + // CPKScopeInfo contains a group of parameters for client provided encryption scope. + CPKScopeInfo *CPKScopeInfo } func (o *DownloadStreamOptions) format() *blob.DownloadStreamOptions { @@ -383,26 +387,19 @@ func (o *DownloadStreamOptions) format() *blob.DownloadStreamOptions { type DownloadBufferOptions struct { // Range specifies a range of bytes. The default value is all bytes. Range *HTTPRange - - // ChunkSize specifies the block size to use for each parallel download; the default size is DefaultDownloadBlockSize. + // ChunkSize specifies the chunk size to use for each parallel download; the default size is 4MB. ChunkSize int64 - // Progress is a function that is invoked periodically as bytes are received. Progress func(bytesTransferred int64) - - // BlobAccessConditions indicates the access conditions used when making HTTP GET requests against the blob. + // AccessConditions indicates the access conditions used when making HTTP GET requests against the file. AccessConditions *AccessConditions - // CPKInfo contains a group of parameters for client provided encryption key. CPKInfo *CPKInfo - // CPKScopeInfo contains a group of parameters for client provided encryption scope. CPKScopeInfo *CPKScopeInfo - - // Concurrency indicates the maximum number of blocks to download in parallel (0=default). + // Concurrency indicates the maximum number of chunks to download in parallel (0=default). Concurrency uint16 - - // RetryReaderOptionsPerChunk is used when downloading each block. + // RetryReaderOptionsPerChunk is used when downloading each chunk. RetryReaderOptionsPerChunk *RetryReaderOptions } @@ -444,24 +441,19 @@ func (o *DownloadBufferOptions) format() *blob.DownloadBufferOptions { type DownloadFileOptions struct { // Range specifies a range of bytes. The default value is all bytes. Range *HTTPRange - - // ChunkSize specifies the block size to use for each parallel download; the default size is DefaultDownloadBlockSize. + // ChunkSize specifies the chunk size to use for each parallel download; the default size is 4MB. ChunkSize int64 - // Progress is a function that is invoked periodically as bytes are received. Progress func(bytesTransferred int64) - - // BlobAccessConditions indicates the access conditions used when making HTTP GET requests against the blob. + // AccessConditions indicates the access conditions used when making HTTP GET requests against the file. AccessConditions *AccessConditions - - // ClientProvidedKeyOptions indicates the client provided key by name and/or by value to encrypt/decrypt data. - CPKInfo *CPKInfo + // CPKInfo contains a group of parameters for client provided encryption key. + CPKInfo *CPKInfo + // CPKScopeInfo contains a group of parameters for client provided encryption scope. CPKScopeInfo *CPKScopeInfo - - // Concurrency indicates the maximum number of blocks to download in parallel. The default value is 5. + // Concurrency indicates the maximum number of chunks to download in parallel. The default value is 5. Concurrency uint16 - - // RetryReaderOptionsPerChunk is used when downloading each block. + // RetryReaderOptionsPerChunk is used when downloading each chunk. RetryReaderOptionsPerChunk *RetryReaderOptions } @@ -522,11 +514,14 @@ type SetExpiryOptions struct { // placeholder for future options } +// 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 = exported.HTTPRange // ================================= path imports ================================== -// DeleteOptions contains the optional parameters when calling the Delete operation. dfs endpoint +// DeleteOptions contains the optional parameters when calling the Delete operation. type DeleteOptions = path.DeleteOptions // RenameOptions contains the optional parameters when calling the Rename operation. @@ -535,13 +530,13 @@ type RenameOptions = path.RenameOptions // GetPropertiesOptions contains the optional parameters for the Client.GetProperties method type GetPropertiesOptions = path.GetPropertiesOptions -// SetAccessControlOptions contains the optional parameters when calling the SetAccessControl operation. dfs endpoint +// SetAccessControlOptions contains the optional parameters when calling the SetAccessControl operation. type SetAccessControlOptions = path.SetAccessControlOptions // GetAccessControlOptions contains the optional parameters when calling the GetAccessControl operation. type GetAccessControlOptions = path.GetAccessControlOptions -// CPKInfo contains a group of parameters for the PathClient.Download method. +// CPKInfo contains CPK related information. type CPKInfo = path.CPKInfo // GetSASURLOptions contains the optional parameters for the Client.GetSASURL method. @@ -559,10 +554,10 @@ type SetMetadataOptions = path.SetMetadataOptions // SharedKeyCredential contains an account's name and its primary or secondary key. type SharedKeyCredential = path.SharedKeyCredential -// AccessConditions identifies blob-specific access conditions which you optionally set. +// AccessConditions identifies file-specific access conditions which you optionally set. type AccessConditions = path.AccessConditions -// SourceAccessConditions identifies blob-specific access conditions which you optionally set. +// SourceAccessConditions identifies file-specific source access conditions which you optionally set. type SourceAccessConditions = path.SourceAccessConditions // LeaseAccessConditions contains optional parameters to access leased entity. diff --git a/sdk/storage/azdatalake/file/responses.go b/sdk/storage/azdatalake/file/responses.go index 801c9d03b0c0..f72747584ab7 100644 --- a/sdk/storage/azdatalake/file/responses.go +++ b/sdk/storage/azdatalake/file/responses.go @@ -26,15 +26,13 @@ type AppendDataResponse = generated.PathClientAppendDataResponse // FlushDataResponse contains the response from method Client.FlushData. type FlushDataResponse = generated.PathClientFlushDataResponse -// RenameResponse contains the response fields for the Create operation. -type RenameResponse struct { - Response CreateResponse - NewFileClient *Client -} +// RenameResponse contains the response fields for the Rename operation. +type RenameResponse = path.RenameResponse // DownloadStreamResponse contains the response from the DownloadStream method. // To read from the stream, read from the Body field, or call the NewRetryReader method. type DownloadStreamResponse struct { + // DownloadResponse contains response fields from DownloadStream. DownloadResponse client *Client getInfo httpGetterInfo diff --git a/sdk/storage/azdatalake/file/retry_reader.go b/sdk/storage/azdatalake/file/retry_reader.go index 66e3f35edf0d..139278e54b85 100644 --- a/sdk/storage/azdatalake/file/retry_reader.go +++ b/sdk/storage/azdatalake/file/retry_reader.go @@ -21,6 +21,7 @@ type httpGetter func(ctx context.Context, i httpGetterInfo) (io.ReadCloser, erro // HTTPGetterInfo is passed to an HTTPGetter function passing it parameters // that should be used to make an HTTP GET request. type httpGetterInfo struct { + // HTTPRange contains range Range *HTTPRange // ETag specifies the resource's etag that should be used when creating diff --git a/sdk/storage/azdatalake/file/retry_reader_test.go b/sdk/storage/azdatalake/file/retry_reader_test.go new file mode 100644 index 000000000000..61013cd1de46 --- /dev/null +++ b/sdk/storage/azdatalake/file/retry_reader_test.go @@ -0,0 +1,433 @@ +//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 file + +import ( + "context" + "crypto/rand" + "errors" + "fmt" + "io" + "net" + "net/http" + "testing" + "time" + + "github.com/stretchr/testify/require" +) + +// Testings for RetryReader +// This reader return one byte through each Read call +type perByteReader struct { + RandomBytes []byte // Random generated bytes + + byteCount int // Bytes can be returned before EOF + currentByteIndex int // Bytes that have already been returned. + doInjectError bool + doInjectErrorByteIndex int + doInjectTimes int + injectedError error + + // sleepDuration and closeChannel are only use in "forced cancellation" tests + sleepDuration time.Duration + closeChannel chan struct{} +} + +func newPerByteReader(byteCount int) *perByteReader { + perByteReader := perByteReader{ + byteCount: byteCount, + closeChannel: nil, + } + + perByteReader.RandomBytes = make([]byte, byteCount) + _, _ = rand.Read(perByteReader.RandomBytes) + + return &perByteReader +} + +func newSingleUsePerByteReader(contents []byte) *perByteReader { + perByteReader := perByteReader{ + byteCount: len(contents), + closeChannel: make(chan struct{}, 10), + } + + perByteReader.RandomBytes = contents + + return &perByteReader +} + +func (r *perByteReader) Read(b []byte) (n int, err error) { + if r.doInjectError && r.doInjectErrorByteIndex == r.currentByteIndex && r.doInjectTimes > 0 { + r.doInjectTimes-- + return 0, r.injectedError + } + + if r.currentByteIndex < r.byteCount { + n = copy(b, r.RandomBytes[r.currentByteIndex:r.currentByteIndex+1]) + r.currentByteIndex += n + + // simulate a delay, which may be successful or, if we're closed from another go-routine, may return an + // error + select { + case <-r.closeChannel: + return n, errors.New(ReadOnClosedBodyMessage) + case <-time.After(r.sleepDuration): + return n, nil + } + } + + return 0, io.EOF +} + +func (r *perByteReader) Close() error { + if r.closeChannel != nil { + r.closeChannel <- struct{}{} + } + return nil +} + +// Test normal retry succeed, note initial response not provided. +// Tests both with and without notification of failures +func TestRetryReaderReadWithRetry(t *testing.T) { + // Test twice, the second time using the optional "logging"/notification callback for failed tries + // We must test both with and without the callback, since be testing without + // we are testing that it is, indeed, optional to provide the callback + for _, logThisRun := range []bool{false, true} { + + // Extra setup for testing notification of failures (i.e. of unsuccessful tries) + failureMethodNumCalls := 0 + failureWillRetryCount := 0 + failureLastReportedFailureCount := int32(-1) + var failureLastReportedError error = nil + failureMethod := func(failureCount int32, lastError error, rnge HTTPRange, willRetry bool) { + failureMethodNumCalls++ + if willRetry { + failureWillRetryCount++ + } + failureLastReportedFailureCount = failureCount + failureLastReportedError = lastError + } + + // Main test setup + byteCount := 1 + body := newPerByteReader(byteCount) + body.doInjectError = true + body.doInjectErrorByteIndex = 0 + body.doInjectTimes = 1 + body.injectedError = &net.DNSError{IsTemporary: true} + + getter := func(ctx context.Context, info httpGetterInfo) (io.ReadCloser, error) { + r := http.Response{} + body.currentByteIndex = int(info.Range.Offset) + r.Body = body + + return r.Body, nil + } + + httpGetterInfo := httpGetterInfo{ + Range: &HTTPRange{ + Count: int64(byteCount), + }, + } + initResponse, err := getter(context.Background(), httpGetterInfo) + require.NoError(t, err) + + rrOptions := RetryReaderOptions{MaxRetries: 1} + if logThisRun { + rrOptions.OnFailedRead = failureMethod + } + retryReader := newRetryReader(context.Background(), initResponse, httpGetterInfo, getter, rrOptions) + + // should fail and succeed through retry + can := make([]byte, 1) + n, err := retryReader.Read(can) + require.Equal(t, n, 1) + require.NoError(t, err) + + // check "logging", if it was enabled + if logThisRun { + // We only expect one failed try in this test + // And the notification method is not called for successes + require.Equal(t, failureMethodNumCalls, 1) // this is the number of calls we counted + require.Equal(t, failureWillRetryCount, 1) // the sole failure was retried + require.Equal(t, failureLastReportedFailureCount, int32(1)) // this is the number of failures reported by the notification method + require.Error(t, failureLastReportedError) + } + // should return EOF + n, err = retryReader.Read(can) + require.Equal(t, n, 0) + require.Equal(t, err, io.EOF) + } +} + +// Test normal retry succeed, note initial response not provided. +// Tests both with and without notification of failures +func TestRetryReaderWithRetryIoUnexpectedEOF(t *testing.T) { + // Test twice, the second time using the optional "logging"/notification callback for failed tries + // We must test both with and without the callback, since be testing without + // we are testing that it is, indeed, optional to provide the callback + for _, logThisRun := range []bool{false, true} { + + // Extra setup for testing notification of failures (i.e. of unsuccessful tries) + failureMethodNumCalls := 0 + failureWillRetryCount := 0 + failureLastReportedFailureCount := int32(-1) + var failureLastReportedError error = nil + failureMethod := func(failureCount int32, lastError error, rnge HTTPRange, willRetry bool) { + failureMethodNumCalls++ + if willRetry { + failureWillRetryCount++ + } + failureLastReportedFailureCount = failureCount + failureLastReportedError = lastError + } + + // Main test setup + byteCount := 1 + body := newPerByteReader(byteCount) + body.doInjectError = true + body.doInjectErrorByteIndex = 0 + body.doInjectTimes = 1 + body.injectedError = io.ErrUnexpectedEOF + + getter := func(ctx context.Context, info httpGetterInfo) (io.ReadCloser, error) { + r := http.Response{} + body.currentByteIndex = int(info.Range.Offset) + r.Body = body + + return r.Body, nil + } + + httpGetterInfo := httpGetterInfo{ + Range: &HTTPRange{ + Count: int64(byteCount), + }, + } + initResponse, err := getter(context.Background(), httpGetterInfo) + require.NoError(t, err) + + rrOptions := RetryReaderOptions{MaxRetries: 1} + if logThisRun { + rrOptions.OnFailedRead = failureMethod + } + retryReader := newRetryReader(context.Background(), initResponse, httpGetterInfo, getter, rrOptions) + + // should fail and succeed through retry + can := make([]byte, 1) + n, err := retryReader.Read(can) + require.Equal(t, n, 1) + require.NoError(t, err) + + // check "logging", if it was enabled + if logThisRun { + // We only expect one failed try in this test + // And the notification method is not called for successes + require.Equal(t, failureMethodNumCalls, 1) // this is the number of calls we counted + require.Equal(t, failureWillRetryCount, 1) // the sole failure was retried + require.Equal(t, failureLastReportedFailureCount, int32(1)) // this is the number of failures reported by the notification method + require.Error(t, failureLastReportedError) + } + // should return EOF + n, err = retryReader.Read(can) + require.Equal(t, n, 0) + require.Equal(t, err, io.EOF) + } +} + +// Test normal retry fail as retry Count not enough. +func TestRetryReaderReadNegativeNormalFail(t *testing.T) { + // Extra setup for testing notification of failures (i.e. of unsuccessful tries) + failureMethodNumCalls := 0 + failureWillRetryCount := 0 + failureLastReportedFailureCount := int32(-1) + var failureLastReportedError error = nil + failureMethod := func(failureCount int32, lastError error, rnge HTTPRange, willRetry bool) { + failureMethodNumCalls++ + if willRetry { + failureWillRetryCount++ + } + failureLastReportedFailureCount = failureCount + failureLastReportedError = lastError + } + + // Main test setup + byteCount := 1 + body := newPerByteReader(byteCount) + body.doInjectError = true + body.doInjectErrorByteIndex = 0 + body.doInjectTimes = 2 + body.injectedError = &net.DNSError{IsTemporary: true} + + startResponse := body + + getter := func(ctx context.Context, info httpGetterInfo) (io.ReadCloser, error) { + r := http.Response{} + body.currentByteIndex = int(info.Range.Offset) + r.Body = body + + return r.Body, nil + } + + rrOptions := RetryReaderOptions{ + MaxRetries: 1, + OnFailedRead: failureMethod, + } + httpGetterInfo := httpGetterInfo{ + Range: &HTTPRange{ + Count: int64(byteCount), + }, + } + retryReader := newRetryReader(context.Background(), startResponse, httpGetterInfo, getter, rrOptions) + + // should fail + can := make([]byte, 1) + n, err := retryReader.Read(can) + require.Equal(t, n, 0) + require.Equal(t, err, body.injectedError) + + // Check that we received the right notification callbacks + // We only expect two failed tries in this test, but only one + // of the would have had willRetry = true + require.Equal(t, failureMethodNumCalls, 2) // this is the number of calls we counted + require.Equal(t, failureWillRetryCount, 1) // only the first failure was retried + require.Equal(t, failureLastReportedFailureCount, int32(2)) // this is the number of failures reported by the notification method + require.Error(t, failureLastReportedError) +} + +// Test boundary case when Count equals to 0 and fail. +func TestRetryReaderReadCount0(t *testing.T) { + byteCount := 1 + body := newPerByteReader(byteCount) + body.doInjectError = true + body.doInjectErrorByteIndex = 1 + body.doInjectTimes = 1 + body.injectedError = &net.DNSError{IsTemporary: true} + + startResponseBody := body + + getter := func(ctx context.Context, info httpGetterInfo) (io.ReadCloser, error) { + r := http.Response{} + body.currentByteIndex = int(info.Range.Offset) + r.Body = body + + return r.Body, nil + } + + httpGetterInfo := httpGetterInfo{ + Range: &HTTPRange{ + Count: int64(byteCount), + }, + } + + retryReader := newRetryReader(context.Background(), startResponseBody, httpGetterInfo, getter, RetryReaderOptions{MaxRetries: 1}) + + // should consume the only byte + can := make([]byte, 1) + n, err := retryReader.Read(can) + require.Equal(t, n, 1) + require.NoError(t, err) + + // should not read when Count=0, and should return EOF + n, err = retryReader.Read(can) + require.Equal(t, n, 0) + require.Equal(t, err, io.EOF) +} + +func TestRetryReaderReadNegativeNonRetriableError(t *testing.T) { + byteCount := 1 + body := newPerByteReader(byteCount) + body.doInjectError = true + body.doInjectErrorByteIndex = 0 + body.doInjectTimes = 1 + body.injectedError = fmt.Errorf("not retriable error") + + startResponseBody := body + + getter := func(ctx context.Context, info httpGetterInfo) (io.ReadCloser, error) { + r := http.Response{} + body.currentByteIndex = int(info.Range.Offset) + r.Body = body + + return r.Body, nil + } + + httpGetterInfo := httpGetterInfo{ + Range: &HTTPRange{ + Count: int64(byteCount), + }, + } + + retryReader := newRetryReader(context.Background(), startResponseBody, httpGetterInfo, getter, RetryReaderOptions{MaxRetries: 2}) + + dest := make([]byte, 1) + _, err := retryReader.Read(dest) + require.Equal(t, err, body.injectedError) +} + +// Test the case where we programmatically force a retry to happen, via closing the body early from another goroutine +// Unlike the retries orchestrated elsewhere in this test file, which simulate network failures for the +// purposes of unit testing, here we are testing the cancellation mechanism that is exposed to +// consumers of the API, to allow programmatic forcing of retries (e.g. if the consumer deems +// the read to be taking too long, they may force a retry in the hope of better performance next time). +func TestRetryReaderReadWithForcedRetry(t *testing.T) { + for _, enableRetryOnEarlyClose := range []bool{false, true} { + + // use the notification callback, so we know that the retry really did happen + failureMethodNumCalls := 0 + failureMethod := func(failureCount int32, lastError error, rnge HTTPRange, willRetry bool) { + failureMethodNumCalls++ + } + + // Main test setup + byteCount := 10 // so multiple passes through read loop will be required + sleepDuration := 100 * time.Millisecond + randBytes := make([]byte, byteCount) + _, _ = rand.Read(randBytes) + getter := func(ctx context.Context, info httpGetterInfo) (io.ReadCloser, error) { + body := newSingleUsePerByteReader(randBytes) // make new one every time, since we force closes in this test, and it is unusable after a close + body.sleepDuration = sleepDuration + r := http.Response{} + body.currentByteIndex = int(info.Range.Offset) + r.Body = body + + return r.Body, nil + } + + httpGetterInfo := httpGetterInfo{ + Range: &HTTPRange{ + Count: int64(byteCount), + }, + } + initResponse, err := getter(context.Background(), httpGetterInfo) + require.NoError(t, err) + + rrOptions := RetryReaderOptions{MaxRetries: 2, EarlyCloseAsError: !enableRetryOnEarlyClose} + rrOptions.OnFailedRead = failureMethod + retryReader := newRetryReader(context.Background(), initResponse, httpGetterInfo, getter, rrOptions) + + // set up timed cancellation from separate goroutine + go func() { + time.Sleep(sleepDuration * 5) + err := retryReader.Close() + if err != nil { + return + } + }() + + // do the read (should fail, due to forced cancellation, and succeed through retry) + output := make([]byte, byteCount) + n, err := io.ReadFull(retryReader, output) + if enableRetryOnEarlyClose { + require.Equal(t, n, byteCount) + require.NoError(t, err) + require.EqualValues(t, output, randBytes) + require.Equal(t, failureMethodNumCalls, 1) // assert that the cancellation did indeed happen + } else { + require.Error(t, err) + } + } +} diff --git a/sdk/storage/azdatalake/filesystem/client.go b/sdk/storage/azdatalake/filesystem/client.go index b42803edb8cf..40dc0768aaad 100644 --- a/sdk/storage/azdatalake/filesystem/client.go +++ b/sdk/storage/azdatalake/filesystem/client.go @@ -47,7 +47,7 @@ func NewClient(filesystemURL string, cred azcore.TokenCredential, options *Clien } base.SetPipelineOptions((*base.ClientOptions)(conOptions), &plOpts) - azClient, err := azcore.NewClient(shared.FilesystemClient, exported.ModuleVersion, plOpts, &conOptions.ClientOptions) + azClient, err := azcore.NewClient(shared.FileSystemClient, exported.ModuleVersion, plOpts, &conOptions.ClientOptions) if err != nil { return nil, err } @@ -59,7 +59,7 @@ func NewClient(filesystemURL string, cred azcore.TokenCredential, options *Clien ClientOptions: options.ClientOptions, } blobContainerClient, _ := container.NewClient(containerURL, cred, &containerClientOpts) - fsClient := base.NewFilesystemClient(filesystemURL, containerURL, blobContainerClient, azClient, nil, &cred, (*base.ClientOptions)(conOptions)) + fsClient := base.NewFileSystemClient(filesystemURL, containerURL, blobContainerClient, azClient, nil, &cred, (*base.ClientOptions)(conOptions)) return (*Client)(fsClient), nil } @@ -74,7 +74,7 @@ func NewClientWithNoCredential(filesystemURL string, options *ClientOptions) (*C plOpts := runtime.PipelineOptions{} base.SetPipelineOptions((*base.ClientOptions)(conOptions), &plOpts) - azClient, err := azcore.NewClient(shared.FilesystemClient, exported.ModuleVersion, plOpts, &conOptions.ClientOptions) + azClient, err := azcore.NewClient(shared.FileSystemClient, exported.ModuleVersion, plOpts, &conOptions.ClientOptions) if err != nil { return nil, err } @@ -86,7 +86,7 @@ func NewClientWithNoCredential(filesystemURL string, options *ClientOptions) (*C ClientOptions: options.ClientOptions, } blobContainerClient, _ := container.NewClientWithNoCredential(containerURL, &containerClientOpts) - fsClient := base.NewFilesystemClient(filesystemURL, containerURL, blobContainerClient, azClient, nil, nil, (*base.ClientOptions)(conOptions)) + fsClient := base.NewFileSystemClient(filesystemURL, containerURL, blobContainerClient, azClient, nil, nil, (*base.ClientOptions)(conOptions)) return (*Client)(fsClient), nil } @@ -104,7 +104,7 @@ func NewClientWithSharedKeyCredential(filesystemURL string, cred *SharedKeyCrede } base.SetPipelineOptions((*base.ClientOptions)(conOptions), &plOpts) - azClient, err := azcore.NewClient(shared.FilesystemClient, exported.ModuleVersion, plOpts, &conOptions.ClientOptions) + azClient, err := azcore.NewClient(shared.FileSystemClient, exported.ModuleVersion, plOpts, &conOptions.ClientOptions) if err != nil { return nil, err } @@ -115,12 +115,12 @@ func NewClientWithSharedKeyCredential(filesystemURL string, cred *SharedKeyCrede containerClientOpts := container.ClientOptions{ ClientOptions: options.ClientOptions, } - blobSharedKey, err := cred.ConvertToBlobSharedKey() + blobSharedKey, err := exported.ConvertToBlobSharedKey(cred) if err != nil { return nil, err } blobContainerClient, _ := container.NewClientWithSharedKeyCredential(containerURL, blobSharedKey, &containerClientOpts) - fsClient := base.NewFilesystemClient(filesystemURL, containerURL, blobContainerClient, azClient, cred, nil, (*base.ClientOptions)(conOptions)) + fsClient := base.NewFileSystemClient(filesystemURL, containerURL, blobContainerClient, azClient, cred, nil, (*base.ClientOptions)(conOptions)) return (*Client)(fsClient), nil } @@ -201,7 +201,7 @@ func (fs *Client) NewFileClient(filePath string) *file.Client { return (*file.Client)(base.NewPathClient(fileURL, blobURL, fs.containerClient().NewBlockBlobClient(filePath), fs.generatedFSClientWithDFS().InternalClient().WithClientName(shared.FileClient), fs.sharedKey(), fs.identityCredential(), fs.getClientOptions())) } -// Create creates a new filesystem under the specified account. (blob3). +// Create creates a new filesystem under the specified account. func (fs *Client) Create(ctx context.Context, options *CreateOptions) (CreateResponse, error) { opts := options.format() resp, err := fs.containerClient().Create(ctx, opts) @@ -209,7 +209,7 @@ func (fs *Client) Create(ctx context.Context, options *CreateOptions) (CreateRes return resp, err } -// Delete deletes the specified filesystem and any files or directories it contains. (blob3). +// Delete deletes the specified filesystem and any files or directories it contains. func (fs *Client) Delete(ctx context.Context, options *DeleteOptions) (DeleteResponse, error) { opts := options.format() resp, err := fs.containerClient().Delete(ctx, opts) @@ -217,17 +217,17 @@ func (fs *Client) Delete(ctx context.Context, options *DeleteOptions) (DeleteRes return resp, err } -// GetProperties returns all user-defined metadata, standard HTTP properties, and system properties for the filesystem. (blob3). +// GetProperties returns all user-defined metadata, standard HTTP properties, and system properties for the filesystem. func (fs *Client) GetProperties(ctx context.Context, options *GetPropertiesOptions) (GetPropertiesResponse, error) { opts := options.format() newResp := GetPropertiesResponse{} resp, err := fs.containerClient().GetProperties(ctx, opts) - formatFilesystemProperties(&newResp, &resp) + formatFileSystemProperties(&newResp, &resp) err = exported.ConvertToDFSError(err) return newResp, err } -// SetMetadata sets one or more user-defined name-value pairs for the specified filesystem. (blob3). +// SetMetadata sets one or more user-defined name-value pairs for the specified filesystem. func (fs *Client) SetMetadata(ctx context.Context, options *SetMetadataOptions) (SetMetadataResponse, error) { opts := options.format() resp, err := fs.containerClient().SetMetadata(ctx, opts) @@ -235,7 +235,7 @@ func (fs *Client) SetMetadata(ctx context.Context, options *SetMetadataOptions) return resp, err } -// SetAccessPolicy sets the permissions for the specified filesystem or the files and directories under it. (blob3). +// SetAccessPolicy sets the permissions for the specified filesystem or the files and directories under it. func (fs *Client) SetAccessPolicy(ctx context.Context, options *SetAccessPolicyOptions) (SetAccessPolicyResponse, error) { opts := options.format() resp, err := fs.containerClient().SetAccessPolicy(ctx, opts) @@ -243,7 +243,7 @@ func (fs *Client) SetAccessPolicy(ctx context.Context, options *SetAccessPolicyO return resp, err } -// GetAccessPolicy returns the permissions for the specified filesystem or the files and directories under it. (blob3). +// GetAccessPolicy returns the permissions for the specified filesystem or the files and directories under it. func (fs *Client) GetAccessPolicy(ctx context.Context, options *GetAccessPolicyOptions) (GetAccessPolicyResponse, error) { opts := options.format() newResp := GetAccessPolicyResponse{} @@ -255,7 +255,7 @@ func (fs *Client) GetAccessPolicy(ctx context.Context, options *GetAccessPolicyO // TODO: implement undelete path in fs client as well -// NewListPathsPager operation returns a pager of the shares under the specified account. (dfs1) +// NewListPathsPager operation returns a pager of the shares under the specified account. // For more information, see https://learn.microsoft.com/en-us/rest/api/storageservices/list-shares func (fs *Client) NewListPathsPager(recursive bool, options *ListPathsOptions) *runtime.Pager[ListPathsSegmentResponse] { listOptions := options.format() @@ -291,7 +291,7 @@ func (fs *Client) NewListPathsPager(recursive bool, options *ListPathsOptions) * }) } -// NewListDeletedPathsPager operation returns a pager of the shares under the specified account. (dfs op/blob2). +// NewListDeletedPathsPager operation returns a pager of the shares under the specified account. // For more information, see https://learn.microsoft.com/en-us/rest/api/storageservices/list-shares func (fs *Client) NewListDeletedPathsPager(options *ListDeletedPathsOptions) *runtime.Pager[ListDeletedPathsSegmentResponse] { listOptions := options.format() @@ -327,9 +327,9 @@ func (fs *Client) NewListDeletedPathsPager(options *ListDeletedPathsOptions) *ru }) } -// GetSASURL is a convenience method for generating a SAS token for the currently pointed at container. +// GetSASURL is a convenience method for generating a SAS token for the currently pointed at filesystem. // It can only be used if the credential supplied during creation was a SharedKeyCredential. -func (fs *Client) GetSASURL(permissions sas.FilesystemPermissions, expiry time.Time, o *GetSASURLOptions) (string, error) { +func (fs *Client) GetSASURL(permissions sas.FileSystemPermissions, expiry time.Time, o *GetSASURLOptions) (string, error) { if fs.sharedKey() == nil { return "", datalakeerror.MissingSharedKeyCredential } @@ -342,7 +342,7 @@ func (fs *Client) GetSASURL(permissions sas.FilesystemPermissions, expiry time.T qps, err := sas.DatalakeSignatureValues{ Version: sas.Version, Protocol: sas.ProtocolHTTPS, - FilesystemName: urlParts.FilesystemName, + FileSystemName: urlParts.FileSystemName, Permissions: permissions.String(), StartTime: st, ExpiryTime: expiry.UTC(), diff --git a/sdk/storage/azdatalake/filesystem/client_test.go b/sdk/storage/azdatalake/filesystem/client_test.go index 3cf5cae5ae0a..571bbce8055e 100644 --- a/sdk/storage/azdatalake/filesystem/client_test.go +++ b/sdk/storage/azdatalake/filesystem/client_test.go @@ -24,6 +24,8 @@ import ( "github.com/stretchr/testify/suite" ) +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) @@ -61,21 +63,21 @@ type UnrecordedTestSuite struct { suite.Suite } -func validateFilesystemDeleted(_require *require.Assertions, filesystemClient *filesystem.Client) { +func validateFileSystemDeleted(_require *require.Assertions, filesystemClient *filesystem.Client) { _, err := filesystemClient.GetAccessPolicy(context.Background(), nil) _require.NotNil(err) - testcommon.ValidateErrorCode(_require, err, datalakeerror.FilesystemNotFound) + testcommon.ValidateErrorCode(_require, err, datalakeerror.FileSystemNotFound) } func (s *RecordedTestSuite) TestCreateFilesystem() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + filesystemName := testcommon.GenerateFileSystemName(testName) + fsClient, err := testcommon.GetFileSystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) - defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) _, err = fsClient.Create(context.Background(), nil) _require.Nil(err) @@ -85,17 +87,17 @@ func (s *RecordedTestSuite) TestCreateFilesystemWithOptions() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) + filesystemName := testcommon.GenerateFileSystemName(testName) testStr := "hello" metadata := map[string]*string{"foo": &testStr, "bar": &testStr} - access := filesystem.Filesystem + access := filesystem.FileSystem opts := filesystem.CreateOptions{ Metadata: metadata, Access: &access, } - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + fsClient, err := testcommon.GetFileSystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) - defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) _, err = fsClient.Create(context.Background(), &opts) _require.Nil(err) @@ -103,14 +105,14 @@ func (s *RecordedTestSuite) TestCreateFilesystemWithOptions() { props, err := fsClient.GetProperties(context.Background(), nil) _require.NoError(err) _require.NotNil(props.Metadata) - _require.Equal(*props.PublicAccess, filesystem.Filesystem) + _require.Equal(*props.PublicAccess, filesystem.FileSystem) } func (s *RecordedTestSuite) TestCreateFilesystemWithFileAccess() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) + filesystemName := testcommon.GenerateFileSystemName(testName) testStr := "hello" metadata := map[string]*string{"foo": &testStr, "bar": &testStr} access := filesystem.File @@ -118,9 +120,9 @@ func (s *RecordedTestSuite) TestCreateFilesystemWithFileAccess() { Metadata: metadata, Access: &access, } - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + fsClient, err := testcommon.GetFileSystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) - defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) _, err = fsClient.Create(context.Background(), &opts) _require.Nil(err) @@ -134,16 +136,16 @@ func (s *RecordedTestSuite) TestCreateFilesystemEmptyMetadata() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) + filesystemName := testcommon.GenerateFileSystemName(testName) metadata := map[string]*string{"foo": nil, "bar": nil} - access := filesystem.Filesystem + access := filesystem.FileSystem opts := filesystem.CreateOptions{ Metadata: metadata, Access: &access, } - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + fsClient, err := testcommon.GetFileSystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) - defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) _, err = fsClient.Create(context.Background(), &opts) _require.Nil(err) @@ -151,14 +153,14 @@ func (s *RecordedTestSuite) TestCreateFilesystemEmptyMetadata() { props, err := fsClient.GetProperties(context.Background(), nil) _require.NoError(err) _require.Nil(props.Metadata) - _require.Equal(*props.PublicAccess, filesystem.Filesystem) + _require.Equal(*props.PublicAccess, filesystem.FileSystem) } func (s *RecordedTestSuite) TestFilesystemCreateInvalidName() { _require := require.New(s.T()) - fsClient, err := testcommon.GetFilesystemClient("foo bar", s.T(), testcommon.TestAccountDatalake, nil) + fsClient, err := testcommon.GetFileSystemClient("foo bar", s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) _, err = fsClient.Create(context.Background(), nil) @@ -170,27 +172,27 @@ func (s *RecordedTestSuite) TestFilesystemCreateNameCollision() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + filesystemName := testcommon.GenerateFileSystemName(testName) + fsClient, err := testcommon.GetFileSystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) - defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) _, err = fsClient.Create(context.Background(), nil) _require.Nil(err) _, err = fsClient.Create(context.Background(), nil) _require.NotNil(err) - testcommon.ValidateErrorCode(_require, err, datalakeerror.FilesystemAlreadyExists) + testcommon.ValidateErrorCode(_require, err, datalakeerror.FileSystemAlreadyExists) } func (s *RecordedTestSuite) TestFilesystemGetProperties() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + filesystemName := testcommon.GenerateFileSystemName(testName) + fsClient, err := testcommon.GetFileSystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) - defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) _, err = fsClient.Create(context.Background(), nil) _require.Nil(err) @@ -201,12 +203,61 @@ func (s *RecordedTestSuite) TestFilesystemGetProperties() { _require.Nil(resp.Metadata) } +func (s *RecordedTestSuite) TestFilesystemGetPropertiesWithEmptyOpts() { + _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) + + opts := &filesystem.GetPropertiesOptions{} + resp, err := fsClient.GetProperties(context.Background(), opts) + _require.Nil(err) + _require.NotNil(resp.ETag) + _require.Nil(resp.Metadata) +} + +func (s *RecordedTestSuite) TestFilesystemGetPropertiesWithLease() { + _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) + + fsLeaseClient, err := lease.NewFileSystemClient(fsClient, &lease.FileSystemClientOptions{LeaseID: proposedLeaseIDs[0]}) + _require.Nil(err) + _, err = fsLeaseClient.AcquireLease(context.Background(), int32(60), nil) + _require.Nil(err) + + opts := &filesystem.GetPropertiesOptions{LeaseAccessConditions: &filesystem.LeaseAccessConditions{ + LeaseID: fsLeaseClient.LeaseID(), + }} + + resp, err := fsClient.GetProperties(context.Background(), opts) + _require.Nil(err) + _require.NotNil(resp.ETag) + _require.Nil(resp.Metadata) + + _, err = fsLeaseClient.ReleaseLease(context.Background(), nil) + _require.Nil(err) +} + func (s *RecordedTestSuite) TestFilesystemDelete() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + filesystemName := testcommon.GenerateFileSystemName(testName) + fsClient, err := testcommon.GetFileSystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) _, err = fsClient.Create(context.Background(), nil) @@ -215,29 +266,29 @@ func (s *RecordedTestSuite) TestFilesystemDelete() { _, err = fsClient.Delete(context.Background(), nil) _require.Nil(err) - validateFilesystemDeleted(_require, fsClient) + validateFileSystemDeleted(_require, fsClient) } func (s *RecordedTestSuite) TestFilesystemDeleteNonExistent() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + filesystemName := testcommon.GenerateFileSystemName(testName) + fsClient, err := testcommon.GetFileSystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) _, err = fsClient.Delete(context.Background(), nil) _require.NotNil(err) - testcommon.ValidateErrorCode(_require, err, datalakeerror.FilesystemNotFound) + testcommon.ValidateErrorCode(_require, err, datalakeerror.FileSystemNotFound) } func (s *RecordedTestSuite) TestFilesystemDeleteIfModifiedSinceTrue() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + filesystemName := testcommon.GenerateFileSystemName(testName) + fsClient, err := testcommon.GetFileSystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) resp, err := fsClient.Create(context.Background(), nil) @@ -245,40 +296,40 @@ func (s *RecordedTestSuite) TestFilesystemDeleteIfModifiedSinceTrue() { currentTime := testcommon.GetRelativeTimeFromAnchor(resp.Date, -10) - deleteFilesystemOptions := filesystem.DeleteOptions{ + deleteFileSystemOptions := filesystem.DeleteOptions{ AccessConditions: &filesystem.AccessConditions{ ModifiedAccessConditions: &filesystem.ModifiedAccessConditions{ IfModifiedSince: ¤tTime, }, }, } - _, err = fsClient.Delete(context.Background(), &deleteFilesystemOptions) + _, err = fsClient.Delete(context.Background(), &deleteFileSystemOptions) _require.Nil(err) - validateFilesystemDeleted(_require, fsClient) + validateFileSystemDeleted(_require, fsClient) } func (s *RecordedTestSuite) TestFilesystemDeleteIfModifiedSinceFalse() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + filesystemName := testcommon.GenerateFileSystemName(testName) + fsClient, err := testcommon.GetFileSystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) resp, err := fsClient.Create(context.Background(), nil) _require.Nil(err) - defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) currentTime := testcommon.GetRelativeTimeFromAnchor(resp.Date, 10) - deleteFilesystemOptions := filesystem.DeleteOptions{ + deleteFileSystemOptions := filesystem.DeleteOptions{ AccessConditions: &filesystem.AccessConditions{ ModifiedAccessConditions: &filesystem.ModifiedAccessConditions{ IfModifiedSince: ¤tTime, }, }, } - _, err = fsClient.Delete(context.Background(), &deleteFilesystemOptions) + _, err = fsClient.Delete(context.Background(), &deleteFileSystemOptions) _require.NotNil(err) testcommon.ValidateErrorCode(_require, err, datalakeerror.ConditionNotMet) } @@ -287,8 +338,8 @@ func (s *RecordedTestSuite) TestFilesystemDeleteIfUnModifiedSinceTrue() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + filesystemName := testcommon.GenerateFileSystemName(testName) + fsClient, err := testcommon.GetFileSystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) resp, err := fsClient.Create(context.Background(), nil) @@ -296,41 +347,41 @@ func (s *RecordedTestSuite) TestFilesystemDeleteIfUnModifiedSinceTrue() { currentTime := testcommon.GetRelativeTimeFromAnchor(resp.Date, 10) - deleteFilesystemOptions := filesystem.DeleteOptions{ + deleteFileSystemOptions := filesystem.DeleteOptions{ AccessConditions: &filesystem.AccessConditions{ ModifiedAccessConditions: &filesystem.ModifiedAccessConditions{ IfUnmodifiedSince: ¤tTime, }, }, } - _, err = fsClient.Delete(context.Background(), &deleteFilesystemOptions) + _, err = fsClient.Delete(context.Background(), &deleteFileSystemOptions) _require.Nil(err) - validateFilesystemDeleted(_require, fsClient) + validateFileSystemDeleted(_require, fsClient) } func (s *RecordedTestSuite) TestFilesystemDeleteIfUnModifiedSinceFalse() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + filesystemName := testcommon.GenerateFileSystemName(testName) + fsClient, err := testcommon.GetFileSystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) resp, err := fsClient.Create(context.Background(), nil) _require.Nil(err) - defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) currentTime := testcommon.GetRelativeTimeFromAnchor(resp.Date, -10) - deleteFilesystemOptions := filesystem.DeleteOptions{ + deleteFileSystemOptions := filesystem.DeleteOptions{ AccessConditions: &filesystem.AccessConditions{ ModifiedAccessConditions: &filesystem.ModifiedAccessConditions{ IfUnmodifiedSince: ¤tTime, }, }, } - _, err = fsClient.Delete(context.Background(), &deleteFilesystemOptions) + _, err = fsClient.Delete(context.Background(), &deleteFileSystemOptions) _require.NotNil(err) testcommon.ValidateErrorCode(_require, err, datalakeerror.ConditionNotMet) @@ -340,13 +391,13 @@ func (s *RecordedTestSuite) TestFilesystemSetMetadataNonEmpty() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + filesystemName := testcommon.GenerateFileSystemName(testName) + fsClient, err := testcommon.GetFileSystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) _, err = fsClient.Create(context.Background(), nil) _require.Nil(err) - defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) opts := filesystem.SetMetadataOptions{ Metadata: testcommon.BasicMetadata, @@ -366,13 +417,13 @@ func (s *RecordedTestSuite) TestFilesystemSetMetadataEmpty() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + filesystemName := testcommon.GenerateFileSystemName(testName) + fsClient, err := testcommon.GetFileSystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) _, err = fsClient.Create(context.Background(), nil) _require.Nil(err) - defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) opts := filesystem.SetMetadataOptions{ Metadata: map[string]*string{}, @@ -390,13 +441,13 @@ func (s *RecordedTestSuite) TestFilesystemSetMetadataNil() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + filesystemName := testcommon.GenerateFileSystemName(testName) + fsClient, err := testcommon.GetFileSystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) _, err = fsClient.Create(context.Background(), nil) _require.Nil(err) - defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) _, err = fsClient.SetMetadata(context.Background(), nil) _require.Nil(err) @@ -410,13 +461,13 @@ func (s *RecordedTestSuite) TestFilesystemSetMetadataInvalidField() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + filesystemName := testcommon.GenerateFileSystemName(testName) + fsClient, err := testcommon.GetFileSystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) _, err = fsClient.Create(context.Background(), nil) _require.Nil(err) - defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) opts := filesystem.SetMetadataOptions{ Metadata: map[string]*string{"!nval!d Field!@#%": to.Ptr("value")}, @@ -430,27 +481,27 @@ func (s *RecordedTestSuite) TestFilesystemSetMetadataNonExistent() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + filesystemName := testcommon.GenerateFileSystemName(testName) + fsClient, err := testcommon.GetFileSystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) _, err = fsClient.SetMetadata(context.Background(), nil) _require.NotNil(err) - testcommon.ValidateErrorCode(_require, err, datalakeerror.FilesystemNotFound) + testcommon.ValidateErrorCode(_require, err, datalakeerror.FileSystemNotFound) } func (s *RecordedTestSuite) TestFilesystemSetEmptyAccessPolicy() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + filesystemName := testcommon.GenerateFileSystemName(testName) + fsClient, err := testcommon.GetFileSystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) _, err = fsClient.Create(context.Background(), nil) _require.Nil(err) - defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) _, err = fsClient.SetAccessPolicy(context.Background(), &filesystem.SetAccessPolicyOptions{}) _require.Nil(err) @@ -460,13 +511,13 @@ func (s *RecordedTestSuite) TestFilesystemSetNilAccessPolicy() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + filesystemName := testcommon.GenerateFileSystemName(testName) + fsClient, err := testcommon.GetFileSystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) _, err = fsClient.Create(context.Background(), nil) _require.Nil(err) - defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) _, err = fsClient.SetAccessPolicy(context.Background(), nil) _require.Nil(err) @@ -476,13 +527,13 @@ func (s *RecordedTestSuite) TestFilesystemSetAccessPolicy() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + filesystemName := testcommon.GenerateFileSystemName(testName) + fsClient, err := testcommon.GetFileSystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) _, err = fsClient.Create(context.Background(), nil) _require.Nil(err) - defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) start := time.Date(2020, 1, 1, 0, 0, 0, 0, time.UTC) expiration := time.Date(2024, 1, 1, 0, 0, 0, 0, time.UTC) @@ -499,7 +550,7 @@ func (s *RecordedTestSuite) TestFilesystemSetAccessPolicy() { }, ID: &id, }) - options := filesystem.SetAccessPolicyOptions{FilesystemACL: signedIdentifiers} + options := filesystem.SetAccessPolicyOptions{FileSystemACL: signedIdentifiers} _, err = fsClient.SetAccessPolicy(context.Background(), &options) _require.Nil(err) } @@ -508,13 +559,13 @@ func (s *RecordedTestSuite) TestFilesystemSetMultipleAccessPolicies() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + filesystemName := testcommon.GenerateFileSystemName(testName) + fsClient, err := testcommon.GetFileSystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) _, err = fsClient.Create(context.Background(), nil) _require.Nil(err) - defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) id := "empty" @@ -546,7 +597,7 @@ func (s *RecordedTestSuite) TestFilesystemSetMultipleAccessPolicies() { Permission: &permission3, }, }) - options := filesystem.SetAccessPolicyOptions{FilesystemACL: signedIdentifiers} + options := filesystem.SetAccessPolicyOptions{FileSystemACL: signedIdentifiers} _, err = fsClient.SetAccessPolicy(context.Background(), &options) _require.Nil(err) @@ -560,13 +611,13 @@ func (s *RecordedTestSuite) TestFilesystemSetNullAccessPolicy() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + filesystemName := testcommon.GenerateFileSystemName(testName) + fsClient, err := testcommon.GetFileSystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) _, err = fsClient.Create(context.Background(), nil) _require.Nil(err) - defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) id := "null" @@ -574,7 +625,7 @@ func (s *RecordedTestSuite) TestFilesystemSetNullAccessPolicy() { signedIdentifiers = append(signedIdentifiers, &filesystem.SignedIdentifier{ ID: &id, }) - options := filesystem.SetAccessPolicyOptions{FilesystemACL: signedIdentifiers} + options := filesystem.SetAccessPolicyOptions{FileSystemACL: signedIdentifiers} _, err = fsClient.SetAccessPolicy(context.Background(), &options) _require.Nil(err) @@ -587,13 +638,13 @@ func (s *RecordedTestSuite) TestFilesystemGetAccessPolicyWithEmptyOpts() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + filesystemName := testcommon.GenerateFileSystemName(testName) + fsClient, err := testcommon.GetFileSystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) _, err = fsClient.Create(context.Background(), nil) _require.Nil(err) - defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) id := "null" @@ -601,7 +652,7 @@ func (s *RecordedTestSuite) TestFilesystemGetAccessPolicyWithEmptyOpts() { signedIdentifiers = append(signedIdentifiers, &filesystem.SignedIdentifier{ ID: &id, }) - options := filesystem.SetAccessPolicyOptions{FilesystemACL: signedIdentifiers} + options := filesystem.SetAccessPolicyOptions{FileSystemACL: signedIdentifiers} _, err = fsClient.SetAccessPolicy(context.Background(), &options) _require.Nil(err) @@ -616,8 +667,8 @@ func (s *RecordedTestSuite) TestFilesystemGetAccessPolicyOnLeasedFilesystem() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + filesystemName := testcommon.GenerateFileSystemName(testName) + fsClient, err := testcommon.GetFileSystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) _, err = fsClient.Create(context.Background(), nil) @@ -625,7 +676,7 @@ func (s *RecordedTestSuite) TestFilesystemGetAccessPolicyOnLeasedFilesystem() { var proposedLeaseIDs = []*string{to.Ptr("c820a799-76d7-4ee2-6e15-546f19325c2c"), to.Ptr("326cc5e1-746e-4af8-4811-a50e6629a8ca")} - fsLeaseClient, err := lease.NewFilesystemClient(fsClient, &lease.FilesystemClientOptions{ + fsLeaseClient, err := lease.NewFileSystemClient(fsClient, &lease.FileSystemClientOptions{ LeaseID: proposedLeaseIDs[0], }) _require.Nil(err) @@ -636,7 +687,7 @@ func (s *RecordedTestSuite) TestFilesystemGetAccessPolicyOnLeasedFilesystem() { signedIdentifiers = append(signedIdentifiers, &filesystem.SignedIdentifier{ ID: &id, }) - options := filesystem.SetAccessPolicyOptions{FilesystemACL: signedIdentifiers} + options := filesystem.SetAccessPolicyOptions{FileSystemACL: signedIdentifiers} _, err = fsClient.SetAccessPolicy(context.Background(), &options) _require.Nil(err) @@ -668,13 +719,13 @@ func (s *RecordedTestSuite) TestFilesystemGetSetPermissionsMultiplePolicies() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + filesystemName := testcommon.GenerateFileSystemName(testName) + fsClient, err := testcommon.GetFileSystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) _, err = fsClient.Create(context.Background(), nil) _require.Nil(err) - defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) // Define the policies start, err := time.Parse(time.UnixDate, "Fri Jun 11 20:00:00 UTC 2021") @@ -700,7 +751,7 @@ func (s *RecordedTestSuite) TestFilesystemGetSetPermissionsMultiplePolicies() { }, }, } - options := filesystem.SetAccessPolicyOptions{FilesystemACL: permissions} + options := filesystem.SetAccessPolicyOptions{FileSystemACL: permissions} _, err = fsClient.SetAccessPolicy(context.Background(), &options) _require.Nil(err) @@ -714,8 +765,8 @@ func (s *RecordedTestSuite) TestFilesystemGetPermissionsPublicAccessNotNone() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + filesystemName := testcommon.GenerateFileSystemName(testName) + fsClient, err := testcommon.GetFileSystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) access := filesystem.File @@ -724,7 +775,7 @@ func (s *RecordedTestSuite) TestFilesystemGetPermissionsPublicAccessNotNone() { } _, err = fsClient.Create(context.Background(), &createContainerOptions) // We create the container explicitly so we can be sure the access policy is not empty _require.Nil(err) - defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) resp, err := fsClient.GetAccessPolicy(context.Background(), nil) @@ -738,13 +789,13 @@ func (s *RecordedTestSuite) TestFilesystemSetPermissionsPublicAccessTypeFile() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + filesystemName := testcommon.GenerateFileSystemName(testName) + fsClient, err := testcommon.GetFileSystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) _, err = fsClient.Create(context.Background(), nil) _require.Nil(err) - defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) setAccessPolicyOptions := filesystem.SetAccessPolicyOptions{ Access: to.Ptr(filesystem.File), } @@ -760,36 +811,36 @@ func (s *RecordedTestSuite) TestFilesystemSetPermissionsPublicAccessFilesystem() _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + filesystemName := testcommon.GenerateFileSystemName(testName) + fsClient, err := testcommon.GetFileSystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) _, err = fsClient.Create(context.Background(), nil) _require.Nil(err) - defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) setAccessPolicyOptions := filesystem.SetAccessPolicyOptions{ - Access: to.Ptr(filesystem.Filesystem), + Access: to.Ptr(filesystem.FileSystem), } _, err = fsClient.SetAccessPolicy(context.Background(), &setAccessPolicyOptions) _require.Nil(err) resp, err := fsClient.GetAccessPolicy(context.Background(), nil) _require.Nil(err) - _require.Equal(*resp.PublicAccess, filesystem.Filesystem) + _require.Equal(*resp.PublicAccess, filesystem.FileSystem) } func (s *RecordedTestSuite) TestFilesystemSetPermissionsACLMoreThanFive() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + filesystemName := testcommon.GenerateFileSystemName(testName) + fsClient, err := testcommon.GetFileSystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) _, err = fsClient.Create(context.Background(), nil) _require.Nil(err) - defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) start, err := time.Parse(time.UnixDate, "Fri Jun 11 20:00:00 UTC 2021") _require.Nil(err) @@ -813,7 +864,7 @@ func (s *RecordedTestSuite) TestFilesystemSetPermissionsACLMoreThanFive() { setAccessPolicyOptions := filesystem.SetAccessPolicyOptions{ Access: &access, } - setAccessPolicyOptions.FilesystemACL = permissions + setAccessPolicyOptions.FileSystemACL = permissions _, err = fsClient.SetAccessPolicy(context.Background(), &setAccessPolicyOptions) _require.NotNil(err) @@ -824,13 +875,13 @@ func (s *RecordedTestSuite) TestFilesystemSetPermissionsDeleteAndModifyACL() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + filesystemName := testcommon.GenerateFileSystemName(testName) + fsClient, err := testcommon.GetFileSystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) _, err = fsClient.Create(context.Background(), nil) _require.Nil(err) - defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) start, err := time.Parse(time.UnixDate, "Fri Jun 11 20:00:00 UTC 2021") _require.Nil(err) @@ -854,7 +905,7 @@ func (s *RecordedTestSuite) TestFilesystemSetPermissionsDeleteAndModifyACL() { setAccessPolicyOptions := filesystem.SetAccessPolicyOptions{ Access: &access, } - setAccessPolicyOptions.FilesystemACL = permissions + setAccessPolicyOptions.FileSystemACL = permissions _, err = fsClient.SetAccessPolicy(context.Background(), &setAccessPolicyOptions) _require.Nil(err) @@ -868,7 +919,7 @@ func (s *RecordedTestSuite) TestFilesystemSetPermissionsDeleteAndModifyACL() { setAccessPolicyOptions1 := filesystem.SetAccessPolicyOptions{ Access: &access, } - setAccessPolicyOptions1.FilesystemACL = permissions + setAccessPolicyOptions1.FileSystemACL = permissions _, err = fsClient.SetAccessPolicy(context.Background(), &setAccessPolicyOptions1) _require.Nil(err) @@ -882,13 +933,13 @@ func (s *RecordedTestSuite) TestFilesystemSetPermissionsDeleteAllPolicies() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + filesystemName := testcommon.GenerateFileSystemName(testName) + fsClient, err := testcommon.GetFileSystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) _, err = fsClient.Create(context.Background(), nil) _require.Nil(err) - defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) start, err := time.Parse(time.UnixDate, "Fri Jun 11 20:00:00 UTC 2021") _require.Nil(err) @@ -911,7 +962,7 @@ func (s *RecordedTestSuite) TestFilesystemSetPermissionsDeleteAllPolicies() { setAccessPolicyOptions := filesystem.SetAccessPolicyOptions{ Access: to.Ptr(filesystem.File), } - setAccessPolicyOptions.FilesystemACL = permissions + setAccessPolicyOptions.FileSystemACL = permissions _, err = fsClient.SetAccessPolicy(context.Background(), &setAccessPolicyOptions) _require.Nil(err) @@ -923,7 +974,7 @@ func (s *RecordedTestSuite) TestFilesystemSetPermissionsDeleteAllPolicies() { setAccessPolicyOptions = filesystem.SetAccessPolicyOptions{ Access: to.Ptr(filesystem.File), } - setAccessPolicyOptions.FilesystemACL = []*filesystem.SignedIdentifier{} + setAccessPolicyOptions.FileSystemACL = []*filesystem.SignedIdentifier{} _, err = fsClient.SetAccessPolicy(context.Background(), &setAccessPolicyOptions) _require.Nil(err) @@ -936,13 +987,13 @@ func (s *RecordedTestSuite) TestFilesystemSetPermissionsInvalidPolicyTimes() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + filesystemName := testcommon.GenerateFileSystemName(testName) + fsClient, err := testcommon.GetFileSystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) _, err = fsClient.Create(context.Background(), nil) _require.Nil(err) - defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) // Swap start and expiry expiry, err := time.Parse(time.UnixDate, "Fri Jun 11 20:00:00 UTC 2021") @@ -966,7 +1017,7 @@ func (s *RecordedTestSuite) TestFilesystemSetPermissionsInvalidPolicyTimes() { setAccessPolicyOptions := filesystem.SetAccessPolicyOptions{ Access: to.Ptr(filesystem.File), } - setAccessPolicyOptions.FilesystemACL = permissions + setAccessPolicyOptions.FileSystemACL = permissions _, err = fsClient.SetAccessPolicy(context.Background(), &setAccessPolicyOptions) _require.Nil(err) } @@ -975,13 +1026,13 @@ func (s *RecordedTestSuite) TestFilesystemSetPermissionsNilPolicySlice() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + filesystemName := testcommon.GenerateFileSystemName(testName) + fsClient, err := testcommon.GetFileSystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) _, err = fsClient.Create(context.Background(), nil) _require.Nil(err) - defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) _, err = fsClient.SetAccessPolicy(context.Background(), nil) _require.Nil(err) @@ -991,13 +1042,13 @@ func (s *RecordedTestSuite) TestFilesystemSetPermissionsSignedIdentifierTooLong( _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + filesystemName := testcommon.GenerateFileSystemName(testName) + fsClient, err := testcommon.GetFileSystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) _, err = fsClient.Create(context.Background(), nil) _require.Nil(err) - defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) id := "" for i := 0; i < 65; i++ { @@ -1022,7 +1073,7 @@ func (s *RecordedTestSuite) TestFilesystemSetPermissionsSignedIdentifierTooLong( setAccessPolicyOptions := filesystem.SetAccessPolicyOptions{ Access: to.Ptr(filesystem.File), } - setAccessPolicyOptions.FilesystemACL = permissions + setAccessPolicyOptions.FileSystemACL = permissions _, err = fsClient.SetAccessPolicy(context.Background(), &setAccessPolicyOptions) _require.NotNil(err) @@ -1033,13 +1084,13 @@ func (s *RecordedTestSuite) TestFilesystemSetPermissionsIfModifiedSinceTrue() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + filesystemName := testcommon.GenerateFileSystemName(testName) + fsClient, err := testcommon.GetFileSystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) resp, err := fsClient.Create(context.Background(), nil) _require.Nil(err) - defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) currentTime := testcommon.GetRelativeTimeFromAnchor(resp.Date, -10) @@ -1060,13 +1111,13 @@ func (s *RecordedTestSuite) TestFilesystemSetPermissionsIfModifiedSinceFalse() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + filesystemName := testcommon.GenerateFileSystemName(testName) + fsClient, err := testcommon.GetFileSystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) resp, err := fsClient.Create(context.Background(), nil) _require.Nil(err) - defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) currentTime := testcommon.GetRelativeTimeFromAnchor(resp.Date, 10) @@ -1085,13 +1136,13 @@ func (s *RecordedTestSuite) TestFilesystemSetPermissionsIfUnModifiedSinceTrue() _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + filesystemName := testcommon.GenerateFileSystemName(testName) + fsClient, err := testcommon.GetFileSystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) resp, err := fsClient.Create(context.Background(), nil) _require.Nil(err) - defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) currentTime := testcommon.GetRelativeTimeFromAnchor(resp.Date, 10) @@ -1112,13 +1163,13 @@ func (s *RecordedTestSuite) TestFilesystemSetPermissionsIfUnModifiedSinceFalse() _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + filesystemName := testcommon.GenerateFileSystemName(testName) + fsClient, err := testcommon.GetFileSystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) resp, err := fsClient.Create(context.Background(), nil) _require.Nil(err) - defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) currentTime := testcommon.GetRelativeTimeFromAnchor(resp.Date, -10) @@ -1137,13 +1188,13 @@ func (s *UnrecordedTestSuite) TestFilesystemSetAccessPoliciesInDifferentTimeForm _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + filesystemName := testcommon.GenerateFileSystemName(testName) + fsClient, err := testcommon.GetFileSystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) _, err = fsClient.Create(context.Background(), nil) _require.Nil(err) - defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) id := "timeInEST" permission := "rw" @@ -1187,7 +1238,7 @@ func (s *UnrecordedTestSuite) TestFilesystemSetAccessPoliciesInDifferentTimeForm Permission: &permission3, }, }) - options := filesystem.SetAccessPolicyOptions{FilesystemACL: signedIdentifiers} + options := filesystem.SetAccessPolicyOptions{FileSystemACL: signedIdentifiers} _, err = fsClient.SetAccessPolicy(context.Background(), &options) _require.Nil(err) @@ -1202,13 +1253,13 @@ func (s *RecordedTestSuite) TestFilesystemSetAccessPolicyWithNullId() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + filesystemName := testcommon.GenerateFileSystemName(testName) + fsClient, err := testcommon.GetFileSystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) _, err = fsClient.Create(context.Background(), nil) _require.Nil(err) - defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) signedIdentifiers := make([]*filesystem.SignedIdentifier, 0) signedIdentifiers = append(signedIdentifiers, &filesystem.SignedIdentifier{ @@ -1217,7 +1268,7 @@ func (s *RecordedTestSuite) TestFilesystemSetAccessPolicyWithNullId() { }, }) - options := filesystem.SetAccessPolicyOptions{FilesystemACL: signedIdentifiers} + options := filesystem.SetAccessPolicyOptions{FileSystemACL: signedIdentifiers} _, err = fsClient.SetAccessPolicy(context.Background(), &options) _require.NotNil(err) testcommon.ValidateErrorCode(_require, err, datalakeerror.InvalidXMLDocument) @@ -1227,20 +1278,20 @@ func (s *RecordedTestSuite) TestFilesystemSetAccessPolicyWithNullId() { _require.Len(resp1.SignedIdentifiers, 0) } -func (s *UnrecordedTestSuite) TestSASFilesystemClient() { +func (s *UnrecordedTestSuite) TestSASFileSystemClient() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + filesystemName := testcommon.GenerateFileSystemName(testName) + fsClient, err := testcommon.GetFileSystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) _, err = fsClient.Create(context.Background(), nil) _require.Nil(err) - defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) // Adding SAS and options - permissions := sas.FilesystemPermissions{ + permissions := sas.FileSystemPermissions{ Read: true, Add: true, Write: true, @@ -1262,10 +1313,10 @@ func (s *RecordedTestSuite) TestFilesystemListPathsWithRecursive() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + filesystemName := testcommon.GenerateFileSystemName(testName) + fsClient, err := testcommon.GetFileSystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) - defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) _, err = fsClient.Create(context.Background(), nil) _require.Nil(err) @@ -1288,6 +1339,45 @@ func (s *RecordedTestSuite) TestFilesystemListPathsWithRecursive() { resp, err := pager.NextPage(context.Background()) _require.Nil(err) _require.Equal(5, len(resp.Paths)) + _require.NotNil(resp.PathList.Paths[0].IsDirectory) + + if err != nil { + break + } + } +} + +func (s *RecordedTestSuite) TestFilesystemListPathsWithRecursiveNoPrefix() { + _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) + + client := fsClient.NewFileClient("file1") + _, err = client.Create(context.Background(), nil) + _require.Nil(err) + client = fsClient.NewFileClient("file2") + _, err = client.Create(context.Background(), nil) + _require.Nil(err) + dirClient := fsClient.NewDirectoryClient("dir1") + _, err = dirClient.Create(context.Background(), nil) + _require.Nil(err) + dirClient = fsClient.NewDirectoryClient("dir2") + _, err = dirClient.Create(context.Background(), nil) + _require.Nil(err) + + pager := fsClient.NewListPathsPager(true, nil) + for pager.More() { + resp, err := pager.NextPage(context.Background()) + _require.Nil(err) + _require.Equal(4, len(resp.Paths)) + _require.NotNil(resp.PathList.Paths[0].IsDirectory) if err != nil { break } @@ -1298,10 +1388,10 @@ func (s *RecordedTestSuite) TestFilesystemListPathsWithoutRecursive() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + filesystemName := testcommon.GenerateFileSystemName(testName) + fsClient, err := testcommon.GetFileSystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) - defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) _, err = fsClient.Create(context.Background(), nil) _require.Nil(err) @@ -1334,10 +1424,10 @@ func (s *RecordedTestSuite) TestFilesystemListPathsWithMaxResults() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + filesystemName := testcommon.GenerateFileSystemName(testName) + fsClient, err := testcommon.GetFileSystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) - defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) _, err = fsClient.Create(context.Background(), nil) _require.Nil(err) @@ -1376,10 +1466,10 @@ func (s *RecordedTestSuite) TestFilesystemListPathsWithPrefix() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + filesystemName := testcommon.GenerateFileSystemName(testName) + fsClient, err := testcommon.GetFileSystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) - defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) _, err = fsClient.Create(context.Background(), nil) _require.Nil(err) @@ -1415,10 +1505,10 @@ func (s *RecordedTestSuite) TestFilesystemListPathsWithContinuation() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + filesystemName := testcommon.GenerateFileSystemName(testName) + fsClient, err := testcommon.GetFileSystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) - defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) _, err = fsClient.Create(context.Background(), nil) _require.Nil(err) @@ -1460,10 +1550,10 @@ func (s *RecordedTestSuite) TestFilesystemListDeletedPaths() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + filesystemName := testcommon.GenerateFileSystemName(testName) + fsClient, err := testcommon.GetFileSystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) - defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) _, err = fsClient.Create(context.Background(), nil) _require.Nil(err) @@ -1498,10 +1588,10 @@ func (s *RecordedTestSuite) TestFilesystemListDeletedPathsWithMaxResults() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + filesystemName := testcommon.GenerateFileSystemName(testName) + fsClient, err := testcommon.GetFileSystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) - defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) _, err = fsClient.Create(context.Background(), nil) _require.Nil(err) @@ -1548,10 +1638,10 @@ func (s *RecordedTestSuite) TestFilesystemListDeletedPathsWithPrefix() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + filesystemName := testcommon.GenerateFileSystemName(testName) + fsClient, err := testcommon.GetFileSystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) - defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) _, err = fsClient.Create(context.Background(), nil) _require.Nil(err) @@ -1595,10 +1685,10 @@ func (s *RecordedTestSuite) TestFilesystemListDeletedPathsWithContinuation() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + filesystemName := testcommon.GenerateFileSystemName(testName) + fsClient, err := testcommon.GetFileSystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) - defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) _, err = fsClient.Create(context.Background(), nil) _require.Nil(err) @@ -1644,20 +1734,20 @@ func (s *RecordedTestSuite) TestFilesystemListDeletedPathsWithContinuation() { _require.Equal("", *resp.NextMarker) } -func (s *UnrecordedTestSuite) TestSASFilesystemCreateAndDeleteFile() { +func (s *UnrecordedTestSuite) TestSASFileSystemCreateAndDeleteFile() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + filesystemName := testcommon.GenerateFileSystemName(testName) + fsClient, err := testcommon.GetFileSystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) _, err = fsClient.Create(context.Background(), nil) _require.Nil(err) - defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) // Adding SAS and options - permissions := sas.FilesystemPermissions{ + permissions := sas.FileSystemPermissions{ Read: true, Add: true, Write: true, @@ -1682,20 +1772,20 @@ func (s *UnrecordedTestSuite) TestSASFilesystemCreateAndDeleteFile() { _require.Nil(err) } -func (s *UnrecordedTestSuite) TestSASFilesystemCreateAndDeleteDirectory() { +func (s *UnrecordedTestSuite) TestSASFileSystemCreateAndDeleteDirectory() { _require := require.New(s.T()) testName := s.T().Name() - filesystemName := testcommon.GenerateFilesystemName(testName) - fsClient, err := testcommon.GetFilesystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) + filesystemName := testcommon.GenerateFileSystemName(testName) + fsClient, err := testcommon.GetFileSystemClient(filesystemName, s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) _, err = fsClient.Create(context.Background(), nil) _require.Nil(err) - defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) // Adding SAS and options - permissions := sas.FilesystemPermissions{ + permissions := sas.FileSystemPermissions{ Read: true, Add: true, Write: true, diff --git a/sdk/storage/azdatalake/filesystem/constants.go b/sdk/storage/azdatalake/filesystem/constants.go index 1b2916076c46..037d182790e0 100644 --- a/sdk/storage/azdatalake/filesystem/constants.go +++ b/sdk/storage/azdatalake/filesystem/constants.go @@ -16,7 +16,7 @@ type PublicAccessType = azblob.PublicAccessType const ( File PublicAccessType = azblob.PublicAccessTypeBlob - Filesystem PublicAccessType = azblob.PublicAccessTypeContainer + FileSystem PublicAccessType = azblob.PublicAccessTypeContainer ) // StatusType defines values for StatusType diff --git a/sdk/storage/azdatalake/filesystem/examples_test.go b/sdk/storage/azdatalake/filesystem/examples_test.go new file mode 100644 index 000000000000..ad8e7b293c0f --- /dev/null +++ b/sdk/storage/azdatalake/filesystem/examples_test.go @@ -0,0 +1,330 @@ +//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 filesystem_test + +import ( + "bytes" + "context" + "fmt" + "io" + "log" + "net/http" + "os" + "strings" + "time" + + "github.com/Azure/azure-sdk-for-go/sdk/azcore/streaming" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/to" + "github.com/Azure/azure-sdk-for-go/sdk/azidentity" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/filesystem" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/sas" +) + +func handleError(err error) { + if err != nil { + log.Fatal(err.Error()) + } +} + +func Example_fs_NewClient() { + accountName, ok := os.LookupEnv("AZURE_STORAGE_ACCOUNT_NAME") + if !ok { + panic("AZURE_STORAGE_ACCOUNT_NAME could not be found") + } + fsName := "testfs" + fsURL := fmt.Sprintf("https://%s.dfs.core.windows.net/%s", accountName, fsName) + + cred, err := azidentity.NewDefaultAzureCredential(nil) + handleError(err) + + fsClient, err := filesystem.NewClient(fsURL, cred, nil) + handleError(err) + fmt.Println(fsClient.DFSURL()) +} + +func Example_fs_NewClientWithSharedKeyCredential() { + accountName, ok := os.LookupEnv("AZURE_STORAGE_ACCOUNT_NAME") + if !ok { + panic("AZURE_STORAGE_ACCOUNT_NAME could not be found") + } + accountKey, ok := os.LookupEnv("AZURE_STORAGE_ACCOUNT_KEY") + if !ok { + panic("AZURE_STORAGE_ACCOUNT_KEY could not be found") + } + fsName := "testfs" + fsURL := fmt.Sprintf("https://%s.dfs.core.windows.net/%s", accountName, fsName) + + cred, err := azdatalake.NewSharedKeyCredential(accountName, accountKey) + handleError(err) + fsClient, err := filesystem.NewClientWithSharedKeyCredential(fsURL, cred, nil) + handleError(err) + fmt.Println(fsClient.DFSURL()) +} + +func Example_fs_NewClientWithNoCredential() { + accountName, ok := os.LookupEnv("AZURE_STORAGE_ACCOUNT_NAME") + if !ok { + panic("AZURE_STORAGE_ACCOUNT_NAME could not be found") + } + sharedAccessSignature, ok := os.LookupEnv("AZURE_STORAGE_SHARED_ACCESS_SIGNATURE") + if !ok { + panic("AZURE_STORAGE_SHARED_ACCESS_SIGNATURE could not be found") + } + fsName := "testfs" + fsURL := fmt.Sprintf("https://%s.dfs.core.windows.net/%s?%s", accountName, fsName, sharedAccessSignature) + + fsClient, err := filesystem.NewClientWithNoCredential(fsURL, nil) + handleError(err) + fmt.Println(fsClient.DFSURL()) +} + +func Example_fs_NewClientFromConnectionString() { + // Your connection string can be obtained from the Azure Portal. + connectionString, ok := os.LookupEnv("AZURE_STORAGE_CONNECTION_STRING") + if !ok { + log.Fatal("the environment variable 'AZURE_STORAGE_CONNECTION_STRING' could not be found") + } + fsName := "testfs" + fsClient, err := filesystem.NewClientFromConnectionString(connectionString, fsName, nil) + handleError(err) + fmt.Println(fsClient.DFSURL()) +} + +func Example_fs_ClientNewFileClient() { + accountName, ok := os.LookupEnv("AZURE_STORAGE_ACCOUNT_NAME") + if !ok { + panic("AZURE_STORAGE_ACCOUNT_NAME could not be found") + } + fsName := "testfs" + fsURL := fmt.Sprintf("https://%s.dfs.core.windows.net/%s", accountName, fsName) + + cred, err := azidentity.NewDefaultAzureCredential(nil) + handleError(err) + + fsClient, err := filesystem.NewClient(fsURL, cred, nil) + handleError(err) + + fileClient := fsClient.NewFileClient("test_File") + handleError(err) + fmt.Println(fileClient.DFSURL()) +} + +func Example_fs_ClientCreate() { + accountName, ok := os.LookupEnv("AZURE_STORAGE_ACCOUNT_NAME") + if !ok { + panic("AZURE_STORAGE_ACCOUNT_NAME could not be found") + } + fsName := "testfs" + fsURL := fmt.Sprintf("https://%s.dfs.core.windows.net/%s", accountName, fsName) + + cred, err := azidentity.NewDefaultAzureCredential(nil) + handleError(err) + + fsClient, err := filesystem.NewClient(fsURL, cred, nil) + handleError(err) + + fsCreateResponse, err := fsClient.Create(context.TODO(), &filesystem.CreateOptions{ + Metadata: map[string]*string{"Foo": to.Ptr("Bar")}, + }) + handleError(err) + fmt.Println(fsCreateResponse) +} + +func Example_fs_ClientDelete() { + accountName, ok := os.LookupEnv("AZURE_STORAGE_ACCOUNT_NAME") + if !ok { + panic("AZURE_STORAGE_ACCOUNT_NAME could not be found") + } + fsName := "testfs" + fsURL := fmt.Sprintf("https://%s.dfs.core.windows.net/%s", accountName, fsName) + + cred, err := azidentity.NewDefaultAzureCredential(nil) + handleError(err) + + fsClient, err := filesystem.NewClient(fsURL, cred, nil) + handleError(err) + + fsDeleteResponse, err := fsClient.Delete(context.TODO(), nil) + handleError(err) + fmt.Println(fsDeleteResponse) +} + +func Example_fs_ClientListPaths() { + accountName, ok := os.LookupEnv("AZURE_STORAGE_ACCOUNT_NAME") + if !ok { + panic("AZURE_STORAGE_ACCOUNT_NAME could not be found") + } + fsName := "testfs" + fsURL := fmt.Sprintf("https://%s.dfs.core.windows.net/%s", accountName, fsName) + + cred, err := azidentity.NewDefaultAzureCredential(nil) + handleError(err) + + fsClient, err := filesystem.NewClient(fsURL, cred, nil) + handleError(err) + + pager := fsClient.NewListPathsPager(true, nil) + + for pager.More() { + resp, err := pager.NextPage(context.TODO()) + if err != nil { + log.Fatal(err) + } + for _, path := range resp.Paths { + fmt.Println(*path.Name) + } + } +} + +func Example_fs_ClientListDeletedPaths() { + accountName, ok := os.LookupEnv("AZURE_STORAGE_ACCOUNT_NAME") + if !ok { + panic("AZURE_STORAGE_ACCOUNT_NAME could not be found") + } + fsName := "testfs" + fsURL := fmt.Sprintf("https://%s.dfs.core.windows.net/%s", accountName, fsName) + + cred, err := azidentity.NewDefaultAzureCredential(nil) + handleError(err) + + fsClient, err := filesystem.NewClient(fsURL, cred, nil) + handleError(err) + + pager := fsClient.NewListDeletedPathsPager(nil) + + for pager.More() { + resp, err := pager.NextPage(context.TODO()) + if err != nil { + log.Fatal(err) + } + for _, path := range resp.Segment.PathItems { + fmt.Println(*path.Name) + } + } +} + +func Example_fs_ClientGetSASURL() { + accountName, ok := os.LookupEnv("AZURE_STORAGE_ACCOUNT_NAME") + if !ok { + panic("AZURE_STORAGE_ACCOUNT_NAME could not be found") + } + fsName := "testfs" + fsURL := fmt.Sprintf("https://%s.dfs.core.windows.net/%s", accountName, fsName) + + cred, err := azidentity.NewDefaultAzureCredential(nil) + handleError(err) + + fsClient, err := filesystem.NewClient(fsURL, cred, nil) + handleError(err) + + permission := sas.FileSystemPermissions{Read: true} + start := time.Now() + expiry := start.AddDate(1, 0, 0) + options := filesystem.GetSASURLOptions{StartTime: &start} + sasURL, err := fsClient.GetSASURL(permission, expiry, &options) + handleError(err) + _ = sasURL +} + +// This example shows how to manipulate a fs's permissions. +func Example_fs_ClientSetAccessPolicy() { + accountName, ok := os.LookupEnv("AZURE_STORAGE_ACCOUNT_NAME") + if !ok { + panic("AZURE_STORAGE_ACCOUNT_NAME could not be found") + } + fsName := "testfs" + fsURL := fmt.Sprintf("https://%s.dfs.core.windows.net/%s", accountName, fsName) + + cred, err := azidentity.NewDefaultAzureCredential(nil) + handleError(err) + + fsClient, err := filesystem.NewClient(fsURL, cred, nil) + handleError(err) + + // Create the fs + _, err = fsClient.Create(context.TODO(), nil) + handleError(err) + + // Upload a simple File. + fileClient := fsClient.NewFileClient("HelloWorld.txt") + handleError(err) + + err = fileClient.UploadStream(context.TODO(), streaming.NopCloser(strings.NewReader("Hello World!")), nil) + handleError(err) + + // Attempt to read the File + get, err := http.Get(fileClient.DFSURL()) + handleError(err) + if get.StatusCode == http.StatusNotFound { + // ChangeLease the File to be public access File + _, err := fsClient.SetAccessPolicy( + context.TODO(), + &filesystem.SetAccessPolicyOptions{ + Access: to.Ptr(filesystem.File), + }, + ) + if err != nil { + log.Fatal(err) + } + + // Now, this works + get, err = http.Get(fileClient.DFSURL()) + if err != nil { + log.Fatal(err) + } + var text bytes.Buffer + _, err = text.ReadFrom(get.Body) + if err != nil { + return + } + defer func(Body io.ReadCloser) { + _ = Body.Close() + }(get.Body) + + fmt.Println("Public access File data: ", text.String()) + } +} + +func Example_fs_ClientSetMetadata() { + accountName, ok := os.LookupEnv("AZURE_STORAGE_ACCOUNT_NAME") + if !ok { + panic("AZURE_STORAGE_ACCOUNT_NAME could not be found") + } + fsName := "testfs" + fsURL := fmt.Sprintf("https://%s.dfs.core.windows.net/%s", accountName, fsName) + + cred, err := azidentity.NewDefaultAzureCredential(nil) + handleError(err) + + fsClient, err := filesystem.NewClient(fsURL, cred, nil) + handleError(err) + + // Create a fs with some metadata, key names are converted to lowercase before being sent to the service. + // You should always use lowercase letters, especially when querying a map for a metadata key. + creatingApp, err := os.Executable() + handleError(err) + _, err = fsClient.Create(context.TODO(), &filesystem.CreateOptions{Metadata: map[string]*string{"author": to.Ptr("azFile"), "app": to.Ptr(creatingApp)}}) + handleError(err) + + // Query the fs's metadata + fsGetPropertiesResponse, err := fsClient.GetProperties(context.TODO(), nil) + handleError(err) + + if fsGetPropertiesResponse.Metadata == nil { + log.Fatal("metadata is empty!") + } + + for k, v := range fsGetPropertiesResponse.Metadata { + fmt.Printf("%s=%s\n", k, *v) + } + + // Update the metadata and write it back to the fs + fsGetPropertiesResponse.Metadata["author"] = to.Ptr("Mohit") + _, err = fsClient.SetMetadata(context.TODO(), &filesystem.SetMetadataOptions{Metadata: fsGetPropertiesResponse.Metadata}) + handleError(err) +} diff --git a/sdk/storage/azdatalake/filesystem/models.go b/sdk/storage/azdatalake/filesystem/models.go index 50944097d146..05c395fc20c3 100644 --- a/sdk/storage/azdatalake/filesystem/models.go +++ b/sdk/storage/azdatalake/filesystem/models.go @@ -13,13 +13,15 @@ import ( "time" ) -// SetAccessPolicyOptions provides set of configurations for Filesystem.SetAccessPolicy operation. +// SetAccessPolicyOptions provides set of configurations for FileSystem.SetAccessPolicy operation. type SetAccessPolicyOptions struct { - // Specifies whether data in the filesystem may be accessed publicly and the level of access. + // Access Specifies whether data in the filesystem may be accessed publicly and the level of access. // If this header is not included in the request, filesystem data is private to the account owner. - Access *PublicAccessType + Access *PublicAccessType + // AccessConditions identifies filesystem-specific access conditions which you optionally set. AccessConditions *AccessConditions - FilesystemACL []*SignedIdentifier + // FileSystemACL sets the access policy for the filesystem. + FileSystemACL []*SignedIdentifier } func (o *SetAccessPolicyOptions) format() *container.SetAccessPolicyOptions { @@ -29,19 +31,17 @@ func (o *SetAccessPolicyOptions) format() *container.SetAccessPolicyOptions { return &container.SetAccessPolicyOptions{ Access: o.Access, AccessConditions: exported.FormatContainerAccessConditions(o.AccessConditions), - ContainerACL: o.FilesystemACL, + ContainerACL: o.FileSystemACL, } } // CreateOptions contains the optional parameters for the Client.Create method. type CreateOptions struct { - // Specifies whether data in the filesystem may be accessed publicly and the level of access. + // Access specifies whether data in the filesystem may be accessed publicly and the level of access. Access *PublicAccessType - - // Optional. Specifies a user-defined name-value pair associated with the filesystem. + // Metadata specifies a user-defined name-value pair associated with the filesystem. Metadata map[string]*string - - // Optional. Specifies the encryption scope settings to set on the filesystem. + // CPKScopeInfo specifies the encryption scope settings to set on the filesystem. CPKScopeInfo *CPKScopeInfo } @@ -58,6 +58,7 @@ func (o *CreateOptions) format() *container.CreateOptions { // DeleteOptions contains the optional parameters for the Client.Delete method. type DeleteOptions struct { + // AccessConditions identifies filesystem-specific access conditions which you optionally set. AccessConditions *AccessConditions } @@ -70,8 +71,9 @@ func (o *DeleteOptions) format() *container.DeleteOptions { } } -// GetPropertiesOptions contains the optional parameters for the FilesystemClient.GetProperties method. +// GetPropertiesOptions contains the optional parameters for the FileSystemClient.GetProperties method. type GetPropertiesOptions struct { + // LeaseAccessConditions contains parameters to access leased filesystem. LeaseAccessConditions *LeaseAccessConditions } @@ -91,7 +93,9 @@ func (o *GetPropertiesOptions) format() *container.GetPropertiesOptions { // SetMetadataOptions contains the optional parameters for the Client.SetMetadata method. type SetMetadataOptions struct { - Metadata map[string]*string + // Metadata sets the metadata key-value pairs to set on the filesystem. + Metadata map[string]*string + // AccessConditions identifies filesystem-specific access conditions which you optionally set. AccessConditions *AccessConditions } @@ -109,6 +113,7 @@ func (o *SetMetadataOptions) format() *container.SetMetadataOptions { // GetAccessPolicyOptions contains the optional parameters for the Client.GetAccessPolicy method. type GetAccessPolicyOptions struct { + // LeaseAccessConditions contains parameters to access leased filesystem. LeaseAccessConditions *LeaseAccessConditions } @@ -126,12 +131,16 @@ func (o *GetAccessPolicyOptions) format() *container.GetAccessPolicyOptions { } } -// ListPathsOptions contains the optional parameters for the Filesystem.ListPaths operation. +// ListPathsOptions contains the optional parameters for the FileSystem.ListPaths operation. type ListPathsOptions struct { - Marker *string + // Marker contains last continuation token returned from the service for listing. + Marker *string + // MaxResults sets the maximum number of paths that will be returned per page. MaxResults *int32 - Prefix *string - Upn *bool + // Prefix filters the results to return only paths whose names begin with the specified prefix path. + Prefix *string + // UPN is the user principal name. + UPN *bool } func (o *ListPathsOptions) format() generated.FileSystemClientListPathsOptions { @@ -143,15 +152,18 @@ func (o *ListPathsOptions) format() generated.FileSystemClientListPathsOptions { Continuation: o.Marker, MaxResults: o.MaxResults, Path: o.Prefix, - Upn: o.Upn, + Upn: o.UPN, } } -// ListDeletedPathsOptions contains the optional parameters for the Filesystem.ListDeletedPaths operation. PLACEHOLDER +// ListDeletedPathsOptions contains the optional parameters for the FileSystem.ListDeletedPaths operation. type ListDeletedPathsOptions struct { - Marker *string + // Marker contains last continuation token returned from the service for listing. + Marker *string + // MaxResults sets the maximum number of paths that will be returned per page. MaxResults *int32 - Prefix *string + // Prefix filters the results to return only paths whose names begin with the specified prefix path. + Prefix *string } func (o *ListDeletedPathsOptions) format() generated.FileSystemClientListBlobHierarchySegmentOptions { @@ -169,6 +181,7 @@ func (o *ListDeletedPathsOptions) format() generated.FileSystemClientListBlobHie // GetSASURLOptions contains the optional parameters for the Client.GetSASURL method. type GetSASURLOptions struct { + // StartTime is the time after which the SAS will become valid. StartTime *time.Time } @@ -186,7 +199,7 @@ func (o *GetSASURLOptions) format() time.Time { return st } -//// UndeletePathOptions contains the optional parameters for the Filesystem.UndeletePath operation. +//// UndeletePathOptions contains the optional parameters for the FileSystem.UndeletePath operation. //type UndeletePathOptions struct { // // placeholder //} @@ -198,7 +211,7 @@ func (o *GetSASURLOptions) format() time.Time { // return &UndeletePathOptions{} //} -// CPKScopeInfo contains a group of parameters for the FilesystemClient.Create method. +// CPKScopeInfo contains a group of parameters for the FileSystemClient.Create method. type CPKScopeInfo = container.CPKScopeInfo // AccessPolicy - An Access policy. @@ -214,7 +227,7 @@ type SignedIdentifier = container.SignedIdentifier // SharedKeyCredential contains an account's name and its primary or secondary key. type SharedKeyCredential = exported.SharedKeyCredential -// AccessConditions identifies blob-specific access conditions which you optionally set. +// AccessConditions identifies filesystem-specific access conditions which you optionally set. type AccessConditions = exported.AccessConditions // LeaseAccessConditions contains optional parameters to access leased entity. @@ -229,11 +242,11 @@ type PathList = generated.PathList // Path contains the path properties from the ListPaths operation type Path = generated.Path -// PathItem contains the response from method FilesystemClient.ListBlobsHierarchySegment. +// PathItem contains the response from method FileSystemClient.ListPathsHierarchySegment. type PathItem = generated.PathItemInternal -// PathProperties contains the response from method FilesystemClient.ListBlobsHierarchySegment. +// PathProperties contains the response from method FileSystemClient.ListPathsHierarchySegment. type PathProperties = generated.PathPropertiesInternal -// PathPrefix contains the response from method FilesystemClient.ListBlobsHierarchySegment. +// PathPrefix contains the response from method FileSystemClient.ListPathsHierarchySegment. type PathPrefix = generated.PathPrefix diff --git a/sdk/storage/azdatalake/filesystem/responses.go b/sdk/storage/azdatalake/filesystem/responses.go index 5651a4a77a9c..15b97decc321 100644 --- a/sdk/storage/azdatalake/filesystem/responses.go +++ b/sdk/storage/azdatalake/filesystem/responses.go @@ -13,7 +13,7 @@ import ( "time" ) -// GetAccessPolicyResponse contains the response from method FilesystemClient.GetAccessPolicy. +// GetAccessPolicyResponse contains the response from method FileSystemClient.GetAccessPolicy. type GetAccessPolicyResponse struct { // PublicAccess contains the information returned from the x-ms-blob-public-access header response. PublicAccess *PublicAccessType @@ -52,7 +52,7 @@ func formatGetAccessPolicyResponse(r *GetAccessPolicyResponse, contResp *contain r.Version = contResp.Version } -// GetPropertiesResponse contains the response from method FilesystemClient.GetProperties. +// GetPropertiesResponse contains the response from method FileSystemClient.GetProperties. type GetPropertiesResponse struct { // BlobPublicAccess contains the information returned from the x-ms-blob-public-access header response. PublicAccess *PublicAccessType @@ -105,7 +105,7 @@ type GetPropertiesResponse struct { } // removes the blob prefix in access type -func formatFilesystemProperties(r *GetPropertiesResponse, contResp *container.GetPropertiesResponse) { +func formatFileSystemProperties(r *GetPropertiesResponse, contResp *container.GetPropertiesResponse) { r.PublicAccess = contResp.BlobPublicAccess r.ClientRequestID = contResp.ClientRequestID r.Date = contResp.Date @@ -124,29 +124,29 @@ func formatFilesystemProperties(r *GetPropertiesResponse, contResp *container.Ge r.Version = contResp.Version } -// CreateResponse contains the response from method FilesystemClient.Create. +// CreateResponse contains the response from method FileSystemClient.Create. type CreateResponse = container.CreateResponse -// DeleteResponse contains the response from method FilesystemClient.Delete. +// DeleteResponse contains the response from method FileSystemClient.Delete. type DeleteResponse = container.DeleteResponse -// SetMetadataResponse contains the response from method FilesystemClient.SetMetadata. +// SetMetadataResponse contains the response from method FileSystemClient.SetMetadata. type SetMetadataResponse = container.SetMetadataResponse -// SetAccessPolicyResponse contains the response from method FilesystemClient.SetAccessPolicy. +// SetAccessPolicyResponse contains the response from method FileSystemClient.SetAccessPolicy. type SetAccessPolicyResponse = container.SetAccessPolicyResponse -// ListPathsSegmentResponse contains the response from method FilesystemClient.ListPathsSegment. +// ListPathsSegmentResponse contains the response from method FileSystemClient.ListPathsSegment. type ListPathsSegmentResponse = generated.FileSystemClientListPathsResponse -// UndeletePathResponse contains the response from method FilesystemClient.UndeletePath. +// UndeletePathResponse contains the response from method FileSystemClient.UndeletePath. type UndeletePathResponse = generated.PathClientUndeleteResponse -// ListDeletedPathsSegmentResponse contains the response from method FilesystemClient.ListPathsSegment. +// ListDeletedPathsSegmentResponse contains the response from method FileSystemClient.ListPathsSegment. type ListDeletedPathsSegmentResponse = generated.FileSystemClientListPathHierarchySegmentResponse -// ListPathsHierarchySegmentResponse contains the response from method FilesystemClient.ListBlobsHierarchySegment. +// ListPathsHierarchySegmentResponse contains the response from method FileSystemClient.ListPathsHierarchySegment. type ListPathsHierarchySegmentResponse = generated.ListPathsHierarchySegmentResponse -// PathHierarchyListSegment contains the response from method FilesystemClient.ListBlobsHierarchySegment. +// PathHierarchyListSegment contains the response from method FileSystemClient.ListPathsHierarchySegment. type PathHierarchyListSegment = generated.PathHierarchyListSegment diff --git a/sdk/storage/azdatalake/go.mod b/sdk/storage/azdatalake/go.mod index 17498bc501b5..e909b1dc0a62 100644 --- a/sdk/storage/azdatalake/go.mod +++ b/sdk/storage/azdatalake/go.mod @@ -4,16 +4,24 @@ go 1.18 require ( github.com/Azure/azure-sdk-for-go/sdk/azcore v1.7.0 + github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.1.0 github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0 github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.0.0 github.com/stretchr/testify v1.7.1 ) require ( + github.com/AzureAD/microsoft-authentication-library-for-go v0.5.1 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/dnaeon/go-vcr v1.1.0 // indirect + github.com/golang-jwt/jwt v3.2.1+incompatible // indirect + github.com/google/uuid v1.1.1 // indirect + github.com/kylelemons/godebug v1.1.0 // indirect + github.com/pkg/browser v0.0.0-20210115035449-ce105d075bb4 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect + golang.org/x/crypto v0.0.0-20220511200225-c6db032c6c88 // indirect golang.org/x/net v0.8.0 // indirect + golang.org/x/sys v0.6.0 // indirect golang.org/x/text v0.8.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect diff --git a/sdk/storage/azdatalake/go.sum b/sdk/storage/azdatalake/go.sum index 3482ec48d6a5..eafa822d8fa4 100644 --- a/sdk/storage/azdatalake/go.sum +++ b/sdk/storage/azdatalake/go.sum @@ -1,30 +1,41 @@ github.com/Azure/azure-sdk-for-go/sdk/azcore v1.7.0 h1:8q4SaHjFsClSvuVne0ID/5Ka8u3fcIHyqkLjcFpNRHQ= github.com/Azure/azure-sdk-for-go/sdk/azcore v1.7.0/go.mod h1:bjGvMhVMb+EEm3VRNQawDMUyMMjo+S5ewNjflkep/0Q= github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.1.0 h1:QkAcEIAKbNL4KoFr4SathZPhDhF4mVwpBMFlYjyAqy8= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.1.0/go.mod h1:bhXu1AjYL+wutSL/kpSq6s7733q2Rb0yuot9Zgfqa/0= github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0 h1:sXr+ck84g/ZlZUOZiNELInmMgOsuGwdjjVkEIde0OtY= github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0/go.mod h1:okt5dMMTOFjX/aovMlrjvvXoPMBVSPzk9185BT0+eZM= github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.0.0 h1:u/LLAOFgsMv7HmNL4Qufg58y+qElGOt5qv0z1mURkRY= github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.0.0/go.mod h1:2e8rMJtl2+2j+HXbTBwnyGpm5Nou7KhvSfxOq8JpTag= github.com/AzureAD/microsoft-authentication-library-for-go v0.5.1 h1:BWe8a+f/t+7KY7zH2mqygeUD0t8hNFXe08p1Pb3/jKE= +github.com/AzureAD/microsoft-authentication-library-for-go v0.5.1/go.mod h1:Vt9sXTKwMyGcOxSmLDMnGPgqsUg7m8pe215qMLrDXw4= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/dnaeon/go-vcr v1.1.0 h1:ReYa/UBrRyQdant9B4fNHGoCNKw6qh6P0fsdGmZpR7c= github.com/dnaeon/go-vcr v1.1.0/go.mod h1:M7tiix8f0r6mKKJ3Yq/kqU1OYf3MnfmBWVbPx/yU9ko= github.com/golang-jwt/jwt v3.2.1+incompatible h1:73Z+4BJcrTC+KczS6WvTPvRGOp1WmfEP4Q1lOd9Z/+c= +github.com/golang-jwt/jwt v3.2.1+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I= +github.com/golang-jwt/jwt/v4 v4.2.0 h1:besgBTC8w8HjP6NzQdxwKH9Z5oQMZ24ThTrHp3cZ8eU= github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY= +github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= +github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= github.com/modocache/gover v0.0.0-20171022184752-b58185e213c5/go.mod h1:caMODM3PzxT8aQXRPkAt8xlV/e7d7w8GM5g0fa5F0D8= +github.com/montanaflynn/stats v0.6.6/go.mod h1:etXPPgVO6n31NxCd9KQUMvCM+ve0ruNzt6R8Bnaayow= github.com/pkg/browser v0.0.0-20210115035449-ce105d075bb4 h1:Qj1ukM4GlMWXNdMBuXcXfz/Kw9s1qm0CLY32QxuSImI= +github.com/pkg/browser v0.0.0-20210115035449-ce105d075bb4/go.mod h1:N6UoU20jOqggOuDwUaBQpluzLNDqif3kq9z2wpdYEfQ= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= golang.org/x/crypto v0.0.0-20220511200225-c6db032c6c88 h1:Tgea0cVUD0ivh5ADBX4WwuI12DUd2to3nCYe2eayMIw= +golang.org/x/crypto v0.0.0-20220511200225-c6db032c6c88/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/net v0.8.0 h1:Zrh2ngAOFYneWTAIAPethzeaQLuHwhuBkuV6ZiRnUaQ= golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= +golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.6.0 h1:MVltZSvRTcU2ljQOhs94SXPftV6DCNnZViHeQps87pQ= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/text v0.8.0 h1:57P1ETyNKtuIjB4SRd15iJxuhj8Gc416Y78H3qgMh68= golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= diff --git a/sdk/storage/azdatalake/internal/base/clients.go b/sdk/storage/azdatalake/internal/base/clients.go index cc4af2b63e93..e5b9e2a300c5 100644 --- a/sdk/storage/azdatalake/internal/base/clients.go +++ b/sdk/storage/azdatalake/internal/base/clients.go @@ -55,10 +55,10 @@ func IdentityCredentialComposite[T, K, U any](client *CompositeClient[T, K, U]) return client.identityCred } -func NewFilesystemClient(fsURL string, fsURLWithBlobEndpoint string, client *container.Client, azClient *azcore.Client, sharedKey *exported.SharedKeyCredential, identityCred *azcore.TokenCredential, options *ClientOptions) *CompositeClient[generated.FileSystemClient, generated.FileSystemClient, container.Client] { +func NewFileSystemClient(fsURL string, fsURLWithBlobEndpoint string, client *container.Client, azClient *azcore.Client, sharedKey *exported.SharedKeyCredential, identityCred *azcore.TokenCredential, options *ClientOptions) *CompositeClient[generated.FileSystemClient, generated.FileSystemClient, container.Client] { return &CompositeClient[generated.FileSystemClient, generated.FileSystemClient, container.Client]{ - innerT: generated.NewFilesystemClient(fsURL, azClient), - innerK: generated.NewFilesystemClient(fsURLWithBlobEndpoint, azClient), + innerT: generated.NewFileSystemClient(fsURL, azClient), + innerK: generated.NewFileSystemClient(fsURLWithBlobEndpoint, azClient), sharedKey: sharedKey, identityCred: identityCred, innerU: client, diff --git a/sdk/storage/azdatalake/internal/exported/access_conditions.go b/sdk/storage/azdatalake/internal/exported/access_conditions.go index 624efc449132..e7b2a8ac7a3f 100644 --- a/sdk/storage/azdatalake/internal/exported/access_conditions.go +++ b/sdk/storage/azdatalake/internal/exported/access_conditions.go @@ -33,7 +33,7 @@ type ModifiedAccessConditions = generated.ModifiedAccessConditions // SourceModifiedAccessConditions contains a group of parameters for specifying access conditions of a source. type SourceModifiedAccessConditions = generated.SourceModifiedAccessConditions -// FormatContainerAccessConditions formats FilesystemAccessConditions into container's LeaseAccessConditions and ModifiedAccessConditions. +// FormatContainerAccessConditions formats FileSystemAccessConditions into container's LeaseAccessConditions and ModifiedAccessConditions. func FormatContainerAccessConditions(b *AccessConditions) *container.AccessConditions { if b == nil { return &container.AccessConditions{ diff --git a/sdk/storage/azdatalake/internal/exported/exported.go b/sdk/storage/azdatalake/internal/exported/exported.go index 0dea8e21223c..c6bbc6fe428d 100644 --- a/sdk/storage/azdatalake/internal/exported/exported.go +++ b/sdk/storage/azdatalake/internal/exported/exported.go @@ -45,7 +45,7 @@ func ConvertToDFSError(err error) error { responseErr.ErrorCode = strings.Replace(responseErr.ErrorCode, "blob", "path", -1) responseErr.ErrorCode = strings.Replace(responseErr.ErrorCode, "Blob", "Path", -1) responseErr.ErrorCode = strings.Replace(responseErr.ErrorCode, "container", "filesystem", -1) - responseErr.ErrorCode = strings.Replace(responseErr.ErrorCode, "Container", "Filesystem", -1) + responseErr.ErrorCode = strings.Replace(responseErr.ErrorCode, "Container", "FileSystem", -1) return responseErr } return err diff --git a/sdk/storage/azdatalake/internal/exported/shared_key_credential.go b/sdk/storage/azdatalake/internal/exported/shared_key_credential.go index d54cdc3a0b76..e75b29f0ad8b 100644 --- a/sdk/storage/azdatalake/internal/exported/shared_key_credential.go +++ b/sdk/storage/azdatalake/internal/exported/shared_key_credential.go @@ -49,7 +49,7 @@ func (c *SharedKeyCredential) AccountName() string { return c.accountName } -func (c *SharedKeyCredential) ConvertToBlobSharedKey() (*azblob.SharedKeyCredential, error) { +func ConvertToBlobSharedKey(c *SharedKeyCredential) (*azblob.SharedKeyCredential, error) { cred, err := azblob.NewSharedKeyCredential(c.accountName, c.accountKeyString) if err != nil { return nil, err diff --git a/sdk/storage/azdatalake/internal/exported/version.go b/sdk/storage/azdatalake/internal/exported/version.go index b570e4653d73..8fdb8eaff91d 100644 --- a/sdk/storage/azdatalake/internal/exported/version.go +++ b/sdk/storage/azdatalake/internal/exported/version.go @@ -8,5 +8,5 @@ package exported const ( ModuleName = "azdatalake" - ModuleVersion = "v0.1.0" + ModuleVersion = "v0.1.0-beta.1" ) diff --git a/sdk/storage/azdatalake/internal/generated/autorest.md b/sdk/storage/azdatalake/internal/generated/autorest.md index 56ce2831277a..edc674717865 100644 --- a/sdk/storage/azdatalake/internal/generated/autorest.md +++ b/sdk/storage/azdatalake/internal/generated/autorest.md @@ -22,7 +22,7 @@ export-clients: true use: "@autorest/go@4.0.0-preview.49" ``` -### Remove Filesystem and PathName from parameter list since they are not needed +### Remove FileSystem and PathName from parameter list since they are not needed ``` yaml directive: - from: swagger-document @@ -253,7 +253,7 @@ directive: transform: >- return $. replace(/PublicAccessTypeBlob/g, 'PublicAccessTypeFile'). - replace(/PublicAccessTypeContainer/g, 'PublicAccessTypeFilesystem'). + replace(/PublicAccessTypeContainer/g, 'PublicAccessTypeFileSystem'). replace(/FileSystemClientListBlobHierarchySegmentResponse/g, 'FileSystemClientListPathHierarchySegmentResponse'). replace(/ListBlobsHierarchySegmentResponse/g, 'ListPathsHierarchySegmentResponse'). replace(/ContainerName\s*\*string/g, 'FileSystemName *string'). @@ -266,13 +266,14 @@ directive: replace(/ContainerProperties/g, 'FileSystemProperties'); ``` -### TODO: FIX THE BELOW IN UNMARSHALASJSON -### Change path props to string +### ``` yaml directive: -- from: swagger-document - where: $.definitions.Path.properties - transform: > - $.isDirectory.type = "string"; - $.contentLength.type = "string"; +- from: + - zz_models_serde.go + where: $ + transform: >- + return $. + replace(/err = unpopulate\((.*), "ContentLength", &p\.ContentLength\)/g, 'var rawVal string\nerr = unpopulate(val, "ContentLength", &rawVal)\nintVal, _ := strconv.ParseInt(rawVal, 10, 64)\np.ContentLength = &intVal'). + replace(/err = unpopulate\((.*), "IsDirectory", &p\.IsDirectory\)/g, 'var rawVal string\nerr = unpopulate(val, "IsDirectory", &rawVal)\nboolVal, _ := strconv.ParseBool(rawVal)\np.IsDirectory = &boolVal'); ``` \ No newline at end of file diff --git a/sdk/storage/azdatalake/internal/generated/filesystem_client.go b/sdk/storage/azdatalake/internal/generated/filesystem_client.go index d35651c781b8..35c7c2e8e8a8 100644 --- a/sdk/storage/azdatalake/internal/generated/filesystem_client.go +++ b/sdk/storage/azdatalake/internal/generated/filesystem_client.go @@ -22,10 +22,10 @@ func (client *FileSystemClient) InternalClient() *azcore.Client { return client.internal } -// NewFilesystemClient creates a new instance of ServiceClient with the specified values. +// NewFileSystemClient creates a new instance of ServiceClient with the specified values. // - endpoint - The URL of the service account, share, directory or file that is the target of the desired operation. // - azClient - azcore.Client is a basic HTTP client. It consists of a pipeline and tracing provider. -func NewFilesystemClient(endpoint string, azClient *azcore.Client) *FileSystemClient { +func NewFileSystemClient(endpoint string, azClient *azcore.Client) *FileSystemClient { client := &FileSystemClient{ internal: azClient, endpoint: endpoint, diff --git a/sdk/storage/azdatalake/internal/generated/zz_models.go b/sdk/storage/azdatalake/internal/generated/zz_models.go index 64f0139f6536..6201c56fa6d4 100644 --- a/sdk/storage/azdatalake/internal/generated/zz_models.go +++ b/sdk/storage/azdatalake/internal/generated/zz_models.go @@ -260,7 +260,7 @@ type ModifiedAccessConditions struct { } type Path struct { - ContentLength *string + ContentLength *int64 CreationTime *string ETag *string @@ -268,7 +268,7 @@ type Path struct { EncryptionScope *string ExpiryTime *string Group *string - IsDirectory *string + IsDirectory *bool LastModified *string Name *string Owner *string diff --git a/sdk/storage/azdatalake/internal/generated/zz_models_serde.go b/sdk/storage/azdatalake/internal/generated/zz_models_serde.go index f118d2a055aa..cb66df1e8173 100644 --- a/sdk/storage/azdatalake/internal/generated/zz_models_serde.go +++ b/sdk/storage/azdatalake/internal/generated/zz_models_serde.go @@ -16,6 +16,7 @@ import ( "github.com/Azure/azure-sdk-for-go/sdk/azcore" "github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime" "reflect" + "strconv" "time" ) @@ -230,7 +231,10 @@ func (p *Path) UnmarshalJSON(data []byte) error { var err error switch key { case "contentLength": - err = unpopulate(val, "ContentLength", &p.ContentLength) + var rawVal string + err = unpopulate(val, "ContentLength", &rawVal) + intVal, _ := strconv.ParseInt(rawVal, 10, 64) + p.ContentLength = &intVal delete(rawMsg, key) case "creationTime": err = unpopulate(val, "CreationTime", &p.CreationTime) @@ -248,7 +252,10 @@ func (p *Path) UnmarshalJSON(data []byte) error { err = unpopulate(val, "Group", &p.Group) delete(rawMsg, key) case "isDirectory": - err = unpopulate(val, "IsDirectory", &p.IsDirectory) + var rawVal string + err = unpopulate(val, "IsDirectory", &rawVal) + boolVal, _ := strconv.ParseBool(rawVal) + p.IsDirectory = &boolVal delete(rawMsg, key) case "lastModified": err = unpopulate(val, "LastModified", &p.LastModified) diff --git a/sdk/storage/azdatalake/internal/generated_blob/autorest.md b/sdk/storage/azdatalake/internal/generated_blob/autorest.md index f0e08dcb686d..5905e9ac68ee 100644 --- a/sdk/storage/azdatalake/internal/generated_blob/autorest.md +++ b/sdk/storage/azdatalake/internal/generated_blob/autorest.md @@ -469,7 +469,7 @@ directive: replace(/PublicAccessTypeContainer/g, 'PublicAccessTypeFileSystem'). replace(/ContainerClientListBlobHierarchySegmentResponse/g, 'FileSystemClientListPathHierarchySegmentResponse'). replace(/ListBlobsHierarchySegmentResponse/g, 'ListPathsHierarchySegmentResponse'). - replace(/(^|[^"])ContainerName/g, '$1FilesystemName'). + replace(/(^|[^"])ContainerName/g, '$1FileSystemName'). replace(/BlobHierarchyListSegment/g, 'PathHierarchyListSegment'). replace(/BlobItems/g, 'PathItems'). replace(/BlobItem/g, 'PathItem'). diff --git a/sdk/storage/azdatalake/internal/generated_blob/zz_container_client.go b/sdk/storage/azdatalake/internal/generated_blob/zz_container_client.go index 778da1718b7c..3f34ec1a47c4 100644 --- a/sdk/storage/azdatalake/internal/generated_blob/zz_container_client.go +++ b/sdk/storage/azdatalake/internal/generated_blob/zz_container_client.go @@ -1001,10 +1001,10 @@ func (client *ContainerClient) releaseLeaseHandleResponse(resp *http.Response) ( // If the operation fails it returns an *azcore.ResponseError type. // // Generated from API version 2020-10-02 -// - sourceFilesystemName - Required. Specifies the name of the container to rename. +// - sourceFileSystemName - Required. Specifies the name of the container to rename. // - options - ContainerClientRenameOptions contains the optional parameters for the ContainerClient.Rename method. -func (client *ContainerClient) Rename(ctx context.Context, sourceFilesystemName string, options *ContainerClientRenameOptions) (ContainerClientRenameResponse, error) { - req, err := client.renameCreateRequest(ctx, sourceFilesystemName, options) +func (client *ContainerClient) Rename(ctx context.Context, sourceFileSystemName string, options *ContainerClientRenameOptions) (ContainerClientRenameResponse, error) { + req, err := client.renameCreateRequest(ctx, sourceFileSystemName, options) if err != nil { return ContainerClientRenameResponse{}, err } @@ -1019,7 +1019,7 @@ func (client *ContainerClient) Rename(ctx context.Context, sourceFilesystemName } // renameCreateRequest creates the Rename request. -func (client *ContainerClient) renameCreateRequest(ctx context.Context, sourceFilesystemName string, options *ContainerClientRenameOptions) (*policy.Request, error) { +func (client *ContainerClient) renameCreateRequest(ctx context.Context, sourceFileSystemName string, options *ContainerClientRenameOptions) (*policy.Request, error) { req, err := runtime.NewRequest(ctx, http.MethodPut, client.endpoint) if err != nil { return nil, err @@ -1035,7 +1035,7 @@ func (client *ContainerClient) renameCreateRequest(ctx context.Context, sourceFi if options != nil && options.RequestID != nil { req.Raw().Header["x-ms-client-request-id"] = []string{*options.RequestID} } - req.Raw().Header["x-ms-source-container-name"] = []string{sourceFilesystemName} + req.Raw().Header["x-ms-source-container-name"] = []string{sourceFileSystemName} if options != nil && options.SourceLeaseID != nil { req.Raw().Header["x-ms-source-lease-id"] = []string{*options.SourceLeaseID} } @@ -1189,8 +1189,8 @@ func (client *ContainerClient) restoreCreateRequest(ctx context.Context, options if options != nil && options.RequestID != nil { req.Raw().Header["x-ms-client-request-id"] = []string{*options.RequestID} } - if options != nil && options.DeletedFilesystemName != nil { - req.Raw().Header["x-ms-deleted-container-name"] = []string{*options.DeletedFilesystemName} + if options != nil && options.DeletedFileSystemName != nil { + req.Raw().Header["x-ms-deleted-container-name"] = []string{*options.DeletedFileSystemName} } if options != nil && options.DeletedContainerVersion != nil { req.Raw().Header["x-ms-deleted-container-version"] = []string{*options.DeletedContainerVersion} diff --git a/sdk/storage/azdatalake/internal/generated_blob/zz_models.go b/sdk/storage/azdatalake/internal/generated_blob/zz_models.go index d60fbd9ff1b3..c07e6bdb3b39 100644 --- a/sdk/storage/azdatalake/internal/generated_blob/zz_models.go +++ b/sdk/storage/azdatalake/internal/generated_blob/zz_models.go @@ -974,7 +974,7 @@ type ContainerClientRenewLeaseOptions struct { // ContainerClientRestoreOptions contains the optional parameters for the ContainerClient.Restore method. type ContainerClientRestoreOptions struct { // Optional. Version 2019-12-12 and later. Specifies the name of the deleted container to restore. - DeletedFilesystemName *string + DeletedFileSystemName *string // Optional. Version 2019-12-12 and later. Specifies the version of the deleted container to restore. DeletedContainerVersion *string // Provides a client-generated, opaque value with a 1 KB character limit that is recorded in the analytics logs when storage @@ -1137,7 +1137,7 @@ type DelimitedTextConfiguration struct { // FilterPathItem - Blob info from a Filter Blobs API call type FilterPathItem struct { // REQUIRED - FilesystemName *string `xml:"ContainerName"` + FileSystemName *string `xml:"ContainerName"` // REQUIRED Name *string `xml:"Name"` @@ -1194,7 +1194,7 @@ type LeaseAccessConditions struct { // ListBlobsFlatSegmentResponse - An enumeration of blobs type ListBlobsFlatSegmentResponse struct { // REQUIRED - FilesystemName *string `xml:"ContainerName,attr"` + FileSystemName *string `xml:"ContainerName,attr"` // REQUIRED Segment *BlobFlatListSegment `xml:"Blobs"` @@ -1210,7 +1210,7 @@ type ListBlobsFlatSegmentResponse struct { // ListPathsHierarchySegmentResponse - An enumeration of blobs type ListPathsHierarchySegmentResponse struct { // REQUIRED - FilesystemName *string `xml:"ContainerName,attr"` + FileSystemName *string `xml:"ContainerName,attr"` // REQUIRED Segment *PathHierarchyListSegment `xml:"Blobs"` diff --git a/sdk/storage/azdatalake/internal/path/models.go b/sdk/storage/azdatalake/internal/path/models.go index a66c7bfc448c..3a25acce5a27 100644 --- a/sdk/storage/azdatalake/internal/path/models.go +++ b/sdk/storage/azdatalake/internal/path/models.go @@ -15,9 +15,9 @@ import ( "time" ) -// DeleteOptions contains the optional parameters when calling the Delete operation. dfs endpoint +// DeleteOptions contains the optional parameters when calling the Delete operation. type DeleteOptions struct { - // AccessConditions contains parameters for accessing the file. + // AccessConditions contains parameters for accessing the path. AccessConditions *AccessConditions } @@ -36,7 +36,7 @@ func FormatDeleteOptions(o *DeleteOptions, recursive bool) (*generated.LeaseAcce type RenameOptions struct { // SourceAccessConditions identifies the source path access conditions. SourceAccessConditions *SourceAccessConditions - // AccessConditions contains parameters for accessing the file. + // AccessConditions contains parameters for accessing the path. AccessConditions *AccessConditions } @@ -68,7 +68,7 @@ func FormatRenameOptions(o *RenameOptions, path string) (*generated.LeaseAccessC return leaseAccessConditions, modifiedAccessConditions, nil, createOpts } -// GetPropertiesOptions contains the optional parameters for the Client.GetProperties method +// GetPropertiesOptions contains the optional parameters for the Client.GetProperties method. type GetPropertiesOptions struct { AccessConditions *AccessConditions CPKInfo *CPKInfo @@ -94,7 +94,7 @@ func FormatGetPropertiesOptions(o *GetPropertiesOptions) *blob.GetPropertiesOpti // ===================================== PATH IMPORTS =========================================== -// SetAccessControlOptions contains the optional parameters when calling the SetAccessControl operation. dfs endpoint +// SetAccessControlOptions contains the optional parameters when calling the SetAccessControl operation. type SetAccessControlOptions struct { // Owner is the owner of the path. Owner *string @@ -148,15 +148,19 @@ func FormatGetAccessControlOptions(o *GetAccessControlOptions) (*generated.PathC }, leaseAccessConditions, modifiedAccessConditions } -// CPKInfo contains a group of parameters for the PathClient.Download method. +// CPKInfo contains CPK related information. type CPKInfo struct { + // EncryptionAlgorithm is the algorithm used to encrypt the data. EncryptionAlgorithm *EncryptionAlgorithmType - EncryptionKey *string + // EncryptionKey is the base64 encoded encryption key. + EncryptionKey *string + // EncryptionKeySHA256 is the base64 encoded SHA256 of the encryption key. EncryptionKeySHA256 *string } // GetSASURLOptions contains the optional parameters for the Client.GetSASURL method. type GetSASURLOptions struct { + // StartTime is the start time for this SAS token. StartTime *time.Time } @@ -176,6 +180,7 @@ func FormatGetSASURLOptions(o *GetSASURLOptions) time.Time { // SetHTTPHeadersOptions contains the optional parameters for the Client.SetHTTPHeaders method. type SetHTTPHeadersOptions struct { + // AccessConditions contains parameters for accessing the path. AccessConditions *AccessConditions } @@ -199,19 +204,19 @@ func FormatSetHTTPHeadersOptions(o *SetHTTPHeadersOptions, httpHeaders HTTPHeade // HTTPHeaders contains the HTTP headers for path operations. type HTTPHeaders struct { - // Sets the path's cache control. If specified, this property is stored with the path and returned with a read request. + // CacheControl Sets the path's cache control. If specified, this property is stored with the path and returned with a read request. CacheControl *string - // Sets the path's Content-Disposition header. + // ContentDisposition Sets the path's Content-Disposition header. ContentDisposition *string - // Sets the path's content encoding. If specified, this property is stored with the blobpath and returned with a read + // ContentEncoding Sets the path's content encoding. If specified, this property is stored with the path and returned with a read // request. ContentEncoding *string - // Set the path's content language. If specified, this property is stored with the path and returned with a read + // ContentLanguage Set the path's content language. If specified, this property is stored with the path and returned with a read // request. ContentLanguage *string - // Specify the transactional md5 for the body, to be validated by the service. + // ContentMD5 Specify the transactional md5 for the body, to be validated by the service. ContentMD5 []byte - // Sets the path's content type. If specified, this property is stored with the path and returned with a read request. + // ContentType Sets the path's content type. If specified, this property is stored with the path and returned with a read request. ContentType *string } @@ -246,15 +251,17 @@ func FormatPathHTTPHeaders(o *HTTPHeaders) *generated.PathHTTPHeaders { // SetMetadataOptions provides set of configurations for Set Metadata on path operation type SetMetadataOptions struct { - Metadata map[string]*string + // AccessConditions contains parameters for accessing the path. AccessConditions *AccessConditions - CPKInfo *CPKInfo - CPKScopeInfo *CPKScopeInfo + // CPKInfo contains CPK related information. + CPKInfo *CPKInfo + // CPKScopeInfo specifies the encryption scope settings. + CPKScopeInfo *CPKScopeInfo } -func FormatSetMetadataOptions(o *SetMetadataOptions) (*blob.SetMetadataOptions, map[string]*string) { +func FormatSetMetadataOptions(o *SetMetadataOptions) *blob.SetMetadataOptions { if o == nil { - return nil, nil + return nil } accessConditions := exported.FormatBlobAccessConditions(o.AccessConditions) opts := &blob.SetMetadataOptions{ @@ -270,7 +277,7 @@ func FormatSetMetadataOptions(o *SetMetadataOptions) (*blob.SetMetadataOptions, if o.CPKScopeInfo != nil { opts.CPKScopeInfo = o.CPKScopeInfo } - return opts, o.Metadata + return opts } // ========================================= constants ========================================= diff --git a/sdk/storage/azdatalake/internal/path/responses.go b/sdk/storage/azdatalake/internal/path/responses.go index 1189ff02d693..1cf49ce01acf 100644 --- a/sdk/storage/azdatalake/internal/path/responses.go +++ b/sdk/storage/azdatalake/internal/path/responses.go @@ -32,6 +32,51 @@ type CreateResponse = generated.PathClientCreateResponse // DeleteResponse contains the response fields for the Delete operation. type DeleteResponse = generated.PathClientDeleteResponse +type RenameResponse struct { + // ContentLength contains the information returned from the Content-Length header response. + ContentLength *int64 + + // Continuation contains the information returned from the x-ms-continuation header response. + Continuation *string + + // Date contains the information returned from the Date header response. + Date *time.Time + + // ETag contains the information returned from the ETag header response. + ETag *azcore.ETag + + // EncryptionKeySHA256 contains the information returned from the x-ms-encryption-key-sha256 header response. + EncryptionKeySHA256 *string + + // IsServerEncrypted contains the information returned from the x-ms-request-server-encrypted header response. + IsServerEncrypted *bool + + // LastModified contains the information returned from the Last-Modified header response. + LastModified *time.Time + + // RequestID contains the information returned from the x-ms-request-id header response. + RequestID *string + + // Version contains the information returned from the x-ms-version header response. + Version *string +} + +// We need to do this now in case we add the new client to renamed response - we don't want to break the cx + +func FormatRenameResponse(createResp *CreateResponse) RenameResponse { + newResp := RenameResponse{} + newResp.ContentLength = createResp.ContentLength + newResp.Continuation = createResp.Continuation + newResp.Date = createResp.Date + newResp.ETag = createResp.ETag + newResp.EncryptionKeySHA256 = createResp.EncryptionKeySHA256 + newResp.IsServerEncrypted = createResp.IsServerEncrypted + newResp.LastModified = createResp.LastModified + newResp.RequestID = createResp.RequestID + newResp.Version = createResp.Version + return newResp +} + // removed BlobSequenceNumber, BlobCommittedBlockCount and BlobType headers from the original response: // GetPropertiesResponse contains the response fields for the GetProperties operation. diff --git a/sdk/storage/azdatalake/internal/shared/shared.go b/sdk/storage/azdatalake/internal/shared/shared.go index 0e54e94827df..f6ae4ea2fe66 100644 --- a/sdk/storage/azdatalake/internal/shared/shared.go +++ b/sdk/storage/azdatalake/internal/shared/shared.go @@ -26,7 +26,7 @@ const ( const ( ServiceClient = "azdatalake/service.Client" - FilesystemClient = "azdatalake/share.Client" + FileSystemClient = "azdatalake/filesystem.Client" DirectoryClient = "azdatalake/directory.Client" FileClient = "azdatalake/file.Client" ) diff --git a/sdk/storage/azdatalake/internal/testcommon/clients_auth.go b/sdk/storage/azdatalake/internal/testcommon/clients_auth.go index 6f93a8517585..acc034183de4 100644 --- a/sdk/storage/azdatalake/internal/testcommon/clients_auth.go +++ b/sdk/storage/azdatalake/internal/testcommon/clients_auth.go @@ -113,7 +113,7 @@ func GetServiceClient(t *testing.T, accountType TestAccountType, options *servic return serviceClient, err } -func GetFilesystemClient(fsName string, t *testing.T, accountType TestAccountType, options *filesystem.ClientOptions) (*filesystem.Client, error) { +func GetFileSystemClient(fsName string, t *testing.T, accountType TestAccountType, options *filesystem.ClientOptions) (*filesystem.Client, error) { if options == nil { options = &filesystem.ClientOptions{} } @@ -178,11 +178,11 @@ func GetDirClient(fsName, dirName string, t *testing.T, accountType TestAccountT return dirClient, err } -func ServiceGetFilesystemClient(filesystemName string, s *service.Client) *filesystem.Client { - return s.NewFilesystemClient(filesystemName) +func ServiceGetFileSystemClient(filesystemName string, s *service.Client) *filesystem.Client { + return s.NewFileSystemClient(filesystemName) } -func DeleteFilesystem(ctx context.Context, _require *require.Assertions, filesystemClient *filesystem.Client) { +func DeleteFileSystem(ctx context.Context, _require *require.Assertions, filesystemClient *filesystem.Client) { _, err := filesystemClient.Delete(ctx, nil) _require.Nil(err) } @@ -207,8 +207,8 @@ func GetGenericConnectionString(accountType TestAccountType) (*string, error) { return &connectionString, nil } -func CreateNewFilesystem(ctx context.Context, _require *require.Assertions, filesystemName string, serviceClient *service.Client) *filesystem.Client { - fsClient := ServiceGetFilesystemClient(filesystemName, serviceClient) +func CreateNewFileSystem(ctx context.Context, _require *require.Assertions, filesystemName string, serviceClient *service.Client) *filesystem.Client { + fsClient := ServiceGetFileSystemClient(filesystemName, serviceClient) _, err := fsClient.Create(ctx, nil) _require.Nil(err) diff --git a/sdk/storage/azdatalake/internal/testcommon/common.go b/sdk/storage/azdatalake/internal/testcommon/common.go index 4cc181b9b297..8c7fb0923b7f 100644 --- a/sdk/storage/azdatalake/internal/testcommon/common.go +++ b/sdk/storage/azdatalake/internal/testcommon/common.go @@ -22,15 +22,15 @@ import ( ) const ( - FilesystemPrefix = "gofs" + FileSystemPrefix = "gofs" FilePrefix = "gotestfile" DirPrefix = "gotestdir" DefaultData = "Godatalakedata" InvalidHeaderErrorSubstring = "invalid header field" // error thrown by the http client ) -func GenerateFilesystemName(testName string) string { - return FilesystemPrefix + GenerateEntityName(testName) +func GenerateFileSystemName(testName string) string { + return FileSystemPrefix + GenerateEntityName(testName) } func GenerateFileName(testName string) string { diff --git a/sdk/storage/azdatalake/lease/client.go b/sdk/storage/azdatalake/lease/client.go index d59dfcf1a7da..8e33db303761 100644 --- a/sdk/storage/azdatalake/lease/client.go +++ b/sdk/storage/azdatalake/lease/client.go @@ -16,39 +16,39 @@ import ( "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/internal/generated" ) -// FilesystemClient provides lease functionality for the underlying filesystem client. -type FilesystemClient struct { +// FileSystemClient provides lease functionality for the underlying filesystem client. +type FileSystemClient struct { containerClient *lease.ContainerClient leaseID *string } -// FilesystemClientOptions contains the optional values when creating a FilesystemClient. -type FilesystemClientOptions = lease.ContainerClientOptions +// FileSystemClientOptions contains the optional values when creating a FileSystemClient. +type FileSystemClientOptions = lease.ContainerClientOptions -// NewFilesystemClient creates a filesystem lease client for the provided filesystem client. +// NewFileSystemClient creates a filesystem lease client for the provided filesystem client. // - client - an instance of a filesystem client // - options - client options; pass nil to accept the default values -func NewFilesystemClient(client *filesystem.Client, options *FilesystemClientOptions) (*FilesystemClient, error) { +func NewFileSystemClient(client *filesystem.Client, options *FileSystemClientOptions) (*FileSystemClient, error) { _, _, containerClient := base.InnerClients((*base.CompositeClient[generated.FileSystemClient, generated.FileSystemClient, container.Client])(client)) containerLeaseClient, err := lease.NewContainerClient(containerClient, options) if err != nil { return nil, exported.ConvertToDFSError(err) } - return &FilesystemClient{ + return &FileSystemClient{ containerClient: containerLeaseClient, leaseID: containerLeaseClient.LeaseID(), }, nil } // LeaseID returns leaseID of the client. -func (c *FilesystemClient) LeaseID() *string { +func (c *FileSystemClient) LeaseID() *string { return c.leaseID } // AcquireLease acquires a lease on the filesystem for write and delete operations. // The lease Duration must be between 15 and 60 seconds, or infinite (-1). // For more information, see https://docs.microsoft.com/rest/api/storageservices/lease-blob. -func (c *FilesystemClient) AcquireLease(ctx context.Context, duration int32, o *FilesystemAcquireOptions) (FilesystemAcquireResponse, error) { +func (c *FileSystemClient) AcquireLease(ctx context.Context, duration int32, o *FileSystemAcquireOptions) (FileSystemAcquireResponse, error) { opts := o.format() resp, err := c.containerClient.AcquireLease(ctx, duration, opts) return resp, exported.ConvertToDFSError(err) @@ -57,7 +57,7 @@ func (c *FilesystemClient) AcquireLease(ctx context.Context, duration int32, o * // BreakLease breaks the filesystem's previously-acquired lease (if it exists). Pass the LeaseBreakDefault (-1) // constant to break a fixed-Duration lease when it expires or an infinite lease immediately. // For more information, see https://docs.microsoft.com/rest/api/storageservices/lease-blob. -func (c *FilesystemClient) BreakLease(ctx context.Context, o *FilesystemBreakOptions) (FilesystemBreakResponse, error) { +func (c *FileSystemClient) BreakLease(ctx context.Context, o *FileSystemBreakOptions) (FileSystemBreakResponse, error) { opts := o.format() resp, err := c.containerClient.BreakLease(ctx, opts) return resp, exported.ConvertToDFSError(err) @@ -65,7 +65,7 @@ func (c *FilesystemClient) BreakLease(ctx context.Context, o *FilesystemBreakOpt // ChangeLease changes the filesystem's lease ID. // For more information, see https://docs.microsoft.com/rest/api/storageservices/lease-blob. -func (c *FilesystemClient) ChangeLease(ctx context.Context, proposedLeaseID string, o *FilesystemChangeOptions) (FilesystemChangeResponse, error) { +func (c *FileSystemClient) ChangeLease(ctx context.Context, proposedLeaseID string, o *FileSystemChangeOptions) (FileSystemChangeResponse, error) { opts := o.format() resp, err := c.containerClient.ChangeLease(ctx, proposedLeaseID, opts) if err != nil { @@ -77,14 +77,14 @@ func (c *FilesystemClient) ChangeLease(ctx context.Context, proposedLeaseID stri // RenewLease renews the filesystem's previously-acquired lease. // For more information, see https://docs.microsoft.com/rest/api/storageservices/lease-blob. -func (c *FilesystemClient) RenewLease(ctx context.Context, o *FilesystemRenewOptions) (FilesystemRenewResponse, error) { +func (c *FileSystemClient) RenewLease(ctx context.Context, o *FileSystemRenewOptions) (FileSystemRenewResponse, error) { opts := o.format() resp, err := c.containerClient.RenewLease(ctx, opts) return resp, exported.ConvertToDFSError(err) } // ReleaseLease releases the filesystem's previously-acquired lease. -func (c *FilesystemClient) ReleaseLease(ctx context.Context, o *FilesystemReleaseOptions) (FilesystemReleaseResponse, error) { +func (c *FileSystemClient) ReleaseLease(ctx context.Context, o *FileSystemReleaseOptions) (FileSystemReleaseResponse, error) { opts := o.format() resp, err := c.containerClient.ReleaseLease(ctx, opts) return resp, exported.ConvertToDFSError(err) diff --git a/sdk/storage/azdatalake/lease/client_test.go b/sdk/storage/azdatalake/lease/client_test.go index 51f2183ea718..9095690f1d15 100644 --- a/sdk/storage/azdatalake/lease/client_test.go +++ b/sdk/storage/azdatalake/lease/client_test.go @@ -68,11 +68,11 @@ func (s *LeaseRecordedTestsSuite) TestFilesystemAcquireLease() { svcClient, err := testcommon.GetServiceClient(s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) - filesystemName := testcommon.GenerateFilesystemName(testName) - filesystemClient := testcommon.CreateNewFilesystem(context.Background(), _require, filesystemName, svcClient) - defer testcommon.DeleteFilesystem(context.Background(), _require, filesystemClient) + filesystemName := testcommon.GenerateFileSystemName(testName) + filesystemClient := testcommon.CreateNewFileSystem(context.Background(), _require, filesystemName, svcClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, filesystemClient) - filesystemLeaseClient, _ := lease.NewFilesystemClient(filesystemClient, &lease.FilesystemClientOptions{ + filesystemLeaseClient, _ := lease.NewFileSystemClient(filesystemClient, &lease.FileSystemClientOptions{ LeaseID: proposedLeaseIDs[0], }) @@ -93,11 +93,11 @@ func (s *LeaseRecordedTestsSuite) TestFilesystemDeleteFilesystemWithoutLeaseId() svcClient, err := testcommon.GetServiceClient(s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) - filesystemName := testcommon.GenerateFilesystemName(testName) - filesystemClient := testcommon.CreateNewFilesystem(context.Background(), _require, filesystemName, svcClient) - defer testcommon.DeleteFilesystem(context.Background(), _require, filesystemClient) + filesystemName := testcommon.GenerateFileSystemName(testName) + filesystemClient := testcommon.CreateNewFileSystem(context.Background(), _require, filesystemName, svcClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, filesystemClient) - filesystemLeaseClient, _ := lease.NewFilesystemClient(filesystemClient, &lease.FilesystemClientOptions{ + filesystemLeaseClient, _ := lease.NewFileSystemClient(filesystemClient, &lease.FileSystemClientOptions{ LeaseID: proposedLeaseIDs[0], }) @@ -130,11 +130,11 @@ func (s *LeaseRecordedTestsSuite) TestFilesystemReleaseLease() { svcClient, err := testcommon.GetServiceClient(s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) - filesystemName := testcommon.GenerateFilesystemName(testName) - filesystemClient := testcommon.CreateNewFilesystem(context.Background(), _require, filesystemName, svcClient) - defer testcommon.DeleteFilesystem(context.Background(), _require, filesystemClient) + filesystemName := testcommon.GenerateFileSystemName(testName) + filesystemClient := testcommon.CreateNewFileSystem(context.Background(), _require, filesystemName, svcClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, filesystemClient) - filesystemLeaseClient, _ := lease.NewFilesystemClient(filesystemClient, &lease.FilesystemClientOptions{ + filesystemLeaseClient, _ := lease.NewFileSystemClient(filesystemClient, &lease.FileSystemClientOptions{ LeaseID: proposedLeaseIDs[0], }) @@ -163,11 +163,11 @@ func (s *LeaseRecordedTestsSuite) TestFilesystemRenewLease() { svcClient, err := testcommon.GetServiceClient(s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) - filesystemName := testcommon.GenerateFilesystemName(testName) - filesystemClient := testcommon.CreateNewFilesystem(context.Background(), _require, filesystemName, svcClient) - defer testcommon.DeleteFilesystem(context.Background(), _require, filesystemClient) + filesystemName := testcommon.GenerateFileSystemName(testName) + filesystemClient := testcommon.CreateNewFileSystem(context.Background(), _require, filesystemName, svcClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, filesystemClient) - filesystemLeaseClient, _ := lease.NewFilesystemClient(filesystemClient, &lease.FilesystemClientOptions{ + filesystemLeaseClient, _ := lease.NewFileSystemClient(filesystemClient, &lease.FileSystemClientOptions{ LeaseID: proposedLeaseIDs[0], }) @@ -193,11 +193,11 @@ func (s *LeaseRecordedTestsSuite) TestFilesystemChangeLease() { svcClient, err := testcommon.GetServiceClient(s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) - fsName := testcommon.GenerateFilesystemName(testName) - fsClient := testcommon.CreateNewFilesystem(context.Background(), _require, fsName, svcClient) - defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + fsName := testcommon.GenerateFileSystemName(testName) + fsClient := testcommon.CreateNewFileSystem(context.Background(), _require, fsName, svcClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) - fsLeaseClient, _ := lease.NewFilesystemClient(fsClient, &lease.FilesystemClientOptions{ + fsLeaseClient, _ := lease.NewFileSystemClient(fsClient, &lease.FileSystemClientOptions{ LeaseID: proposedLeaseIDs[0], }) @@ -228,9 +228,9 @@ func (s *LeaseRecordedTestsSuite) TestFileAcquireLease() { svcClient, err := testcommon.GetServiceClient(s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) - filesystemName := testcommon.GenerateFilesystemName(testName) - filesystemClient := testcommon.CreateNewFilesystem(context.Background(), _require, filesystemName, svcClient) - defer testcommon.DeleteFilesystem(context.Background(), _require, filesystemClient) + filesystemName := testcommon.GenerateFileSystemName(testName) + filesystemClient := testcommon.CreateNewFileSystem(context.Background(), _require, filesystemName, svcClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, filesystemClient) fileName := testcommon.GenerateFileName(testName) fileClient := testcommon.CreateNewFile(context.Background(), _require, fileName, filesystemClient) @@ -258,9 +258,9 @@ func (s *LeaseRecordedTestsSuite) TestDeleteFileWithoutLeaseId() { svcClient, err := testcommon.GetServiceClient(s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) - filesystemName := testcommon.GenerateFilesystemName(testName) - filesystemClient := testcommon.CreateNewFilesystem(context.Background(), _require, filesystemName, svcClient) - defer testcommon.DeleteFilesystem(context.Background(), _require, filesystemClient) + filesystemName := testcommon.GenerateFileSystemName(testName) + filesystemClient := testcommon.CreateNewFileSystem(context.Background(), _require, filesystemName, svcClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, filesystemClient) fileName := testcommon.GenerateFileName(testName) fileClient := testcommon.CreateNewFile(context.Background(), _require, fileName, filesystemClient) @@ -298,9 +298,9 @@ func (s *LeaseRecordedTestsSuite) TestFileReleaseLease() { svcClient, err := testcommon.GetServiceClient(s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) - filesystemName := testcommon.GenerateFilesystemName(testName) - filesystemClient := testcommon.CreateNewFilesystem(context.Background(), _require, filesystemName, svcClient) - defer testcommon.DeleteFilesystem(context.Background(), _require, filesystemClient) + filesystemName := testcommon.GenerateFileSystemName(testName) + filesystemClient := testcommon.CreateNewFileSystem(context.Background(), _require, filesystemName, svcClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, filesystemClient) fileName := testcommon.GenerateFileName(testName) fileClient := testcommon.CreateNewFile(context.Background(), _require, fileName, filesystemClient) @@ -330,9 +330,9 @@ func (s *LeaseRecordedTestsSuite) TestFileRenewLease() { svcClient, err := testcommon.GetServiceClient(s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) - filesystemName := testcommon.GenerateFilesystemName(testName) - filesystemClient := testcommon.CreateNewFilesystem(context.Background(), _require, filesystemName, svcClient) - defer testcommon.DeleteFilesystem(context.Background(), _require, filesystemClient) + filesystemName := testcommon.GenerateFileSystemName(testName) + filesystemClient := testcommon.CreateNewFileSystem(context.Background(), _require, filesystemName, svcClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, filesystemClient) fileName := testcommon.GenerateFileName(testName) fileClient := testcommon.CreateNewFile(context.Background(), _require, fileName, filesystemClient) @@ -362,9 +362,9 @@ func (s *LeaseRecordedTestsSuite) TestFileChangeLease() { svcClient, err := testcommon.GetServiceClient(s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) - filesystemName := testcommon.GenerateFilesystemName(testName) - filesystemClient := testcommon.CreateNewFilesystem(context.Background(), _require, filesystemName, svcClient) - defer testcommon.DeleteFilesystem(context.Background(), _require, filesystemClient) + filesystemName := testcommon.GenerateFileSystemName(testName) + filesystemClient := testcommon.CreateNewFileSystem(context.Background(), _require, filesystemName, svcClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, filesystemClient) fileName := testcommon.GenerateFileName(testName) fileClient := testcommon.CreateNewFile(context.Background(), _require, fileName, filesystemClient) @@ -398,9 +398,9 @@ func (s *LeaseRecordedTestsSuite) TestDirAcquireLease() { svcClient, err := testcommon.GetServiceClient(s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) - filesystemName := testcommon.GenerateFilesystemName(testName) - filesystemClient := testcommon.CreateNewFilesystem(context.Background(), _require, filesystemName, svcClient) - defer testcommon.DeleteFilesystem(context.Background(), _require, filesystemClient) + filesystemName := testcommon.GenerateFileSystemName(testName) + filesystemClient := testcommon.CreateNewFileSystem(context.Background(), _require, filesystemName, svcClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, filesystemClient) dirName := testcommon.GenerateDirName(testName) dirClient := testcommon.CreateNewDir(context.Background(), _require, dirName, filesystemClient) @@ -428,9 +428,9 @@ func (s *LeaseRecordedTestsSuite) TestDeleteDirWithoutLeaseId() { svcClient, err := testcommon.GetServiceClient(s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) - filesystemName := testcommon.GenerateFilesystemName(testName) - filesystemClient := testcommon.CreateNewFilesystem(context.Background(), _require, filesystemName, svcClient) - defer testcommon.DeleteFilesystem(context.Background(), _require, filesystemClient) + filesystemName := testcommon.GenerateFileSystemName(testName) + filesystemClient := testcommon.CreateNewFileSystem(context.Background(), _require, filesystemName, svcClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, filesystemClient) dirName := testcommon.GenerateDirName(testName) dirClient := testcommon.CreateNewDir(context.Background(), _require, dirName, filesystemClient) @@ -468,9 +468,9 @@ func (s *LeaseRecordedTestsSuite) TestDirReleaseLease() { svcClient, err := testcommon.GetServiceClient(s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) - filesystemName := testcommon.GenerateFilesystemName(testName) - filesystemClient := testcommon.CreateNewFilesystem(context.Background(), _require, filesystemName, svcClient) - defer testcommon.DeleteFilesystem(context.Background(), _require, filesystemClient) + filesystemName := testcommon.GenerateFileSystemName(testName) + filesystemClient := testcommon.CreateNewFileSystem(context.Background(), _require, filesystemName, svcClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, filesystemClient) DirName := testcommon.GenerateDirName(testName) DirClient := testcommon.CreateNewDir(context.Background(), _require, DirName, filesystemClient) @@ -500,9 +500,9 @@ func (s *LeaseRecordedTestsSuite) TestDirRenewLease() { svcClient, err := testcommon.GetServiceClient(s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) - filesystemName := testcommon.GenerateFilesystemName(testName) - filesystemClient := testcommon.CreateNewFilesystem(context.Background(), _require, filesystemName, svcClient) - defer testcommon.DeleteFilesystem(context.Background(), _require, filesystemClient) + filesystemName := testcommon.GenerateFileSystemName(testName) + filesystemClient := testcommon.CreateNewFileSystem(context.Background(), _require, filesystemName, svcClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, filesystemClient) dirName := testcommon.GenerateDirName(testName) dirClient := testcommon.CreateNewDir(context.Background(), _require, dirName, filesystemClient) @@ -532,9 +532,9 @@ func (s *LeaseRecordedTestsSuite) TestDirChangeLease() { svcClient, err := testcommon.GetServiceClient(s.T(), testcommon.TestAccountDatalake, nil) _require.NoError(err) - filesystemName := testcommon.GenerateFilesystemName(testName) - filesystemClient := testcommon.CreateNewFilesystem(context.Background(), _require, filesystemName, svcClient) - defer testcommon.DeleteFilesystem(context.Background(), _require, filesystemClient) + filesystemName := testcommon.GenerateFileSystemName(testName) + filesystemClient := testcommon.CreateNewFileSystem(context.Background(), _require, filesystemName, svcClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, filesystemClient) dirName := testcommon.GenerateDirName(testName) dirClient := testcommon.CreateNewDir(context.Background(), _require, dirName, filesystemClient) diff --git a/sdk/storage/azdatalake/lease/examples_test.go b/sdk/storage/azdatalake/lease/examples_test.go new file mode 100644 index 000000000000..adc847cb3050 --- /dev/null +++ b/sdk/storage/azdatalake/lease/examples_test.go @@ -0,0 +1,92 @@ +//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 lease_test + +import ( + "context" + "fmt" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/filesystem" + "log" + "os" + + "github.com/Azure/azure-sdk-for-go/sdk/azcore/to" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/lease" +) + +func handleError(err error) { + if err != nil { + log.Fatal(err.Error()) + } +} + +// This example shows how to perform various lease operations on a filesystem. +// The same lease operations can be performed on individual files as well. +// A lease on a filesystem prevents it from being deleted by others, while a lease on a file +// protects it from both modifications and deletions. +func Example_lease_FileSystemClient_AcquireLease() { + // From the Azure portal, get your Storage account's name and account key. + accountName, accountKey := os.Getenv("AZURE_STORAGE_ACCOUNT_NAME"), os.Getenv("AZURE_STORAGE_ACCOUNT_KEY") + + // Use your Storage account's name and key to create a credential object; this is used to access your account. + credential, err := azdatalake.NewSharedKeyCredential(accountName, accountKey) + handleError(err) + + // Create an fsClient object that wraps the filesystem's URL and a default pipeline. + filesystemURL := fmt.Sprintf("https://%s.dfs.core.windows.net/myfs", accountName) + fsClient, err := filesystem.NewClientWithSharedKeyCredential(filesystemURL, credential, nil) + handleError(err) + + // Create a unique ID for the lease + // A lease ID can be any valid GUID string format. To generate UUIDs, consider the github.com/google/uuid package + leaseID := "36b1a876-cf98-4eb2-a5c3-6d68489658ff" + filesystemLeaseClient, err := lease.NewFileSystemClient(fsClient, + &lease.FileSystemClientOptions{LeaseID: to.Ptr(leaseID)}) + handleError(err) + + // Now acquire a lease on the filesystem. + // You can choose to pass an empty string for proposed ID so that the service automatically assigns one for you. + duration := int32(60) + acquireLeaseResponse, err := filesystemLeaseClient.AcquireLease(context.TODO(), duration, nil) + handleError(err) + fmt.Println("The filesystem is leased for delete operations with lease ID", *acquireLeaseResponse.LeaseID) + + // The filesystem cannot be deleted without providing the lease ID. + _, err = fsClient.Delete(context.TODO(), nil) + if err == nil { + log.Fatal("delete should have failed") + } + + fmt.Println("The filesystem cannot be deleted while there is an active lease") + + // We can release the lease now and the filesystem can be deleted. + _, err = filesystemLeaseClient.ReleaseLease(context.TODO(), nil) + handleError(err) + fmt.Println("The lease on the filesystem is now released") + + // AcquireLease a lease again to perform other operations. + // Duration is still 60 + acquireLeaseResponse, err = filesystemLeaseClient.AcquireLease(context.TODO(), duration, nil) + handleError(err) + fmt.Println("The filesystem is leased again with lease ID", *acquireLeaseResponse.LeaseID) + + // We can change the ID of an existing lease. + newLeaseID := "6b3e65e5-e1bb-4a3f-8b72-13e9bc9cd3bf" + changeLeaseResponse, err := filesystemLeaseClient.ChangeLease(context.TODO(), newLeaseID, nil) + handleError(err) + fmt.Println("The lease ID was changed to", *changeLeaseResponse.LeaseID) + + // The lease can be renewed. + renewLeaseResponse, err := filesystemLeaseClient.RenewLease(context.TODO(), nil) + handleError(err) + fmt.Println("The lease was renewed with the same ID", *renewLeaseResponse.LeaseID) + + // Finally, the lease can be broken, and we could prevent others from acquiring a lease for a period of time + _, err = filesystemLeaseClient.BreakLease(context.TODO(), &lease.FileSystemBreakOptions{BreakPeriod: to.Ptr(int32(60))}) + handleError(err) + fmt.Println("The lease was broken, and nobody can acquire a lease for 60 seconds") +} diff --git a/sdk/storage/azdatalake/lease/models.go b/sdk/storage/azdatalake/lease/models.go index ce552403c698..fced59eab55c 100644 --- a/sdk/storage/azdatalake/lease/models.go +++ b/sdk/storage/azdatalake/lease/models.go @@ -12,12 +12,13 @@ import ( "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/internal/exported" ) -// FilesystemAcquireOptions contains the optional parameters for the LeaseClient.AcquireLease method. -type FilesystemAcquireOptions struct { +// FileSystemAcquireOptions contains the optional parameters for the LeaseClient.AcquireLease method. +type FileSystemAcquireOptions struct { + // ModifiedAccessConditions contains optional parameters to access filesystem. ModifiedAccessConditions *ModifiedAccessConditions } -func (o *FilesystemAcquireOptions) format() *lease.ContainerAcquireOptions { +func (o *FileSystemAcquireOptions) format() *lease.ContainerAcquireOptions { if o == nil || o.ModifiedAccessConditions == nil { return nil } @@ -31,13 +32,15 @@ func (o *FilesystemAcquireOptions) format() *lease.ContainerAcquireOptions { } } -// FilesystemBreakOptions contains the optional parameters for the LeaseClient.BreakLease method. -type FilesystemBreakOptions struct { - BreakPeriod *int32 +// FileSystemBreakOptions contains the optional parameters for the LeaseClient.BreakLease method. +type FileSystemBreakOptions struct { + // BreakPeriod is the proposed duration of seconds that the lease should continue before it is broken. + BreakPeriod *int32 + // ModifiedAccessConditions contains optional parameters to access filesystem. ModifiedAccessConditions *ModifiedAccessConditions } -func (o *FilesystemBreakOptions) format() *lease.ContainerBreakOptions { +func (o *FileSystemBreakOptions) format() *lease.ContainerBreakOptions { opts := &lease.ContainerBreakOptions{} if o == nil { return opts @@ -57,12 +60,13 @@ func (o *FilesystemBreakOptions) format() *lease.ContainerBreakOptions { } } -// FilesystemChangeOptions contains the optional parameters for the LeaseClient.ChangeLease method. -type FilesystemChangeOptions struct { +// FileSystemChangeOptions contains the optional parameters for the LeaseClient.ChangeLease method. +type FileSystemChangeOptions struct { + // ModifiedAccessConditions contains optional parameters to access filesystem. ModifiedAccessConditions *ModifiedAccessConditions } -func (o *FilesystemChangeOptions) format() *lease.ContainerChangeOptions { +func (o *FileSystemChangeOptions) format() *lease.ContainerChangeOptions { if o == nil || o.ModifiedAccessConditions == nil { return nil } @@ -76,11 +80,13 @@ func (o *FilesystemChangeOptions) format() *lease.ContainerChangeOptions { } } -type FilesystemReleaseOptions struct { +// FileSystemReleaseOptions contains the optional parameters for the LeaseClient.ReleaseLease method. +type FileSystemReleaseOptions struct { + // ModifiedAccessConditions contains optional parameters to access filesystem. ModifiedAccessConditions *ModifiedAccessConditions } -func (o *FilesystemReleaseOptions) format() *lease.ContainerReleaseOptions { +func (o *FileSystemReleaseOptions) format() *lease.ContainerReleaseOptions { if o == nil || o.ModifiedAccessConditions == nil { return nil } @@ -94,11 +100,13 @@ func (o *FilesystemReleaseOptions) format() *lease.ContainerReleaseOptions { } } -type FilesystemRenewOptions struct { +// FileSystemRenewOptions contains the optional parameters for the LeaseClient.RenewLease method. +type FileSystemRenewOptions struct { + // ModifiedAccessConditions contains optional parameters to access filesystem. ModifiedAccessConditions *ModifiedAccessConditions } -func (o *FilesystemRenewOptions) format() *lease.ContainerRenewOptions { +func (o *FileSystemRenewOptions) format() *lease.ContainerRenewOptions { if o == nil || o.ModifiedAccessConditions == nil { return nil } @@ -114,6 +122,7 @@ func (o *FilesystemRenewOptions) format() *lease.ContainerRenewOptions { // PathAcquireOptions contains the optional parameters for the LeaseClient.AcquireLease method. type PathAcquireOptions struct { + // ModifiedAccessConditions contains optional parameters to access path. ModifiedAccessConditions *ModifiedAccessConditions } @@ -133,7 +142,9 @@ func (o *PathAcquireOptions) format() *lease.BlobAcquireOptions { // PathBreakOptions contains the optional parameters for the LeaseClient.BreakLease method. type PathBreakOptions struct { - BreakPeriod *int32 + // BreakPeriod is the proposed duration of seconds that the lease should continue before it is broken. + BreakPeriod *int32 + // ModifiedAccessConditions contains optional parameters to access path. ModifiedAccessConditions *ModifiedAccessConditions } @@ -159,6 +170,7 @@ func (o *PathBreakOptions) format() *lease.BlobBreakOptions { // PathChangeOptions contains the optional parameters for the LeaseClient.ChangeLease method. type PathChangeOptions struct { + // ModifiedAccessConditions contains optional parameters to access path. ModifiedAccessConditions *ModifiedAccessConditions } @@ -176,7 +188,9 @@ func (o *PathChangeOptions) format() *lease.BlobChangeOptions { } } +// PathReleaseOptions contains the optional parameters for the LeaseClient.ReleaseLease method. type PathReleaseOptions struct { + // ModifiedAccessConditions contains optional parameters to access path. ModifiedAccessConditions *ModifiedAccessConditions } @@ -194,7 +208,9 @@ func (o *PathReleaseOptions) format() *lease.BlobReleaseOptions { } } +// PathRenewOptions contains the optional parameters for the LeaseClient.RenewLease method. type PathRenewOptions struct { + // ModifiedAccessConditions contains optional parameters to access path. ModifiedAccessConditions *ModifiedAccessConditions } diff --git a/sdk/storage/azdatalake/lease/responses.go b/sdk/storage/azdatalake/lease/responses.go index 1ff60df3b227..55a174ccd6f8 100644 --- a/sdk/storage/azdatalake/lease/responses.go +++ b/sdk/storage/azdatalake/lease/responses.go @@ -8,20 +8,20 @@ package lease import "github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/lease" -// FilesystemAcquireResponse contains the response from method FilesystemClient.AcquireLease. -type FilesystemAcquireResponse = lease.ContainerAcquireResponse +// FileSystemAcquireResponse contains the response from method FileSystemClient.AcquireLease. +type FileSystemAcquireResponse = lease.ContainerAcquireResponse -// FilesystemBreakResponse contains the response from method FilesystemClient.BreakLease. -type FilesystemBreakResponse = lease.ContainerBreakResponse +// FileSystemBreakResponse contains the response from method FileSystemClient.BreakLease. +type FileSystemBreakResponse = lease.ContainerBreakResponse -// FilesystemChangeResponse contains the response from method FilesystemClient.ChangeLease. -type FilesystemChangeResponse = lease.ContainerChangeResponse +// FileSystemChangeResponse contains the response from method FileSystemClient.ChangeLease. +type FileSystemChangeResponse = lease.ContainerChangeResponse -// FilesystemReleaseResponse contains the response from method FilesystemClient.ReleaseLease. -type FilesystemReleaseResponse = lease.ContainerReleaseResponse +// FileSystemReleaseResponse contains the response from method FileSystemClient.ReleaseLease. +type FileSystemReleaseResponse = lease.ContainerReleaseResponse -// FilesystemRenewResponse contains the response from method FilesystemClient.RenewLease. -type FilesystemRenewResponse = lease.ContainerRenewResponse +// FileSystemRenewResponse contains the response from method FileSystemClient.RenewLease. +type FileSystemRenewResponse = lease.ContainerRenewResponse // PathAcquireResponse contains the response from method PathClient.AcquireLease. type PathAcquireResponse = lease.BlobAcquireResponse diff --git a/sdk/storage/azdatalake/sas/query_params.go b/sdk/storage/azdatalake/sas/query_params.go index ed3cd252d93f..7806687833c0 100644 --- a/sdk/storage/azdatalake/sas/query_params.go +++ b/sdk/storage/azdatalake/sas/query_params.go @@ -14,9 +14,9 @@ import ( "time" ) -// timeFormat represents the format of a SAS start or expiry time. Use it when formatting/parsing a time.Time. +// TimeFormat represents the format of a SAS start or expiry time. Use it when formatting/parsing a time.Time. const ( - timeFormat = "2006-01-02T15:04:05Z" // "2017-07-27T00:00:00Z" // ISO 8601 + TimeFormat = "2006-01-02T15:04:05Z" // "2017-07-27T00:00:00Z" // ISO 8601 ) var ( @@ -26,7 +26,7 @@ var ( // TimeFormats ISO 8601 format. // Please refer to https://docs.microsoft.com/en-us/rest/api/storageservices/constructing-a-service-sas for more details. -var timeFormats = []string{"2006-01-02T15:04:05.0000000Z", timeFormat, "2006-01-02T15:04Z", "2006-01-02"} +var timeFormats = []string{"2006-01-02T15:04:05.0000000Z", TimeFormat, "2006-01-02T15:04Z", "2006-01-02"} // Protocol indicates the http/https. type Protocol string @@ -55,7 +55,7 @@ func formatTimesForSigning(startTime, expiryTime time.Time) (string, string) { // formatTimeWithDefaultFormat format time with ISO 8601 in "yyyy-MM-ddTHH:mm:ssZ". func formatTimeWithDefaultFormat(t *time.Time) string { - return formatTime(t, timeFormat) // By default, "yyyy-MM-ddTHH:mm:ssZ" is used + return formatTime(t, TimeFormat) // By default, "yyyy-MM-ddTHH:mm:ssZ" is used } // formatTime format time with given format, use ISO 8601 in "yyyy-MM-ddTHH:mm:ssZ" by default. @@ -63,7 +63,7 @@ func formatTime(t *time.Time, format string) string { if format != "" { return t.Format(format) } - return t.Format(timeFormat) // By default, "yyyy-MM-ddTHH:mm:ssZ" is used + return t.Format(TimeFormat) // By default, "yyyy-MM-ddTHH:mm:ssZ" is used } // ParseTime try to parse a SAS time string. @@ -314,8 +314,8 @@ func (p *QueryParameters) Encode() string { if p.signedOID != "" { v.Add("skoid", p.signedOID) v.Add("sktid", p.signedTID) - v.Add("skt", p.signedStart.Format(timeFormat)) - v.Add("ske", p.signedExpiry.Format(timeFormat)) + v.Add("skt", p.signedStart.Format(TimeFormat)) + v.Add("ske", p.signedExpiry.Format(TimeFormat)) v.Add("sks", p.signedService) v.Add("skv", p.signedVersion) } @@ -403,9 +403,9 @@ func NewQueryParameters(values url.Values) QueryParameters { case "sktid": p.signedTID = val case "skt": - p.signedStart, _ = time.Parse(timeFormat, val) + p.signedStart, _ = time.Parse(TimeFormat, val) case "ske": - p.signedExpiry, _ = time.Parse(timeFormat, val) + p.signedExpiry, _ = time.Parse(TimeFormat, val) case "sks": p.signedService = val case "skv": @@ -480,9 +480,9 @@ func newQueryParameters(values url.Values, deleteSASParametersFromValues bool) Q case "sktid": p.signedTID = val case "skt": - p.signedStart, _ = time.Parse(timeFormat, val) + p.signedStart, _ = time.Parse(TimeFormat, val) case "ske": - p.signedExpiry, _ = time.Parse(timeFormat, val) + p.signedExpiry, _ = time.Parse(TimeFormat, val) case "sks": p.signedService = val case "skv": diff --git a/sdk/storage/azdatalake/sas/service.go b/sdk/storage/azdatalake/sas/service.go index 92ccaa8101a3..22784206a667 100644 --- a/sdk/storage/azdatalake/sas/service.go +++ b/sdk/storage/azdatalake/sas/service.go @@ -24,15 +24,15 @@ type DatalakeSignatureValues struct { Protocol Protocol `param:"spr"` // See the Protocol* constants StartTime time.Time `param:"st"` // Not specified if IsZero ExpiryTime time.Time `param:"se"` // Not specified if IsZero - Permissions string `param:"sp"` // Create by initializing FilesystemPermissions, FilePermissions or DirectoryPermissions and then call String() + Permissions string `param:"sp"` // Create by initializing FileSystemPermissions, FilePermissions or DirectoryPermissions and then call String() IPRange IPRange `param:"sip"` Identifier string `param:"si"` - FilesystemName string - // Use "" to create a Filesystem SAS + FileSystemName string + // Use "" to create a FileSystem SAS // DirectoryPath will set this to "" if it is passed FilePath string // Not nil for a directory SAS (ie sr=d) - // Use "" to create a Filesystem SAS + // Use "" to create a FileSystem SAS DirectoryPath string CacheControl string // rscc ContentDisposition string // rscd @@ -88,7 +88,7 @@ func (v DatalakeSignatureValues) SignWithSharedKey(sharedKeyCredential *SharedKe v.Permissions, startTime, expiryTime, - getCanonicalName(sharedKeyCredential.AccountName(), v.FilesystemName, v.FilePath, v.DirectoryPath), + getCanonicalName(sharedKeyCredential.AccountName(), v.FileSystemName, v.FilePath, v.DirectoryPath), signedIdentifier, v.IPRange.String(), string(v.Protocol), @@ -157,7 +157,7 @@ func (v DatalakeSignatureValues) SignWithUserDelegation(userDelegationCredential } // make sure the permission characters are in the correct order if resource == "c" { - perms, err := parseFilesystemPermissions(v.Permissions) + perms, err := parseFileSystemPermissions(v.Permissions) if err != nil { return QueryParameters{}, err } @@ -183,7 +183,7 @@ func (v DatalakeSignatureValues) SignWithUserDelegation(userDelegationCredential v.Permissions, startTime, expiryTime, - getCanonicalName(exported.GetAccountName(userDelegationCredential), v.FilesystemName, v.FilePath, v.DirectoryPath), + getCanonicalName(exported.GetAccountName(userDelegationCredential), v.FileSystemName, v.FilePath, v.DirectoryPath), *udk.SignedOID, *udk.SignedTID, udkStart, @@ -259,17 +259,17 @@ func getCanonicalName(account string, filesystemName string, fileName string, di return strings.Join(elements, "") } -// FilesystemPermissions type simplifies creating the permissions string for an Azure Storage container SAS. +// FileSystemPermissions type simplifies creating the permissions string for an Azure Storage container SAS. // Initialize an instance of this type and then call its String method to set BlobSignatureValues' Permissions field. // All permissions descriptions can be found here: https://docs.microsoft.com/en-us/rest/api/storageservices/create-service-sas#permissions-for-a-directory-container-or-blob -type FilesystemPermissions struct { +type FileSystemPermissions struct { Read, Add, Create, Write, Delete, List, Move bool Execute, ModifyOwnership, ModifyPermissions bool // Meant for hierarchical namespace accounts } // String produces the SAS permissions string for an Azure Storage container. // Call this method to set BlobSignatureValues' Permissions field. -func (p *FilesystemPermissions) String() string { +func (p *FileSystemPermissions) String() string { var b bytes.Buffer if p.Read { b.WriteRune('r') @@ -305,8 +305,8 @@ func (p *FilesystemPermissions) String() string { } // Parse initializes ContainerPermissions' fields from a string. -func parseFilesystemPermissions(s string) (FilesystemPermissions, error) { - p := FilesystemPermissions{} // Clear the flags +func parseFileSystemPermissions(s string) (FileSystemPermissions, error) { + p := FileSystemPermissions{} // Clear the flags for _, r := range s { switch r { case 'r': @@ -330,7 +330,7 @@ func parseFilesystemPermissions(s string) (FilesystemPermissions, error) { case 'p': p.ModifyPermissions = true default: - return FilesystemPermissions{}, fmt.Errorf("invalid permission: '%v'", r) + return FileSystemPermissions{}, fmt.Errorf("invalid permission: '%v'", r) } } return p, nil diff --git a/sdk/storage/azdatalake/sas/service_test.go b/sdk/storage/azdatalake/sas/service_test.go index 186eb7e43a9f..be33f9f68035 100644 --- a/sdk/storage/azdatalake/sas/service_test.go +++ b/sdk/storage/azdatalake/sas/service_test.go @@ -11,22 +11,22 @@ import ( "testing" ) -func TestFilesystemPermissions_String(t *testing.T) { +func TestFileSystemPermissions_String(t *testing.T) { testdata := []struct { - input FilesystemPermissions + input FileSystemPermissions expected string }{ - {input: FilesystemPermissions{Read: true}, expected: "r"}, - {input: FilesystemPermissions{Add: true}, expected: "a"}, - {input: FilesystemPermissions{Create: true}, expected: "c"}, - {input: FilesystemPermissions{Write: true}, expected: "w"}, - {input: FilesystemPermissions{Delete: true}, expected: "d"}, - {input: FilesystemPermissions{List: true}, expected: "l"}, - {input: FilesystemPermissions{Move: true}, expected: "m"}, - {input: FilesystemPermissions{Execute: true}, expected: "e"}, - {input: FilesystemPermissions{ModifyOwnership: true}, expected: "o"}, - {input: FilesystemPermissions{ModifyPermissions: true}, expected: "p"}, - {input: FilesystemPermissions{ + {input: FileSystemPermissions{Read: true}, expected: "r"}, + {input: FileSystemPermissions{Add: true}, expected: "a"}, + {input: FileSystemPermissions{Create: true}, expected: "c"}, + {input: FileSystemPermissions{Write: true}, expected: "w"}, + {input: FileSystemPermissions{Delete: true}, expected: "d"}, + {input: FileSystemPermissions{List: true}, expected: "l"}, + {input: FileSystemPermissions{Move: true}, expected: "m"}, + {input: FileSystemPermissions{Execute: true}, expected: "e"}, + {input: FileSystemPermissions{ModifyOwnership: true}, expected: "o"}, + {input: FileSystemPermissions{ModifyPermissions: true}, expected: "p"}, + {input: FileSystemPermissions{ Read: true, Add: true, Create: true, @@ -44,22 +44,22 @@ func TestFilesystemPermissions_String(t *testing.T) { } } -func TestFilesystemPermissions_Parse(t *testing.T) { +func TestFileSystemPermissions_Parse(t *testing.T) { testdata := []struct { input string - expected FilesystemPermissions + expected FileSystemPermissions }{ - {expected: FilesystemPermissions{Read: true}, input: "r"}, - {expected: FilesystemPermissions{Add: true}, input: "a"}, - {expected: FilesystemPermissions{Create: true}, input: "c"}, - {expected: FilesystemPermissions{Write: true}, input: "w"}, - {expected: FilesystemPermissions{Delete: true}, input: "d"}, - {expected: FilesystemPermissions{List: true}, input: "l"}, - {expected: FilesystemPermissions{Move: true}, input: "m"}, - {expected: FilesystemPermissions{Execute: true}, input: "e"}, - {expected: FilesystemPermissions{ModifyOwnership: true}, input: "o"}, - {expected: FilesystemPermissions{ModifyPermissions: true}, input: "p"}, - {expected: FilesystemPermissions{ + {expected: FileSystemPermissions{Read: true}, input: "r"}, + {expected: FileSystemPermissions{Add: true}, input: "a"}, + {expected: FileSystemPermissions{Create: true}, input: "c"}, + {expected: FileSystemPermissions{Write: true}, input: "w"}, + {expected: FileSystemPermissions{Delete: true}, input: "d"}, + {expected: FileSystemPermissions{List: true}, input: "l"}, + {expected: FileSystemPermissions{Move: true}, input: "m"}, + {expected: FileSystemPermissions{Execute: true}, input: "e"}, + {expected: FileSystemPermissions{ModifyOwnership: true}, input: "o"}, + {expected: FileSystemPermissions{ModifyPermissions: true}, input: "p"}, + {expected: FileSystemPermissions{ Read: true, Add: true, Create: true, @@ -71,7 +71,7 @@ func TestFilesystemPermissions_Parse(t *testing.T) { ModifyOwnership: true, ModifyPermissions: true, }, input: "racwdlmeop"}, - {expected: FilesystemPermissions{ + {expected: FileSystemPermissions{ Read: true, Add: true, Create: true, @@ -85,14 +85,14 @@ func TestFilesystemPermissions_Parse(t *testing.T) { }, input: "cpwmreodal"}, // Wrong order parses correctly } for _, c := range testdata { - permissions, err := parseFilesystemPermissions(c.input) + permissions, err := parseFileSystemPermissions(c.input) require.Nil(t, err) require.Equal(t, c.expected, permissions) } } -func TestFilesystemPermissions_ParseNegative(t *testing.T) { - _, err := parseFilesystemPermissions("cpwmreodalz") // Here 'z' is invalid +func TestFileSystemPermissions_ParseNegative(t *testing.T) { + _, err := parseFileSystemPermissions("cpwmreodalz") // Here 'z' is invalid require.NotNil(t, err) require.Contains(t, err.Error(), "122") } @@ -177,6 +177,39 @@ func TestFilePermissions_Parse(t *testing.T) { } } +func TestDirectoryPermissions_String(t *testing.T) { + testdata := []struct { + input DirectoryPermissions + expected string + }{ + {input: DirectoryPermissions{Read: true}, expected: "r"}, + {input: DirectoryPermissions{Add: true}, expected: "a"}, + {input: DirectoryPermissions{Create: true}, expected: "c"}, + {input: DirectoryPermissions{Write: true}, expected: "w"}, + {input: DirectoryPermissions{Delete: true}, expected: "d"}, + {input: DirectoryPermissions{List: true}, expected: "l"}, + {input: DirectoryPermissions{Move: true}, expected: "m"}, + {input: DirectoryPermissions{Execute: true}, expected: "e"}, + {input: DirectoryPermissions{Ownership: true}, expected: "o"}, + {input: DirectoryPermissions{Permissions: true}, expected: "p"}, + {input: DirectoryPermissions{ + Read: true, + Add: true, + Create: true, + Write: true, + Delete: true, + List: true, + Move: true, + Execute: true, + Ownership: true, + Permissions: true, + }, expected: "racwdlmeop"}, + } + for _, c := range testdata { + require.Equal(t, c.expected, c.input.String()) + } +} + func TestParsePermissionsNegative(t *testing.T) { _, err := parsePathPermissions("awecrdlfmo") // Here 'f' is invalid require.NotNil(t, err) diff --git a/sdk/storage/azdatalake/sas/url_parts.go b/sdk/storage/azdatalake/sas/url_parts.go index 8af46a1329ad..bef6a601e451 100644 --- a/sdk/storage/azdatalake/sas/url_parts.go +++ b/sdk/storage/azdatalake/sas/url_parts.go @@ -25,7 +25,7 @@ type URLParts struct { Scheme string // Ex: "https://" Host string // Ex: "account.blob.core.windows.net", "10.132.141.33", "10.132.141.33:80" IPEndpointStyleInfo IPEndpointStyleInfo - FilesystemName string // "" if no container + FileSystemName string // "" if no container PathName string // "" if no blob SAS QueryParameters UnparsedParams string @@ -62,9 +62,9 @@ func ParseURL(u string) (URLParts, error) { filesystemEndIndex := strings.Index(path, "/") // Find the next slash (if it exists) if filesystemEndIndex == -1 { // Slash not found; path has container name & no blob name - up.FilesystemName = path + up.FileSystemName = path } else { - up.FilesystemName = path[:filesystemEndIndex] // The container name is the part between the slashes + up.FileSystemName = path[:filesystemEndIndex] // The container name is the part between the slashes up.PathName = path[filesystemEndIndex+1:] // The blob name is after the container slash } } @@ -84,8 +84,8 @@ func (up URLParts) String() string { path += "/" + up.IPEndpointStyleInfo.AccountName } // Concatenate container & blob names (if they exist) - if up.FilesystemName != "" { - path += "/" + up.FilesystemName + if up.FileSystemName != "" { + path += "/" + up.FileSystemName if up.PathName != "" { path += "/" + up.PathName } diff --git a/sdk/storage/azdatalake/sas/url_parts_test.go b/sdk/storage/azdatalake/sas/url_parts_test.go index f4694b148056..32fa9569d957 100644 --- a/sdk/storage/azdatalake/sas/url_parts_test.go +++ b/sdk/storage/azdatalake/sas/url_parts_test.go @@ -27,7 +27,7 @@ func TestParseURLIPStyle(t *testing.T) { require.Equal(t, blobURLParts.Scheme, "https") require.Equal(t, blobURLParts.Host, "127.0.0.1:5000") require.Equal(t, blobURLParts.IPEndpointStyleInfo.AccountName, "fakestorageaccount") - require.Equal(t, blobURLParts.FilesystemName, "fakecontainer") + require.Equal(t, blobURLParts.FileSystemName, "fakecontainer") urlWithIP = "https://127.0.0.1:5000/fakestorageaccount/fakecontainer/fakeblob" blobURLParts, err = ParseURL(urlWithIP) @@ -35,7 +35,7 @@ func TestParseURLIPStyle(t *testing.T) { require.Equal(t, blobURLParts.Scheme, "https") require.Equal(t, blobURLParts.Host, "127.0.0.1:5000") require.Equal(t, blobURLParts.IPEndpointStyleInfo.AccountName, "fakestorageaccount") - require.Equal(t, blobURLParts.FilesystemName, "fakecontainer") + require.Equal(t, blobURLParts.FileSystemName, "fakecontainer") require.Equal(t, blobURLParts.PathName, "fakeblob") } @@ -54,7 +54,7 @@ func TestParseURL(t *testing.T) { require.Equal(t, blobURLParts.Scheme, "https") require.Equal(t, blobURLParts.Host, host) - require.Equal(t, blobURLParts.FilesystemName, testContainer) + require.Equal(t, blobURLParts.FileSystemName, testContainer) validateSAS(t, sasStr, blobURLParts.SAS) } @@ -66,7 +66,7 @@ func TestParseURL(t *testing.T) { require.Equal(t, blobURLParts.Scheme, "https") require.Equal(t, blobURLParts.Host, host) - require.Equal(t, blobURLParts.FilesystemName, testContainer) + require.Equal(t, blobURLParts.FileSystemName, testContainer) validateSAS(t, sasStr, blobURLParts.SAS) } diff --git a/sdk/storage/azdatalake/service/client.go b/sdk/storage/azdatalake/service/client.go index 9a20d5fdf076..3a5f0c734ab5 100644 --- a/sdk/storage/azdatalake/service/client.go +++ b/sdk/storage/azdatalake/service/client.go @@ -113,7 +113,7 @@ func NewClientWithSharedKeyCredential(serviceURL string, cred *SharedKeyCredenti blobServiceClientOpts := service.ClientOptions{ ClientOptions: options.ClientOptions, } - blobSharedKey, err := cred.ConvertToBlobSharedKey() + blobSharedKey, err := exported.ConvertToBlobSharedKey(cred) if err != nil { return nil, err } @@ -147,12 +147,12 @@ func (s *Client) getClientOptions() *base.ClientOptions { return base.GetCompositeClientOptions((*base.CompositeClient[generated.ServiceClient, generated_blob.ServiceClient, service.Client])(s)) } -// NewFilesystemClient creates a new filesystem.Client object by concatenating filesystemName to the end of this Client's URL. +// NewFileSystemClient creates a new filesystem.Client object by concatenating filesystemName to the end of this Client's URL. // The new filesystem.Client uses the same request policy pipeline as the Client. -func (s *Client) NewFilesystemClient(filesystemName string) *filesystem.Client { +func (s *Client) NewFileSystemClient(filesystemName string) *filesystem.Client { filesystemURL := runtime.JoinPaths(s.generatedServiceClientWithDFS().Endpoint(), filesystemName) containerURL, filesystemURL := shared.GetURLs(filesystemURL) - return (*filesystem.Client)(base.NewFilesystemClient(filesystemURL, containerURL, s.serviceClient().NewContainerClient(filesystemName), s.generatedServiceClientWithDFS().InternalClient().WithClientName(shared.FilesystemClient), s.sharedKey(), s.identityCredential(), s.getClientOptions())) + return (*filesystem.Client)(base.NewFileSystemClient(filesystemURL, containerURL, s.serviceClient().NewContainerClient(filesystemName), s.generatedServiceClientWithDFS().InternalClient().WithClientName(shared.FileSystemClient), s.sharedKey(), s.identityCredential(), s.getClientOptions())) } // GetUserDelegationCredential obtains a UserDelegationKey object using the base ServiceURL object. @@ -205,23 +205,23 @@ func (s *Client) BlobURL() string { return s.generatedServiceClientWithBlob().Endpoint() } -// CreateFilesystem creates a new filesystem under the specified account. (blob3) -func (s *Client) CreateFilesystem(ctx context.Context, filesystem string, options *CreateFilesystemOptions) (CreateFilesystemResponse, error) { - filesystemClient := s.NewFilesystemClient(filesystem) +// CreateFileSystem creates a new filesystem under the specified account. +func (s *Client) CreateFileSystem(ctx context.Context, filesystem string, options *CreateFileSystemOptions) (CreateFileSystemResponse, error) { + filesystemClient := s.NewFileSystemClient(filesystem) resp, err := filesystemClient.Create(ctx, options) err = exported.ConvertToDFSError(err) return resp, err } -// DeleteFilesystem deletes the specified filesystem. (blob3) -func (s *Client) DeleteFilesystem(ctx context.Context, filesystem string, options *DeleteFilesystemOptions) (DeleteFilesystemResponse, error) { - filesystemClient := s.NewFilesystemClient(filesystem) +// DeleteFileSystem deletes the specified filesystem. +func (s *Client) DeleteFileSystem(ctx context.Context, filesystem string, options *DeleteFileSystemOptions) (DeleteFileSystemResponse, error) { + filesystemClient := s.NewFileSystemClient(filesystem) resp, err := filesystemClient.Delete(ctx, options) err = exported.ConvertToDFSError(err) return resp, err } -// SetProperties sets properties for a storage account's File service endpoint. (blob3) +// SetProperties sets properties for a storage account's Datalake service endpoint. func (s *Client) SetProperties(ctx context.Context, options *SetPropertiesOptions) (SetPropertiesResponse, error) { opts := options.format() resp, err := s.serviceClient().SetProperties(ctx, opts) @@ -229,7 +229,7 @@ func (s *Client) SetProperties(ctx context.Context, options *SetPropertiesOption return resp, err } -// GetProperties gets properties for a storage account's File service endpoint. (blob3) +// GetProperties gets properties for a storage account's Datalake service endpoint. func (s *Client) GetProperties(ctx context.Context, options *GetPropertiesOptions) (GetPropertiesResponse, error) { opts := options.format() resp, err := s.serviceClient().GetProperties(ctx, opts) @@ -238,29 +238,30 @@ func (s *Client) GetProperties(ctx context.Context, options *GetPropertiesOption } -// NewListFilesystemsPager operation returns a pager of the shares under the specified account. (blob3) +// NewListFileSystemsPager operation returns a pager of the shares under the specified account. // For more information, see https://learn.microsoft.com/en-us/rest/api/storageservices/list-shares -func (s *Client) NewListFilesystemsPager(o *ListFilesystemsOptions) *runtime.Pager[ListFilesystemsResponse] { +func (s *Client) NewListFileSystemsPager(o *ListFileSystemsOptions) *runtime.Pager[ListFileSystemsResponse] { listOptions := generated_blob.ServiceClientListContainersSegmentOptions{} + defaultInclude := ListFileSystemsInclude{} if o != nil { - if o.Include.Deleted { + if o.Include != defaultInclude && o.Include.Deleted != nil && *o.Include.Deleted { listOptions.Include = append(listOptions.Include, generated_blob.ListContainersIncludeTypeDeleted) } - if o.Include.Metadata { + if o.Include != defaultInclude && o.Include.Metadata != nil && *o.Include.Metadata { listOptions.Include = append(listOptions.Include, generated_blob.ListContainersIncludeTypeMetadata) } - if o.Include.System { + if o.Include != defaultInclude && o.Include.System != nil && *o.Include.System { listOptions.Include = append(listOptions.Include, generated_blob.ListContainersIncludeTypeSystem) } listOptions.Marker = o.Marker listOptions.Maxresults = o.MaxResults listOptions.Prefix = o.Prefix } - return runtime.NewPager(runtime.PagingHandler[ListFilesystemsResponse]{ - More: func(page ListFilesystemsResponse) bool { + return runtime.NewPager(runtime.PagingHandler[ListFileSystemsResponse]{ + More: func(page ListFileSystemsResponse) bool { return page.NextMarker != nil && len(*page.NextMarker) > 0 }, - Fetcher: func(ctx context.Context, page *ListFilesystemsResponse) (ListFilesystemsResponse, error) { + Fetcher: func(ctx context.Context, page *ListFileSystemsResponse) (ListFileSystemsResponse, error) { var req *policy.Request var err error if page == nil { @@ -270,14 +271,14 @@ func (s *Client) NewListFilesystemsPager(o *ListFilesystemsOptions) *runtime.Pag req, err = s.generatedServiceClientWithBlob().ListContainersSegmentCreateRequest(ctx, &listOptions) } if err != nil { - return ListFilesystemsResponse{}, exported.ConvertToDFSError(err) + return ListFileSystemsResponse{}, exported.ConvertToDFSError(err) } resp, err := s.generatedServiceClientWithBlob().InternalClient().Pipeline().Do(req) if err != nil { - return ListFilesystemsResponse{}, exported.ConvertToDFSError(err) + return ListFileSystemsResponse{}, exported.ConvertToDFSError(err) } if !runtime.HasStatusCode(resp, http.StatusOK) { - return ListFilesystemsResponse{}, exported.ConvertToDFSError(runtime.NewResponseError(resp)) + return ListFileSystemsResponse{}, exported.ConvertToDFSError(runtime.NewResponseError(resp)) } resp1, err := s.generatedServiceClientWithBlob().ListContainersSegmentHandleResponse(resp) return resp1, exported.ConvertToDFSError(err) diff --git a/sdk/storage/azdatalake/service/client_test.go b/sdk/storage/azdatalake/service/client_test.go index 6d009463b140..286bc62a4cef 100644 --- a/sdk/storage/azdatalake/service/client_test.go +++ b/sdk/storage/azdatalake/service/client_test.go @@ -78,8 +78,8 @@ func (s *ServiceUnrecordedTestsSuite) TestServiceClientFromConnectionString() { svcClient, err := service.NewClientWithSharedKeyCredential(parsedConnStr.ServiceURL, sharedKeyCred, nil) _require.Nil(err) - fsClient := testcommon.CreateNewFilesystem(context.Background(), _require, testcommon.GenerateFilesystemName(testName), svcClient) - defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + fsClient := testcommon.CreateNewFileSystem(context.Background(), _require, testcommon.GenerateFileSystemName(testName), svcClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) } func (s *ServiceRecordedTestsSuite) TestSetPropertiesLogging() { @@ -182,6 +182,7 @@ func (s *ServiceRecordedTestsSuite) TestSetPropertiesSetCORSMultiple() { _require.Nil(err) resp, err := svcClient.GetProperties(context.Background(), nil) + _require.NoError(err) for i := 0; i < len(resp.CORS); i++ { if resp.CORS[i].AllowedOrigins == &allowedOrigins1 { _require.Equal(resp.CORS[i].AllowedMethods, &allowedMethods1) @@ -196,7 +197,6 @@ func (s *ServiceRecordedTestsSuite) TestSetPropertiesSetCORSMultiple() { _require.Equal(resp.CORS[i].AllowedHeaders, &allowedHeaders2) } } - _require.Nil(err) } func (s *ServiceRecordedTestsSuite) TestAccountDeleteRetentionPolicy() { @@ -331,7 +331,7 @@ func (s *ServiceUnrecordedTestsSuite) TestSASServiceClient() { serviceClient, err := service.NewClientWithSharedKeyCredential(fmt.Sprintf("https://%s.dfs.core.windows.net/", cred.AccountName()), cred, nil) _require.Nil(err) - fsName := testcommon.GenerateFilesystemName(testName) + fsName := testcommon.GenerateFileSystemName(testName) // Note: Always set all permissions, services, types to true to ensure order of string formed is correct. resources := sas.AccountResourceTypes{ @@ -361,10 +361,10 @@ func (s *ServiceUnrecordedTestsSuite) TestSASServiceClient() { _require.Nil(err) // create fs using SAS - _, err = svcClient.CreateFilesystem(context.Background(), fsName, nil) + _, err = svcClient.CreateFileSystem(context.Background(), fsName, nil) _require.Nil(err) - _, err = svcClient.DeleteFilesystem(context.Background(), fsName, nil) + _, err = svcClient.DeleteFileSystem(context.Background(), fsName, nil) _require.Nil(err) } @@ -464,7 +464,7 @@ func (s *ServiceUnrecordedTestsSuite) TestNoSharedKeyCredError() { } -func (s *ServiceUnrecordedTestsSuite) TestGetFilesystemClient() { +func (s *ServiceUnrecordedTestsSuite) TestGetFileSystemClient() { _require := require.New(s.T()) testName := s.T().Name() accountName := os.Getenv("AZURE_STORAGE_ACCOUNT_NAME") @@ -475,10 +475,10 @@ func (s *ServiceUnrecordedTestsSuite) TestGetFilesystemClient() { serviceClient, err := service.NewClientWithSharedKeyCredential(fmt.Sprintf("https://%s.blob.core.windows.net/", accountName), cred, nil) _require.Nil(err) - fsName := testcommon.GenerateFilesystemName(testName + "1") - fsClient := serviceClient.NewFilesystemClient(fsName) + fsName := testcommon.GenerateFileSystemName(testName + "1") + fsClient := serviceClient.NewFileSystemClient(fsName) - defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) _, err = fsClient.Create(context.Background(), nil) _require.Nil(err) @@ -486,7 +486,7 @@ func (s *ServiceUnrecordedTestsSuite) TestGetFilesystemClient() { _require.Nil(err) } -func (s *ServiceUnrecordedTestsSuite) TestSASFilesystemClient() { +func (s *ServiceUnrecordedTestsSuite) TestSASFileSystemClient() { _require := require.New(s.T()) testName := s.T().Name() accountName := os.Getenv("AZURE_STORAGE_ACCOUNT_NAME") @@ -497,10 +497,10 @@ func (s *ServiceUnrecordedTestsSuite) TestSASFilesystemClient() { serviceClient, err := service.NewClientWithSharedKeyCredential(fmt.Sprintf("https://%s.blob.core.windows.net/", accountName), cred, nil) _require.Nil(err) - fsName := testcommon.GenerateFilesystemName(testName) - fsClient := serviceClient.NewFilesystemClient(fsName) + fsName := testcommon.GenerateFileSystemName(testName) + fsClient := serviceClient.NewFileSystemClient(fsName) - permissions := sas.FilesystemPermissions{ + permissions := sas.FileSystemPermissions{ Read: true, Add: true, } @@ -519,7 +519,7 @@ func (s *ServiceUnrecordedTestsSuite) TestSASFilesystemClient() { testcommon.ValidateErrorCode(_require, err, datalakeerror.AuthorizationFailure) } -func (s *ServiceUnrecordedTestsSuite) TestSASFilesystem2() { +func (s *ServiceUnrecordedTestsSuite) TestSASFileSystem2() { _require := require.New(s.T()) testName := s.T().Name() accountName := os.Getenv("AZURE_STORAGE_ACCOUNT_NAME") @@ -530,16 +530,16 @@ func (s *ServiceUnrecordedTestsSuite) TestSASFilesystem2() { serviceClient, err := service.NewClientWithSharedKeyCredential(fmt.Sprintf("https://%s.blob.core.windows.net/", accountName), cred, nil) _require.Nil(err) - fsName := testcommon.GenerateFilesystemName(testName) - fsClient := serviceClient.NewFilesystemClient(fsName) + fsName := testcommon.GenerateFileSystemName(testName) + fsClient := serviceClient.NewFileSystemClient(fsName) start := time.Now().Add(-5 * time.Minute).UTC() opts := filesystem.GetSASURLOptions{StartTime: &start} - sasUrlReadAdd, err := fsClient.GetSASURL(sas.FilesystemPermissions{Read: true, Add: true}, time.Now().Add(time.Hour), &opts) + sasUrlReadAdd, err := fsClient.GetSASURL(sas.FileSystemPermissions{Read: true, Add: true}, time.Now().Add(time.Hour), &opts) _require.Nil(err) _, err = fsClient.Create(context.Background(), &filesystem.CreateOptions{Metadata: testcommon.BasicMetadata}) _require.Nil(err) - defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient) fsClient1, err := filesystem.NewClientWithNoCredential(sasUrlReadAdd, nil) _require.Nil(err) @@ -552,7 +552,7 @@ func (s *ServiceUnrecordedTestsSuite) TestSASFilesystem2() { start = time.Now().Add(-5 * time.Minute).UTC() opts = filesystem.GetSASURLOptions{StartTime: &start} - sasUrlRCWL, err := fsClient.GetSASURL(sas.FilesystemPermissions{Add: true, Create: true, Delete: true, List: true}, time.Now().Add(time.Hour), &opts) + sasUrlRCWL, err := fsClient.GetSASURL(sas.FileSystemPermissions{Add: true, Create: true, Delete: true, List: true}, time.Now().Add(time.Hour), &opts) _require.Nil(err) fsClient2, err := filesystem.NewClientWithNoCredential(sasUrlRCWL, nil) @@ -574,8 +574,8 @@ func (s *ServiceRecordedTestsSuite) TestListFilesystemsBasic() { "bar": to.Ptr("barvalue"), } - fsName := testcommon.GenerateFilesystemName(testName) - fsClient := svcClient.NewFilesystemClient(fsName) + fsName := testcommon.GenerateFileSystemName(testName) + fsClient := svcClient.NewFileSystemClient(fsName) _, err = fsClient.Create(context.Background(), &filesystem.CreateOptions{Metadata: md}) defer func(fsClient *filesystem.Client, ctx context.Context, options *filesystem.DeleteOptions) { _, err := fsClient.Delete(ctx, options) @@ -584,9 +584,9 @@ func (s *ServiceRecordedTestsSuite) TestListFilesystemsBasic() { } }(fsClient, context.Background(), nil) _require.Nil(err) - prefix := testcommon.FilesystemPrefix - listOptions := service.ListFilesystemsOptions{Prefix: &prefix, Include: service.ListFilesystemsInclude{Metadata: true}} - pager := svcClient.NewListFilesystemsPager(&listOptions) + prefix := testcommon.FileSystemPrefix + listOptions := service.ListFileSystemsOptions{Prefix: &prefix, Include: service.ListFileSystemsInclude{Metadata: to.Ptr(true)}} + pager := svcClient.NewListFileSystemsPager(&listOptions) count := 0 for pager.More() { @@ -634,8 +634,8 @@ func (s *ServiceRecordedTestsSuite) TestListFilesystemsBasicUsingConnectionStrin "bar": to.Ptr("barvalue"), } - fsName := testcommon.GenerateFilesystemName(testName) - fsClient := testcommon.ServiceGetFilesystemClient(fsName, svcClient) + fsName := testcommon.GenerateFileSystemName(testName) + fsClient := testcommon.ServiceGetFileSystemClient(fsName, svcClient) _, err = fsClient.Create(context.Background(), &filesystem.CreateOptions{Metadata: md}) defer func(fsClient *filesystem.Client, ctx context.Context, options *filesystem.DeleteOptions) { _, err := fsClient.Delete(ctx, options) @@ -644,9 +644,9 @@ func (s *ServiceRecordedTestsSuite) TestListFilesystemsBasicUsingConnectionStrin } }(fsClient, context.Background(), nil) _require.Nil(err) - prefix := testcommon.FilesystemPrefix - listOptions := service.ListFilesystemsOptions{Prefix: &prefix, Include: service.ListFilesystemsInclude{Metadata: true}} - pager := svcClient.NewListFilesystemsPager(&listOptions) + prefix := testcommon.FileSystemPrefix + listOptions := service.ListFileSystemsOptions{Prefix: &prefix, Include: service.ListFileSystemsInclude{Metadata: to.Ptr(true)}} + pager := svcClient.NewListFileSystemsPager(&listOptions) count := 0 for pager.More() { @@ -690,30 +690,30 @@ func (s *ServiceRecordedTestsSuite) TestListFilesystemsPaged() { testName := s.T().Name() svcClient, err := testcommon.GetServiceClient(s.T(), testcommon.TestAccountDefault, nil) _require.Nil(err) - const numFilesystems = 6 + const numFileSystems = 6 maxResults := int32(2) - const pagedFilesystemsPrefix = "azfilesystempaged" + const pagedFileSystemsPrefix = "azfilesystempaged" - filesystems := make([]*filesystem.Client, numFilesystems) + filesystems := make([]*filesystem.Client, numFileSystems) expectedResults := make(map[string]bool) - for i := 0; i < numFilesystems; i++ { - fsName := pagedFilesystemsPrefix + testcommon.GenerateFilesystemName(testName) + fmt.Sprintf("%d", i) - fsClient := testcommon.CreateNewFilesystem(context.Background(), _require, fsName, svcClient) + for i := 0; i < numFileSystems; i++ { + fsName := pagedFileSystemsPrefix + testcommon.GenerateFileSystemName(testName) + fmt.Sprintf("%d", i) + fsClient := testcommon.CreateNewFileSystem(context.Background(), _require, fsName, svcClient) filesystems[i] = fsClient expectedResults[fsName] = false } defer func() { for i := range filesystems { - testcommon.DeleteFilesystem(context.Background(), _require, filesystems[i]) + testcommon.DeleteFileSystem(context.Background(), _require, filesystems[i]) } }() - prefix := pagedFilesystemsPrefix + testcommon.FilesystemPrefix - listOptions := service.ListFilesystemsOptions{MaxResults: &maxResults, Prefix: &prefix, Include: service.ListFilesystemsInclude{Metadata: true}} + prefix := pagedFileSystemsPrefix + testcommon.FileSystemPrefix + listOptions := service.ListFileSystemsOptions{MaxResults: &maxResults, Prefix: &prefix, Include: service.ListFileSystemsInclude{Metadata: to.Ptr(true)}} count := 0 - results := make([]service.FilesystemItem, 0) - pager := svcClient.NewListFilesystemsPager(&listOptions) + results := make([]service.FileSystemItem, 0) + pager := svcClient.NewListFileSystemsPager(&listOptions) for pager.More() { resp, err := pager.NextPage(context.Background()) @@ -725,8 +725,8 @@ func (s *ServiceRecordedTestsSuite) TestListFilesystemsPaged() { } } - _require.Equal(count, numFilesystems) - _require.Equal(len(results), numFilesystems) + _require.Equal(count, numFileSystems) + _require.Equal(len(results), numFileSystems) // make sure each fs we see is expected for _, ctnr := range results { @@ -748,13 +748,13 @@ func (s *ServiceRecordedTestsSuite) TestAccountListFilesystemsEmptyPrefix() { svcClient, err := testcommon.GetServiceClient(s.T(), testcommon.TestAccountDefault, nil) _require.NoError(err) - fsClient1 := testcommon.CreateNewFilesystem(context.Background(), _require, testcommon.GenerateFilesystemName(testName)+"1", svcClient) - defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient1) - fsClient2 := testcommon.CreateNewFilesystem(context.Background(), _require, testcommon.GenerateFilesystemName(testName)+"2", svcClient) - defer testcommon.DeleteFilesystem(context.Background(), _require, fsClient2) + fsClient1 := testcommon.CreateNewFileSystem(context.Background(), _require, testcommon.GenerateFileSystemName(testName)+"1", svcClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient1) + fsClient2 := testcommon.CreateNewFileSystem(context.Background(), _require, testcommon.GenerateFileSystemName(testName)+"2", svcClient) + defer testcommon.DeleteFileSystem(context.Background(), _require, fsClient2) count := 0 - pager := svcClient.NewListFilesystemsPager(nil) + pager := svcClient.NewListFileSystemsPager(nil) for pager.More() { resp, err := pager.NextPage(context.Background()) diff --git a/sdk/storage/azdatalake/service/constants.go b/sdk/storage/azdatalake/service/constants.go index 76069177867b..a06f2a41a79a 100644 --- a/sdk/storage/azdatalake/service/constants.go +++ b/sdk/storage/azdatalake/service/constants.go @@ -16,7 +16,7 @@ type PublicAccessType = filesystem.PublicAccessType const ( File PublicAccessType = filesystem.File - Filesystem PublicAccessType = filesystem.Filesystem + FileSystem PublicAccessType = filesystem.FileSystem ) // StatusType defines values for StatusType diff --git a/sdk/storage/azdatalake/service/examples_test.go b/sdk/storage/azdatalake/service/examples_test.go new file mode 100644 index 000000000000..525c86d582d1 --- /dev/null +++ b/sdk/storage/azdatalake/service/examples_test.go @@ -0,0 +1,335 @@ +//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 service_test + +import ( + "context" + "fmt" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/filesystem" + "log" + "os" + "time" + + "github.com/Azure/azure-sdk-for-go/sdk/azcore" + "github.com/Azure/azure-sdk-for-go/sdk/azcore/to" + "github.com/Azure/azure-sdk-for-go/sdk/azidentity" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/sas" + "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/service" +) + +func handleError(err error) { + if err != nil { + log.Fatal(err.Error()) + } +} + +func Example_service_Client_NewClient() { + accountName, ok := os.LookupEnv("AZURE_STORAGE_ACCOUNT_NAME") + if !ok { + panic("AZURE_STORAGE_ACCOUNT_NAME could not be found") + } + serviceURL := fmt.Sprintf("https://%s.dfs.core.windows.net/", accountName) + + cred, err := azidentity.NewDefaultAzureCredential(nil) + handleError(err) + serviceClient, err := service.NewClient(serviceURL, cred, nil) + handleError(err) + fmt.Println(serviceClient.DFSURL()) + fmt.Println(serviceClient.BlobURL()) +} + +func Example_service_Client_NewClientWithSharedKeyCredential() { + accountName, ok := os.LookupEnv("AZURE_STORAGE_ACCOUNT_NAME") + if !ok { + panic("AZURE_STORAGE_ACCOUNT_NAME could not be found") + } + accountKey, ok := os.LookupEnv("AZURE_STORAGE_ACCOUNT_KEY") + if !ok { + panic("AZURE_STORAGE_ACCOUNT_KEY could not be found") + } + serviceURL := fmt.Sprintf("https://%s.dfs.core.windows.net/", accountName) + + cred, err := azdatalake.NewSharedKeyCredential(accountName, accountKey) + handleError(err) + serviceClient, err := service.NewClientWithSharedKeyCredential(serviceURL, cred, nil) + handleError(err) + fmt.Println(serviceClient.DFSURL()) + fmt.Println(serviceClient.BlobURL()) +} + +func Example_service_Client_NewClientWithNoCredential() { + accountName, ok := os.LookupEnv("AZURE_STORAGE_ACCOUNT_NAME") + if !ok { + panic("AZURE_STORAGE_ACCOUNT_NAME could not be found") + } + sharedAccessSignature, ok := os.LookupEnv("AZURE_STORAGE_SHARED_ACCESS_SIGNATURE") + if !ok { + panic("AZURE_STORAGE_SHARED_ACCESS_SIGNATURE could not be found") + } + serviceURL := fmt.Sprintf("https://%s.dfs.core.windows.net/?%s", accountName, sharedAccessSignature) + + serviceClient, err := service.NewClientWithNoCredential(serviceURL, nil) + handleError(err) + fmt.Println(serviceClient.DFSURL()) + fmt.Println(serviceClient.BlobURL()) +} + +func Example_service_Client_NewClientFromConnectionString() { + // Your connection string can be obtained from the Azure Portal. + connectionString, ok := os.LookupEnv("AZURE_STORAGE_CONNECTION_STRING") + if !ok { + log.Fatal("the environment variable 'AZURE_STORAGE_CONNECTION_STRING' could not be found") + } + + serviceClient, err := service.NewClientFromConnectionString(connectionString, nil) + handleError(err) + fmt.Println(serviceClient.DFSURL()) + fmt.Println(serviceClient.BlobURL()) +} + +func Example_service_Client_CreateContainer() { + accountName, ok := os.LookupEnv("AZURE_STORAGE_ACCOUNT_NAME") + if !ok { + panic("AZURE_STORAGE_ACCOUNT_NAME could not be found") + } + serviceURL := fmt.Sprintf("https://%s.dfs.core.windows.net/", accountName) + + cred, err := azidentity.NewDefaultAzureCredential(nil) + handleError(err) + + serviceClient, err := service.NewClient(serviceURL, cred, nil) + handleError(err) + + _, err = serviceClient.CreateFileSystem(context.TODO(), "testfs", nil) + handleError(err) + + // ======== 2. Delete a container ======== + defer func(serviceClient1 *service.Client, ctx context.Context, fsName string, options *filesystem.DeleteOptions) { + _, err = serviceClient1.DeleteFileSystem(ctx, fsName, options) + if err != nil { + log.Fatal(err) + } + }(serviceClient, context.TODO(), "testfs", nil) +} + +func Example_service_Client_DeleteFileSystem() { + accountName, ok := os.LookupEnv("AZURE_STORAGE_ACCOUNT_NAME") + if !ok { + panic("AZURE_STORAGE_ACCOUNT_NAME could not be found") + } + serviceURL := fmt.Sprintf("https://%s.dfs.core.windows.net/", accountName) + + cred, err := azidentity.NewDefaultAzureCredential(nil) + handleError(err) + serviceClient, err := service.NewClient(serviceURL, cred, nil) + handleError(err) + + _, err = serviceClient.DeleteFileSystem(context.TODO(), "testfs", nil) + handleError(err) +} + +func Example_service_Client_ListFileSystems() { + accountName, ok := os.LookupEnv("AZURE_STORAGE_ACCOUNT_NAME") + if !ok { + panic("AZURE_STORAGE_ACCOUNT_NAME could not be found") + } + serviceURL := fmt.Sprintf("https://%s.dfs.core.windows.net/", accountName) + + cred, err := azidentity.NewDefaultAzureCredential(nil) + handleError(err) + serviceClient, err := service.NewClient(serviceURL, cred, nil) + handleError(err) + + listFSOptions := service.ListFileSystemsOptions{ + Include: service.ListFileSystemsInclude{ + Metadata: to.Ptr(true), // Include Metadata + Deleted: to.Ptr(true), // Include deleted containers in the result as well + }, + } + pager := serviceClient.NewListFileSystemsPager(&listFSOptions) + + for pager.More() { + resp, err := pager.NextPage(context.TODO()) + if err != nil { + log.Fatal(err) + } + for _, fs := range resp.FileSystemItems { + fmt.Println(*fs.Name) + } + } +} + +func Example_service_Client_GetSASURL() { + cred, err := azdatalake.NewSharedKeyCredential("myAccountName", "myAccountKey") + handleError(err) + serviceClient, err := service.NewClientWithSharedKeyCredential("https://.dfs.core.windows.net", cred, nil) + handleError(err) + + resources := sas.AccountResourceTypes{Service: true} + permission := sas.AccountPermissions{Read: true} + start := time.Now() + expiry := start.AddDate(1, 0, 0) + options := service.GetSASURLOptions{StartTime: &start} + sasURL, err := serviceClient.GetSASURL(resources, permission, expiry, &options) + handleError(err) + + serviceURL := fmt.Sprintf("https://.dfs.core.windows.net/?%s", sasURL) + serviceClientWithSAS, err := service.NewClientWithNoCredential(serviceURL, nil) + handleError(err) + _ = serviceClientWithSAS +} + +func Example_service_Client_SetProperties() { + accountName, ok := os.LookupEnv("AZURE_STORAGE_ACCOUNT_NAME") + if !ok { + panic("AZURE_STORAGE_ACCOUNT_NAME could not be found") + } + serviceURL := fmt.Sprintf("https://%s.dfs.core.windows.net/", accountName) + + cred, err := azidentity.NewDefaultAzureCredential(nil) + handleError(err) + serviceClient, err := service.NewClient(serviceURL, cred, nil) + handleError(err) + + enabled := true // enabling retention period + days := int32(5) // setting retention period to 5 days + serviceSetPropertiesResponse, err := serviceClient.SetProperties(context.TODO(), &service.SetPropertiesOptions{ + DeleteRetentionPolicy: &service.RetentionPolicy{Enabled: &enabled, Days: &days}, + }) + + handleError(err) + fmt.Println(serviceSetPropertiesResponse) +} + +func Example_service_Client_GetProperties() { + accountName, ok := os.LookupEnv("AZURE_STORAGE_ACCOUNT_NAME") + if !ok { + panic("AZURE_STORAGE_ACCOUNT_NAME could not be found") + } + serviceURL := fmt.Sprintf("https://%s.dfs.core.windows.net/", accountName) + + cred, err := azidentity.NewDefaultAzureCredential(nil) + handleError(err) + + serviceClient, err := service.NewClient(serviceURL, cred, nil) + handleError(err) + + serviceGetPropertiesResponse, err := serviceClient.GetProperties(context.TODO(), nil) + handleError(err) + + fmt.Println(serviceGetPropertiesResponse) +} + +// This example shows how to create and use an Azure Storage account Shared Access Signature (SAS). +func Example_service_SASSignatureValues_Sign() { + accountName, accountKey := os.Getenv("AZURE_STORAGE_ACCOUNT_NAME"), os.Getenv("AZURE_STORAGE_ACCOUNT_KEY") + + credential, err := azdatalake.NewSharedKeyCredential(accountName, accountKey) + handleError(err) + + sasQueryParams, err := sas.AccountSignatureValues{ + Protocol: sas.ProtocolHTTPS, + ExpiryTime: time.Now().UTC().Add(48 * time.Hour), + Permissions: to.Ptr(sas.AccountPermissions{Read: true, List: true}).String(), + ResourceTypes: to.Ptr(sas.AccountResourceTypes{Container: true, Object: true}).String(), + }.SignWithSharedKey(credential) + handleError(err) + + sasURL := fmt.Sprintf("https://%s.dfs.core.windows.net/?%s", accountName, sasQueryParams.Encode()) + + // This URL can be used to authenticate requests now + serviceClient, err := service.NewClientWithNoCredential(sasURL, nil) + handleError(err) + + // You can also break a blob URL up into it's constituent parts + blobURLParts, _ := azdatalake.ParseURL(serviceClient.DFSURL()) + fmt.Printf("SAS expiry time = %s\n", blobURLParts.SAS.ExpiryTime()) +} + +func Example_service_Client_NewClientWithUserDelegationCredential() { + accountName, ok := os.LookupEnv("AZURE_STORAGE_ACCOUNT_NAME") + if !ok { + panic("AZURE_STORAGE_ACCOUNT_NAME could not be found") + } + const containerName = "testContainer" + + // Create Managed Identity (OAuth) Credentials using Client ID + clientOptions := azcore.ClientOptions{} // Fill clientOptions as needed + optsClientID := azidentity.ManagedIdentityCredentialOptions{ClientOptions: clientOptions, ID: azidentity.ClientID("7cf7db0d-...")} + cred, err := azidentity.NewManagedIdentityCredential(&optsClientID) + handleError(err) + clientOptionsService := service.ClientOptions{} // Same as azcore.ClientOptions using service instead + + svcClient, err := service.NewClient(fmt.Sprintf("https://%s.dfs.core.windows.net/", accountName), cred, &clientOptionsService) + handleError(err) + + // Set current and past time and create key + currentTime := time.Now().UTC().Add(-10 * time.Second) + pastTime := currentTime.Add(48 * time.Hour) + info := service.KeyInfo{ + Start: to.Ptr(currentTime.UTC().Format(sas.TimeFormat)), + Expiry: to.Ptr(pastTime.UTC().Format(sas.TimeFormat)), + } + + udc, err := svcClient.GetUserDelegationCredential(context.Background(), info, nil) + handleError(err) + + fmt.Println("User Delegation Key has been created for ", accountName) + + // Create Blob Signature Values with desired permissions and sign with user delegation credential + sasQueryParams, err := sas.DatalakeSignatureValues{ + Protocol: sas.ProtocolHTTPS, + StartTime: time.Now().UTC().Add(time.Second * -10), + ExpiryTime: time.Now().UTC().Add(15 * time.Minute), + Permissions: to.Ptr(sas.FileSystemPermissions{Read: true, List: true}).String(), + FileSystemName: containerName, + }.SignWithUserDelegation(udc) + handleError(err) + + sasURL := fmt.Sprintf("https://%s.dfs.core.windows.net/?%s", accountName, sasQueryParams.Encode()) + + // This URL can be used to authenticate requests now + serviceClient, err := service.NewClientWithNoCredential(sasURL, nil) + handleError(err) + + // You can also break a blob URL up into it's constituent parts + blobURLParts, _ := azdatalake.ParseURL(serviceClient.DFSURL()) + fmt.Printf("SAS expiry time = %s\n", blobURLParts.SAS.ExpiryTime()) + + // Create Managed Identity (OAuth) Credentials using Resource ID + optsResourceID := azidentity.ManagedIdentityCredentialOptions{ClientOptions: clientOptions, ID: azidentity.ResourceID("/subscriptions/...")} + cred, err = azidentity.NewManagedIdentityCredential(&optsResourceID) + handleError(err) + + svcClient, err = service.NewClient(fmt.Sprintf("https://%s.dfs.core.windows.net/", accountName), cred, &clientOptionsService) + handleError(err) + + udc, err = svcClient.GetUserDelegationCredential(context.Background(), info, nil) + handleError(err) + fmt.Println("User Delegation Key has been created for ", accountName) + + // Create Blob Signature Values with desired permissions and sign with user delegation credential + sasQueryParams, err = sas.DatalakeSignatureValues{ + Protocol: sas.ProtocolHTTPS, + StartTime: time.Now().UTC().Add(time.Second * -10), + ExpiryTime: time.Now().UTC().Add(15 * time.Minute), + Permissions: to.Ptr(sas.FileSystemPermissions{Read: true, List: true}).String(), + FileSystemName: containerName, + }.SignWithUserDelegation(udc) + handleError(err) + + sasURL = fmt.Sprintf("https://%s.dfs.core.windows.net/?%s", accountName, sasQueryParams.Encode()) + + // This URL can be used to authenticate requests now + serviceClient, err = service.NewClientWithNoCredential(sasURL, nil) + handleError(err) + + // You can also break a blob URL up into it's constituent parts + blobURLParts, _ = azdatalake.ParseURL(serviceClient.DFSURL()) + fmt.Printf("SAS expiry time = %s\n", blobURLParts.SAS.ExpiryTime()) +} diff --git a/sdk/storage/azdatalake/service/models.go b/sdk/storage/azdatalake/service/models.go index 2c2c27af8d5e..7fec5e4fc6fc 100644 --- a/sdk/storage/azdatalake/service/models.go +++ b/sdk/storage/azdatalake/service/models.go @@ -16,13 +16,13 @@ import ( ) import blobSAS "github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/sas" -// CreateFilesystemOptions contains the optional parameters for the Filesystem Create method. -type CreateFilesystemOptions = filesystem.CreateOptions +// CreateFileSystemOptions contains the optional parameters for the FileSystem Create method. +type CreateFileSystemOptions = filesystem.CreateOptions -// DeleteFilesystemOptions contains the optional parameters for the Filesystem Delete method. -type DeleteFilesystemOptions = filesystem.DeleteOptions +// DeleteFileSystemOptions contains the optional parameters for the FileSystem Delete method. +type DeleteFileSystemOptions = filesystem.DeleteOptions -// GetUserDelegationCredentialOptions contains optional parameters for Service.GetUserDelegationKey method. +// GetUserDelegationCredentialOptions contains optional parameters for GetUserDelegationKey method. type GetUserDelegationCredentialOptions struct { // placeholder for future options } @@ -45,29 +45,23 @@ func (o *GetPropertiesOptions) format() *service.GetPropertiesOptions { // SetPropertiesOptions provides set of options for Client.SetProperties type SetPropertiesOptions struct { - // The set of CORS rules. + // CORS The set of CORS rules. CORS []*CORSRule - - // The default version to use for requests to the Datalake service if an incoming request's version is not specified. Possible + // DefaultServiceVersion The default version to use for requests to the Datalake service if an incoming request's version is not specified. Possible // values include version 2008-10-27 and all more recent versions. DefaultServiceVersion *string - - // the retention policy which determines how long the associated data should persist. + // DeleteRetentionPolicy the retention policy which determines how long the associated data should persist. DeleteRetentionPolicy *RetentionPolicy - - // a summary of request statistics grouped by API in hour or minute aggregates + // HourMetrics a summary of request statistics grouped by API in hour or minute aggregates // If version is not set - we default to "1.0" HourMetrics *Metrics - - // Azure Analytics Logging settings. + // Logging Azure Analytics Logging settings. // If version is not set - we default to "1.0" Logging *Logging - - // a summary of request statistics grouped by API in hour or minute aggregates + // MinuteMetrics a summary of request statistics grouped by API in hour or minute aggregates // If version is not set - we default to "1.0" MinuteMetrics *Metrics - - // The properties that enable an account to host a static website. + // StaticWebsite The properties that enable an account to host a static website. StaticWebsite *StaticWebsite } @@ -86,27 +80,31 @@ func (o *SetPropertiesOptions) format() *service.SetPropertiesOptions { } } -// ListFilesystemsInclude indicates what additional information the service should return with each filesystem. -type ListFilesystemsInclude struct { - // Tells the service whether to return metadata for each filesystem. - Metadata bool - - // Tells the service whether to return soft-deleted filesystems. - Deleted bool - - System bool +// ListFileSystemsInclude indicates what additional information the service should return with each filesystem. +type ListFileSystemsInclude struct { + // Metadata tells the service whether to return metadata for each filesystem. + Metadata *bool + // Deleted tells the service whether to return soft-deleted filesystems. + Deleted *bool + // System tells the service whether to return system filesystems. + System *bool } -// ListFilesystemsOptions contains the optional parameters for the Client.List method. -type ListFilesystemsOptions struct { - Include ListFilesystemsInclude - Marker *string +// ListFileSystemsOptions contains the optional parameters for the ListFileSystems method. +type ListFileSystemsOptions struct { + // Include tells the service whether to return filesystem metadata. + Include ListFileSystemsInclude + // Marker is the continuation token to use when continuing the operation. + Marker *string + // MaxResults sets the maximum number of paths that will be returned per page. MaxResults *int32 - Prefix *string + // Prefix filters the results to return only filesystems whose names begin with the specified prefix. + Prefix *string } // GetSASURLOptions contains the optional parameters for the Client.GetSASURL method. type GetSASURLOptions struct { + // StartTime is the time after which the SAS will become valid. StartTime *time.Time } @@ -174,17 +172,17 @@ type LeaseAccessConditions = exported.LeaseAccessConditions // ModifiedAccessConditions contains a group of parameters for specifying access conditions. type ModifiedAccessConditions = exported.ModifiedAccessConditions -// CPKScopeInfo contains a group of parameters for the FilesystemClient.Create method. +// CPKScopeInfo contains a group of parameters for the FileSystemClient.Create method. type CPKScopeInfo = filesystem.CPKScopeInfo // StorageServiceProperties - Storage Service Properties. Returned in GetServiceProperties call. type StorageServiceProperties = service.StorageServiceProperties -// ListFilesystemsSegmentResponse contains fields from the ListFilesystems operation -type ListFilesystemsSegmentResponse = generated_blob.ListFileSystemsSegmentResponse +// ListFileSystemsSegmentResponse contains fields from the ListFileSystems operation +type ListFileSystemsSegmentResponse = generated_blob.ListFileSystemsSegmentResponse -// FilesystemItem contains fields from the ListFilesystems operation -type FilesystemItem = generated_blob.FileSystemItem +// FileSystemItem contains fields from the ListFileSystems operation +type FileSystemItem = generated_blob.FileSystemItem -// FilesystemProperties contains fields from the ListFilesystems operation -type FilesystemProperties = generated_blob.FileSystemProperties +// FileSystemProperties contains fields from the ListFileSystems operation +type FileSystemProperties = generated_blob.FileSystemProperties diff --git a/sdk/storage/azdatalake/service/responses.go b/sdk/storage/azdatalake/service/responses.go index aa3581babdd7..27ef525cf8d7 100644 --- a/sdk/storage/azdatalake/service/responses.go +++ b/sdk/storage/azdatalake/service/responses.go @@ -15,11 +15,11 @@ import ( "github.com/Azure/azure-sdk-for-go/sdk/storage/azdatalake/internal/generated_blob" ) -// CreateFilesystemResponse contains the response fields for the CreateFilesystem operation. -type CreateFilesystemResponse = filesystem.CreateResponse +// CreateFileSystemResponse contains the response fields for the CreateFileSystem operation. +type CreateFileSystemResponse = filesystem.CreateResponse -// DeleteFilesystemResponse contains the response fields for the DeleteFilesystem operation. -type DeleteFilesystemResponse = filesystem.DeleteResponse +// DeleteFileSystemResponse contains the response fields for the DeleteFileSystem operation. +type DeleteFileSystemResponse = filesystem.DeleteResponse // SetPropertiesResponse contains the response fields for the SetProperties operation. type SetPropertiesResponse = service.SetPropertiesResponse @@ -27,5 +27,5 @@ type SetPropertiesResponse = service.SetPropertiesResponse // GetPropertiesResponse contains the response fields for the GetProperties operation. type GetPropertiesResponse = service.GetPropertiesResponse -// ListFilesystemsResponse contains the response fields for the ListFilesystems operation. -type ListFilesystemsResponse = generated_blob.ServiceClientListFileSystemsSegmentResponse +// ListFileSystemsResponse contains the response fields for the ListFileSystems operation. +type ListFileSystemsResponse = generated_blob.ServiceClientListFileSystemsSegmentResponse diff --git a/sdk/storage/azdatalake/test-resources.json b/sdk/storage/azdatalake/test-resources.json index c6259f7ab02f..88c380e64a8f 100644 --- a/sdk/storage/azdatalake/test-resources.json +++ b/sdk/storage/azdatalake/test-resources.json @@ -229,6 +229,11 @@ "apiVersion": "[variables('mgmtApiVersion')]", "name": "[concat(variables('dataLakeAccountName'), '/default')]", "properties": { + "deleteRetentionPolicy": { + "allowPermanentDelete": false, + "enabled": true, + "days": 7 + }, "containerDeleteRetentionPolicy": { "enabled": true, "days": 1 @@ -262,9 +267,9 @@ "properties": { "isVersioningEnabled": true, "deleteRetentionPolicy": { - "allowPermanentDelete": true, + "allowPermanentDelete": false, "enabled": true, - "days": 1 + "days": 7 }, "containerDeleteRetentionPolicy": { "enabled": true, From fd63ad0680c705c58ae17a99f3bc65bd23ace91e Mon Sep 17 00:00:00 2001 From: Tamer Sherif <69483382+tasherif-msft@users.noreply.github.com> Date: Wed, 16 Aug 2023 13:59:34 -0700 Subject: [PATCH 16/16] Merge main into Datalake branch (#21386) * remove old keyvault modules (#20931) * remove old keyvault * remove remaining references to sdk/keyvault * [azservicebus] Some cleanup in prep for release (#20932) - Removing some of unpredictability from the scheduled messages tests, now that we have messages state. - Noted some defers that were a little late in the new DefaultRule tests. * Enable CAE by default in azidentity beta (#20928) * Increment package version after release of containers/azcontainerregistry (#20956) * Use t.Setenv for setting/unsetting test-specific env vars (#20946) * replace pow util function with bit operation (#20941) * azidentity test cleanup (#20947) * prep for release (#20960) * Refactor some public surface in azcore/tracing (#20944) * Refactor some public surface in azcore/tracing This contains breaking changes against the previous beta. * update azotel for breaking changes * fix off-by-one error in var name * Sync eng/common directory with azure-sdk-tools for PR 6272 (#20957) * Support localspecrepo if pass in this parameter * Support regen sdk code based on local typespecs * Added reference doc to error message --------- Co-authored-by: raychen * Updating azcore to 1.6.0 (#20914) * Updating azcore to 1.6.0 * updating azidentity * [keyvault] azkeys renames (#20892) * azsecrets prep for release (#20962) * Increment package version after release of azidentity (#20966) * Fix populating module name in telemetry policy (#20967) SDKs that contain one or more clients in sub-packages could have their module name incorrectly set in the telemetry string. * Set telemetry schema on tracers (#20963) * Set telemetry schema on tracers Document the version in use. * remove unnecessary doc comment use string for version for now * Prep for azcore v1.7.0-beta.2 release (#20972) * [keyvault] update azcore (#20975) * update dependencies * update perf tests too * Increment package version after release of messaging/azeventhubs (#20969) * Increment package version after release of messaging/azservicebus (#20968) * Prep azotel for v0.1.0 release (#20977) * Prep azotel for v0.1.0 release * add code owners for azotel * fix build status links * Increment package version after release of tracing/azotel (#20979) * Increment package version after release of azcore (#20976) * Sync eng/common directory with azure-sdk-tools for PR 6293 (#20980) * Use local HEAD commit to create tsp-location.yaml * Set default repo value in tsp-location * Update eng/common/scripts/TypeSpec-Project-Process.ps1 Co-authored-by: Wes Haggard * Update eng/common/scripts/TypeSpec-Project-Process.ps1 Co-authored-by: Konrad Jamrozik * Resolve feedback * Fixed git remote repo parsing --------- Co-authored-by: raychen Co-authored-by: Wes Haggard Co-authored-by: Konrad Jamrozik * refine some logics and comments according to ACR service team's review (#20981) * Sync common script changes from azure-sdk repo (#20983) Co-authored-by: Wes Haggard * [keyvault] prep-for-release (#20991) * Increment package version after release of security/keyvault/azkeys (#20992) * Increment package version after release of security/keyvault/azsecrets (#20993) * Increment package version after release of security/keyvault/azadmin (#20994) * Remove autorest core version from build scripts (#20995) The code generator MUST be the ONLY source of this value. * Sync eng/common directory with azure-sdk-tools for PR 6305 (#20996) * Added switch to skip sync and generate script call * output switch * support forked spec repo in regex --------- Co-authored-by: raychen * [azeventgrid] Basic client, basic CloudEvent support (#20940) First generation of the Event Grid client, _very_ beta. It has all the basic functionality but needs some more work around CloudEvent and adding in documentation, etc... * armcompute 5.1.0-beta.1 release (#20985) * armcompute 5.1.0-beta.1 release Includes updated codegen for fakes and trace spans. * add module settinig to config file update build script to recursively clean files * update to latest code generator add fake testable example * update release date * armcontainerregistry 1.1.0-beta.2 release (#20986) * armcontainerregistry 1.1.0-beta.2 release * add module setting to config file * update to latest code generator add testable fake example bump release date * armnetwork 3.1.0-beta.1 release (#20987) * armnetwork 3.1.0-beta.1 release * update to latest code generator added testable fake example bump release date * armresources 1.2.0-beta.1 release (#20988) * armresources 1.2.0-beta.1 release * update to latest code generator added testable fake example bump release date * armsubscriptions 1.3.0-beta.1 release (#20989) * armsubscriptions 1.3.0-beta.1 release * update to latest code generator added fake testable example bump release date * armstorage 1.4.0-beta.1 release (#20990) * armstorage 1.4.0-beta.1 release * update to latest code generator added fake testable example bump release date * armcontainerservice 4.1.0-beta.2 release (#20998) * armmarketplaceordering v1.2.0-beta.1 release (#21006) * armmonitor 0.10.0 release (#20997) * armmonitor 0.10.0 release * bump release date * armresourcegraph v0.8.0 release (#21007) * Turn off git auto gc for sparse-checkout (#21014) Co-authored-by: James Suplizio * Add managed identity timeout to troubleshooting guide (#21018) * sdk/resourcemanager/batch/armbatch live test (#21025) * sdk/resourcemanager/managementgroups/armmanagementgroups live test (#21020) * sdk/resourcemanager/managementgroups/armmanagementgroups live test * subscriptioId default value * sdk/resourcemanager/relay/armrelay live test (#21016) * sdk/resourcemanager/search/armsearch live test (#20999) * sdk/resourcemanager/search/armsearch live test * subscriodId default value * azfile: Adding migration guide (#21022) * Sync eng/common directory with azure-sdk-tools for PR 6300 (#21026) * add fallback onto azure.sdk.tools.testproxy within generate-assets-json.ps1 Co-authored-by: scbedd <45376673+scbedd@users.noreply.github.com> Co-authored-by: Sameeksha Vaity Co-authored-by: Konrad Jamrozik * Adding in the CloudEvent type (#21027) The `CloudEvent` type implements the CloudEvent from https://github.com/cloudevents/spec/blob/v1.0.2/cloudevents/spec.md. This same format (and type) is used in the upcoming EventGrid SDK and is also intended to be usable with other messaging packages as well. Part of the fix for #20970 (remainder comes in a PR for Event Grid) * [Release] sdk/resourcemanager/recoveryservices/armrecoveryservices/1.4.0 (#20954) * [Release] sdk/resourcemanager/recoveryservices/armrecoveryservices/1.4.0 generation from spec commit: 0d41e635294dce73dfa99b07f3da4b68a9c9e29c * update assets * [Release] sdk/resourcemanager/selfhelp/armselfhelp/1.0.0 (#20952) * [Release] sdk/resourcemanager/selfhelp/armselfhelp/1.0.0 generation from spec commit: 0d41e635294dce73dfa99b07f3da4b68a9c9e29c * update assets and changelog * [Release] sdk/resourcemanager/containerservicefleet/armcontainerservicefleet/0.1.0 (#21012) * [Release] sdk/resourcemanager/containerservicefleet/armcontainerservicefleet/0.1.0 generation from spec commit: de14cb8751b978b1877597b13292818e80f8c661 * update readme * [Release] sdk/resourcemanager/redis/armredis/2.3.0 (#21001) * [Release] sdk/resourcemanager/redis/armredis/2.3.0 generation from spec commit: 1b33e81bbdc28fcd6644a1315b8d7b1b6d030590 * update assets * [Release] sdk/resourcemanager/cosmos/armcosmos/3.0.0-beta.1 generation from spec commit: 1b33e81bbdc28fcd6644a1315b8d7b1b6d030590 (#21005) * [Release] sdk/resourcemanager/trafficmanager/armtrafficmanager/1.2.0 generation from spec commit: 0d41e635294dce73dfa99b07f3da4b68a9c9e29c (#20949) * [Release] sdk/resourcemanager/graphservices/armgraphservices/1.0.0 (#20951) * [Release] sdk/resourcemanager/graphservices/armgraphservices/1.0.0 generation from spec commit: 0d41e635294dce73dfa99b07f3da4b68a9c9e29c * update changelog: rename func * [Release] sdk/resourcemanager/deviceprovisioningservices/armdeviceprovisioningservices/1.2.0-beta.1 (#20950) * [Release] sdk/resourcemanager/deviceprovisioningservices/armdeviceprovisioningservices/2.0.0-beta.1 generation from spec commit: 0d41e635294dce73dfa99b07f3da4b68a9c9e29c * add flag * [Release] sdk/resourcemanager/cosmosforpostgresql/armcosmosforpostgresql/0.1.0 (#20953) * [Release] sdk/resourcemanager/cosmosforpostgresql/armcosmosforpostgresql/1.0.0 generation from spec commit: 0d41e635294dce73dfa99b07f3da4b68a9c9e29c * replace version to v0.1.0 * add sdk/resourcemanager/cosmosforpostgresql/armcosmosforpostgresql live test * add readreplica live test * update assets * fix assests * [Release] sdk/resourcemanager/dataprotection/armdataprotection/2.2.0 generation from spec commit: 1b33e81bbdc28fcd6644a1315b8d7b1b6d030590 (#21003) * [Release] sdk/resourcemanager/storagecache/armstoragecache/3.2.0 (#21002) * [Release] sdk/resourcemanager/storagecache/armstoragecache/4.0.0 generation from spec commit: 1b33e81bbdc28fcd6644a1315b8d7b1b6d030590 * update * [Release] sdk/resourcemanager/containerservice/armcontainerservice/4.1.0-beta.2 (#21000) * [Release] sdk/resourcemanager/containerservice/armcontainerservice/4.1.0-beta.2 generation from spec commit: 1b33e81bbdc28fcd6644a1315b8d7b1b6d030590 * update assets * update * gofmt (#21039) * OpenAI client (#20617) Checking in @mikekistler's great work on the azopenai client. It covers completions, chat completions and embeddings, which places it at par with the features offered in our other beta Azure Open AI libraries. This client _also_ works against the public Open AI endpoint! * Deprecated sdk/resourcemanager/postgresqlhsc/armpostgresqlhsc (#21041) * Deprecated sdk/resourcemanager/postgresqlhsc/armpostgresqlhsc * update other version * [Release] sdk/resourcemanager/storagecache/armstoragecache/3.2.1 (#21045) * [Release] sdk/resourcemanager/storagecache/armstoragecache/3.2.1 generation from spec commit: c7f3e601fd326ca910c3d2939b516e15581e7e41 * add changelog * fix * update release-date * Enable Codeql in Analyze job for Go pipelines (#20682) * Enable CodeQL for scheduled builds only * Do this in Analyze instead * Adjust globals.yml scope and fix syntax * fix globals.yml scoping again * Update eng/pipelines/templates/jobs/archetype-sdk-client.yml Co-authored-by: Ben Broderick Phillips --------- Co-authored-by: Ben Broderick Phillips * [azeventgrid] Use the common azcore/messaging/CloudEvent model (#21028) * Using the new CloudEvent from azcore. * Used @jhendrixMSFT's trick to cleanly remove "external" models, which removed even more code. * Activated the live test part of the pipeline. * [azopenai] Fixing example's typo, creating a constructor for KeyCredential (#21042) Fixing a few things based on feedback from @JeffreyRichter. - Example had a typo and a hardcoded calculation. - Adding a constructor for KeyCredential. * [keyvault] azcertificates renames (#20978) * renames * update tests * feedback * id type * Add branch merging support to our mirror pipeline (#21050) This adds the ability to do a branch merge as part of our mirroring pipeline. The merge will allow configuration of which files to move from source to target so it can be scoped to part of the branch. Instead of a standard push it will create a PR with the merge so it can be manually reviewed. Co-authored-by: Wes Haggard * Add support for shallow cloning azcore.Client instances (#21065) * Add support for shallow cloning azcore.Client instances This allows for multiple clients to share the same underlying pipeline while having the correct client name string in traces. * improved field names * [Release] sdk/resourcemanager/managednetworkfabric/armmanagednetworkfabric/0.1.0 generation from spec commit: d03c1964cb76ffd6884d10a1871bbe779a2f68ef (#21070) * chore: pkg imported more than once (#21076) * chore: fmt modify (#21069) * chore: slice replace loop (#21064) * [azopenai] Adding in streaming for ChatCompletions, like we have for Completions. (#21072) Also, did some cleanup/moving around of code to make it easier to find tests, etc... Fixes #21052 * [keyvault] id type (#21071) * update proxy version to include a few bugfixes (#21077) Co-authored-by: scbedd <45376673+scbedd@users.noreply.github.com> * update gotest version (#21082) * Updates for Codeowneers changes (#21084) Co-authored-by: James Suplizio * Updates for Codeowneers changes (#21085) Co-authored-by: James Suplizio * [azeventgrid] Removing the empty `Interface any` from `PublishCloudEventsResponse` (#21081) - Addressing some of the API feedback. - Removing the `Interface any` from the generated code for an empty response. - Making our env variable just line up with the common convention for writing out the ephemeral key. Still only available for our tests. * sdk/resourcemanager/search/armsearch fix require link (#21097) * Use otel tracerProvider interface instead of specific type (#21049) * use tracerProvider interface instead of specific type * update changelog --------- Co-authored-by: Joel Hendrix * Update test to ensure pipelines are equal (#21099) * [azopenai] Adding in image generation, as exported by the current .tsp (#21054) Adding in image generation for both Azure OpenAI and OpenAI. - Automated the remaining pieces so we can generate from a .tsp file. - Updated from the latest tsp from Travis - Adding a workaround for the bug in Azure OpenAI with streaming. Working on a fix as it needs to be done service side. * Update DefaultAzureCredentialOptions docs (#21100) * bump targeted proxy version (#21105) Co-authored-by: scbedd <45376673+scbedd@users.noreply.github.com> * [azeventgrid] Updates prior to release (#21115) * Updated to the latest autorest and using byval-slice. * Silly typo I noticed in the eventhubs readme * Refactor internal MSAL client constructors (#21117) * [azopenai] Improving one of the image tests a bit to check that we did get back a valid PNG #21127 * Sync eng/common directory with azure-sdk-tools for PR 6468 (#21130) * Update typespec common scripts * Revert change of specCloneDir variable --------- Co-authored-by: raychen * [azopenai] Errors weren't propagating properly in image generation for OpenAI (#21125) Code that was handwritten needs to check and return ResponseError's by hand. Added in code to fix this for image generation, and to add in testing for all the areas that have hand-written code (ChatCompletions and Completions streaming and Dall-E integration with OpenAI). Fixes #21120 * Pin original version of test-proxy while investigating azadmin/azfile/azblob issue (#21142) * azfile: Updating changelog for GA (#21140) * DefaultAzureCredential TenantID applies to workload identity (#21123) * Add flag to enable skipping of dependency checks (#21146) The dependency checking tool has some broken corner-cases. Until those are fixed, we need a flag to skip it in order to release. * Prepare for azcore 1.8.0-beta.1 release (#21150) * Prepare for azcore 1.8.0-beta.1 release * update changelog * Increment package version after release of azcore (#21153) * [azeventgrid] Prep for release #21154 Use azcore@v1.8.0-beta.1 * Increment package version after release of storage/azfile (#21147) * Add DragonFlyBSD in azfile (#21119) * Add DragonFlyBSD in azfile * include aix, update changelog --------- Co-authored-by: Joel Hendrix Co-authored-by: Sourav Gupta * sdk/resourcemanager/botservice/armbotservice live test (#21156) * Prep azotel for release (#21145) * Prep azotel for release * update to latest azcore beta * Increment package version after release of tracing/azotel (#21161) * changelog for azblob GA (#21159) * Update version of github-event-processor (#21163) Co-authored-by: James Suplizio * [azadmin] prep for release (#21165) * changelog * prep-for-release * Simplify GetToken synchronization (#21162) * Increment package version after release of storage/azblob (#21164) * Prepare azidentity v1.4.0-beta.2 for release (#21167) * Increment package version after release of azidentity (#21174) * Add Service Labels to CODEOWNERS (#21176) * [azopenai] Updating to the 2023-07-01 API surface (#21169) * Updating to the 2023-07-01 API surface - Adding in functions support and example. - Added in accomodation for content filtering info. - Make it so we can use separate service instances for some tests so we can test against the latest upcoming fixes/changes. * Sync eng/common directory with azure-sdk-tools for PR 6521 (#21180) * Use System.Threading.Mutex to make threadsafe * Rename test, add comments --------- Co-authored-by: Mike Harder * sdk/resourcemanager/advisor/armadvisor live test (#21170) * [Release] sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/1.0.0 (#21108) * [Release] sdk/resourcemanager/paloaltonetworksngfw/armpanngfw/1.0.0 generation from spec commit: 310a0100f5b020c1900c527a6aa70d21992f078a * update changelog * sdk/resourcemanager/analysisservices/armanalysisservices live test (#21181) * Disable CP1 for regional STS test (#21178) * Enable TLS renegotiation (#21182) Some endpoints require TLS renegotiation. There is no change in behavior for endpoints that don't. * [monitor] azingest (#21155) * [azsecrets] prep for release (#21186) * prep for release * fix time; * prep-for-release (#21187) * prep for release (#21185) * Increment package version after release of security/keyvault/azsecrets (#21191) * Increment package version after release of security/keyvault/azadmin (#21190) * Increment package version after release of security/keyvault/azcertificates (#21189) * Prep armmonitor for release (#21194) * Prep armmonitor for release * bump version * Increment package version after release of security/keyvault/azkeys (#21198) * update date (#21202) * [azopenai] Readme and examples (#21192) Creating examples and a readme for azopenai. Fixes #21038 * Sync eng/common directory with azure-sdk-tools for PR 6530 (#21199) * Update-DocsMsMetadata.ps1 can fail the build on invalid packages * Better error handling and logging * Review feedback --------- Co-authored-by: Daniel Jurek * Prep latest armcompute beta for release (#21203) * Prep armcontainerregistry beta for release (#21204) * Prep latest armcontainerservice beta for release (#21205) * Prep latest armcontainerservice beta for release * fix changelog entry * Prep latest armmarketplaceordering beta for release (#21206) * Prep latest armmonitor beta for release (#21207) * Prep latest armnetwork beta for release (#21209) * Prep latest armresourcegraph beta for release (#21210) * Prep latest armresources beta for release (#21211) * Prep latest armsubscriptions beta for release (#21212) * Prep latest armstorage beta for release (#21213) * [Release] sdk/resourcemanager/networkcloud/armnetworkcloud/0.2.0 generation from spec commit: c53808ba54beef57059371708f1fa6949a11a280 (#21137) * [azopenai] Removing the constants in functions example, they seem to confuse more than help. (#21218) * Also, updated changelog release date to today * Formalize contract for fakes sanitizing request URLs (#21217) The current fakes codegen makes assumptions about the faked URL format. Make the faked next page URL a bit more unique/obvious it's a fake. Propagate any query parameters from the original request's URL to the faked URL. * AzureCLICredential and OnBehalfOfCredential return errors immediately on failure (#21219) * update deps for spelling tool (#21220) Co-authored-by: Jeff Fisher * Sync eng/common directory with azure-sdk-tools for PR 6544 (#21221) * Only save package properties for track 2 packages (prevents overwrites of track 2 package info by track 1 packages) * Only overwrite if the package is track 2 --------- Co-authored-by: Daniel Jurek * upgrage @autorest/go version (#21225) * [azopenai] Make the deployment ID a per-request parameter, rather than a constructor parameter. (#21223) A rather big change. Prior to this we required the deployment ID to be passed as a parameter when constructing the client. This had some advantages in that it matched the underlying physical properties for Azure (it's a route parameter, not a request parameteR), but it broke the de-facto conventions established by OpenAI, where the model is considered a request parameter. This is now changed, with the one concession being that the `Model` field has been renamed to `DeploymentID`, to match with the other Azure SDKs. * [azopenai] Add in REQUIRED (#21233) * Escape single-quote characters in partition and row keys (#21232) * Escapse single-quote characters in partition and row keys * update dependencies * fix swapped test parameters add requirement of non-empty slice to prevent panic if it is updated all test recordings * add unit test for prepareKey * prepare for release add empty string test * Increment package version after release of data/aztables (#21237) * azidentity test cleanup (#21235) * upgrade @autorest/go (#21239) * upgrade @autorest/go * reset dataplane * remove * [CODEOWNERS] Fix label pattern (#21242) The focus of these changes is to fix the naming pattern used in one of the IoT labels. * [Release] sdk/resourcemanager/cognitiveservices/armcognitiveservices/1.5.0 generation from spec commit: 310a0100f5b020c1900c527a6aa70d21992f078a (#21112) * [Release] sdk/resourcemanager/hdinsight/armhdinsight/1.2.0-beta.1 (#21114) * [Release] sdk/resourcemanager/hdinsight/armhdinsight/1.2.0-beta.1 generation from spec commit: 310a0100f5b020c1900c527a6aa70d21992f078a * Update CHANGELOG.md add changelog * [Release] sdk/resourcemanager/netapp/armnetapp/4.1.0 generation from spec commit: 310a0100f5b020c1900c527a6aa70d21992f078a (#21121) * [Release] sdk/resourcemanager/iotfirmwaredefense/armiotfirmwaredefense/0.1.0 generation from spec commit: 310a0100f5b020c1900c527a6aa70d21992f078a (#21113) * [Release] sdk/resourcemanager/dataprotection/armdataprotection/2.3.0 generation from spec commit: c53808ba54beef57059371708f1fa6949a11a280 (#21134) * [Release] sdk/resourcemanager/webpubsub/armwebpubsub/1.2.0-beta.1 generation from spec commit: c53808ba54beef57059371708f1fa6949a11a280 (#21139) * Regenerate azkeys with the latest code generator (#21248) In preparation to generate with tracing enabled. * Bump coverage gate up for identity (#21179) * Update aztables to use latest code generator (#21238) * Update aztables to use latest code generator * fix version number * Revert breaking change to Span.End() (#21252) The method has been in GA since v1.2.0 so we can't change it. * Set DOCKER_BUILDKIT to 1 in stress deploy image build (#21246) Co-authored-by: Ben Broderick Phillips * Make x509 certificate script from azure-sdk-for-net common to repos (#21253) Co-authored-by: Ben Broderick Phillips * Increment package version after release of messaging/azeventgrid (#21158) * Increment package version after release of cognitiveservices/azopenai (#21236) * [Release] sdk/resourcemanager/sphere/armsphere/0.1.0 (#21109) * [Release] sdk/resourcemanager/azuresphere/armazuresphere/0.1.0 generation from spec commit: 310a0100f5b020c1900c527a6aa70d21992f078a * rename namespaces * [Release] sdk/resourcemanager/elasticsan/armelasticsan/0.3.0 generation from spec commit: c53808ba54beef57059371708f1fa6949a11a280 (#21135) * [Release] sdk/resourcemanager/managednetworkfabric/armmanagednetworkfabric/1.0.0 generation from spec commit: 925ba149e17454ce91ecd3f9f4134effb2f97844 (#21171) * [Release] sdk/resourcemanager/authorization/armauthorization/3.0.0-beta.1 generation from spec commit: 310a0100f5b020c1900c527a6aa70d21992f078a (#21110) * [Release] sdk/resourcemanager/compute/armcompute/5.1.0 (#21132) * [Release] sdk/resourcemanager/compute/armcompute/5.1.0 generation from spec commit: c53808ba54beef57059371708f1fa6949a11a280 * update live test and assets * [Release] sdk/resourcemanager/containerservice/armcontainerservice/4.1.0 (#21133) * [Release] sdk/resourcemanager/containerservice/armcontainerservice/4.1.0 generation from spec commit: c53808ba54beef57059371708f1fa6949a11a280 * gomod and update assets * update * [Release] sdk/resourcemanager/storagemover/armstoragemover/2.0.0-beta.1 generation from spec commit: c53808ba54beef57059371708f1fa6949a11a280 (#21138) * [Release] sdk/resourcemanager/kusto/armkusto/2.0.0 generation from spec commit: 310a0100f5b020c1900c527a6aa70d21992f078a (#21107) * [Release] sdk/resourcemanager/batch/armbatch/2.0.0 generation from spec commit: 310a0100f5b020c1900c527a6aa70d21992f078a (#21111) * [Release] sdk/resourcemanager/network/armnetwork/4.0.0 (#21131) * [Release] sdk/resourcemanager/network/armnetwork/4.0.0 generation from spec commit: 9975d3476c05bcc6bd9535ad3dfb564e6a168fa5 * replace stable azcore * update live test and assets * [Release] sdk/resourcemanager/mobilenetwork/armmobilenetwork/3.0.0 (#21136) * [Release] sdk/resourcemanager/mobilenetwork/armmobilenetwork/3.0.0 generation from spec commit: c53808ba54beef57059371708f1fa6949a11a280 * regenerate * SAS creation fix when stored access policy is used (#21241) * [azblob][sas] Fix SignWithSharedKey if stored access policy is used @stotz89 (#21230) * [azblob][sas] Fix SignWithSharedKey if stored access policy is used * Adding test and changelog --------- Co-authored-by: Sourav Gupta * [azopenai] Move azopenai from `cognitiveservices/azopenai` to `ai/azopenai` (#21264) Part of the fix for #21260. - Moved the code (to preserve history) into `ai/azopenai` - Marked `cognitiveservices/azopenai`, prepping to release one last release to deprecate it. We still need to submit an issue to de-list `cognitiveservices/azopenai` but I believe this takes care of our end. * Update legacy azopenai yaml to add cognitiveservices suffix directive (#21269) * [azopenai] Update changelog to reflect new spot. (#21271) * Increment package version after release of ai/azopenai (#21272) * [internal] Extend telemetry test regexp (#21277) Regexp checks for major, minor and patch level, but fails with golang release candidate versions, as doesn't match regexp. Example: azsdk-go-azservicebus/v1.0.0 (go1.21rc3; linux) * [Storage] Lower Case Query Param Keys in String to Sign (#21262) * fixed string to sign issue * fixed test and added changelog * Auto-install and run standalone test proxy server per test package (#21168) * Auto-install and run standalone test proxy server per test package * Update recording tests to use standalone proxy * Simplify proxy binary switch statement * Add test proxy auto-install docs * Fix up recording test coverage * Add StopTestProxy note about go process handling * Proxy restore/race condition handling. Force ignore PROXY_MANUAL_START in internal tests * Fix recording readme error handling * [Release]sdk/resourcemanager/network/armnetwork/4.1.0-beta.1 (#21265) * sdk/resourcemanager/network/armnetwork/4.1.0-beta.1 * add fake_example_test.go * [Release] sdk/resourcemanager/containerservice/armcontainerservice/4.2.0-beta.1 (#21274) * [Release] sdk/resourcemanager/compute/armcompute/5.2.0-beta.1 (#21275) * [Release] sdk/resourcemanager/compute/armcompute/5.2.0-beta.1 * Update CHANGELOG.md * [Release] sdk/resourcemanager/sql/armsql/2.0.0-beta.1 (#21040) * [Release] sdk/resourcemanager/sql/armsql/2.0.0-beta.1 generation from spec commit: fba7ffa9cee6453e2a3cf8c857074a323252a12d * update release date * regenerated * regenerate * [azopenai] Rename the DeploymentID field to Deployment to match other Azure OpenAI packages (#21284) * Clean up constants in aztables (#21258) * Clean up constants in aztables Older versions of autorest implicitly sealed single-value enums, so enable the legacy behavior to avoid having to pass constant values. Updated the perf test to use the current version of aztables. * update perf test with renamed APIs * [azopenai] Enabling live testing (#21276) Adds in a ci.yml with live testing enabled and re-recordings since we moved to `ai` instead of `cognitiveservices`. * Make recording.proxyManualStartEnv private (#21288) * Sync eng/common directory with azure-sdk-tools for PR 6518 (#21200) * Bump test proxy version * move proxy transition-scripts folder to onboarding Co-authored-by: Bill Wert Co-authored-by: Scott Beddall * upgrade autorest extension version (#21293) * [azcore/azeventgrid] Remove json.RawMessage usage in the public API (#21282) * azcore: Removing the json.RawMessage dependency in the public API (it wasn't part of the signature (formally) but it was part of the returned type. * Consume new pre-release azcore in azeventgrid. * Sync eng/common directory with azure-sdk-tools for PR 6611 (#21295) * update dotnet dev cert being shipped with the proxy to renew for another year --------- Co-authored-by: Scott Beddall * Improve example for runtime.WithCaptureResponse (#21302) * Improve example for runtime.WithCaptureResponse * make linter happy * fix sentence * Don't swallow error on Close() (#21304) Return the result of reader.Close() to the caller. * update azadmin test (#21305) * [azopenai] Make sure we defer close the eventreader in our examples. (#21312) * prep for release (#21316) * Major version upgrade when processing fake (#21285) * add replaceFakeImport function * generic func * remove breakingchange judgment * fix * generator tool fix (#21320) * generator tool fix * fix README.md.tpl * Increment package version after release of monitor/azingest (#21208) * bump the proxy version (#21322) Co-authored-by: Scott Beddall * Prepare azidentity v1.4.0-beta.3 for release (#21331) * Increment package version after release of azidentity (#21337) * [azopenai] If the scanner reaches the end of stream and we haven't gotten the '[done]' token then return an error instead of silently failing. (#21323) Also: - Fixing casing of error message - shouldn't have a leading uppercase letter. - Fixing misspelled comment * add onboard judgment (#21341) * Used ScheduledPurgeDate for both KV, MHSM (#21344) The previous property was calculated so didn't exist from the REST-based call. Also updated the api-version to the latest stable control plane version. Co-authored-by: Heath Stewart * Increase azidentity test coverage (#21345) * [azopenai] Retract old congitiveservices/azopenai package. (#21350) This was the recommendation from the Go team on how to delist our old package from pkg.go.dev. * Include response body in IMDS 400 error message (#21351) * Add TokenRequestOptions.EnableCAE (#21362) * Prep azcore@v1.8.0-beta.2 for release (#21364) * Prep azcore@v1.8.0-beta.2 for release * remove empty section in readme * Update CODEOWNERS (#21366) Add @Azure/azure-sdk-write-identity as an owner of /sdk/azidentity * [azadmin] update test (#21369) * Fix typo in doc comment for the TokenFilePath field in workload_identity (#21353) * update date (#21370) * ARM bearer auth policy opts in to CAE (#21367) * Increment package version after release of azcore (#21371) * [azopenai] Add test for different formats in chat completions streaming (#21374) Also, updating CODEOWNERS to add @jhendrixMSFT to the ai folder. * Increment package version after release of security/keyvault/internal (#21375) * Update CODEOWNERS file for Monitor (#21377) * azblob: Upgrade to STG 85-86 (#21381) * Regenerating AzBlob to STG 85/86 (#20724) * Regenerating azblob to stg 85/86 * Updating CopyFromURL * minor change * minor fixes * undo some minor fixes * Updating Go code generator * Fixing calls to pipeline * Adding custom UnmarshalXML for BlobItem and BlobPrefix * Updating constructor method for AppendBlobClient * Updating Client constructors * Undoing minor fixes to blob examples * Fixing authpolicy * Updating azcore version * Fixing client strings * Const for service client * Minor fix * fixing go mod files * Shared constants client name * Addressing comments * [Feature STG 85/86] Cold Tier * [Checksum Work] BlockBlob Client: Transactional/Source Content Validation (#21033) * Adding test for transactional validation in block blob * StageBlockFromURL tests * Deprecating options in CommitBlockList * CopyFromURL test * Updating checksum behavior * Record tests * Updated recording * Updated recording again * Added error for user gen checksums, tests for UploadStream, UploadBuffer, and UploadFile * Added recorded test * Updated CommitBlockList, added tests for CommitBlockList, and added CRC64 test for Upload * Updating UploadStream test * Recorded test * Recorded test * Fixing CommitBlockList errors * Fixing linting issues * Addressing comment + handling CI issues * Removing TransactionalValidation from CommitBlockList + cleaning up tests * Rerecorded tests * Update azcore (#21188) * Updating azcore * Updating changelog.md * Updating go sum file * Update perf go file * Copy Blob from URL/Put Blob from URL copy source tags (#21128) * Regenerating AzBlob to STG 85/86 (#20724) * Regenerating azblob to stg 85/86 * Updating CopyFromURL * minor change * minor fixes * undo some minor fixes * Updating Go code generator * Fixing calls to pipeline * Adding custom UnmarshalXML for BlobItem and BlobPrefix * Updating constructor method for AppendBlobClient * Updating Client constructors * Undoing minor fixes to blob examples * Fixing authpolicy * Updating azcore version * Fixing client strings * Const for service client * Minor fix * fixing go mod files * Shared constants client name * Addressing comments * [Feature STG 85/86] Cold Tier (#21032) * Adding Cold Tier + tests * Recorded tests * Updated CHANGELOG.md * Fixing linting issues * Updating Cold tier test and recording * Addressing commits * Adding CopySourceBlobTags * Fixing enum variable name, adding default test, changelog update * Cleaning up constants * Moving const to constants.go * Small change * Adding PossibleBlobCopySourceTagsValues() Method for CopySourceTags * List System Containers (#21243) * Listing system containers * Updating CHANGELOG.md * Record test * Filter Tags API on Container (#21197) * Adding FilterBlobs to container client * Updating and adding tests * Updating URL Co-authored-by: Sourav Gupta <98318303+souravgupta-msft@users.noreply.github.com> * Updating comment Co-authored-by: Sourav Gupta <98318303+souravgupta-msft@users.noreply.github.com> * Updating CHANGELOG.md * Updating test --------- Co-authored-by: Sourav Gupta <98318303+souravgupta-msft@users.noreply.github.com> * Encryption Scope SAS (#21294) * Adding encryption sas to blob, account, and identity sas * Fixing issues with Blob SAS * Undo some changes * Undo some changes pt 2 * Undo some changes pt 3 * Adding doc comment * Updating variable names in the tests and updated account sas test * Updating tests * Adding back comment * Updating CHANGELOG.md * Update sdk/storage/azblob/sas/query_params.go Co-authored-by: Sourav Gupta <98318303+souravgupta-msft@users.noreply.github.com> * Update sdk/storage/azblob/CHANGELOG.md Co-authored-by: Sourav Gupta <98318303+souravgupta-msft@users.noreply.github.com> * Removing SI from Account SAS --------- Co-authored-by: Sourav Gupta <98318303+souravgupta-msft@users.noreply.github.com> * Test Encryption Scope support for Sync Blob Copy (SyncCopyFromUrl) (#21332) * Test List Blobs Fix for Invalid XML Characters * minor fixes to changelog --------- Co-authored-by: Sourav Gupta <98318303+souravgupta-msft@users.noreply.github.com> * Upgrade azidentity dependencies (#21379) * Increment package version after release of azidentity (#21385) --------- Co-authored-by: gracewilcox <43627800+gracewilcox@users.noreply.github.com> Co-authored-by: Richard Park <51494936+richardpark-msft@users.noreply.github.com> Co-authored-by: Charles Lowell <10964656+chlowell@users.noreply.github.com> Co-authored-by: Azure SDK Bot <53356347+azure-sdk@users.noreply.github.com> Co-authored-by: Joel Hendrix Co-authored-by: MartinForReal Co-authored-by: raychen Co-authored-by: Sourav Gupta <98318303+souravgupta-msft@users.noreply.github.com> Co-authored-by: Wes Haggard Co-authored-by: Konrad Jamrozik Co-authored-by: Chenjie Shi Co-authored-by: Wes Haggard Co-authored-by: James Suplizio Co-authored-by: Peng Jiahui <46921893+Alancere@users.noreply.github.com> Co-authored-by: scbedd <45376673+scbedd@users.noreply.github.com> Co-authored-by: Sameeksha Vaity Co-authored-by: Konrad Jamrozik Co-authored-by: Mike Kistler Co-authored-by: Scott Kurtzeborn Co-authored-by: Ben Broderick Phillips Co-authored-by: guangwu Co-authored-by: Benjamin Tamasi Co-authored-by: Antonio Huete Jimenez Co-authored-by: Sourav Gupta Co-authored-by: Mike Harder Co-authored-by: Daniel Jurek Co-authored-by: Jeff Fisher Co-authored-by: Jesse Squire Co-authored-by: Rick Winter Co-authored-by: Ben Broderick Phillips Co-authored-by: Philipp Co-authored-by: Mikel Olasagasti Uranga Co-authored-by: Bill Wert Co-authored-by: Scott Beddall Co-authored-by: Heath Stewart Co-authored-by: Josh Free Co-authored-by: Ahson Khan Co-authored-by: Scott Addie <10702007+scottaddie@users.noreply.github.com> Co-authored-by: siminsavani-msft <77068571+siminsavani-msft@users.noreply.github.com> --- .github/CODEOWNERS | 562 +- .github/workflows/event-processor.yml | 7 +- .../workflows/scheduled-event-processor.yml | 32 +- .gitignore | 3 + documentation/developer_setup.md | 7 +- eng/common/TestResources/README.md | 1 + .../templates/steps/create-pull-request.yml | 12 +- .../templates/steps/docs-metadata-release.yml | 119 - .../steps/docsms-ensure-validation.yml | 11 + .../templates/steps/sparse-checkout.yml | 4 + eng/common/scripts/Delete-RemoteBranches.ps1 | 67 +- .../Helpers/DevOps-WorkItem-Helpers.ps1 | 13 +- .../scripts/Helpers/PSModule-Helpers.ps1 | 71 +- .../scripts/Helpers/Resource-Helpers.ps1 | 8 +- .../scripts/Save-Package-Properties.ps1 | 14 + eng/common/scripts/Test-SampleMetadata.ps1 | 1 + .../scripts/TypeSpec-Project-Generate.ps1 | 26 +- .../scripts/TypeSpec-Project-Process.ps1 | 228 + eng/common/scripts/TypeSpec-Project-Sync.ps1 | 182 +- eng/common/scripts/Update-DocsMsMetadata.ps1 | 39 +- eng/common/scripts/Update-DocsMsPackages.ps1 | 76 +- eng/common/scripts/X509Certificate2/README.md | 24 + .../X509Certificate2/X509Certificate2.psm1 | 339 + eng/common/scripts/get-codeowners.lib.ps1 | 35 +- .../stress-testing/deploy-stress-tests.ps1 | 8 +- .../stress-test-deployment-lib.ps1 | 46 +- eng/common/spelling/package-lock.json | 1694 +- eng/common/testproxy/dotnet-devcert.crt | 33 +- eng/common/testproxy/dotnet-devcert.pfx | Bin 2445 -> 2627 bytes .../README.md => onboarding/README.me} | 10 +- .../generate-assets-json.ps1 | 50 +- eng/common/testproxy/publish-proxy-logs.yml | 4 +- eng/common/testproxy/target_version.txt | 2 +- eng/config.json | 20 +- .../templates/jobs/archetype-go-release.yml | 5 +- .../templates/jobs/archetype-sdk-client.yml | 31 +- eng/pipelines/templates/steps/analyze.yml | 1 + eng/pipelines/templates/steps/build-test.yml | 2 + eng/pipelines/templates/variables/globals.yml | 3 + eng/scripts/MgmtTestLib.ps1 | 9 +- eng/scripts/build.ps1 | 13 +- eng/tools/generator/autorest/generation.go | 2 +- .../generator/autorest/model/changelog.go | 2 +- .../cmd/v2/common/changelogProcessor_test.go | 15 +- .../generator/cmd/v2/common/fileProcessor.go | 76 +- .../cmd/v2/common/fileProcessor_test.go | 2 +- .../generator/cmd/v2/common/generation.go | 10 +- .../generator/cmd/v2/release/releaseCmd.go | 11 +- .../template/rpName/packageName/README.md.tpl | 2 +- eng/tools/internal/report/packages.go | 8 +- eng/tools/mgmtreport/mgmtreport.tpl | 6 +- sdk/ai/azopenai/CHANGELOG.md | 28 + sdk/ai/azopenai/LICENSE.txt | 21 + sdk/ai/azopenai/README.md | 98 + sdk/ai/azopenai/assets.json | 6 + sdk/ai/azopenai/autorest.md | 297 + sdk/ai/azopenai/build.go | 14 + sdk/ai/azopenai/ci.yml | 57 + sdk/ai/azopenai/client.go | 231 + .../azopenai/client_chat_completions_test.go | 233 + sdk/ai/azopenai/client_completions_test.go | 81 + sdk/ai/azopenai/client_embeddings_test.go | 97 + sdk/ai/azopenai/client_functions_test.go | 94 + sdk/ai/azopenai/client_rai_test.go | 93 + sdk/ai/azopenai/client_shared_test.go | 259 + sdk/ai/azopenai/client_test.go | 42 + sdk/ai/azopenai/constants.go | 131 + sdk/ai/azopenai/custom_client.go | 259 + sdk/ai/azopenai/custom_client_functions.go | 41 + sdk/ai/azopenai/custom_client_image.go | 88 + sdk/ai/azopenai/custom_client_image_test.go | 118 + sdk/ai/azopenai/custom_client_test.go | 179 + sdk/ai/azopenai/custom_models.go | 97 + sdk/ai/azopenai/custom_models_test.go | 66 + sdk/ai/azopenai/event_reader.go | 68 + sdk/ai/azopenai/event_reader_test.go | 77 + .../example_client_createimage_test.go | 66 + .../example_client_embeddings_test.go | 55 + .../example_client_getchatcompletions_test.go | 271 + .../example_client_getcompletions_test.go | 118 + sdk/ai/azopenai/example_client_test.go | 63 + sdk/ai/azopenai/genopenapi3.ps1 | 5 + sdk/ai/azopenai/go.mod | 28 + sdk/ai/azopenai/go.sum | 46 + .../build.go => ai/azopenai/main_test.go} | 18 +- sdk/ai/azopenai/models.go | 707 + sdk/ai/azopenai/models_serde.go | 1551 ++ sdk/ai/azopenai/options.go | 31 + sdk/ai/azopenai/policy_apikey.go | 46 + sdk/ai/azopenai/policy_apikey_test.go | 84 + sdk/ai/azopenai/response_types.go | 39 + sdk/ai/azopenai/sample.env | 19 + sdk/ai/azopenai/testdata/.gitignore | 3 + .../content_filter_response_error.json | 30 + sdk/ai/azopenai/testdata/package-lock.json | 1009 + sdk/ai/azopenai/testdata/package.json | 16 + sdk/ai/azopenai/testdata/tsp-location.yaml | 4 + sdk/ai/azopenai/testdata/tspconfig.yaml | 11 + .../doc.go => ai/azopenai/version.go} | 6 +- sdk/azcore/CHANGELOG.md | 80 +- sdk/azcore/arm/client.go | 9 +- sdk/azcore/arm/runtime/pipeline_test.go | 2 +- sdk/azcore/arm/runtime/policy_bearer_token.go | 16 +- .../arm/runtime/policy_bearer_token_test.go | 3 + sdk/azcore/arm/runtime/policy_register_rp.go | 18 +- .../arm/runtime/policy_register_rp_test.go | 34 +- .../arm/runtime/policy_trace_namespace.go | 5 +- .../runtime/policy_trace_namespace_test.go | 8 +- sdk/azcore/core.go | 34 +- sdk/azcore/core_test.go | 49 + sdk/azcore/fake/example_test.go | 31 +- sdk/azcore/fake/fake.go | 320 +- sdk/azcore/fake/fake_test.go | 147 +- sdk/azcore/fake/internal/exported/fake.go | 415 + .../fake/internal/exported/fake_test.go | 265 + sdk/azcore/fake/server/server.go | 230 + sdk/azcore/fake/server/server_test.go | 286 + sdk/azcore/internal/exported/exported.go | 41 + sdk/azcore/internal/exported/request.go | 23 + sdk/azcore/internal/pollers/fake/fake.go | 23 +- sdk/azcore/internal/pollers/fake/fake_test.go | 4 + sdk/azcore/internal/shared/constants.go | 7 +- sdk/azcore/internal/shared/shared.go | 54 +- sdk/azcore/internal/shared/shared_test.go | 52 +- sdk/azcore/messaging/cloud_event.go | 291 + sdk/azcore/messaging/cloud_event_test.go | 228 + .../messaging/example_usingcloudevent_test.go | 59 + .../cloudevent_binary_with_extensions.json | 15 + .../testdata/cloudevent_required_only.json | 6 + sdk/azcore/runtime/examples_test.go | 12 +- sdk/azcore/runtime/policy_bearer_token.go | 24 +- .../runtime/policy_bearer_token_test.go | 9 +- sdk/azcore/runtime/policy_retry.go | 13 +- sdk/azcore/runtime/policy_retry_test.go | 33 + sdk/azcore/runtime/poller_test.go | 14 +- sdk/azcore/runtime/request.go | 12 +- sdk/azcore/runtime/response.go | 30 +- .../runtime/transport_default_http_client.go | 3 +- sdk/azcore/tracing/tracing.go | 18 +- sdk/azcore/tracing/tracing_test.go | 17 +- sdk/azidentity/CHANGELOG.md | 37 + sdk/azidentity/TROUBLESHOOTING.md | 2 + sdk/azidentity/azidentity.go | 34 +- sdk/azidentity/azidentity_test.go | 145 +- sdk/azidentity/azure_cli_credential.go | 100 +- sdk/azidentity/azure_cli_credential_test.go | 34 +- .../chained_token_credential_test.go | 29 +- sdk/azidentity/client_assertion_credential.go | 18 +- .../client_assertion_credential_test.go | 33 +- .../client_certificate_credential.go | 22 +- .../client_certificate_credential_test.go | 35 +- sdk/azidentity/client_secret_credential.go | 20 +- .../client_secret_credential_test.go | 5 +- sdk/azidentity/default_azure_credential.go | 10 +- .../default_azure_credential_test.go | 113 +- sdk/azidentity/device_code_credential.go | 21 +- sdk/azidentity/device_code_credential_test.go | 9 +- sdk/azidentity/environment_credential_test.go | 43 +- sdk/azidentity/go.mod | 14 +- sdk/azidentity/go.sum | 28 +- .../interactive_browser_credential.go | 18 +- .../interactive_browser_credential_test.go | 12 +- sdk/azidentity/live_test.go | 69 +- sdk/azidentity/managed_identity_client.go | 6 +- .../managed_identity_client_test.go | 97 +- sdk/azidentity/managed_identity_credential.go | 2 +- .../managed_identity_credential_test.go | 98 +- sdk/azidentity/mock_test.go | 131 +- sdk/azidentity/on_behalf_of_credential.go | 18 +- .../on_behalf_of_credential_test.go | 37 +- sdk/azidentity/syncer.go | 44 +- sdk/azidentity/syncer_test.go | 7 +- .../username_password_credential.go | 19 +- .../username_password_credential_test.go | 5 +- sdk/azidentity/version.go | 2 +- sdk/azidentity/workload_identity.go | 2 +- sdk/azidentity/workload_identity_test.go | 40 +- sdk/cognitiveservices/azopenai/CHANGELOG.md | 17 + sdk/cognitiveservices/azopenai/LICENSE.txt | 21 + sdk/cognitiveservices/azopenai/README.md | 1 + sdk/cognitiveservices/azopenai/assets.json | 6 + sdk/cognitiveservices/azopenai/autorest.md | 297 + sdk/cognitiveservices/azopenai/build.go | 14 + .../azopenai/ci.cognitiveservices.yml | 28 + sdk/cognitiveservices/azopenai/client.go | 231 + .../azopenai/client_chat_completions_test.go | 233 + .../azopenai/client_completions_test.go | 74 + .../azopenai/client_embeddings_test.go | 99 + .../azopenai/client_functions_test.go | 94 + .../azopenai/client_rai_test.go | 93 + .../azopenai/client_shared_test.go | 260 + sdk/cognitiveservices/azopenai/client_test.go | 42 + sdk/cognitiveservices/azopenai/constants.go | 131 + .../azopenai/custom_client.go | 259 + .../azopenai/custom_client_functions.go | 41 + .../azopenai/custom_client_image.go | 88 + .../azopenai/custom_client_image_test.go | 118 + .../azopenai/custom_client_test.go | 175 + .../azopenai/custom_models.go | 97 + .../azopenai/custom_models_test.go | 66 + .../azopenai/event_reader.go | 63 + .../azopenai/event_reader_test.go | 42 + .../example_client_createimage_test.go | 66 + .../example_client_embeddings_test.go | 55 + .../example_client_getchatcompletions_test.go | 270 + .../example_client_getcompletions_test.go | 116 + .../azopenai/example_client_test.go | 63 + .../azopenai/genopenapi3.ps1 | 5 + sdk/cognitiveservices/azopenai/go.mod | 31 + sdk/cognitiveservices/azopenai/go.sum | 46 + sdk/cognitiveservices/azopenai/main_test.go | 14 + sdk/cognitiveservices/azopenai/models.go | 707 + .../azopenai/models_serde.go | 1551 ++ sdk/cognitiveservices/azopenai/options.go | 31 + .../azopenai/policy_apikey.go | 46 + .../azopenai/policy_apikey_test.go | 84 + .../azopenai/response_types.go | 39 + sdk/cognitiveservices/azopenai/sample.env | 19 + .../azopenai/testdata/.gitignore | 3 + .../content_filter_response_error.json | 30 + .../azopenai/testdata/package-lock.json | 1009 + .../azopenai/testdata/package.json | 16 + .../azopenai/testdata/tsp-location.yaml | 4 + .../azopenai/testdata/tspconfig.yaml | 11 + .../azopenai}/version.go | 5 +- .../azcontainerregistry/CHANGELOG.md | 18 +- sdk/containers/azcontainerregistry/README.md | 50 +- .../azcontainerregistry/TROUBLESHOOTING.md | 177 + .../azcontainerregistry/assets.json | 2 +- .../authentication_client_test.go | 45 + .../authentication_policy_test.go | 79 + .../azcontainerregistry/autorest.md | 22 + .../azcontainerregistry/blob_client_test.go | 252 +- .../azcontainerregistry/blob_custom_client.go | 44 +- .../blob_custom_client_test.go | 79 +- sdk/containers/azcontainerregistry/build.go | 2 +- sdk/containers/azcontainerregistry/ci.yml | 2 +- .../azcontainerregistry/client_test.go | 283 +- .../azcontainerregistry/cloud_config.go | 4 + .../azcontainerregistry/constants_test.go | 40 + .../azcontainerregistry/custom_client.go | 3 +- .../azcontainerregistry/custom_constants.go | 5 +- .../azcontainerregistry/digest_helper.go | 163 + .../azcontainerregistry/digest_helper_test.go | 53 + ...le_test.go => example_blob_client_test.go} | 65 +- ....go => example_blob_custom_client_test.go} | 34 +- ...example_test.go => example_client_test.go} | 62 +- ..._test.go => example_custom_client_test.go} | 0 .../example_download_image_test.go | 98 + .../example_upload_download_blob_test.go | 53 - ...t_test.go => example_upload_image_test.go} | 33 +- .../azcontainerregistry/models_serde.go | 108 - .../azcontainerregistry/time_rfc3339_test.go | 76 + sdk/data/aztables/CHANGELOG.md | 10 +- sdk/data/aztables/assets.json | 2 +- sdk/data/aztables/autorest.md | 7 +- sdk/data/aztables/build.go | 1 + sdk/data/aztables/client.go | 41 +- sdk/data/aztables/client_test.go | 3 +- sdk/data/aztables/connection_string_test.go | 32 +- sdk/data/aztables/entity.go | 7 +- sdk/data/aztables/entity_test.go | 11 + sdk/data/aztables/go.mod | 26 +- sdk/data/aztables/go.sum | 65 +- sdk/data/aztables/internal/connection.go | 39 - sdk/data/aztables/internal/models_serde.go | 121 - sdk/data/aztables/internal/service_client.go | 220 +- sdk/data/aztables/internal/table_client.go | 942 +- .../aztables/internal/version.go} | 3 +- .../{constants.go => zz_constants.go} | 85 +- sdk/data/aztables/internal/zz_models.go | 193 + sdk/data/aztables/internal/zz_models_serde.go | 314 + .../internal/{models.go => zz_options.go} | 217 +- ...response_types.go => zz_response_types.go} | 38 +- .../aztables/internal/zz_service_client.go | 223 + sdk/data/aztables/internal/zz_table_client.go | 985 + .../{time_rfc1123.go => zz_time_rfc1123.go} | 2 +- .../{time_rfc3339.go => zz_time_rfc3339.go} | 2 +- sdk/data/aztables/service_client.go | 64 +- sdk/data/aztables/testdata/perf/go.mod | 18 +- sdk/data/aztables/testdata/perf/go.sum | 76 +- .../aztables/testdata/perf/insert_entity.go | 4 +- .../aztables/testdata/perf/list_entities.go | 6 +- sdk/data/aztables/transactional_batch.go | 10 +- sdk/data/aztables/zt_table_recorded_tests.go | 6 +- sdk/internal/CHANGELOG.md | 2 + sdk/internal/perf/README.md | 2 +- sdk/internal/perf/recording_test.go | 25 +- sdk/internal/recording/README.md | 26 +- sdk/internal/recording/matchers.go | 4 +- sdk/internal/recording/matchers_test.go | 172 +- sdk/internal/recording/recording.go | 16 +- sdk/internal/recording/recording_test.go | 373 +- sdk/internal/recording/sanitizer_test.go | 525 +- sdk/internal/recording/server.go | 446 + sdk/internal/recording/server_test.go | 84 + .../TestBackwardSlashPath.json | 0 .../TestGenerateAlphaNumericID.json | 2 +- .../TestModeNotSetStartStop.json | 0 .../TestSetBodilessMatcherNilTest.json | 0 .../{ => TestRecording}/TestStartStop.json | 0 .../TestBodyKeySanitizer.json | 0 .../TestBodyRegexSanitizer.json | 0 .../TestContinuationSanitizer.json | 0 .../TestGeneralRegexSanitizer.json | 0 .../TestHeaderRegexSanitizer.json | 0 .../TestOAuthResponseSanitizer.json | 0 .../TestRemoveHeaderSanitizer.json | 0 .../TestResetSanitizers.json | 0 .../TestSingleTestSanitizer-0.json | 0 .../TestSingleTestSanitizer-1.json | 0 .../TestUriSanitizer.json | 0 .../TestUriSubscriptionIdSanitizer.json | 0 .../recordings/TestSetBodilessMatcher.json | 36 - .../recordings/TestSetDefaultMatcher.json | 36 - sdk/internal/telemetry/telemetry_test.go | 3 +- sdk/keyvault/TROUBLESHOOTING.md | 121 - sdk/keyvault/azcertificates/CHANGELOG.md | 102 - sdk/keyvault/azcertificates/LICENSE.txt | 21 - sdk/keyvault/azcertificates/README.md | 146 - .../azcertificates/TROUBLESHOOTING.md | 4 - sdk/keyvault/azcertificates/autorest.md | 133 - sdk/keyvault/azcertificates/client.go | 1415 -- sdk/keyvault/azcertificates/client_test.go | 670 - sdk/keyvault/azcertificates/constants.go | 153 - sdk/keyvault/azcertificates/custom_client.go | 93 - sdk/keyvault/azcertificates/example_test.go | 96 - sdk/keyvault/azcertificates/go.mod | 29 - sdk/keyvault/azcertificates/models.go | 662 - sdk/keyvault/azcertificates/models_serde.go | 1377 -- sdk/keyvault/azcertificates/response_types.go | 145 - .../azcertificates/test-resources.json | 331 - sdk/keyvault/azcertificates/testdata/ca.crt | 21 - sdk/keyvault/azcertificates/testdata/ca.key | 27 - .../testdata/perf/get_certificate.go | 107 - .../azcertificates/testdata/perf/go.mod | 23 - .../azcertificates/testdata/perf/go.sum | 57 - .../azcertificates/testdata/perf/main.go | 12 - .../recordings/TestBackupRestore.json | 653 - .../testdata/recordings/TestCRUD.json | 592 - .../testdata/recordings/TestContactsCRUD.json | 176 - .../recordings/TestDeleteRecover.json | 687 - .../recordings/TestImportCertificate.json | 210 - .../testdata/recordings/TestIssuerCRUD.json | 295 - .../TestListCertificateVersions.json | 573 - .../recordings/TestListCertificates.json | 1997 -- .../recordings/TestMergeCertificate.json | 319 - .../recordings/TestOperationCRUD.json | 205 - .../TestUpdateCertificatePolicy.json | 384 - sdk/keyvault/azcertificates/time_unix.go | 62 - sdk/keyvault/azcertificates/utils_test.go | 162 - sdk/keyvault/azcertificates/version.go | 12 - sdk/keyvault/azkeys/CHANGELOG.md | 109 - sdk/keyvault/azkeys/LICENSE.txt | 21 - sdk/keyvault/azkeys/README.md | 147 - sdk/keyvault/azkeys/TROUBLESHOOTING.md | 4 - sdk/keyvault/azkeys/autorest.md | 122 - sdk/keyvault/azkeys/client.go | 1302 -- sdk/keyvault/azkeys/client_test.go | 743 - sdk/keyvault/azkeys/constants.go | 270 - sdk/keyvault/azkeys/custom_client.go | 63 - sdk/keyvault/azkeys/example_test.go | 155 - sdk/keyvault/azkeys/go.mod | 29 - sdk/keyvault/azkeys/go.sum | 48 - sdk/keyvault/azkeys/models.go | 549 - sdk/keyvault/azkeys/models_serde.go | 1120 -- sdk/keyvault/azkeys/platform-matrix.json | 17 - sdk/keyvault/azkeys/response_types.go | 130 - sdk/keyvault/azkeys/test-resources-post.ps1 | 118 - sdk/keyvault/azkeys/test-resources.json | 296 - sdk/keyvault/azkeys/testdata/perf/decrypt.go | 132 - sdk/keyvault/azkeys/testdata/perf/get_key.go | 96 - sdk/keyvault/azkeys/testdata/perf/go.mod | 23 - sdk/keyvault/azkeys/testdata/perf/go.sum | 57 - sdk/keyvault/azkeys/testdata/perf/main.go | 15 - sdk/keyvault/azkeys/testdata/perf/sign.go | 125 - sdk/keyvault/azkeys/testdata/perf/unwrap.go | 129 - .../recordings/TestBackupRestore/KV.json | 498 - .../recordings/TestBackupRestore/MHSM.json | 398 - .../testdata/recordings/TestCRUD/EC.json | 393 - .../testdata/recordings/TestCRUD/EC_MHSM.json | 337 - .../testdata/recordings/TestCRUD/RSA.json | 409 - .../recordings/TestCRUD/RSA_MHSM.json | 353 - .../recordings/TestEncryptDecrypt/KV.json | 168 - .../recordings/TestEncryptDecrypt/MHSM.json | 153 - .../TestEncryptDecryptSymmetric.json | 155 - .../recordings/TestGetRandomBytes.json | 62 - .../testdata/recordings/TestImportKey/KV.json | 153 - .../recordings/TestImportKey/MHSM.json | 139 - .../recordings/TestListDeletedKeys/KV.json | 1352 -- .../recordings/TestListDeletedKeys/MHSM.json | 986 - .../recordings/TestListKeyVersions/KV.json | 490 - .../recordings/TestListKeyVersions/MHSM.json | 458 - .../testdata/recordings/TestListKeys/KV.json | 915 - .../recordings/TestListKeys/MHSM.json | 696 - .../recordings/TestRecoverDeletedKey/KV.json | 414 - .../TestRecoverDeletedKey/MHSM.json | 322 - .../recordings/TestReleaseKey/KV.json | 211 - .../recordings/TestReleaseKey/MHSM.json | 199 - .../testdata/recordings/TestRotateKey/KV.json | 354 - .../recordings/TestRotateKey/MHSM.json | 311 - .../recordings/TestSignVerify/KV.json | 170 - .../recordings/TestSignVerify/MHSM.json | 156 - .../recordings/TestWrapUnwrap/KV.json | 168 - .../recordings/TestWrapUnwrap/MHSM.json | 153 - sdk/keyvault/azkeys/utils_test.go | 247 - sdk/keyvault/azsecrets/CHANGELOG.md | 120 - sdk/keyvault/azsecrets/LICENSE.txt | 21 - sdk/keyvault/azsecrets/README.md | 144 - sdk/keyvault/azsecrets/TROUBLESHOOTING.md | 4 - sdk/keyvault/azsecrets/autorest.md | 96 - sdk/keyvault/azsecrets/client.go | 650 - sdk/keyvault/azsecrets/client_test.go | 416 - sdk/keyvault/azsecrets/constants.go | 63 - sdk/keyvault/azsecrets/custom_client.go | 63 - sdk/keyvault/azsecrets/example_test.go | 155 - sdk/keyvault/azsecrets/go.mod | 29 - sdk/keyvault/azsecrets/go.sum | 48 - sdk/keyvault/azsecrets/models.go | 268 - sdk/keyvault/azsecrets/models_serde.go | 501 - sdk/keyvault/azsecrets/response_types.go | 70 - sdk/keyvault/azsecrets/test-resources.json | 331 - .../azsecrets/testdata/perf/get_secret.go | 95 - sdk/keyvault/azsecrets/testdata/perf/go.mod | 23 - sdk/keyvault/azsecrets/testdata/perf/go.sum | 57 - .../azsecrets/testdata/perf/list_secrets.go | 117 - sdk/keyvault/azsecrets/testdata/perf/main.go | 13 - .../recordings/TestBackupRestore.json | 377 - .../testdata/recordings/TestCRUD.json | 390 - .../recordings/TestListDeletedSecrets.json | 498 - .../recordings/TestListSecretVersions.json | 401 - .../testdata/recordings/TestListSecrets.json | 574 - .../testdata/recordings/TestRecover.json | 350 - sdk/keyvault/azsecrets/time_unix.go | 62 - sdk/keyvault/azsecrets/utils_test.go | 160 - sdk/keyvault/internal/CHANGELOG.md | 65 - sdk/keyvault/internal/LICENSE.txt | 21 - sdk/keyvault/internal/README.md | 23 - sdk/keyvault/internal/challenge_policy.go | 175 - .../internal/challenge_policy_test.go | 109 - sdk/keyvault/internal/go.mod | 17 - sdk/keyvault/internal/go.sum | 19 - sdk/keyvault/internal/parse.go | 37 - sdk/keyvault/internal/parse_test.go | 46 - sdk/messaging/azeventgrid/CHANGELOG.md | 17 + sdk/messaging/azeventgrid/LICENSE.txt | 21 + sdk/messaging/azeventgrid/NOTICE.txt | 32 + sdk/messaging/azeventgrid/README.md | 114 + sdk/messaging/azeventgrid/assets.json | 6 + sdk/messaging/azeventgrid/autorest.md | 79 + .../azkeys => messaging/azeventgrid}/build.go | 9 +- sdk/messaging/azeventgrid/ci.yml | 30 + sdk/messaging/azeventgrid/client.go | 326 + sdk/messaging/azeventgrid/client_custom.go | 77 + sdk/messaging/azeventgrid/client_test.go | 291 + .../example_publish_and_receive_test.go | 154 + sdk/messaging/azeventgrid/example_test.go | 23 + sdk/messaging/azeventgrid/go.mod | 25 + sdk/messaging/azeventgrid/go.sum | 29 + sdk/messaging/azeventgrid/main_test.go | 28 + sdk/messaging/azeventgrid/models.go | 97 + sdk/messaging/azeventgrid/models_serde.go | 335 + sdk/messaging/azeventgrid/options.go | 42 + sdk/messaging/azeventgrid/response_types.go | 38 + sdk/messaging/azeventgrid/sample.env | 4 + sdk/messaging/azeventgrid/shared_test.go | 259 + .../azeventgrid/test-resources.bicep | 61 + sdk/messaging/azeventgrid/time_rfc3339.go | 87 + sdk/messaging/azeventgrid/version.go | 18 + sdk/messaging/azeventhubs/CHANGELOG.md | 17 + sdk/messaging/azeventhubs/README.md | 2 +- sdk/messaging/azeventhubs/consumer_client.go | 20 +- .../consumer_client_internal_test.go | 2 +- .../azeventhubs/consumer_client_test.go | 16 +- .../azeventhubs/internal/amqp_fakes.go | 4 +- .../azeventhubs/internal/amqpwrap/amqpwrap.go | 100 +- .../internal/amqpwrap/amqpwrap_test.go | 330 +- .../azeventhubs/internal/amqpwrap/error.go | 42 + .../internal/amqpwrap/mock_amqp_test.go | 245 +- .../azeventhubs/internal/amqpwrap/rpc.go | 1 + sdk/messaging/azeventhubs/internal/cbs.go | 3 +- .../azeventhubs/internal/cbs_test.go | 38 +- .../azeventhubs/internal/constants.go | 2 +- .../azeventhubs/internal/eh/stress/deploy.ps1 | 6 +- .../azeventhubs/internal/eh/stress/readme.md | 28 + sdk/messaging/azeventhubs/internal/errors.go | 99 +- .../azeventhubs/internal/errors_test.go | 32 +- sdk/messaging/azeventhubs/internal/links.go | 299 +- .../azeventhubs/internal/links_recover.go | 155 + .../azeventhubs/internal/links_test.go | 156 +- .../azeventhubs/internal/links_unit_test.go | 65 +- .../azeventhubs/internal/mock/mock_amqp.go | 444 +- .../azeventhubs/internal/mock/mock_helpers.go | 73 - .../azeventhubs/internal/namespace.go | 14 +- .../internal/{eh.go => namespace_eh.go} | 0 .../azeventhubs/internal/namespace_test.go | 20 +- sdk/messaging/azeventhubs/internal/rpc.go | 27 +- .../azeventhubs/internal/rpc_test.go | 153 +- .../azeventhubs/internal/test/mock_helpers.go | 83 + .../azeventhubs/internal/test/test_helpers.go | 27 +- sdk/messaging/azeventhubs/mgmt.go | 40 +- sdk/messaging/azeventhubs/partition_client.go | 12 +- sdk/messaging/azeventhubs/producer_client.go | 27 +- sdk/messaging/azservicebus/CHANGELOG.md | 17 + .../azservicebus/admin/admin_client_rules.go | 218 +- .../admin/admin_client_subscription.go | 52 +- .../azservicebus/admin/admin_client_test.go | 147 + .../azservicebus/internal/atom/models.go | 9 +- .../azservicebus/internal/constants.go | 2 +- .../azservicebus/internal/stress/deploy.ps1 | 6 +- .../azservicebus/internal/stress/readme.md | 24 + .../azservicebus/internal/utils/sync.go | 26 - .../azservicebus/liveTestHelpers_test.go | 26 + sdk/messaging/azservicebus/sender_test.go | 173 +- sdk/monitor/azingest/CHANGELOG.md | 14 + sdk/monitor/azingest/LICENSE.txt | 21 + sdk/monitor/azingest/README.md | 119 + sdk/monitor/azingest/assets.json | 6 + sdk/monitor/azingest/autorest.md | 60 + .../azingest}/build.go | 4 +- sdk/monitor/azingest/ci.yml | 30 + sdk/monitor/azingest/client.go | 78 + sdk/monitor/azingest/client_test.go | 92 + sdk/monitor/azingest/custom_client.go | 34 + sdk/monitor/azingest/example_test.go | 68 + sdk/monitor/azingest/go.mod | 27 + sdk/monitor/azingest/go.sum | 44 + sdk/monitor/azingest/models.go | 16 + sdk/monitor/azingest/response_types.go | 15 + sdk/monitor/azingest/test-resources.bicep | 240 + sdk/monitor/azingest/utils_test.go | 114 + sdk/monitor/azingest/version.go | 12 + sdk/monitor/azquery/README.md | 8 +- .../advisor/armadvisor/advisor_live_test.go | 213 + .../advisor/armadvisor/assets.json | 6 + sdk/resourcemanager/advisor/armadvisor/go.mod | 10 +- sdk/resourcemanager/advisor/armadvisor/go.sum | 17 + .../alertsmanagement_live_test.go | 227 + .../armalertsmanagement/assets.json | 6 + .../armalertsmanagement/go.mod | 10 +- .../armalertsmanagement/go.sum | 17 + .../analysisservices_live_test.go | 177 + .../armanalysisservices/assets.json | 6 + .../armanalysisservices/go.mod | 10 +- .../armanalysisservices/go.sum | 17 + .../armappcontainers/CHANGELOG.md | 86 + .../armappcontainers/autorest.md | 8 +- .../availableworkloadprofiles_client.go | 110 + ...bleworkloadprofiles_client_example_test.go | 176 + .../armappcontainers/billingmeters_client.go | 97 + .../billingmeters_client_example_test.go | 107 + .../armappcontainers/certificates_client.go | 20 +- .../certificates_client_example_test.go | 104 +- .../armappcontainers/client_factory.go | 64 +- .../connectedenvironments_client.go | 480 + ...nnectedenvironments_client_example_test.go | 357 + ...onnectedenvironmentscertificates_client.go | 362 + ...onmentscertificates_client_example_test.go | 223 + ...nectedenvironmentsdaprcomponents_client.go | 359 + ...mentsdaprcomponents_client_example_test.go | 272 + .../connectedenvironmentsstorages_client.go | 284 + ...nvironmentsstorages_client_example_test.go | 144 + .../armappcontainers/constants.go | 222 +- .../armappcontainers/containerapps_client.go | 106 +- .../containerapps_client_example_test.go | 711 +- .../containerappsauthconfigs_client.go | 16 +- ...inerappsauthconfigs_client_example_test.go | 10 +- .../containerappsdiagnostics_client.go | 372 + ...inerappsdiagnostics_client_example_test.go | 384 + .../containerappsrevisionreplicas_client.go | 8 +- ...ppsrevisionreplicas_client_example_test.go | 10 +- .../containerappsrevisions_client.go | 20 +- ...tainerappsrevisions_client_example_test.go | 20 +- .../containerappssourcecontrols_client.go | 22 +- ...rappssourcecontrols_client_example_test.go | 10 +- .../armappcontainers/daprcomponents_client.go | 20 +- .../daprcomponents_client_example_test.go | 218 +- .../appcontainers/armappcontainers/go.mod | 2 +- .../armappcontainers/jobs_client.go | 689 + .../jobs_client_example_test.go | 716 + .../armappcontainers/jobsexecutions_client.go | 117 + .../jobsexecutions_client_example_test.go | 77 + .../managedcertificates_client.go | 370 + ...managedcertificates_client_example_test.go | 200 + .../managedenvironmentdiagnostics_client.go | 166 + ...ironmentdiagnostics_client_example_test.go | 135 + .../managedenvironments_client.go | 160 +- ...managedenvironments_client_example_test.go | 468 +- .../managedenvironmentsdiagnostics_client.go | 103 + ...ronmentsdiagnostics_client_example_test.go | 93 + .../managedenvironmentsstorages_client.go | 16 +- ...nvironmentsstorages_client_example_test.go | 10 +- .../appcontainers/armappcontainers/models.go | 2415 ++- .../armappcontainers/models_serde.go | 4236 +++- .../armappcontainers/namespaces_client.go | 4 +- .../namespaces_client_example_test.go | 6 +- .../armappcontainers/operations_client.go | 4 +- .../operations_client_example_test.go | 4 +- .../armappcontainers/response_types.go | 254 +- .../armappplatform/appplatform_live_test.go | 787 + .../appplatform/armappplatform/assets.json | 6 + .../configservices_live_test.go | 141 + .../appplatform/armappplatform/go.mod | 8 + .../appplatform/armappplatform/go.sum | 17 + .../armauthorization/CHANGELOG.md | 234 + .../accessreviewdefaultsettings_client.go | 142 + .../accessreviewhistorydefinition_client.go | 143 + ...sreviewhistorydefinitioninstance_client.go | 104 + ...reviewhistorydefinitioninstances_client.go | 110 + .../accessreviewhistorydefinitions_client.go | 164 + .../accessreviewinstance_client.go | 286 + ...ccessreviewinstance_client_example_test.go | 35 + ...reviewinstancecontactedreviewers_client.go | 115 + .../accessreviewinstancedecisions_client.go | 120 + .../accessreviewinstancemydecisions_client.go | 232 + ...instancemydecisions_client_example_test.go | 204 + .../accessreviewinstances_client.go | 232 + ...ewinstancesassignedformyapproval_client.go | 162 + ...signedformyapproval_client_example_test.go | 87 + .../accessreviewscheduledefinitions_client.go | 305 + ...definitionsassignedformyapproval_client.go | 101 + ...signedformyapproval_client_example_test.go | 103 + .../alertconfigurations_client.go | 190 + ...alertconfigurations_client_example_test.go | 151 + .../alertdefinitions_client.go | 150 + .../alertdefinitions_client_example_test.go | 146 + .../armauthorization/alertincidents_client.go | 195 + .../alertincidents_client_example_test.go | 103 + .../armauthorization/alertoperation_client.go | 87 + .../alertoperation_client_example_test.go | 46 + .../armauthorization/alerts_client.go | 298 + .../alerts_client_example_test.go | 286 + .../armauthorization/autorest.md | 8 +- ...assicadministrators_client_example_test.go | 4 +- .../armauthorization/client_factory.go | 150 + .../armauthorization/constants.go | 410 +- .../denyassignments_client_example_test.go | 14 +- .../eligiblechildresources_client.go | 4 +- ...giblechildresources_client_example_test.go | 8 +- ...globaladministrator_client_example_test.go | 4 +- .../authorization/armauthorization/go.mod | 18 +- .../authorization/armauthorization/go.sum | 36 +- .../authorization/armauthorization/models.go | 1673 +- .../armauthorization/models_serde.go | 2598 ++- .../armauthorization/operations_client.go | 94 + .../armauthorization/permissions_client.go | 8 +- .../permissions_client_example_test.go | 6 +- .../armauthorization/polymorphic_helpers.go | 86 + ...roperationsmetadata_client_example_test.go | 6 +- .../armauthorization/response_types.go | 340 + .../roleassignments_client_example_test.go | 26 +- .../roleassignmentscheduleinstances_client.go | 8 +- ...ntscheduleinstances_client_example_test.go | 20 +- .../roleassignmentschedulerequests_client.go | 27 +- ...entschedulerequests_client_example_test.go | 24 +- .../roleassignmentschedules_client.go | 8 +- ...assignmentschedules_client_example_test.go | 18 +- .../roledefinitions_client.go | 42 +- .../roledefinitions_client_example_test.go | 12 +- ...roleeligibilityscheduleinstances_client.go | 8 +- ...tyscheduleinstances_client_example_test.go | 18 +- .../roleeligibilityschedulerequests_client.go | 27 +- ...ityschedulerequests_client_example_test.go | 24 +- .../roleeligibilityschedules_client.go | 8 +- ...ligibilityschedules_client_example_test.go | 18 +- .../rolemanagementpolicies_client.go | 16 +- ...emanagementpolicies_client_example_test.go | 20 +- .../rolemanagementpolicyassignments_client.go | 16 +- ...ntpolicyassignments_client_example_test.go | 638 +- ...scopeaccessreviewdefaultsettings_client.go | 141 + ...viewdefaultsettings_client_example_test.go | 104 + ...opeaccessreviewhistorydefinition_client.go | 142 + ...ewhistorydefinition_client_example_test.go | 99 + ...sreviewhistorydefinitioninstance_client.go | 102 + ...ydefinitioninstance_client_example_test.go | 53 + ...reviewhistorydefinitioninstances_client.go | 108 + ...definitioninstances_client_example_test.go | 60 + ...peaccessreviewhistorydefinitions_client.go | 163 + ...whistorydefinitions_client_example_test.go | 154 + .../scopeaccessreviewinstance_client.go | 293 + ...ccessreviewinstance_client_example_test.go | 103 + ...reviewinstancecontactedreviewers_client.go | 113 + ...econtactedreviewers_client_example_test.go | 56 + ...opeaccessreviewinstancedecisions_client.go | 118 + ...ewinstancedecisions_client_example_test.go | 87 + .../scopeaccessreviewinstances_client.go | 232 + ...cessreviewinstances_client_example_test.go | 127 + ...eaccessreviewscheduledefinitions_client.go | 307 + ...scheduledefinitions_client_example_test.go | 255 + ...reviewinstancecontactedreviewers_client.go | 108 + ...econtactedreviewers_client_example_test.go | 56 + .../batch/armbatch/CHANGELOG.md | 12 + .../batch/armbatch/account_client.go | 52 +- .../armbatch/account_client_example_test.go | 36 +- .../batch/armbatch/application_client.go | 20 +- .../application_client_example_test.go | 12 +- .../armbatch/applicationpackage_client.go | 20 +- .../applicationpackage_client_example_test.go | 12 +- .../batch/armbatch/assets.json | 6 + .../batch/armbatch/autorest.md | 7 +- .../armbatch/batchmanagement_live_test.go | 675 + .../batch/armbatch/certificate_client.go | 26 +- .../certificate_client_example_test.go | 22 +- .../batch/armbatch/constants.go | 20 +- sdk/resourcemanager/batch/armbatch/go.mod | 13 +- sdk/resourcemanager/batch/armbatch/go.sum | 19 + .../batch/armbatch/location_client.go | 16 +- .../armbatch/location_client_example_test.go | 12 +- sdk/resourcemanager/batch/armbatch/models.go | 19 +- .../batch/armbatch/models_serde.go | 10 +- .../batch/armbatch/operations_client.go | 4 +- .../operations_client_example_test.go | 4 +- .../batch/armbatch/pool_client.go | 30 +- .../armbatch/pool_client_example_test.go | 245 +- .../privateendpointconnection_client.go | 20 +- ...eendpointconnection_client_example_test.go | 10 +- .../armbatch/privatelinkresource_client.go | 8 +- ...privatelinkresource_client_example_test.go | 6 +- .../botservice/armbotservice/assets.json | 6 + .../armbotservice/botservice_live_test.go | 445 + .../botservice/armbotservice/go.mod | 10 +- .../botservice/armbotservice/go.sum | 18 + .../armcognitiveservices/CHANGELOG.md | 27 + .../armcognitiveservices/accounts_client.go | 50 +- .../accounts_client_example_test.go | 24 +- .../armcognitiveservices/autorest.md | 7 +- .../armcognitiveservices/client_factory.go | 10 + .../commitmentplans_client.go | 68 +- .../commitmentplans_client_example_test.go | 28 +- .../commitmenttiers_client.go | 4 +- .../commitmenttiers_client_example_test.go | 2 +- .../armcognitiveservices/constants.go | 42 +- .../deletedaccounts_client.go | 14 +- .../deletedaccounts_client_example_test.go | 6 +- .../deployments_client.go | 24 +- .../deployments_client_example_test.go | 24 +- .../armcognitiveservices/go.mod | 16 +- .../armcognitiveservices/go.sum | 36 +- .../armcognitiveservices/management_client.go | 8 +- .../management_client_example_test.go | 4 +- .../armcognitiveservices/models.go | 116 +- .../armcognitiveservices/models_client.go} | 53 +- .../models_client_example_test.go | 94 + .../armcognitiveservices/models_serde.go | 223 + .../armcognitiveservices/operations_client.go | 4 +- .../operations_client_example_test.go | 2 +- .../privateendpointconnections_client.go | 20 +- ...endpointconnections_client_example_test.go | 8 +- .../privatelinkresources_client.go | 4 +- ...rivatelinkresources_client_example_test.go | 2 +- .../resourceskus_client.go | 4 +- .../resourceskus_client_example_test.go | 2 +- .../armcognitiveservices/response_types.go | 10 + .../armcognitiveservices/usages_client.go | 112 + .../usages_client_example_test.go | 55 + .../compute/armcompute/CHANGELOG.md | 59 +- .../compute/armcompute/README.md | 34 + .../compute/armcompute/assets.json | 2 +- .../compute/armcompute/autorest.md | 13 +- .../armcompute/availabilityset_live_test.go | 7 +- .../armcompute/availabilitysets_client.go | 104 +- .../availabilitysets_client_example_test.go | 51 +- .../compute/armcompute/build.go | 2 +- .../capacityreservation_live_test.go | 7 +- .../capacityreservationgroups_client.go | 98 +- ...tyreservationgroups_client_example_test.go | 27 +- .../armcompute/capacityreservations_client.go | 107 +- ...apacityreservations_client_example_test.go | 25 +- .../compute/armcompute/client_factory.go | 199 +- .../cloudserviceoperatingsystems_client.go | 37 +- ...iceoperatingsystems_client_example_test.go | 10 +- .../cloudserviceroleinstances_client.go | 117 +- ...erviceroleinstances_client_example_test.go | 18 +- .../armcompute/cloudserviceroles_client.go | 20 +- .../cloudserviceroles_client_example_test.go | 6 +- .../armcompute/cloudservices_client.go | 220 +- .../cloudservices_client_example_test.go | 36 +- .../cloudservicesupdatedomain_client.go | 42 +- ...ervicesupdatedomain_client_example_test.go | 8 +- .../armcompute/communitygalleries_client.go | 18 +- .../communitygalleries_client_example_test.go | 4 +- .../communitygalleryimages_client.go | 20 +- ...munitygalleryimages_client_example_test.go | 10 +- .../communitygalleryimageversions_client.go | 20 +- ...alleryimageversions_client_example_test.go | 6 +- .../armcompute/computerpcommon_live_test.go | 4 +- .../compute/armcompute/constants.go | 253 +- .../armcompute/dedicatedhost_live_test.go | 20 +- .../armcompute/dedicatedhostgroups_client.go | 98 +- ...dedicatedhostgroups_client_example_test.go | 46 +- .../armcompute/dedicatedhosts_client.go | 206 +- .../dedicatedhosts_client_example_test.go | 119 +- .../compute/armcompute/disk_live_test.go | 7 +- .../armcompute/diskaccess_live_test.go | 7 +- .../compute/armcompute/diskaccesses_client.go | 208 +- .../diskaccesses_client_example_test.go | 26 +- .../armcompute/diskencryptionsets_client.go | 119 +- .../diskencryptionsets_client_example_test.go | 29 +- .../armcompute/diskrestorepoint_client.go | 79 +- .../diskrestorepoint_client_example_test.go | 13 +- .../compute/armcompute/disks_client.go | 164 +- .../armcompute/disks_client_example_test.go | 110 +- .../fake/availabilitysets_server.go | 372 + .../fake/capacityreservationgroups_server.go | 350 + .../fake/capacityreservations_server.go | 344 + .../cloudserviceoperatingsystems_server.go | 232 + .../fake/cloudserviceroleinstances_server.go | 493 + .../fake/cloudserviceroles_server.go | 156 + .../armcompute/fake/cloudservices_server.go | 745 + .../fake/cloudservicesupdatedomain_server.go | 237 + .../fake/communitygalleries_server.go | 100 + .../fake/communitygalleryimages_server.go | 156 + .../communitygalleryimageversions_server.go | 164 + .../fake/dedicatedhostgroups_server.go | 326 + .../armcompute/fake/dedicatedhosts_server.go | 450 + .../armcompute/fake/diskaccesses_server.go | 600 + .../fake/diskencryptionsets_server.go | 402 + .../fake/diskrestorepoint_server.go | 288 + .../compute/armcompute/fake/disks_server.go | 461 + .../armcompute/fake/galleries_server.go | 371 + .../fake/galleryapplications_server.go | 332 + .../fake/galleryapplicationversions_server.go | 364 + .../armcompute/fake/galleryimages_server.go | 332 + .../fake/galleryimageversions_server.go | 364 + .../fake/gallerysharingprofile_server.go | 119 + .../compute/armcompute/fake/images_server.go | 365 + .../compute/armcompute/fake/internal.go | 123 + .../armcompute/fake/loganalytics_server.go | 167 + .../armcompute/fake/operations_server.go | 92 + .../fake/proximityplacementgroups_server.go | 326 + .../armcompute/fake/resourceskus_server.go | 122 + .../fake/restorepointcollections_server.go | 339 + .../armcompute/fake/restorepoints_server.go | 234 + .../armcompute/fake/sharedgalleries_server.go | 160 + .../fake/sharedgalleryimages_server.go | 168 + .../fake/sharedgalleryimageversions_server.go | 176 + .../armcompute/fake/snapshots_server.go | 461 + .../armcompute/fake/sshpublickeys_server.go | 353 + .../compute/armcompute/fake/time_rfc3339.go | 86 + .../compute/armcompute/fake/usage_server.go | 108 + .../virtualmachineextensionimages_server.go | 224 + .../fake/virtualmachineextensions_server.go | 345 + .../fake/virtualmachineimages_server.go | 349 + .../virtualmachineimagesedgezone_server.go | 330 + .../fake/virtualmachineruncommands_server.go | 440 + .../armcompute/fake/virtualmachines_server.go | 1420 ++ ...virtualmachinescalesetextensions_server.go | 344 + ...almachinescalesetrollingupgrades_server.go | 258 + .../fake/virtualmachinescalesets_server.go | 1429 ++ ...rtualmachinescalesetvmextensions_server.go | 365 + ...tualmachinescalesetvmruncommands_server.go | 376 + .../fake/virtualmachinescalesetvms_server.go | 1008 + .../fake/virtualmachinesizes_server.go | 104 + .../compute/armcompute/fake_example_test.go | 79 + .../compute/armcompute/galleries_client.go | 83 +- .../galleries_client_example_test.go | 26 +- .../compute/armcompute/gallery_live_test.go | 11 +- .../armcompute/galleryapplications_client.go | 81 +- ...galleryapplications_client_example_test.go | 12 +- .../galleryapplicationversions_client.go | 81 +- ...applicationversions_client_example_test.go | 14 +- .../armcompute/galleryimages_client.go | 81 +- .../galleryimages_client_example_test.go | 12 +- .../armcompute/galleryimageversions_client.go | 81 +- ...alleryimageversions_client_example_test.go | 38 +- .../gallerysharingprofile_client.go | 25 +- ...llerysharingprofile_client_example_test.go | 8 +- sdk/resourcemanager/compute/armcompute/go.mod | 24 +- sdk/resourcemanager/compute/armcompute/go.sum | 45 +- .../compute/armcompute/images_client.go | 113 +- .../armcompute/images_client_example_test.go | 38 +- .../compute/armcompute/loganalytics_client.go | 59 +- .../loganalytics_client_example_test.go | 6 +- .../compute/armcompute/models.go | 2741 +-- .../compute/armcompute/models_serde.go | 273 +- .../compute/armcompute/operations_client.go | 9 +- .../operations_client_example_test.go | 6 +- .../compute/armcompute/options.go | 1901 ++ .../proximityplacementgroup_live_test.go | 7 +- .../proximityplacementgroups_client.go | 98 +- ...mityplacementgroups_client_example_test.go | 14 +- .../compute/armcompute/resourceskus_client.go | 5 +- .../resourceskus_client_example_test.go | 8 +- .../compute/armcompute/response_types.go | 231 +- .../armcompute/restorepoint_live_test.go | 24 +- .../restorepointcollections_client.go | 105 +- ...orepointcollections_client_example_test.go | 38 +- .../armcompute/restorepoints_client.go | 73 +- .../restorepoints_client_example_test.go | 26 +- .../armcompute/runcommand_live_test.go | 21 +- .../armcompute/sharedgalleries_client.go | 20 +- .../sharedgalleries_client_example_test.go | 6 +- .../armcompute/sharedgalleryimages_client.go | 20 +- ...sharedgalleryimages_client_example_test.go | 6 +- .../sharedgalleryimageversions_client.go | 20 +- ...alleryimageversions_client_example_test.go | 6 +- .../compute/armcompute/skus_live_test.go | 4 +- .../compute/armcompute/snapshot_live_test.go | 7 +- .../compute/armcompute/snapshots_client.go | 164 +- .../snapshots_client_example_test.go | 33 +- .../armcompute/sshpublickey_live_test.go | 7 +- .../armcompute/sshpublickeys_client.go | 117 +- .../sshpublickeys_client_example_test.go | 42 +- .../compute/armcompute/time_rfc3339.go | 3 +- .../compute/armcompute/usage_client.go | 9 +- .../armcompute/usage_client_example_test.go | 6 +- .../armcompute/virtualmachine_live_test.go | 13 +- .../virtualmachineextensionimage_live_test.go | 4 +- .../virtualmachineextensionimages_client.go | 60 +- ...hineextensionimages_client_example_test.go | 29 +- .../virtualmachineextensions_client.go | 120 +- ...almachineextensions_client_example_test.go | 42 +- .../virtualmachineimage_live_test.go | 4 +- .../armcompute/virtualmachineimages_client.go | 117 +- ...irtualmachineimages_client_example_test.go | 51 +- .../virtualmachineimagesedgezone_client.go | 98 +- ...chineimagesedgezone_client_example_test.go | 27 +- .../virtualmachineruncommands_client.go | 132 +- ...lmachineruncommands_client_example_test.go | 64 +- .../armcompute/virtualmachines_client.go | 520 +- .../virtualmachines_client_example_test.go | 459 +- .../virtualmachinescaleset_live_test.go | 13 +- ...virtualmachinescalesetextensions_client.go | 107 +- ...escalesetextensions_client_example_test.go | 42 +- ...almachinescalesetrollingupgrades_client.go | 91 +- ...esetrollingupgrades_client_example_test.go | 29 +- .../virtualmachinescalesets_client.go | 575 +- ...ualmachinescalesets_client_example_test.go | 468 +- ...rtualmachinescalesetvmextensions_client.go | 120 +- ...calesetvmextensions_client_example_test.go | 12 +- ...tualmachinescalesetvmruncommands_client.go | 107 +- ...alesetvmruncommands_client_example_test.go | 53 +- .../virtualmachinescalesetvms_client.go | 350 +- ...lmachinescalesetvms_client_example_test.go | 108 +- .../armcompute/virtualmachinesizes_client.go | 9 +- ...virtualmachinesizes_client_example_test.go | 6 +- .../armcontainerregistry/CHANGELOG.md | 12 + .../armcontainerregistry/README.md | 33 + .../armcontainerregistry/agentpools_client.go | 96 +- .../armcontainerregistry/autorest.md | 9 +- .../armcontainerregistry/build.go | 2 +- .../armcontainerregistry/cacherules_client.go | 81 +- .../armcontainerregistry/client_factory.go | 45 +- .../connectedregistries_client.go | 98 +- .../armcontainerregistry/constants.go | 13 +- .../credentialsets_client.go | 81 +- .../exportpipelines_client.go | 59 +- .../fake/agentpools_server.go | 375 + .../fake/cacherules_server.go | 332 + .../fake/connectedregistries_server.go | 400 + .../fake/credentialsets_server.go | 332 + .../fake/exportpipelines_server.go | 272 + .../fake/importpipelines_server.go | 272 + .../armcontainerregistry/fake/internal.go | 123 + .../fake/operations_server.go | 96 + .../fake/pipelineruns_server.go | 272 + .../fake/polymorphic_helpers.go | 91 + .../fake/privateendpointconnections_server.go | 272 + .../fake/registries_server.go | 812 + .../fake/replications_server.go | 332 + .../armcontainerregistry/fake/runs_server.go | 343 + .../fake/scopemaps_server.go | 332 + .../fake/taskruns_server.go | 375 + .../armcontainerregistry/fake/tasks_server.go | 375 + .../armcontainerregistry/fake/time_rfc3339.go | 86 + .../fake/tokens_server.go | 332 + .../fake/webhooks_server.go | 471 + .../armcontainerregistry/fake_example_test.go | 79 + .../armcontainerregistry/go.mod | 10 +- .../armcontainerregistry/go.sum | 20 +- .../importpipelines_client.go | 59 +- .../armcontainerregistry/interfaces.go | 36 + .../armcontainerregistry/models.go | 2156 +- .../armcontainerregistry/models_serde.go | 3 +- .../armcontainerregistry/operations_client.go | 5 +- .../armcontainerregistry/options.go | 554 + .../pipelineruns_client.go | 59 +- .../polymorphic_helpers.go | 18 +- .../privateendpointconnections_client.go | 59 +- .../armcontainerregistry/registries_client.go | 251 +- .../replications_client.go | 81 +- .../armcontainerregistry/response_types.go | 91 +- .../armcontainerregistry/runs_client.go | 74 +- .../armcontainerregistry/scopemaps_client.go | 81 +- .../armcontainerregistry/taskruns_client.go | 96 +- .../armcontainerregistry/tasks_client.go | 96 +- .../armcontainerregistry/time_rfc3339.go | 3 +- .../armcontainerregistry/tokens_client.go | 81 +- .../armcontainerregistry/webhooks_client.go | 113 +- .../armcontainerservice/CHANGELOG.md | 95 +- .../armcontainerservice/README.md | 27 +- .../armcontainerservice/agentpools_client.go | 171 +- .../agentpools_client_example_test.go | 279 +- .../armcontainerservice/assets.json | 2 +- .../armcontainerservice/autorest.md | 12 +- .../armcontainerservice/build.go | 2 +- .../armcontainerservice/client_factory.go | 34 +- .../armcontainerservice/constants.go | 338 +- .../armcontainerservice/date_type.go | 3 +- .../fake/agentpools_server.go | 466 + .../armcontainerservice/fake/date_type.go} | 37 +- .../armcontainerservice/fake/internal.go | 123 + .../fake/maintenanceconfigurations_server.go | 246 + .../fake/managedclusters_server.go | 1199 ++ .../fake/operations_server.go | 92 + .../fake/privateendpointconnections_server.go | 248 + .../fake/privatelinkresources_server.go | 100 + .../resolveprivatelinkserviceid_server.go | 104 + .../fake/snapshots_server.go | 314 + .../armcontainerservice/fake/time_rfc3339.go | 86 + .../armcontainerservice/fake_example_test.go | 78 + .../armcontainerservice/go.mod | 12 +- .../armcontainerservice/go.sum | 20 +- .../maintenanceconfigurations_client.go | 68 +- ...nanceconfigurations_client_example_test.go | 43 +- .../managedclusters_client.go | 478 +- .../managedclusters_client_example_test.go | 1258 +- .../managedclusters_live_test.go | 2 +- .../managedclustersnapshots_client.go | 395 - ...gedclustersnapshots_client_example_test.go | 343 - .../armcontainerservice/models.go | 909 +- .../armcontainerservice/models_serde.go | 1098 +- .../armcontainerservice/operations_client.go | 9 +- .../operations_client_example_test.go | 4 +- .../armcontainerservice/options.go | 305 + .../privateendpointconnections_client.go | 88 +- ...endpointconnections_client_example_test.go | 10 +- .../privatelinkresources_client.go | 22 +- ...rivatelinkresources_client_example_test.go | 4 +- .../resolveprivatelinkserviceid_client.go | 27 +- ...rivatelinkserviceid_client_example_test.go | 4 +- .../armcontainerservice/response_types.go | 96 +- .../armcontainerservice/snapshots_client.go | 98 +- .../snapshots_client_example_test.go | 14 +- .../armcontainerservice/time_rfc3339.go | 3 +- .../trustedaccessrolebindings_client.go | 296 - ...daccessrolebindings_client_example_test.go | 144 - .../armcontainerservicefleet/CHANGELOG.md | 7 + .../armcontainerservicefleet/LICENSE.txt | 21 + .../armcontainerservicefleet/README.md | 85 + .../armcontainerservicefleet/autorest.md | 13 + .../armcontainerservicefleet/build.go | 7 + .../armcontainerservicefleet}/ci.yml | 14 +- .../client_factory.go | 59 + .../armcontainerservicefleet/constants.go | 185 + .../fleetmembers_client.go | 397 + .../fleetmembers_client_example_test.go | 215 + .../armcontainerservicefleet/fleets_client.go | 488 + .../fleets_client_example_test.go | 340 + .../armcontainerservicefleet/go.mod | 21 + .../armcontainerservicefleet/go.sum | 31 + .../armcontainerservicefleet/models.go | 549 + .../armcontainerservicefleet/models_serde.go | 1174 ++ .../operations_client.go | 94 + .../operations_client_example_test.go} | 43 +- .../response_types.go | 105 + .../armcontainerservicefleet/time_rfc3339.go | 87 + .../updateruns_client.go | 478 + .../updateruns_client_example_test.go | 523 + .../cosmos/armcosmos/CHANGELOG.md | 200 + .../cosmos/armcosmos/assets.json | 2 +- .../cosmos/armcosmos/autorest.md | 8 +- .../armcosmos/cassandraclusters_client.go | 179 +- .../cassandraclusters_client_example_test.go | 107 +- .../armcosmos/cassandradatacenters_client.go | 26 +- ...assandradatacenters_client_example_test.go | 20 +- .../armcosmos/cassandraresources_client.go | 666 +- .../cassandraresources_client_example_test.go | 329 +- .../cosmos/armcosmos/client_factory.go | 15 + .../cosmos/armcosmos/collection_client.go | 12 +- .../collection_client_example_test.go | 8 +- .../armcosmos/collectionpartition_client.go | 8 +- ...collectionpartition_client_example_test.go | 6 +- .../collectionpartitionregion_client.go | 4 +- ...tionpartitionregion_client_example_test.go | 4 +- .../armcosmos/collectionregion_client.go | 4 +- .../collectionregion_client_example_test.go | 4 +- .../cosmos/armcosmos/constants.go | 161 +- .../cosmos/armcosmos/database_client.go | 12 +- .../armcosmos/database_client_example_test.go | 8 +- .../armcosmos/databaseaccountregion_client.go | 4 +- ...tabaseaccountregion_client_example_test.go | 4 +- .../armcosmos/databaseaccounts_client.go | 86 +- .../databaseaccounts_client_example_test.go | 168 +- .../armcosmos/datatransferjobs_client.go | 425 + .../datatransferjobs_client_example_test.go | 286 + sdk/resourcemanager/cosmos/armcosmos/go.mod | 3 +- sdk/resourcemanager/cosmos/armcosmos/go.sum | 2 + .../cosmos/armcosmos/graphresources_client.go | 311 + .../graphresources_client_example_test.go | 160 + .../armcosmos/gremlinresources_client.go | 90 +- .../gremlinresources_client_example_test.go | 36 +- .../cosmos/armcosmos/locations_client.go | 8 +- .../locations_client_example_test.go | 6 +- .../cosmos/armcosmos/models.go | 1432 +- .../cosmos/armcosmos/models_serde.go | 5284 +++-- .../cosmos/armcosmos/mongoclusters_client.go | 824 + .../mongoclusters_client_example_test.go | 784 + .../armcosmos/mongodbresources_client.go | 585 +- .../mongodbresources_client_example_test.go | 551 +- .../armcosmos/notebookworkspaces_client.go | 36 +- .../notebookworkspaces_client_example_test.go | 16 +- .../cosmos/armcosmos/operations_client.go | 4 +- .../operations_client_example_test.go | 4 +- .../armcosmos/partitionkeyrangeid_client.go | 4 +- ...partitionkeyrangeid_client_example_test.go | 4 +- .../partitionkeyrangeidregion_client.go | 4 +- ...ionkeyrangeidregion_client_example_test.go | 4 +- .../cosmos/armcosmos/percentile_client.go | 4 +- .../percentile_client_example_test.go | 4 +- .../percentilesourcetarget_client.go | 4 +- ...centilesourcetarget_client_example_test.go | 4 +- .../armcosmos/percentiletarget_client.go | 4 +- .../percentiletarget_client_example_test.go | 4 +- .../cosmos/armcosmos/polymorphic_helpers.go | 24 + .../privateendpointconnections_client.go | 20 +- ...endpointconnections_client_example_test.go | 10 +- .../armcosmos/privatelinkresources_client.go | 8 +- ...rivatelinkresources_client_example_test.go | 6 +- .../cosmos/armcosmos/response_types.go | 220 + .../restorabledatabaseaccounts_client.go | 12 +- ...bledatabaseaccounts_client_example_test.go | 13 +- .../restorablegremlindatabases_client.go | 4 +- ...blegremlindatabases_client_example_test.go | 4 +- .../restorablegremlingraphs_client.go | 4 +- ...orablegremlingraphs_client_example_test.go | 4 +- .../restorablegremlinresources_client.go | 4 +- ...blegremlinresources_client_example_test.go | 4 +- .../restorablemongodbcollections_client.go | 4 +- ...emongodbcollections_client_example_test.go | 4 +- .../restorablemongodbdatabases_client.go | 4 +- ...blemongodbdatabases_client_example_test.go | 4 +- .../restorablemongodbresources_client.go | 4 +- ...blemongodbresources_client_example_test.go | 4 +- .../restorablesqlcontainers_client.go | 4 +- ...orablesqlcontainers_client_example_test.go | 4 +- .../restorablesqldatabases_client.go | 4 +- ...torablesqldatabases_client_example_test.go | 4 +- .../restorablesqlresources_client.go | 4 +- ...torablesqlresources_client_example_test.go | 4 +- .../restorabletableresources_client.go | 4 +- ...rabletableresources_client_example_test.go | 4 +- .../armcosmos/restorabletables_client.go | 4 +- .../restorabletables_client_example_test.go | 4 +- .../cosmos/armcosmos/service_client.go | 20 +- .../armcosmos/service_client_example_test.go | 28 +- .../cosmos/armcosmos/sqlresources_client.go | 657 +- .../sqlresources_client_example_test.go | 974 +- .../cosmos/armcosmos/tableresources_client.go | 48 +- .../tableresources_client_example_test.go | 20 +- .../armcosmosforpostgresql/CHANGELOG.md | 7 + .../armcosmosforpostgresql/LICENSE.txt | 21 + .../armcosmosforpostgresql/README.md | 85 + .../armcosmosforpostgresql/assets.json | 6 + .../armcosmosforpostgresql/autorest.md | 13 + .../armcosmosforpostgresql/build.go | 7 + .../armcosmosforpostgresql/ci.yml | 28 + .../armcosmosforpostgresql/client_factory.go | 79 + .../armcosmosforpostgresql/clusters_client.go | 710 + .../clusters_client_example_test.go | 1262 ++ .../configurations_client.go | 502 + .../configurations_client_example_test.go | 494 + .../armcosmosforpostgresql/constants.go | 147 + .../firewallrules_client.go | 304 + .../firewallrules_client_example_test.go | 189 + .../armcosmosforpostgresql/go.mod | 29 + .../armcosmosforpostgresql/go.sum | 48 + .../armcosmosforpostgresql/models.go | 896 + .../armcosmosforpostgresql/models_serde.go | 1689 ++ .../operations_client.go | 88 + .../operations_client_example_test.go | 230 + .../postgresqlhsc_live_test.go | 557 + .../privateendpointconnections_client.go | 305 + ...endpointconnections_client_example_test.go | 213 + .../privatelinkresources_client.go | 166 + ...rivatelinkresources_client_example_test.go | 126 + .../readreplica_live_test.go | 123 + .../armcosmosforpostgresql/response_types.go | 185 + .../armcosmosforpostgresql/roles_client.go | 301 + .../roles_client_example_test.go | 180 + .../armcosmosforpostgresql/servers_client.go | 165 + .../servers_client_example_test.go | 182 + .../armcosmosforpostgresql/time_rfc3339.go | 87 + .../armcostmanagement/CHANGELOG.md | 125 + .../armcostmanagement/alerts_client.go | 16 +- .../alerts_client_example_test.go | 28 +- .../armcostmanagement/autorest.md | 7 +- .../benefitrecommendations_client.go | 112 + ...efitrecommendations_client_example_test.go | 154 + .../benefitutilizationsummaries_client.go | 322 + ...tilizationsummaries_client_example_test.go | 235 + .../costmanagement/armcostmanagement/build.go | 2 +- .../armcostmanagement/client_factory.go | 63 +- .../armcostmanagement/constants.go | 461 +- .../armcostmanagement/dimensions_client.go | 8 +- .../dimensions_client_example_test.go | 298 +- .../armcostmanagement/exports_client.go | 28 +- .../exports_client_example_test.go | 110 +- .../armcostmanagement/forecast_client.go | 12 +- .../forecast_client_example_test.go | 360 +- .../generatecostdetailsreport_client.go | 182 + ...tecostdetailsreport_client_example_test.go | 459 + .../generatedetailedcostreport_client.go | 27 +- ...edetailedcostreport_client_example_test.go | 12 +- ...tailedcostreportoperationresults_client.go | 61 +- ...ortoperationresults_client_example_test.go | 12 +- ...etailedcostreportoperationstatus_client.go | 17 +- ...portoperationstatus_client_example_test.go | 4 +- ...generatereservationdetailsreport_client.go | 16 +- ...vationdetailsreport_client_example_test.go | 6 +- .../costmanagement/armcostmanagement/go.mod | 18 +- .../costmanagement/armcostmanagement/go.sum | 36 +- .../armcostmanagement/models.go | 1228 +- .../armcostmanagement/models_serde.go | 3369 +++- .../armcostmanagement/operations_client.go | 4 +- .../operations_client_example_test.go | 6 +- .../armcostmanagement/polymorphic_helpers.go | 71 + .../armcostmanagement/pricesheet_client.go | 183 + .../pricesheet_client_example_test.go | 74 + .../armcostmanagement/query_client.go | 8 +- .../query_client_example_test.go | 62 +- .../armcostmanagement/response_types.go | 111 +- .../scheduledactions_client.go | 720 + .../scheduledactions_client_example_test.go | 899 + .../armcostmanagement/views_client.go | 32 +- .../views_client_example_test.go | 18 +- .../databox/armdatabox/CHANGELOG.md | 33 + .../databox/armdatabox/autorest.md | 8 +- .../databox/armdatabox/constants.go | 65 +- sdk/resourcemanager/databox/armdatabox/go.mod | 2 +- .../databox/armdatabox/jobs_client.go | 46 +- .../armdatabox/jobs_client_example_test.go | 1381 +- .../databox/armdatabox/management_client.go | 4 +- .../management_client_example_test.go | 11 +- .../databox/armdatabox/models.go | 119 +- .../databox/armdatabox/models_serde.go | 188 +- .../databox/armdatabox/operations_client.go | 4 +- .../operations_client_example_test.go | 4 +- .../databox/armdatabox/service_client.go | 24 +- .../armdatabox/service_client_example_test.go | 386 +- .../databricks/armdatabricks/assets.json | 6 + .../armdatabricks/databricks_live_test.go | 457 + .../databricks/armdatabricks/go.mod | 10 +- .../databricks/armdatabricks/go.sum | 18 + .../armdatabricks/vnetpeering_live_test.go | 178 + .../datafactory/armdatafactory/assets.json | 6 + .../armdatafactory/datafactory_live_test.go | 1050 + .../datafactory/armdatafactory/go.mod | 8 + .../datafactory/armdatafactory/go.sum | 17 + .../armdatalakestore/account_live_test.go | 388 + .../armdatalakestore/assets.json | 6 + .../datalake-store/armdatalakestore/go.mod | 8 + .../datalake-store/armdatalakestore/go.sum | 17 + .../armdataprotection/CHANGELOG.md | 44 + .../armdataprotection/autorest.md | 7 +- .../backupinstances_client.go | 84 +- .../backupinstances_client_example_test.go | 34 +- .../backuppolicies_client.go | 16 +- .../backuppolicies_client_example_test.go | 8 +- .../backupvaultoperationresults_client.go | 4 +- ...ultoperationresults_client_example_test.go | 2 +- .../armdataprotection/backupvaults_client.go | 34 +- .../backupvaults_client_example_test.go | 136 +- .../armdataprotection/client.go | 4 +- .../armdataprotection/client_example_test.go | 2 +- .../armdataprotection/client_factory.go | 5 + .../armdataprotection/constants.go | 40 +- .../deletedbackupinstances_client.go | 14 +- ...etedbackupinstances_client_example_test.go | 6 +- .../dppresourceguardproxy_client.go | 345 + ...presourceguardproxy_client_example_test.go | 192 + .../armdataprotection/exportjobs_client.go | 6 +- .../exportjobs_client_example_test.go | 2 +- .../exportjobsoperationresult_client.go | 4 +- ...jobsoperationresult_client_example_test.go | 2 +- .../dataprotection/armdataprotection/go.mod | 16 +- .../dataprotection/armdataprotection/go.sum | 36 +- .../armdataprotection/jobs_client.go | 8 +- .../jobs_client_example_test.go | 4 +- .../armdataprotection/models.go | 191 +- .../armdataprotection/models_serde.go | 405 + .../operationresult_client.go | 4 +- .../operationresult_client_example_test.go | 2 +- .../armdataprotection/operations_client.go | 4 +- .../operations_client_example_test.go | 2 +- .../operationstatus_client.go | 4 +- .../operationstatus_client_example_test.go | 2 +- ...perationstatusbackupvaultcontext_client.go | 4 +- ...sbackupvaultcontext_client_example_test.go | 2 +- ...rationstatusresourcegroupcontext_client.go | 4 +- ...esourcegroupcontext_client_example_test.go | 2 +- .../armdataprotection/polymorphic_helpers.go | 16 + .../recoverypoints_client.go | 8 +- .../recoverypoints_client_example_test.go | 4 +- .../resourceguards_client.go | 72 +- .../resourceguards_client_example_test.go | 36 +- .../armdataprotection/response_types.go | 25 + .../restorabletimeranges_client.go | 4 +- ...estorabletimeranges_client_example_test.go | 2 +- .../devcenter/armdevcenter/CHANGELOG.md | 31 + .../devcenter/armdevcenter/assets.json | 6 + .../armdevcenter/attachednetworks_client.go | 28 +- .../attachednetworks_client_example_test.go | 14 +- .../devcenter/armdevcenter/autorest.md | 8 +- .../devcenter/armdevcenter/catalogs_client.go | 32 +- .../catalogs_client_example_test.go | 14 +- .../checknameavailability_client.go | 4 +- ...ecknameavailability_client_example_test.go | 2 +- .../devcenter/armdevcenter/constants.go | 76 +- .../armdevcenter/devboxdefinitions_client.go | 34 +- .../devboxdefinitions_client_example_test.go | 21 +- .../armdevcenter/devcenter_live_test.go | 580 + .../armdevcenter/devcenters_client.go | 30 +- .../devcenters_client_example_test.go | 14 +- .../armdevcenter/environmenttypes_client.go | 20 +- .../environmenttypes_client_example_test.go | 10 +- .../armdevcenter/galleries_client.go | 20 +- .../galleries_client_example_test.go | 8 +- .../devcenter/armdevcenter/go.mod | 10 +- .../devcenter/armdevcenter/go.sum | 17 + .../devcenter/armdevcenter/images_client.go | 12 +- .../images_client_example_test.go | 6 +- .../armdevcenter/imageversions_client.go | 8 +- .../imageversions_client_example_test.go | 4 +- .../devcenter/armdevcenter/models.go | 114 +- .../devcenter/armdevcenter/models_serde.go | 226 +- .../armdevcenter/networkconnections_client.go | 118 +- .../networkconnections_client_example_test.go | 79 +- .../armdevcenter/operations_client.go | 4 +- .../operations_client_example_test.go | 2 +- .../armdevcenter/operationstatuses_client.go | 4 +- .../operationstatuses_client_example_test.go | 2 +- .../devcenter/armdevcenter/pools_client.go | 98 +- .../armdevcenter/pools_client_example_test.go | 116 +- .../projectallowedenvironmenttypes_client.go | 8 +- ...wedenvironmenttypes_client_example_test.go | 4 +- .../projectenvironmenttypes_client.go | 20 +- ...ectenvironmenttypes_client_example_test.go | 22 +- .../devcenter/armdevcenter/projects_client.go | 30 +- .../projects_client_example_test.go | 72 +- .../devcenter/armdevcenter/response_types.go | 10 + .../armdevcenter/schedules_client.go | 26 +- .../schedules_client_example_test.go | 20 +- .../devcenter/armdevcenter/skus_client.go | 4 +- .../armdevcenter/skus_client_example_test.go | 2 +- .../devcenter/armdevcenter/usages_client.go | 4 +- .../usages_client_example_test.go | 2 +- .../devhub/armdevhub/CHANGELOG.md | 19 + .../devhub/armdevhub/autorest.md | 8 +- .../devhub/armdevhub/constants.go | 149 +- .../armdevhub/developerhubservice_client.go | 65 +- ...developerhubservice_client_example_test.go | 44 +- .../devhub/armdevhub/models.go | 194 +- .../devhub/armdevhub/models_serde.go | 83 + .../devhub/armdevhub/operations_client.go | 4 +- .../operations_client_example_test.go | 2 +- .../devhub/armdevhub/response_types.go | 6 + .../devhub/armdevhub/workflow_client.go | 24 +- .../armdevhub/workflow_client_example_test.go | 144 +- .../CHANGELOG.md | 10 + .../armdeviceprovisioningservices/autorest.md | 7 +- .../armdeviceprovisioningservices/build.go | 2 +- .../constants.go | 22 +- .../dpscertificate_client.go | 24 +- .../dpscertificate_client_example_test.go | 24 +- .../armdeviceprovisioningservices/go.mod | 16 +- .../armdeviceprovisioningservices/go.sum | 36 +- .../iotdpsresource_client.go | 78 +- .../iotdpsresource_client_example_test.go | 201 +- .../armdeviceprovisioningservices/models.go | 311 +- .../models_serde.go | 199 +- .../operations_client.go | 4 +- .../operations_client_example_test.go | 2 +- .../elastic/armelastic/CHANGELOG.md | 20 + .../alltrafficfilters_client_example_test.go | 2 +- ...ociatetrafficfilter_client_example_test.go | 2 +- .../elastic/armelastic/autorest.md | 6 +- .../elastic/armelastic/client_factory.go | 5 + .../elastic/armelastic/constants.go | 2 +- ...ndassociateipfilter_client_example_test.go | 2 +- ...ndassociateplfilter_client_example_test.go | 2 +- .../deploymentinfo_client_example_test.go | 2 +- ...deletetrafficfilter_client_example_test.go | 2 +- ...detachtrafficfilter_client_example_test.go | 2 +- .../externaluser_client_example_test.go | 2 +- sdk/resourcemanager/elastic/armelastic/go.mod | 16 +- sdk/resourcemanager/elastic/armelastic/go.sum | 36 +- ...iatedtrafficfilters_client_example_test.go | 2 +- .../elastic/armelastic/models.go | 292 +- .../elastic/armelastic/models_serde.go | 122 +- .../armelastic/monitor_client_example_test.go | 2 +- .../monitoredresources_client_example_test.go | 2 +- .../monitors_client_example_test.go | 12 +- .../operations_client_example_test.go | 2 +- .../armelastic/organizations_client.go | 13 +- .../organizations_client_example_test.go | 8 +- .../elastic/armelastic/response_types.go | 5 + .../tagrules_client_example_test.go | 8 +- .../trafficfilters_client_example_test.go | 2 +- .../upgradableversions_client_example_test.go | 2 +- .../elastic/armelastic/versions_client.go | 114 + .../versions_client_example_test.go | 59 + .../vmcollection_client_example_test.go | 2 +- .../armelastic/vmhost_client_example_test.go | 2 +- .../vmingestion_client_example_test.go | 2 +- .../elasticsan/armelasticsan/CHANGELOG.md | 38 + .../elasticsan/armelasticsan/autorest.md | 8 +- .../armelasticsan/client_factory.go | 10 + .../elasticsan/armelasticsan/constants.go | 55 +- .../armelasticsan/elasticsans_client.go | 38 +- .../elasticsans_client_example_test.go | 733 +- .../elasticsan/armelasticsan/go.mod | 16 +- .../elasticsan/armelasticsan/go.sum | 36 +- .../elasticsan/armelasticsan/models.go | 421 +- .../elasticsan/armelasticsan/models_serde.go | 390 +- .../armelasticsan/operations_client.go | 4 +- .../operations_client_example_test.go | 20 +- .../privateendpointconnections_client.go | 317 + ...endpointconnections_client_example_test.go | 380 + .../privatelinkresources_client.go | 103 + ...rivatelinkresources_client_example_test.go | 104 + .../armelasticsan/response_types.go | 25 + .../elasticsan/armelasticsan/skus_client.go | 4 +- .../armelasticsan/skus_client_example_test.go | 18 +- .../armelasticsan/volumegroups_client.go | 34 +- .../volumegroups_client_example_test.go | 442 +- .../armelasticsan/volumes_client.go | 34 +- .../volumes_client_example_test.go | 300 +- .../eventgrid/armeventgrid/CHANGELOG.md | 228 + .../eventgrid/armeventgrid/assets.json | 2 +- .../eventgrid/armeventgrid/autorest.md | 7 +- .../armeventgrid/cacertificates_client.go | 330 + .../cacertificates_client_example_test.go | 155 + .../eventgrid/armeventgrid/channels_client.go | 26 +- .../channels_client_example_test.go | 26 +- .../eventgrid/armeventgrid/client_factory.go | 61 +- .../armeventgrid/clientgroups_client.go | 330 + .../clientgroups_client_example_test.go | 146 + .../eventgrid/armeventgrid/clients_client.go | 329 + .../clients_client_example_test.go | 214 + .../eventgrid/armeventgrid/constants.go | 632 +- .../domaineventsubscriptions_client.go | 38 +- ...neventsubscriptions_client_example_test.go | 30 +- .../eventgrid/armeventgrid/domains_client.go | 38 +- .../domains_client_example_test.go | 34 +- .../domaintopiceventsubscriptions_client.go | 34 +- ...ceventsubscriptions_client_example_test.go | 120 +- .../armeventgrid/domaintopics_client.go | 20 +- .../domaintopics_client_example_test.go | 14 +- .../armeventgrid/eventsubscriptions_client.go | 70 +- .../eventsubscriptions_client_example_test.go | 402 +- .../armeventgrid/extensiontopics_client.go | 4 +- .../extensiontopics_client_example_test.go | 10 +- .../eventgrid/armeventgrid/models.go | 1852 +- .../eventgrid/armeventgrid/models_serde.go | 6676 +++++-- .../armeventgrid/namespaces_client.go | 568 + .../namespaces_client_example_test.go | 326 + ...namespacetopiceventsubscriptions_client.go | 435 + ...ceventsubscriptions_client_example_test.go | 247 + .../armeventgrid/namespacetopics_client.go | 539 + .../namespacetopics_client_example_test.go | 257 + .../armeventgrid/operations_client.go | 4 +- .../operations_client_example_test.go | 2 +- .../partnerconfigurations_client.go | 38 +- ...rtnerconfigurations_client_example_test.go | 30 +- .../partnerdestinations_client.go | 502 + ...partnerdestinations_client_example_test.go | 296 + .../armeventgrid/partnernamespaces_client.go | 38 +- .../partnernamespaces_client_example_test.go | 30 +- .../partnerregistrations_client.go | 30 +- ...artnerregistrations_client_example_test.go | 31 +- .../partnertopiceventsubscriptions_client.go | 34 +- ...ceventsubscriptions_client_example_test.go | 36 +- .../armeventgrid/partnertopics_client.go | 34 +- .../partnertopics_client_example_test.go | 28 +- .../armeventgrid/permissionbindings_client.go | 330 + .../permissionbindings_client_example_test.go | 153 + .../armeventgrid/polymorphic_helpers.go | 129 + .../privateendpointconnections_client.go | 48 +- ...endpointconnections_client_example_test.go | 20 +- .../privatelinkresources_client.go | 22 +- ...rivatelinkresources_client_example_test.go | 8 +- .../eventgrid/armeventgrid/response_types.go | 235 + .../systemtopiceventsubscriptions_client.go | 34 +- ...ceventsubscriptions_client_example_test.go | 122 +- .../armeventgrid/systemtopics_client.go | 30 +- .../systemtopics_client_example_test.go | 34 +- .../topiceventsubscriptions_client.go | 38 +- ...ceventsubscriptions_client_example_test.go | 30 +- .../eventgrid/armeventgrid/topics_client.go | 44 +- .../topics_client_example_test.go | 75 +- .../armeventgrid/topicspaces_client.go | 329 + .../topicspaces_client_example_test.go | 153 + .../armeventgrid/topictypes_client.go | 12 +- .../topictypes_client_example_test.go | 6 +- .../armeventgrid/verifiedpartners_client.go | 8 +- .../verifiedpartners_client_example_test.go | 14 +- .../armextendedlocation/CHANGELOG.md | 21 + .../armextendedlocation/autorest.md | 6 +- .../armextendedlocation/client_factory.go | 5 + .../armextendedlocation/constants.go | 2 +- .../customlocations_client.go | 96 +- .../customlocations_client_example_test.go | 109 +- .../armextendedlocation/go.mod | 16 +- .../armextendedlocation/go.sum | 36 +- .../armextendedlocation/models.go | 156 + .../armextendedlocation/models_serde.go | 276 + .../resourcesyncrules_client.go | 383 + .../resourcesyncrules_client_example_test.go | 315 + .../armextendedlocation/response_types.go | 30 + .../frontdoor/armfrontdoor/CHANGELOG.md | 12 + .../frontdoor/armfrontdoor/autorest.md | 8 +- .../frontdoor/armfrontdoor/client_factory.go | 36 +- .../frontdoor/armfrontdoor/constants.go | 16 +- .../armfrontdoor/endpoints_client.go | 6 +- .../endpoints_client_example_test.go | 2 +- .../experiments_client_example_test.go | 10 +- .../armfrontdoor/frontdoors_client.go | 28 +- .../frontdoors_client_example_test.go | 12 +- .../armfrontdoor/frontendendpoints_client.go | 20 +- .../frontendendpoints_client_example_test.go | 8 +- .../armfrontdoor/managedrulesets_client.go | 4 +- .../managedrulesets_client_example_test.go | 2 +- .../frontdoor/armfrontdoor/models.go | 783 +- .../frontdoor/armfrontdoor/models_serde.go | 62 + .../armfrontdoor/nameavailability_client.go | 4 +- .../nameavailability_client_example_test.go | 2 +- ...nameavailabilitywithsubscription_client.go | 4 +- ...itywithsubscription_client_example_test.go | 2 +- ...kexperimentprofiles_client_example_test.go | 10 +- .../frontdoor/armfrontdoor/policies_client.go | 147 +- .../policies_client_example_test.go | 291 +- ...configuredendpoints_client_example_test.go | 2 +- .../reports_client_example_test.go | 4 +- .../frontdoor/armfrontdoor/response_types.go | 10 + .../armfrontdoor/rulesengines_client.go | 20 +- .../rulesengines_client_example_test.go | 8 +- .../armgraphservices/CHANGELOG.md | 10 + .../armgraphservices/account_client.go | 276 - .../account_client_example_test.go | 154 - .../armgraphservices/accounts_client.go | 239 +- .../accounts_client_example_test.go | 136 +- .../armgraphservices/autorest.md | 8 +- .../armgraphservices/client_factory.go | 9 +- .../armgraphservices/constants.go | 2 +- .../graphservices/armgraphservices/go.mod | 16 +- .../graphservices/armgraphservices/go.sum | 36 +- .../graphservices/armgraphservices/models.go | 109 +- ...eration_client.go => operations_client.go} | 42 +- ...t.go => operations_client_example_test.go} | 6 +- .../armgraphservices/response_types.go | 26 +- .../hdinsight/armhdinsight/CHANGELOG.md | 8 +- .../armhdinsight/applications_client.go | 24 +- .../applications_client_example_test.go | 12 +- .../hdinsight/armhdinsight/autorest.md | 7 +- .../hdinsight/armhdinsight/client_factory.go | 38 +- .../hdinsight/armhdinsight/clusters_client.go | 72 +- .../clusters_client_example_test.go | 175 +- .../armhdinsight/configurations_client.go | 14 +- .../configurations_client_example_test.go | 8 +- .../hdinsight/armhdinsight/constants.go | 2 +- .../armhdinsight/extensions_client.go | 52 +- .../extensions_client_example_test.go | 20 +- .../hdinsight/armhdinsight/go.mod | 16 +- .../hdinsight/armhdinsight/go.sum | 36 +- .../armhdinsight/locations_client.go | 24 +- .../locations_client_example_test.go | 25 +- .../hdinsight/armhdinsight/models.go | 4 + .../hdinsight/armhdinsight/models_serde.go | 4 + .../armhdinsight/operations_client.go | 4 +- .../operations_client_example_test.go | 62 + .../privateendpointconnections_client.go | 20 +- ...endpointconnections_client_example_test.go | 8 +- .../privatelinkresources_client.go | 8 +- ...rivatelinkresources_client_example_test.go | 4 +- .../armhdinsight/scriptactions_client.go | 16 +- .../scriptactions_client_example_test.go | 8 +- .../scriptexecutionhistory_client.go | 8 +- ...iptexecutionhistory_client_example_test.go | 4 +- .../armhdinsight/virtualmachines_client.go | 14 +- .../virtualmachines_client_example_test.go | 6 +- .../armiotfirmwaredefense/CHANGELOG.md | 7 + .../armiotfirmwaredefense/LICENSE.txt | 21 + .../armiotfirmwaredefense/README.md | 85 + .../armiotfirmwaredefense/autorest.md | 13 + .../armiotfirmwaredefense/build.go | 7 + .../armiotfirmwaredefense/ci.yml | 28 + .../armiotfirmwaredefense/client_factory.go | 54 + .../armiotfirmwaredefense/constants.go | 270 + .../armiotfirmwaredefense/firmware_client.go | 1375 ++ .../firmware_client_example_test.go | 1488 ++ .../armiotfirmwaredefense/go.mod | 21 + .../armiotfirmwaredefense/go.sum | 31 + .../armiotfirmwaredefense/models.go | 780 + .../armiotfirmwaredefense/models_serde.go | 1520 ++ .../operations_client.go | 94 + .../operations_client_example_test.go | 85 + .../armiotfirmwaredefense/response_types.go | 150 + .../armiotfirmwaredefense/time_rfc3339.go | 87 + .../workspaces_client.go | 450 + .../workspaces_client_example_test.go | 456 + .../iothub/armiothub/assets.json | 6 + sdk/resourcemanager/iothub/armiothub/go.mod | 10 +- sdk/resourcemanager/iothub/armiothub/go.sum | 17 + .../iothub/armiothub/iothub_live_test.go | 297 + .../armkubernetesconfiguration/CHANGELOG.md | 21 + .../armkubernetesconfiguration/autorest.md | 8 +- .../armkubernetesconfiguration/constants.go | 4 +- .../extensions_client.go | 26 +- .../extensions_client_example_test.go | 193 +- .../fluxconfigoperationstatus_client.go | 4 +- ...nfigoperationstatus_client_example_test.go | 4 +- .../fluxconfigurations_client.go | 26 +- .../fluxconfigurations_client_example_test.go | 30 +- .../armkubernetesconfiguration/go.mod | 2 +- .../armkubernetesconfiguration/models.go | 165 +- .../models_serde.go | 331 +- .../operations_client.go | 4 +- .../operations_client_example_test.go | 4 +- .../operationstatus_client.go | 8 +- .../operationstatus_client_example_test.go | 6 +- .../sourcecontrolconfigurations_client.go | 18 +- ...ntrolconfigurations_client_example_test.go | 10 +- .../kusto/armkusto/CHANGELOG.md | 26 + .../attacheddatabaseconfigurations_client.go | 45 +- ...abaseconfigurations_client_example_test.go | 12 +- .../kusto/armkusto/autorest.md | 7 +- .../kusto/armkusto/client_factory.go | 8 +- .../clusterprincipalassignments_client.go | 45 +- ...rincipalassignments_client_example_test.go | 12 +- .../kusto/armkusto/clusters_client.go | 224 +- .../armkusto/clusters_client_example_test.go | 105 +- .../kusto/armkusto/constants.go | 30 +- .../kusto/armkusto/database_client.go | 108 + .../armkusto/database_client_example_test.go | 61 + .../databaseprincipalassignments_client.go | 45 +- ...rincipalassignments_client_example_test.go | 12 +- .../kusto/armkusto/databases_client.go | 92 +- .../armkusto/databases_client_example_test.go | 79 +- .../kusto/armkusto/dataconnections_client.go | 65 +- .../dataconnections_client_example_test.go | 30 +- sdk/resourcemanager/kusto/armkusto/go.mod | 18 +- sdk/resourcemanager/kusto/armkusto/go.sum | 36 +- .../managedprivateendpoints_client.go | 57 +- ...gedprivateendpoints_client_example_test.go | 14 +- sdk/resourcemanager/kusto/armkusto/models.go | 78 +- .../kusto/armkusto/models_serde.go | 171 + .../kusto/armkusto/operations_client.go | 4 +- .../operations_client_example_test.go | 4 +- .../armkusto/operationsresults_client.go | 11 +- .../operationsresults_client_example_test.go | 4 +- .../operationsresultslocation_client.go | 22 +- ...ionsresultslocation_client_example_test.go | 4 +- .../privateendpointconnections_client.go | 39 +- ...endpointconnections_client_example_test.go | 10 +- .../armkusto/privatelinkresources_client.go | 15 +- ...rivatelinkresources_client_example_test.go | 6 +- .../kusto/armkusto/response_types.go | 13 +- .../kusto/armkusto/scripts_client.go | 61 +- .../armkusto/scripts_client_example_test.go | 14 +- .../kusto/armkusto/skus_client.go | 9 +- .../armkusto/skus_client_example_test.go | 4 +- .../liftrqumulo/armqumulo/CHANGELOG.md | 6 + .../liftrqumulo/armqumulo/autorest.md | 8 +- .../liftrqumulo/armqumulo/constants.go | 2 +- .../armqumulo/filesystems_client.go | 28 +- .../filesystems_client_example_test.go | 28 +- .../liftrqumulo/armqumulo/models.go | 114 +- .../armqumulo/operations_client.go | 4 +- .../operations_client_example_test.go | 4 +- .../logic/armlogic/assets.json | 6 + sdk/resourcemanager/logic/armlogic/go.mod | 8 + sdk/resourcemanager/logic/armlogic/go.sum | 17 + .../armlogic/integrationaccounts_live_test.go | 631 + .../logic/armlogic/operations_live_test.go | 68 + .../logic/armlogic/workflows_live_test.go | 235 + .../armmanagednetworkfabric/CHANGELOG.md | 391 + .../armmanagednetworkfabric/LICENSE.txt | 21 + .../armmanagednetworkfabric/README.md | 85 + .../accesscontrollists_client.go | 605 + .../accesscontrollists_client_example_test.go | 956 + .../armmanagednetworkfabric/autorest.md | 13 + .../armmanagednetworkfabric/build.go | 7 + .../armmanagednetworkfabric/ci.yml | 28 + .../armmanagednetworkfabric/client_factory.go | 159 + .../armmanagednetworkfabric/constants.go | 878 + .../externalnetworks_client.go | 520 + .../externalnetworks_client_example_test.go | 572 + .../armmanagednetworkfabric/go.mod | 21 + .../armmanagednetworkfabric/go.sum | 31 + .../internalnetworks_client.go | 591 + .../internalnetworks_client_example_test.go | 777 + .../internetgatewayrules_client.go | 413 + ...nternetgatewayrules_client_example_test.go | 321 + .../internetgateways_client.go | 412 + .../internetgateways_client_example_test.go | 312 + .../ipcommunities_client.go | 412 + .../ipcommunities_client_example_test.go | 353 + .../ipextendedcommunities_client.go | 413 + ...extendedcommunities_client_example_test.go | 342 + .../ipprefixes_client.go | 409 + .../ipprefixes_client_example_test.go | 350 + .../l2isolationdomains_client.go | 607 + .../l2isolationdomains_client_example_test.go | 442 + .../l3isolationdomains_client.go | 609 + .../l3isolationdomains_client_example_test.go | 562 + .../armmanagednetworkfabric/models.go | 4090 ++++ .../armmanagednetworkfabric/models_serde.go | 7669 +++++++ .../neighborgroups_client.go | 412 + .../neighborgroups_client_example_test.go | 402 + .../networkdevices_client.go | 671 + .../networkdevices_client_example_test.go | 507 + .../networkdeviceskus_client.go | 151 + .../networkdeviceskus_client_example_test.go | 140 + .../networkfabriccontrollers_client.go | 413 + ...rkfabriccontrollers_client_example_test.go | 455 + .../networkfabrics_client.go | 996 + .../networkfabrics_client_example_test.go | 1327 ++ .../networkfabricskus_client.go | 151 + .../networkfabricskus_client_example_test.go | 110 + .../networkinterfaces_client.go | 450 + .../networkinterfaces_client_example_test.go | 280 + .../networkpacketbrokers_client.go | 413 + ...etworkpacketbrokers_client_example_test.go | 321 + .../networkracks_client.go | 412 + .../networkracks_client_example_test.go | 303 + .../networktaprules_client.go | 605 + .../networktaprules_client_example_test.go | 953 + .../networktaps_client.go | 537 + .../networktaps_client_example_test.go | 484 + .../networktonetworkinterconnects_client.go | 521 + ...etworkinterconnects_client_example_test.go | 571 + .../operations_client.go | 94 + .../operations_client_example_test.go | 82 + .../armmanagednetworkfabric/response_types.go | 836 + .../routepolicies_client.go | 605 + .../routepolicies_client_example_test.go | 749 + .../armmanagednetworkfabric/time_rfc3339.go | 87 + .../armmanagementgroups/assets.json | 6 + .../armmanagementgroups/go.mod | 10 +- .../armmanagementgroups/go.sum | 17 + .../management_live_test.go | 188 + .../armmarketplaceordering/CHANGELOG.md | 14 +- .../armmarketplaceordering/README.md | 27 +- .../armmarketplaceordering/autorest.md | 9 +- .../armmarketplaceordering/build.go | 2 +- .../armmarketplaceordering/client_factory.go | 3 +- .../armmarketplaceordering/constants.go | 5 +- .../armmarketplaceordering/fake/internal.go | 123 + .../fake/marketplaceagreements_server.go | 319 + .../fake/operations_server.go | 96 + .../fake/time_rfc3339.go | 86 + .../fake_example_test.go | 77 + .../armmarketplaceordering/go.mod | 10 +- .../armmarketplaceordering/go.sum | 20 +- .../marketplaceagreements_client.go | 98 +- .../armmarketplaceordering/models.go | 107 +- .../armmarketplaceordering/models_serde.go | 3 +- .../operations_client.go | 5 +- .../armmarketplaceordering/options.go | 45 + .../armmarketplaceordering/response_types.go | 10 +- .../armmarketplaceordering/time_rfc3339.go | 3 +- .../armmediaservices/accounts_live_test.go | 229 + .../armmediaservices/assets.json | 6 + .../armmediaservices/encoding_live_test.go | 313 + .../mediaservices/armmediaservices/go.mod | 10 +- .../mediaservices/armmediaservices/go.sum | 18 + .../armmediaservices/metadata_live_test.go | 587 + .../streamingservice_live_test.go | 395 + .../armmobilenetwork/CHANGELOG.md | 47 + .../attacheddatanetworks_client.go | 102 +- ...ttacheddatanetworks_client_example_test.go | 20 +- .../armmobilenetwork/autorest.md | 8 +- .../armmobilenetwork/client_factory.go | 29 +- .../armmobilenetwork/constants.go | 135 +- .../armmobilenetwork/datanetworks_client.go | 102 +- .../datanetworks_client_example_test.go | 20 +- .../diagnosticspackages_client.go | 317 + ...diagnosticspackages_client_example_test.go | 143 + .../mobilenetwork/armmobilenetwork/go.mod | 18 +- .../mobilenetwork/armmobilenetwork/go.sum | 36 +- .../armmobilenetwork/mobilenetworks_client.go | 109 +- .../mobilenetworks_client_example_test.go | 24 +- .../mobilenetwork/armmobilenetwork/models.go | 581 +- .../armmobilenetwork/models_serde.go | 381 +- .../armmobilenetwork/operations_client.go | 7 +- .../operations_client_example_test.go | 4 +- .../mobilenetwork/armmobilenetwork/options.go | 472 + .../armmobilenetwork/packetcaptures_client.go | 393 + .../packetcaptures_client_example_test.go | 213 + .../packetcorecontrolplanes_client.go | 188 +- ...etcorecontrolplanes_client_example_test.go | 186 +- .../packetcorecontrolplaneversions_client.go | 134 +- ...ontrolplaneversions_client_example_test.go | 114 +- .../packetcoredataplanes_client.go | 102 +- ...acketcoredataplanes_client_example_test.go | 20 +- .../armmobilenetwork/response_types.go | 127 +- .../armmobilenetwork/services_client.go | 102 +- .../services_client_example_test.go | 20 +- .../armmobilenetwork/simgroups_client.go | 117 +- .../simgroups_client_example_test.go | 56 +- .../armmobilenetwork/simpolicies_client.go | 102 +- .../simpolicies_client_example_test.go | 78 +- .../armmobilenetwork/sims_client.go | 160 +- .../sims_client_example_test.go | 82 +- .../armmobilenetwork/sites_client.go | 178 +- .../sites_client_example_test.go | 51 +- .../armmobilenetwork/slices_client.go | 102 +- .../slices_client_example_test.go | 20 +- .../armmobilenetwork/time_rfc3339.go | 3 +- .../monitor/armmonitor/CHANGELOG.md | 12 + .../monitor/armmonitor/README.md | 27 +- .../monitor/armmonitor/actiongroups_client.go | 128 +- .../armmonitor/activitylogalerts_client.go | 74 +- .../monitor/armmonitor/activitylogs_client.go | 5 +- .../armmonitor/alertruleincidents_client.go | 20 +- .../monitor/armmonitor/alertrules_client.go | 74 +- .../monitor/armmonitor/autorest.md | 6 +- .../armmonitor/autoscalesettings_client.go | 74 +- .../azuremonitorworkspaces_client.go | 74 +- .../monitor/armmonitor/baselines_client.go | 5 +- .../monitor/armmonitor/build.go | 2 +- .../monitor/armmonitor/client_factory.go | 113 +- .../monitor/armmonitor/constants.go | 129 +- .../datacollectionendpoints_client.go | 74 +- .../datacollectionruleassociations_client.go | 56 +- .../armmonitor/datacollectionrules_client.go | 74 +- .../armmonitor/diagnosticsettings_client.go | 52 +- .../diagnosticsettingscategory_client.go | 20 +- .../armmonitor/eventcategories_client.go | 5 +- .../armmonitor/fake/actiongroups_server.go | 449 + .../fake/activitylogalerts_server.go | 314 + .../armmonitor/fake/activitylogs_server.go | 120 + .../fake/alertruleincidents_server.go | 152 + .../armmonitor/fake/alertrules_server.go | 307 + .../fake/autoscalesettings_server.go | 314 + .../fake/azuremonitorworkspaces_server.go | 321 + .../armmonitor/fake/baselines_server.go | 158 + .../fake/datacollectionendpoints_server.go | 327 + .../datacollectionruleassociations_server.go | 335 + .../fake/datacollectionrules_server.go | 327 + .../fake/diagnosticsettings_server.go | 226 + .../fake/diagnosticsettingscategory_server.go | 144 + .../armmonitor/fake/eventcategories_server.go | 92 + .../monitor/armmonitor/fake/internal.go | 123 + .../armmonitor/fake/logprofiles_server.go | 249 + .../armmonitor/fake/metricalerts_server.go | 307 + .../fake/metricalertsstatus_server.go | 143 + .../fake/metricdefinitions_server.go | 170 + .../fake/metricnamespaces_server.go | 116 + .../monitor/armmonitor/fake/metrics_server.go | 434 + .../armmonitor/fake/operations_server.go | 84 + .../fake/operationsformonitor_server.go | 96 + .../armmonitor/fake/polymorphic_helpers.go | 171 + .../fake/predictivemetric_server.go | 121 + .../fake/privateendpointconnections_server.go | 261 + .../fake/privatelinkresources_server.go | 143 + .../fake/privatelinkscopedresources_server.go | 272 + .../privatelinkscopeoperationstatus_server.go | 100 + .../fake/privatelinkscopes_server.go | 327 + .../fake/scheduledqueryrules_server.go | 314 + .../fake/tenantactiongroups_server.go | 269 + .../fake/tenantactivitylogs_server.go | 115 + .../monitor/armmonitor/fake/time_rfc3339.go | 86 + .../armmonitor/fake/vminsights_server.go | 96 + .../monitor/armmonitor/fake_example_test.go | 79 + sdk/resourcemanager/monitor/armmonitor/go.mod | 10 +- sdk/resourcemanager/monitor/armmonitor/go.sum | 20 +- .../monitor/armmonitor/interfaces.go | 55 + .../monitor/armmonitor/logprofiles_client.go | 72 +- .../monitor/armmonitor/metricalerts_client.go | 74 +- .../armmonitor/metricalertsstatus_client.go | 33 +- .../armmonitor/metricdefinitions_client.go | 7 +- .../armmonitor/metricnamespaces_client.go | 5 +- .../monitor/armmonitor/metrics_client.go | 53 +- .../monitor/armmonitor/models.go | 893 +- .../monitor/armmonitor/models_serde.go | 3 +- .../monitor/armmonitor/operations_client.go | 18 +- .../armmonitor/operationsformonitor_client.go | 5 +- .../monitor/armmonitor/options.go | 852 + .../monitor/armmonitor/polymorphic_helpers.go | 28 +- .../armmonitor/predictivemetric_client.go | 18 +- .../privateendpointconnections_client.go | 72 +- .../armmonitor/privatelinkresources_client.go | 33 +- .../privatelinkscopedresources_client.go | 59 +- .../privatelinkscopeoperationstatus_client.go | 18 +- .../armmonitor/privatelinkscopes_client.go | 79 +- .../monitor/armmonitor/response_types.go | 102 +- .../armmonitor/scheduledqueryrules_client.go | 74 +- .../armmonitor/tenantactiongroups_client.go | 72 +- .../armmonitor/tenantactivitylogs_client.go | 5 +- .../monitor/armmonitor/time_rfc3339.go | 3 +- .../monitor/armmonitor/vminsights_client.go | 18 +- .../armmysqlflexibleservers/CHANGELOG.md | 57 + .../mysql/armmysqlflexibleservers/autorest.md | 7 +- .../azureadadministrators_client.go | 321 + ...ureadadministrators_client_example_test.go | 156 + .../backupandexport_client.go | 171 + .../backupandexport_client_example_test.go | 96 + .../armmysqlflexibleservers/backups_client.go | 70 +- .../backups_client_example_test.go | 36 +- .../checknameavailability_client.go | 4 +- ...ecknameavailability_client_example_test.go | 4 +- ...knameavailabilitywithoutlocation_client.go | 94 + ...litywithoutlocation_client_example_test.go | 47 + .../checkvirtualnetworksubnetusage_client.go | 4 +- ...lnetworksubnetusage_client_example_test.go | 6 +- .../armmysqlflexibleservers/client_factory.go | 40 +- .../configurations_client.go | 104 +- .../configurations_client_example_test.go | 59 +- .../armmysqlflexibleservers/constants.go | 105 +- .../databases_client.go | 20 +- .../databases_client_example_test.go | 10 +- .../firewallrules_client.go | 20 +- .../firewallrules_client_example_test.go | 10 +- .../getprivatednszonesuffix_client.go | 4 +- ...rivatednszonesuffix_client_example_test.go | 4 +- .../mysql/armmysqlflexibleservers/go.mod | 2 +- .../locationbasedcapabilities_client.go | 4 +- ...onbasedcapabilities_client_example_test.go | 4 +- .../logfiles_client.go | 115 + .../logfiles_client_example_test.go | 58 + .../mysql/armmysqlflexibleservers/models.go | 311 +- .../armmysqlflexibleservers/models_serde.go | 598 +- .../operations_client.go | 4 +- .../operations_client_example_test.go | 4 +- .../polymorphic_helpers.go | 30 + .../replicas_client.go | 4 +- .../replicas_client_example_test.go | 4 +- .../armmysqlflexibleservers/response_types.go | 55 + .../armmysqlflexibleservers/servers_client.go | 125 +- .../servers_client_example_test.go | 64 +- .../netapp/armnetapp/CHANGELOG.md | 13 + .../netapp/armnetapp/accountbackups_client.go | 14 +- .../accountbackups_client_example_test.go | 6 +- .../netapp/armnetapp/accounts_client.go | 36 +- .../armnetapp/accounts_client_example_test.go | 14 +- .../netapp/armnetapp/autorest.md | 8 +- .../netapp/armnetapp/backuppolicies_client.go | 26 +- .../backuppolicies_client_example_test.go | 10 +- .../netapp/armnetapp/backups_client.go | 40 +- .../armnetapp/backups_client_example_test.go | 16 +- .../netapp/armnetapp/constants.go | 17 +- sdk/resourcemanager/netapp/armnetapp/go.mod | 16 +- sdk/resourcemanager/netapp/armnetapp/go.sum | 36 +- .../netapp/armnetapp/models.go | 974 +- .../netapp/armnetapp/models_serde.go | 70 + .../netapp/armnetapp/operations_client.go | 4 +- .../operations_client_example_test.go | 2 +- .../netapp/armnetapp/pools_client.go | 26 +- .../armnetapp/pools_client_example_test.go | 10 +- .../netapp/armnetapp/resource_client.go | 16 +- .../armnetapp/resource_client_example_test.go | 8 +- .../armnetapp/resourcequotalimits_client.go | 8 +- ...resourcequotalimits_client_example_test.go | 4 +- .../netapp/armnetapp/response_types.go | 5 + .../armnetapp/snapshotpolicies_client.go | 28 +- .../snapshotpolicies_client_example_test.go | 12 +- .../netapp/armnetapp/snapshots_client.go | 36 +- .../snapshots_client_example_test.go | 12 +- .../netapp/armnetapp/subvolumes_client.go | 32 +- .../subvolumes_client_example_test.go | 12 +- .../netapp/armnetapp/volumegroups_client.go | 20 +- .../volumegroups_client_example_test.go | 8 +- .../armnetapp/volumequotarules_client.go | 26 +- .../volumequotarules_client_example_test.go | 10 +- .../netapp/armnetapp/volumes_client.go | 190 +- .../armnetapp/volumes_client_example_test.go | 71 +- .../network/armnetwork/CHANGELOG.md | 88 + .../network/armnetwork/README.md | 25 + .../armnetwork/adminrulecollections_client.go | 75 +- ...dminrulecollections_client_example_test.go | 13 +- .../network/armnetwork/adminrules_client.go | 75 +- .../adminrules_client_example_test.go | 19 +- ...atewayprivateendpointconnections_client.go | 79 +- ...endpointconnections_client_example_test.go | 11 +- ...ationgatewayprivatelinkresources_client.go | 9 +- ...rivatelinkresources_client_example_test.go | 4 +- .../armnetwork/applicationgateways_client.go | 326 +- ...applicationgateways_client_example_test.go | 236 +- ...cationgatewaywafdynamicmanifests_client.go | 9 +- ...wafdynamicmanifests_client_example_test.go | 4 +- ...iongatewaywafdynamicmanifests_live_test.go | 4 +- ...atewaywafdynamicmanifestsdefault_client.go | 22 +- ...micmanifestsdefault_client_example_test.go | 4 +- .../applicationsecuritygroup_live_test.go | 4 +- .../applicationsecuritygroups_client.go | 109 +- ...ationsecuritygroups_client_example_test.go | 14 +- .../network/armnetwork/assets.json | 2 +- .../network/armnetwork/autorest.md | 13 +- .../armnetwork/availabledelegations_client.go | 9 +- ...vailabledelegations_client_example_test.go | 4 +- .../availabledelegations_live_test.go | 4 +- .../availableendpointservices_client.go | 9 +- ...bleendpointservices_client_example_test.go | 4 +- .../availableprivateendpointtypes_client.go | 15 +- ...rivateendpointtypes_client_example_test.go | 6 +- ...vailableresourcegroupdelegations_client.go | 9 +- ...rcegroupdelegations_client_example_test.go | 4 +- .../availableservicealiases_client.go | 15 +- ...lableservicealiases_client_example_test.go | 6 +- .../availableservicealiases_live_test.go | 4 +- .../azurefirewallfqdntag_live_test.go | 4 +- .../azurefirewallfqdntags_client.go | 9 +- ...urefirewallfqdntags_client_example_test.go | 4 +- .../armnetwork/azurefirewalls_client.go | 214 +- .../azurefirewalls_client_example_test.go | 89 +- .../armnetwork/azurewebcategory_live_test.go | 4 +- .../armnetwork/bastionhost_live_test.go | 4 +- .../network/armnetwork/bastionhosts_client.go | 113 +- .../bastionhosts_client_example_test.go | 44 +- .../bgpservicecommunities_client.go | 9 +- ...pservicecommunities_client_example_test.go | 4 +- .../network/armnetwork/build.go | 2 +- .../checkdnsavailability_live_test.go | 4 +- .../network/armnetwork/client_factory.go | 462 +- .../configurationpolicygroups_client.go | 79 +- ...urationpolicygroups_client_example_test.go | 10 +- .../armnetwork/connectionmonitors_client.go | 172 +- .../connectionmonitors_client_example_test.go | 20 +- .../connectivityconfigurations_client.go | 75 +- ...ivityconfigurations_client_example_test.go | 13 +- .../network/armnetwork/constants.go | 243 +- .../armnetwork/customipprefix_live_test.go | 4 +- .../armnetwork/customipprefixes_client.go | 109 +- .../customipprefixes_client_example_test.go | 14 +- .../armnetwork/ddoscustompolicies_client.go | 97 +- .../ddoscustompolicies_client_example_test.go | 10 +- .../ddosprotectionplan_live_test.go | 4 +- .../armnetwork/ddosprotectionplans_client.go | 109 +- ...ddosprotectionplans_client_example_test.go | 14 +- .../armnetwork/defaultsecurityrules_client.go | 28 +- ...efaultsecurityrules_client_example_test.go | 6 +- .../armnetwork/dscpconfiguration_client.go | 85 +- .../dscpconfiguration_client_example_test.go | 12 +- .../armnetwork/endpointservice_live_test.go | 4 +- .../expressroutecircuit_live_test.go | 4 +- ...xpressroutecircuitauthorizations_client.go | 79 +- ...rcuitauthorizations_client_example_test.go | 10 +- .../expressroutecircuitconnections_client.go | 79 +- ...ecircuitconnections_client_example_test.go | 10 +- .../expressroutecircuitpeerings_client.go | 79 +- ...outecircuitpeerings_client_example_test.go | 10 +- .../armnetwork/expressroutecircuits_client.go | 216 +- ...xpressroutecircuits_client_example_test.go | 26 +- .../expressrouteconnections_client.go | 92 +- ...essrouteconnections_client_example_test.go | 10 +- ...ressroutecrossconnectionpeerings_client.go | 79 +- ...sconnectionpeerings_client_example_test.go | 10 +- .../expressroutecrossconnections_client.go | 155 +- ...utecrossconnections_client_example_test.go | 18 +- .../armnetwork/expressroutegateways_client.go | 139 +- ...xpressroutegateways_client_example_test.go | 14 +- .../armnetwork/expressroutelinks_client.go | 28 +- .../expressroutelinks_client_example_test.go | 6 +- .../expressrouteportauthorizations_client.go | 79 +- ...eportauthorizations_client_example_test.go | 10 +- .../armnetwork/expressrouteports_client.go | 133 +- .../expressrouteports_client_example_test.go | 18 +- .../expressrouteportslocations_client.go | 28 +- ...routeportslocations_client_example_test.go | 6 +- ...xpressrouteproviderportslocation_client.go | 22 +- ...oviderportslocation_client_example_test.go | 4 +- .../expressrouteserviceproviders_client.go | 9 +- ...uteserviceproviders_client_example_test.go | 4 +- .../fake/adminrulecollections_server.go | 318 + .../armnetwork/fake/adminrules_server.go | 338 + ...atewayprivateendpointconnections_server.go | 272 + ...ationgatewayprivatelinkresources_server.go | 112 + .../fake/applicationgateways_server.go | 807 + ...cationgatewaywafdynamicmanifests_server.go | 108 + ...atewaywafdynamicmanifestsdefault_server.go | 96 + .../fake/applicationsecuritygroups_server.go | 340 + .../fake/availabledelegations_server.go | 108 + .../fake/availableendpointservices_server.go | 108 + .../availableprivateendpointtypes_server.go | 157 + ...vailableresourcegroupdelegations_server.go | 112 + .../fake/availableservicealiases_server.go | 157 + .../fake/azurefirewallfqdntags_server.go | 103 + .../armnetwork/fake/azurefirewalls_server.go | 461 + .../armnetwork/fake/bastionhosts_server.go | 353 + .../fake/bgpservicecommunities_server.go | 103 + .../fake/configurationpolicygroups_server.go | 272 + .../fake/connectionmonitors_server.go | 495 + .../fake/connectivityconfigurations_server.go | 302 + .../fake/customipprefixes_server.go | 352 + .../fake/ddoscustompolicies_server.go | 253 + .../fake/ddosprotectionplans_server.go | 340 + .../fake/defaultsecurityrules_server.go | 156 + .../fake/dscpconfiguration_server.go | 297 + ...xpressroutecircuitauthorizations_server.go | 272 + .../expressroutecircuitconnections_server.go | 288 + .../expressroutecircuitpeerings_server.go | 272 + .../fake/expressroutecircuits_server.go | 602 + .../fake/expressrouteconnections_server.go | 261 + ...ressroutecrossconnectionpeerings_server.go | 272 + .../expressroutecrossconnections_server.go | 468 + .../fake/expressroutegateways_server.go | 332 + .../fake/expressroutelinks_server.go | 156 + .../expressrouteportauthorizations_server.go | 272 + .../fake/expressrouteports_server.go | 383 + .../fake/expressrouteportslocations_server.go | 140 + ...xpressrouteproviderportslocation_server.go | 104 + .../expressrouteserviceproviders_server.go | 103 + .../fake/firewallpolicies_server.go | 352 + .../firewallpolicyidpssignatures_server.go | 104 + ...policyidpssignaturesfiltervalues_server.go | 104 + ...allpolicyidpssignaturesoverrides_server.go | 225 + ...rewallpolicyrulecollectiongroups_server.go | 272 + .../armnetwork/fake/flowlogs_server.go | 319 + .../network/armnetwork/fake/groups_server.go | 312 + .../armnetwork/fake/hubroutetables_server.go | 272 + .../hubvirtualnetworkconnections_server.go | 272 + .../armnetwork/fake/inboundnatrules_server.go | 284 + .../fake/inboundsecurityrule_server.go | 123 + .../fake/interfaceipconfigurations_server.go | 156 + .../fake/interfaceloadbalancers_server.go | 112 + .../armnetwork/fake/interfaces_server.go | 910 + .../fake/interfacetapconfigurations_server.go | 272 + .../network/armnetwork/fake/internal.go | 123 + .../armnetwork/fake/ipallocations_server.go | 352 + .../armnetwork/fake/ipgroups_server.go | 352 + .../loadbalancerbackendaddresspools_server.go | 272 + ...balancerfrontendipconfigurations_server.go | 156 + .../loadbalancerloadbalancingrules_server.go | 156 + .../loadbalancernetworkinterfaces_server.go | 112 + .../fake/loadbalanceroutboundrules_server.go | 156 + .../fake/loadbalancerprobes_server.go | 156 + .../armnetwork/fake/loadbalancers_server.go | 464 + .../fake/localnetworkgateways_server.go | 299 + .../armnetwork/fake/management_server.go | 761 + ...ntgroupnetworkmanagerconnections_server.go | 258 + .../armnetwork/fake/managercommits_server.go | 119 + .../fake/managerdeploymentstatus_server.go | 126 + .../armnetwork/fake/managers_server.go | 397 + .../armnetwork/fake/natgateways_server.go | 352 + .../armnetwork/fake/natrules_server.go | 272 + .../armnetwork/fake/operations_server.go | 96 + .../armnetwork/fake/p2svpngateways_server.go | 625 + .../armnetwork/fake/packetcaptures_server.go | 380 + ...erexpressroutecircuitconnections_server.go | 164 + .../armnetwork/fake/polymorphic_helpers.go | 226 + .../fake/privatednszonegroups_server.go | 272 + .../fake/privateendpoints_server.go | 309 + .../fake/privatelinkservices_server.go | 718 + .../armnetwork/fake/profiles_server.go | 339 + .../fake/publicipaddresses_server.go | 758 + .../fake/publicipprefixes_server.go | 352 + .../fake/resourcenavigationlinks_server.go | 104 + .../fake/routefilterrules_server.go | 272 + .../armnetwork/fake/routefilters_server.go | 352 + .../armnetwork/fake/routemaps_server.go | 272 + .../network/armnetwork/fake/routes_server.go | 272 + .../armnetwork/fake/routetables_server.go | 352 + .../armnetwork/fake/routingintent_server.go | 272 + .../fake/scopeconnections_server.go | 274 + .../securityadminconfigurations_server.go | 302 + .../armnetwork/fake/securitygroups_server.go | 352 + .../fake/securitypartnerproviders_server.go | 340 + .../armnetwork/fake/securityrules_server.go | 272 + .../fake/serviceassociationlinks_server.go | 104 + .../fake/serviceendpointpolicies_server.go | 352 + ...serviceendpointpolicydefinitions_server.go | 272 + .../fake/servicetaginformation_server.go | 130 + .../armnetwork/fake/servicetags_server.go | 96 + .../armnetwork/fake/staticmembers_server.go | 290 + .../network/armnetwork/fake/subnets_server.go | 404 + ...riptionnetworkmanagerconnections_server.go | 242 + .../network/armnetwork/fake/time_rfc3339.go | 86 + .../network/armnetwork/fake/usages_server.go | 108 + .../network/armnetwork/fake/vipswap_server.go | 197 + .../virtualapplianceconnections_server.go | 272 + .../fake/virtualappliances_server.go | 352 + .../fake/virtualappliancesites_server.go | 272 + .../fake/virtualapplianceskus_server.go | 140 + .../fake/virtualhubbgpconnection_server.go | 222 + .../fake/virtualhubbgpconnections_server.go | 225 + .../fake/virtualhubipconfiguration_server.go | 272 + .../fake/virtualhubroutetablev2s_server.go | 272 + .../armnetwork/fake/virtualhubs_server.go | 515 + ...virtualnetworkgatewayconnections_server.go | 686 + .../virtualnetworkgatewaynatrules_server.go | 272 + .../fake/virtualnetworkgateways_server.go | 1231 ++ .../fake/virtualnetworkpeerings_server.go | 284 + .../armnetwork/fake/virtualnetworks_server.go | 525 + .../fake/virtualnetworktaps_server.go | 340 + .../fake/virtualrouterpeerings_server.go | 272 + .../armnetwork/fake/virtualrouters_server.go | 309 + .../armnetwork/fake/virtualwans_server.go | 340 + .../armnetwork/fake/vpnconnections_server.go | 405 + .../armnetwork/fake/vpngateways_server.go | 542 + .../fake/vpnlinkconnections_server.go | 237 + .../fake/vpnserverconfigurations_server.go | 340 + ...urationsassociatedwithvirtualwan_server.go | 115 + .../fake/vpnsitelinkconnections_server.go | 108 + .../armnetwork/fake/vpnsitelinks_server.go | 156 + .../armnetwork/fake/vpnsites_server.go | 340 + .../fake/vpnsitesconfiguration_server.go | 119 + .../armnetwork/fake/watchers_server.go | 979 + .../webapplicationfirewallpolicies_server.go | 284 + .../armnetwork/fake/webcategories_server.go | 152 + .../network/armnetwork/fake_example_test.go | 79 + .../armnetwork/firewallpolicies_client.go | 109 +- .../firewallpolicies_client_example_test.go | 14 +- .../armnetwork/firewallpolicy_live_test.go | 4 +- .../firewallpolicyidpssignatures_client.go | 27 +- ...olicyidpssignatures_client_example_test.go | 4 +- ...policyidpssignaturesfiltervalues_client.go | 27 +- ...naturesfiltervalues_client_example_test.go | 4 +- ...allpolicyidpssignaturesoverrides_client.go | 89 +- ...signaturesoverrides_client_example_test.go | 10 +- ...rewallpolicyrulecollectiongroups_client.go | 79 +- ...ulecollectiongroups_client_example_test.go | 116 +- .../network/armnetwork/flowlogs_client.go | 103 +- .../flowlogs_client_example_test.go | 12 +- sdk/resourcemanager/network/armnetwork/go.mod | 6 +- sdk/resourcemanager/network/armnetwork/go.sum | 4 +- .../network/armnetwork/groups_client.go | 75 +- .../armnetwork/groups_client_example_test.go | 13 +- .../armnetwork/hubroutetables_client.go | 79 +- .../hubroutetables_client_example_test.go | 10 +- .../hubvirtualnetworkconnections_client.go | 79 +- ...lnetworkconnections_client_example_test.go | 10 +- .../armnetwork/inboundnatrules_client.go | 79 +- .../inboundnatrules_client_example_test.go | 10 +- .../armnetwork/inboundsecurityrule_client.go | 31 +- ...inboundsecurityrule_client_example_test.go | 4 +- .../interfaceipconfigurations_client.go | 28 +- ...aceipconfigurations_client_example_test.go | 6 +- .../interfaceloadbalancers_client.go | 9 +- ...erfaceloadbalancers_client_example_test.go | 4 +- .../network/armnetwork/interfaces.go | 54 + .../network/armnetwork/interfaces_client.go | 222 +- .../interfaces_client_example_test.go | 36 +- .../interfacetapconfigurations_client.go | 79 +- ...cetapconfigurations_client_example_test.go | 10 +- .../armnetwork/ipallocations_client.go | 109 +- .../ipallocations_client_example_test.go | 14 +- .../network/armnetwork/ipgroups_client.go | 109 +- .../ipgroups_client_example_test.go | 14 +- .../network/armnetwork/ipgroups_live_test.go | 4 +- .../armnetwork/loadbalancer_live_test.go | 4 +- .../loadbalancerbackendaddresspools_client.go | 79 +- ...backendaddresspools_client_example_test.go | 14 +- ...balancerfrontendipconfigurations_client.go | 28 +- ...endipconfigurations_client_example_test.go | 6 +- .../loadbalancerloadbalancingrules_client.go | 28 +- ...rloadbalancingrules_client_example_test.go | 6 +- .../loadbalancernetworkinterfaces_client.go | 9 +- ...ernetworkinterfaces_client_example_test.go | 6 +- .../loadbalanceroutboundrules_client.go | 28 +- ...lanceroutboundrules_client_example_test.go | 6 +- .../armnetwork/loadbalancerprobes_client.go | 28 +- .../loadbalancerprobes_client_example_test.go | 6 +- .../armnetwork/loadbalancers_client.go | 165 +- .../loadbalancers_client_example_test.go | 36 +- .../armnetwork/localnetworkgateways_client.go | 103 +- ...ocalnetworkgateways_client_example_test.go | 12 +- .../network/armnetwork/management_client.go | 289 +- .../management_client_example_test.go | 28 +- ...ntgroupnetworkmanagerconnections_client.go | 68 +- ...kmanagerconnections_client_example_test.go | 10 +- .../armnetwork/managercommits_client.go | 31 +- .../managercommits_client_example_test.go | 4 +- .../managerdeploymentstatus_client.go | 27 +- ...gerdeploymentstatus_client_example_test.go | 4 +- .../network/armnetwork/managers_client.go | 105 +- .../managers_client_example_test.go | 19 +- .../network/armnetwork/models.go | 4221 +--- .../network/armnetwork/models_serde.go | 701 +- .../armnetwork/natgateway_live_test.go | 4 +- .../network/armnetwork/natgateways_client.go | 109 +- .../natgateways_client_example_test.go | 14 +- .../network/armnetwork/natrules_client.go | 79 +- .../natrules_client_example_test.go | 10 +- .../armnetwork/networkinterface_live_test.go | 4 +- .../armnetwork/networkmanager_live_test.go | 4 +- .../networkmanagerconnection_live_test.go | 4 +- ...agerconnectivityconfiguration_live_test.go | 4 +- .../networkmanagergroup_live_test.go | 4 +- ...gersecurityadminconfiguration_live_test.go | 4 +- .../armnetwork/networkprofile_live_test.go | 4 +- .../networksecuritygroup_live_test.go | 4 +- .../armnetwork/networkwatcher_live_test.go | 4 +- .../network/armnetwork/operation_live_test.go | 4 +- .../network/armnetwork/operations_client.go | 9 +- .../operations_client_example_test.go | 4 +- .../network/armnetwork/options.go | 3920 ++++ .../armnetwork/p2svpngateways_client.go | 243 +- .../p2svpngateways_client_example_test.go | 24 +- .../armnetwork/packetcaptures_client.go | 125 +- .../packetcaptures_client_example_test.go | 14 +- ...erexpressroutecircuitconnections_client.go | 28 +- ...ecircuitconnections_client_example_test.go | 6 +- .../network/armnetwork/polymorphic_helpers.go | 28 +- .../armnetwork/privatednszonegroups_client.go | 79 +- ...rivatednszonegroups_client_example_test.go | 10 +- .../armnetwork/privateendpoints_client.go | 85 +- .../privateendpoints_client_example_test.go | 20 +- .../armnetwork/privatelinkservices_client.go | 225 +- ...privatelinkservices_client_example_test.go | 28 +- .../network/armnetwork/profiles_client.go | 105 +- .../profiles_client_example_test.go | 16 +- .../armnetwork/publicipaddress_live_test.go | 4 +- .../armnetwork/publicipaddresses_client.go | 182 +- .../publicipaddresses_client_example_test.go | 132 +- .../armnetwork/publicipprefix_live_test.go | 4 +- .../armnetwork/publicipprefixes_client.go | 109 +- .../publicipprefixes_client_example_test.go | 16 +- .../resourcenavigationlinks_client.go | 22 +- ...urcenavigationlinks_client_example_test.go | 4 +- .../network/armnetwork/response_types.go | 575 +- .../armnetwork/routefilterrules_client.go | 79 +- .../routefilterrules_client_example_test.go | 10 +- .../network/armnetwork/routefilters_client.go | 109 +- .../routefilters_client_example_test.go | 14 +- .../network/armnetwork/routemaps_client.go | 79 +- .../routemaps_client_example_test.go | 10 +- .../network/armnetwork/routes_client.go | 79 +- .../armnetwork/routes_client_example_test.go | 10 +- .../armnetwork/routetable_live_test.go | 4 +- .../network/armnetwork/routetables_client.go | 109 +- .../routetables_client_example_test.go | 16 +- .../armnetwork/routingintent_client.go | 79 +- .../routingintent_client_example_test.go | 10 +- .../armnetwork/scopeconnections_client.go | 68 +- .../scopeconnections_client_example_test.go | 10 +- .../securityadminconfigurations_client.go | 75 +- ...adminconfigurations_client_example_test.go | 13 +- .../armnetwork/securitygroups_client.go | 109 +- .../securitygroups_client_example_test.go | 16 +- .../securitypartnerproviders_client.go | 109 +- ...itypartnerproviders_client_example_test.go | 14 +- .../armnetwork/securityrules_client.go | 79 +- .../securityrules_client_example_test.go | 10 +- .../serviceassociationlinks_client.go | 22 +- ...iceassociationlinks_client_example_test.go | 4 +- .../armnetwork/servicecommunity_live_test.go | 4 +- .../serviceendpointpolicies_client.go | 109 +- ...iceendpointpolicies_client_example_test.go | 16 +- .../serviceendpointpolicy_live_test.go | 4 +- ...serviceendpointpolicydefinitions_client.go | 79 +- ...ntpolicydefinitions_client_example_test.go | 10 +- .../servicetaginformation_client.go | 9 +- ...rvicetaginformation_client_example_test.go | 8 +- .../network/armnetwork/servicetags_client.go | 22 +- .../servicetags_client_example_test.go | 4 +- .../armnetwork/servicetags_live_test.go | 4 +- .../armnetwork/staticmembers_client.go | 68 +- .../staticmembers_client_example_test.go | 10 +- .../network/armnetwork/subnets_client.go | 135 +- .../armnetwork/subnets_client_example_test.go | 20 +- ...riptionnetworkmanagerconnections_client.go | 68 +- ...kmanagerconnections_client_example_test.go | 10 +- .../network/armnetwork/time_rfc3339.go | 3 +- .../network/armnetwork/usage_live_test.go | 4 +- .../network/armnetwork/usages_client.go | 9 +- .../armnetwork/usages_client_example_test.go | 6 +- .../network/armnetwork/vipswap_client.go | 69 +- .../armnetwork/vipswap_client_example_test.go | 8 +- .../virtualapplianceconnections_client.go | 350 + ...pplianceconnections_client_example_test.go | 237 + .../armnetwork/virtualappliances_client.go | 109 +- .../virtualappliances_client_example_test.go | 56 +- .../virtualappliancesites_client.go | 79 +- ...rtualappliancesites_client_example_test.go | 10 +- .../armnetwork/virtualapplianceskus_client.go | 28 +- ...irtualapplianceskus_client_example_test.go | 6 +- .../virtualhubbgpconnection_client.go | 73 +- ...ualhubbgpconnection_client_example_test.go | 8 +- .../virtualhubbgpconnections_client.go | 55 +- ...alhubbgpconnections_client_example_test.go | 63 +- .../virtualhubipconfiguration_client.go | 79 +- ...lhubipconfiguration_client_example_test.go | 10 +- .../virtualhubroutetablev2s_client.go | 79 +- ...ualhubroutetablev2s_client_example_test.go | 10 +- .../network/armnetwork/virtualhubs_client.go | 193 +- .../virtualhubs_client_example_test.go | 59 +- .../armnetwork/virtualnetwork_live_test.go | 4 +- .../virtualnetworkgateway_live_test.go | 4 +- ...virtualnetworkgatewayconnections_client.go | 284 +- ...kgatewayconnections_client_example_test.go | 30 +- .../virtualnetworkgatewaynatrules_client.go | 79 +- ...workgatewaynatrules_client_example_test.go | 10 +- .../virtualnetworkgateways_client.go | 508 +- ...tualnetworkgateways_client_example_test.go | 48 +- .../virtualnetworkpeerings_client.go | 79 +- ...tualnetworkpeerings_client_example_test.go | 18 +- .../armnetwork/virtualnetworks_client.go | 159 +- .../virtualnetworks_client_example_test.go | 38 +- .../armnetwork/virtualnetworktaps_client.go | 109 +- .../virtualnetworktaps_client_example_test.go | 14 +- .../virtualrouterpeerings_client.go | 79 +- ...rtualrouterpeerings_client_example_test.go | 10 +- .../armnetwork/virtualrouters_client.go | 85 +- .../virtualrouters_client_example_test.go | 12 +- .../armnetwork/virtualwan_live_test.go | 4 +- .../network/armnetwork/virtualwans_client.go | 109 +- .../virtualwans_client_example_test.go | 14 +- .../armnetwork/vpnconnections_client.go | 135 +- .../vpnconnections_client_example_test.go | 16 +- .../network/armnetwork/vpngateways_client.go | 192 +- .../vpngateways_client_example_test.go | 22 +- .../armnetwork/vpnlinkconnections_client.go | 55 +- .../vpnlinkconnections_client_example_test.go | 8 +- .../vpnserverconfigurations_client.go | 109 +- ...erverconfigurations_client_example_test.go | 14 +- ...urationsassociatedwithvirtualwan_client.go | 26 +- ...iatedwithvirtualwan_client_example_test.go | 4 +- .../vpnsitelinkconnections_client.go | 22 +- ...sitelinkconnections_client_example_test.go | 4 +- .../network/armnetwork/vpnsitelinks_client.go | 28 +- .../vpnsitelinks_client_example_test.go | 6 +- .../network/armnetwork/vpnsites_client.go | 109 +- .../vpnsites_client_example_test.go | 14 +- .../vpnsitesconfiguration_client.go | 31 +- ...nsitesconfiguration_client_example_test.go | 4 +- .../network/armnetwork/watchers_client.go | 437 +- .../watchers_client_example_test.go | 38 +- .../webapplicationfirewall_live_test.go | 4 +- .../webapplicationfirewallpolicies_client.go | 81 +- ...ionfirewallpolicies_client_example_test.go | 663 +- .../armnetwork/webcategories_client.go | 28 +- .../webcategories_client_example_test.go | 6 +- .../networkcloud/armnetworkcloud/CHANGELOG.md | 134 + .../networkcloud/armnetworkcloud/LICENSE.txt | 21 + .../networkcloud/armnetworkcloud/README.md | 85 + .../armnetworkcloud/agentpools_client.go | 380 + .../agentpools_client_example_test.go | 516 + .../networkcloud/armnetworkcloud/autorest.md | 13 + .../baremetalmachinekeysets_client.go | 383 + ...metalmachinekeysets_client_example_test.go | 442 + .../baremetalmachines_client.go | 1147 ++ .../baremetalmachines_client_example_test.go | 802 + .../armnetworkcloud/bmckeysets_client.go | 381 + .../bmckeysets_client_example_test.go | 419 + .../networkcloud/armnetworkcloud/build.go | 7 + .../networkcloud/armnetworkcloud/ci.yml | 28 + .../armnetworkcloud/client_factory.go | 134 + .../cloudservicesnetworks_client.go | 415 + ...oudservicesnetworks_client_example_test.go | 453 + .../armnetworkcloud/clustermanagers_client.go | 403 + .../clustermanagers_client_example_test.go | 389 + .../armnetworkcloud/clusters_client.go | 543 + .../clusters_client_example_test.go | 1375 ++ .../armnetworkcloud/consoles_client.go | 380 + .../consoles_client_example_test.go | 303 + .../networkcloud/armnetworkcloud/constants.go | 1737 ++ .../networkcloud/armnetworkcloud/go.mod | 21 + .../networkcloud/armnetworkcloud/go.sum | 31 + .../kubernetesclusters_client.go | 479 + .../kubernetesclusters_client_example_test.go | 1494 ++ .../armnetworkcloud/l2networks_client.go | 401 + .../l2networks_client_example_test.go | 340 + .../armnetworkcloud/l3networks_client.go | 401 + .../l3networks_client_example_test.go | 363 + .../metricsconfigurations_client.go | 383 + ...tricsconfigurations_client_example_test.go | 299 + .../networkcloud/armnetworkcloud/models.go | 3526 ++++ .../armnetworkcloud/models_serde.go | 6466 ++++++ .../armnetworkcloud/operations_client.go | 95 + .../operations_client_example_test.go | 70 + .../armnetworkcloud/racks_client.go | 416 + .../racks_client_example_test.go | 349 + .../armnetworkcloud/rackskus_client.go | 151 + .../rackskus_client_example_test.go | 244 + .../armnetworkcloud/response_types.go | 625 + .../storageappliances_client.go | 614 + .../storageappliances_client_example_test.go | 465 + .../armnetworkcloud/time_rfc3339.go | 87 + .../armnetworkcloud/trunkednetworks_client.go | 402 + .../trunkednetworks_client_example_test.go | 369 + .../armnetworkcloud/virtualmachines_client.go | 803 + .../virtualmachines_client_example_test.go | 762 + .../armnetworkcloud/volumes_client.go | 401 + .../volumes_client_example_test.go | 333 + .../armnewrelicobservability/CHANGELOG.md | 7 + .../accounts_client.go | 4 +- .../accounts_client_example_test.go | 4 +- .../armnewrelicobservability/autorest.md | 8 +- .../armnewrelicobservability/constants.go | 2 +- .../armnewrelicobservability/models.go | 314 +- .../monitors_client.go | 78 +- .../monitors_client_example_test.go | 205 +- .../operations_client.go | 4 +- .../operations_client_example_test.go | 4 +- .../organizations_client.go | 4 +- .../organizations_client_example_test.go | 4 +- .../armnewrelicobservability/plans_client.go | 4 +- .../plans_client_example_test.go | 4 +- .../response_types.go | 4 +- .../tagrules_client.go | 24 +- .../tagrules_client_example_test.go | 20 +- .../armnotificationhubs/assets.json | 6 + .../armnotificationhubs/go.mod | 10 +- .../armnotificationhubs/go.sum | 17 + .../notificationhubs_live_test.go | 321 + .../armpanngfw/CHANGELOG.md | 5 + .../armpanngfw/autorest.md | 8 +- ...certificateobjectglobalrulestack_client.go | 20 +- ...jectglobalrulestack_client_example_test.go | 16 +- .../certificateobjectlocalrulestack_client.go | 20 +- ...bjectlocalrulestack_client_example_test.go | 24 +- .../armpanngfw/constants.go | 2 +- .../armpanngfw/firewalls_client.go | 44 +- .../firewalls_client_example_test.go | 52 +- .../armpanngfw/firewallstatus_client.go | 8 +- .../firewallstatus_client_example_test.go | 8 +- .../fqdnlistglobalrulestack_client.go | 20 +- ...listglobalrulestack_client_example_test.go | 16 +- .../fqdnlistlocalrulestack_client.go | 20 +- ...nlistlocalrulestack_client_example_test.go | 16 +- .../armpanngfw/globalrulestack_client.go | 62 +- .../globalrulestack_client_example_test.go | 56 +- .../paloaltonetworksngfw/armpanngfw/go.mod | 16 +- .../paloaltonetworksngfw/armpanngfw/go.sum | 36 +- .../armpanngfw/localrules_client.go | 32 +- .../localrules_client_example_test.go | 28 +- .../armpanngfw/localrulestacks_client.go | 70 +- .../localrulestacks_client_example_test.go | 64 +- .../armpanngfw/operations_client.go | 4 +- .../operations_client_example_test.go | 4 +- .../armpanngfw/postrules_client.go | 32 +- .../postrules_client_example_test.go | 28 +- .../prefixlistglobalrulestack_client.go | 20 +- ...listglobalrulestack_client_example_test.go | 16 +- .../prefixlistlocalrulestack_client.go | 20 +- ...xlistlocalrulestack_client_example_test.go | 16 +- .../armpanngfw/prerules_client.go | 32 +- .../prerules_client_example_test.go | 28 +- .../armpostgresqlflexibleservers/CHANGELOG.md | 112 + .../administrators_client.go | 20 +- .../administrators_client_example_test.go | 10 +- .../armpostgresqlflexibleservers/autorest.md | 8 +- .../backups_client.go | 8 +- .../backups_client_example_test.go | 6 +- .../checknameavailability_client.go | 4 +- ...ecknameavailability_client_example_test.go | 4 +- ...hecknameavailabilitywithlocation_client.go | 4 +- ...abilitywithlocation_client_example_test.go | 4 +- .../client_factory.go | 30 + .../configurations_client.go | 20 +- .../configurations_client_example_test.go | 8 +- .../armpostgresqlflexibleservers/constants.go | 446 +- .../databases_client.go | 20 +- .../databases_client_example_test.go | 10 +- .../firewallrules_client.go | 20 +- .../firewallrules_client_example_test.go | 10 +- .../flexibleserver_client.go | 176 + .../flexibleserver_client_example_test.go | 91 + .../getprivatednszonesuffix_client.go | 4 +- ...rivatednszonesuffix_client_example_test.go | 4 +- .../armpostgresqlflexibleservers/go.mod | 18 +- .../armpostgresqlflexibleservers/go.sum | 36 +- .../locationbasedcapabilities_client.go | 4 +- ...onbasedcapabilities_client_example_test.go | 9581 ++------- .../logfiles_client.go | 115 + .../logfiles_client_example_test.go | 58 + .../ltrbackupoperations_client.go | 177 + ...ltrbackupoperations_client_example_test.go | 96 + .../migrations_client.go | 362 + .../migrations_client_example_test.go | 448 + .../armpostgresqlflexibleservers/models.go | 766 +- .../models_serde.go | 1491 +- .../operations_client.go | 4 +- .../operations_client_example_test.go | 4 +- .../postgresqlmanagement_client.go | 102 + ...ostgresqlmanagement_client_example_test.go | 47 + .../replicas_client.go | 4 +- .../replicas_client_example_test.go | 7 +- .../response_types.go | 62 + .../servercapabilities_client.go | 115 + .../servercapabilities_client_example_test.go | 1649 ++ .../servers_client.go | 48 +- .../servers_client_example_test.go | 284 +- .../virtualnetworksubnetusage_client.go | 4 +- ...lnetworksubnetusage_client_example_test.go | 4 +- .../armpostgresqlhsc/CHANGELOG.md | 5 + .../armpostgresqlhsc/autorest.md | 2 +- .../armpostgresqlhsc/constants.go | 2 +- .../postgresqlhsc/armpostgresqlhsc/go.mod | 1 + .../armrecoveryservices/CHANGELOG.md | 9 + .../armrecoveryservices/assets.json | 6 + .../armrecoveryservices/autorest.md | 7 +- .../armrecoveryservices/client.go | 8 +- .../client_example_test.go | 6 +- .../armrecoveryservices/constants.go | 19 +- .../armrecoveryservices/go.mod | 10 +- .../armrecoveryservices/go.sum | 17 + .../armrecoveryservices/models.go | 14 + .../armrecoveryservices/models_serde.go | 58 + .../armrecoveryservices/operations_client.go | 12 +- .../operations_client_example_test.go | 6 +- .../privatelinkresources_client.go | 8 +- ...rivatelinkresources_client_example_test.go | 4 +- .../recoveryservices_live_test.go | 206 + .../registeredidentities_client.go | 4 +- ...egisteredidentities_client_example_test.go | 2 +- .../replicationusages_client.go | 4 +- .../replicationusages_client_example_test.go | 2 +- .../armrecoveryservices/usages_client.go | 4 +- .../usages_client_example_test.go | 2 +- .../vaultcertificates_client.go | 4 +- .../vaultcertificates_client_example_test.go | 2 +- .../vaultextendedinfo_client.go | 12 +- .../vaultextendedinfo_client_example_test.go | 4 +- .../armrecoveryservices/vaults_client.go | 28 +- .../vaults_client_example_test.go | 28 +- .../redis/armredis/CHANGELOG.md | 8 + .../redis/armredis/assets.json | 2 +- .../armredis/asyncoperationstatus_client.go | 4 +- ...syncoperationstatus_client_example_test.go | 2 +- .../redis/armredis/autorest.md | 7 +- sdk/resourcemanager/redis/armredis/client.go | 62 +- .../redis/armredis/client_example_test.go | 38 +- .../redis/armredis/constants.go | 2 +- .../redis/armredis/firewallrules_client.go | 16 +- .../firewallrules_client_example_test.go | 8 +- .../redis/armredis/linkedserver_client.go | 20 +- .../linkedserver_client_example_test.go | 8 +- sdk/resourcemanager/redis/armredis/models.go | 9 + .../redis/armredis/models_serde.go | 12 + .../redis/armredis/operations_client.go | 4 +- .../operations_client_example_test.go | 2 +- .../redis/armredis/patchschedules_client.go | 16 +- .../patchschedules_client_example_test.go | 8 +- .../privateendpointconnections_client.go | 18 +- ...endpointconnections_client_example_test.go | 8 +- .../armredis/privatelinkresources_client.go | 4 +- ...rivatelinkresources_client_example_test.go | 2 +- .../relay/armrelay/assets.json | 6 + sdk/resourcemanager/relay/armrelay/go.mod | 10 +- sdk/resourcemanager/relay/armrelay/go.sum | 18 + .../armrelay/hybridconnections_live_test.go | 174 + .../relay/armrelay/namespaces_live_test.go | 413 + .../relay/armrelay/operations_live_test.go | 68 + .../relay/armrelay/wcfrelays_live_test.go | 176 + .../armresourcegraph/CHANGELOG.md | 12 + .../resourcegraph/armresourcegraph/README.md | 27 +- .../armresourcegraph/autorest.md | 9 +- .../resourcegraph/armresourcegraph/build.go | 2 +- .../resourcegraph/armresourcegraph/client.go | 43 +- .../armresourcegraph/client_factory.go | 3 +- .../armresourcegraph/constants.go | 33 +- .../armresourcegraph/fake/internal.go | 123 + .../fake/operations_server.go | 92 + .../fake/polymorphic_helpers.go | 56 + .../armresourcegraph/fake/server.go | 117 + .../armresourcegraph/fake/time_rfc3339.go | 86 + .../armresourcegraph/fake_example_test.go | 79 + .../resourcegraph/armresourcegraph/go.mod | 10 +- .../resourcegraph/armresourcegraph/go.sum | 20 +- .../armresourcegraph/interfaces.go | 18 + .../resourcegraph/armresourcegraph/models.go | 27 +- .../armresourcegraph/models_serde.go | 3 +- .../armresourcegraph/operations_client.go | 5 +- .../resourcegraph/armresourcegraph/options.go | 24 + .../armresourcegraph/polymorphic_helpers.go | 8 +- .../armresourcegraph/response_types.go | 6 +- .../armresourcegraph/time_rfc3339.go | 3 +- .../armresourcehealth/CHANGELOG.md | 81 + .../armresourcehealth/autorest.md | 7 +- .../availabilitystatuses_client.go | 21 +- ...vailabilitystatuses_client_example_test.go | 20 +- .../resourcehealth/armresourcehealth/build.go | 2 +- .../childavailabilitystatuses_client.go | 161 + ...vailabilitystatuses_client_example_test.go | 227 + .../childresources_client.go | 106 + .../childresources_client_example_test.go | 123 + .../armresourcehealth/client_factory.go | 43 +- .../armresourcehealth/constants.go | 197 +- .../emergingissues_client.go | 145 + .../emergingissues_client_example_test.go | 202 + .../armresourcehealth/event_client.go | 263 + .../event_client_example_test.go | 443 + .../armresourcehealth/events_client.go | 238 + .../events_client_example_test.go | 360 + .../resourcehealth/armresourcehealth/go.mod | 16 +- .../resourcehealth/armresourcehealth/go.sum | 36 +- .../impactedresources_client.go | 288 + .../impactedresources_client_example_test.go | 199 + .../armresourcehealth/metadata_client.go | 145 + .../metadata_client_example_test.go | 1987 ++ .../armresourcehealth/models.go | 729 +- .../armresourcehealth/models_serde.go | 1208 +- .../armresourcehealth/operations_client.go | 4 +- .../operations_client_example_test.go | 2 +- .../armresourcehealth/response_types.go | 100 + ...ecurityadvisoryimpactedresources_client.go | 177 + ...ryimpactedresources_client_example_test.go | 170 + .../resources/armresources/CHANGELOG.md | 12 + .../resources/armresources/README.md | 25 + .../resources/armresources/autorest.md | 8 +- .../resources/armresources/build.go | 2 +- .../resources/armresources/client.go | 231 +- .../resources/armresources/client_factory.go | 25 +- .../resources/armresources/constants.go | 97 +- .../deploymentoperations_client.go | 88 +- .../armresources/deployments_client.go | 706 +- .../fake/deploymentoperations_server.go | 614 + .../armresources/fake/deployments_server.go | 2200 ++ .../resources/armresources/fake/internal.go | 123 + .../armresources/fake/operations_server.go | 96 + .../fake/providerresourcetypes_server.go | 108 + .../armresources/fake/providers_server.go | 413 + .../fake/resourcegroups_server.go | 393 + .../resources/armresources/fake/server.go | 895 + .../armresources/fake/tags_server.go | 401 + .../armresources/fake/time_rfc3339.go | 86 + .../armresources/fake_example_test.go | 74 + .../resources/armresources/go.mod | 10 +- .../resources/armresources/go.sum | 20 +- .../resources/armresources/models.go | 637 +- .../resources/armresources/models_serde.go | 3 +- .../armresources/operations_client.go | 5 +- .../resources/armresources/options.go | 654 + .../providerresourcetypes_client.go | 18 +- .../armresources/providers_client.go | 99 +- .../armresources/resourcegroups_client.go | 113 +- .../resources/armresources/response_types.go | 72 +- .../resources/armresources/tags_client.go | 126 +- .../resources/armresources/time_rfc3339.go | 3 +- .../resources/armsubscriptions/CHANGELOG.md | 31 +- .../resources/armsubscriptions/README.md | 27 +- .../resources/armsubscriptions/assets.json | 2 +- .../resources/armsubscriptions/autorest.md | 13 +- .../resources/armsubscriptions/build.go | 2 +- .../resources/armsubscriptions/client.go | 58 +- .../armsubscriptions/client_example_test.go | 186 +- .../armsubscriptions/client_factory.go | 12 +- .../resources/armsubscriptions/constants.go | 66 +- .../armsubscriptions/fake/internal.go | 123 + .../fake/operations_server.go | 96 + .../resources/armsubscriptions/fake/server.go | 231 + .../fake/subscription_server.go | 95 + .../armsubscriptions/fake/tenants_server.go | 96 + .../armsubscriptions/fake_example_test.go | 79 + .../resources/armsubscriptions/go.mod | 10 +- .../resources/armsubscriptions/go.sum | 20 +- .../resources/armsubscriptions/models.go | 135 +- .../armsubscriptions/models_serde.go | 167 +- .../armsubscriptions/operations_client.go | 95 + .../resources/armsubscriptions/options.go | 47 + .../armsubscriptions/response_types.go | 15 +- .../armsubscriptions/subscription_client.go | 27 +- .../subscription_client_example_test.go | 2 +- .../armsubscriptions/tenants_client.go | 9 +- .../tenants_client_example_test.go | 2 +- .../search/armsearch/assets.json | 6 + sdk/resourcemanager/search/armsearch/go.mod | 10 +- sdk/resourcemanager/search/armsearch/go.sum | 18 + .../search/armsearch/search_live_test.go | 519 + .../selfhelp/armselfhelp/CHANGELOG.md | 12 + .../selfhelp/armselfhelp/LICENSE.txt | 21 + .../selfhelp/armselfhelp/README.md | 85 + .../selfhelp/armselfhelp/assets.json | 6 + .../selfhelp/armselfhelp/autorest.md | 13 + .../selfhelp/armselfhelp/build.go | 7 + .../selfhelp/armselfhelp}/ci.yml | 10 +- .../selfhelp/armselfhelp/client_factory.go | 52 + .../selfhelp/armselfhelp/constants.go | 140 + .../armselfhelp/diagnostics_client.go | 209 + .../diagnostics_client_example_test.go | 169 + .../armselfhelp/discoverysolution_client.go | 112 + .../discoverysolution_client_example_test.go | 87 + .../selfhelp/armselfhelp/go.mod | 29 + .../selfhelp/armselfhelp}/go.sum | 46 +- .../selfhelp/armselfhelp/help_live_test.go | 176 + .../selfhelp/armselfhelp/models.go | 270 + .../selfhelp/armselfhelp/models_serde.go | 610 + .../selfhelp/armselfhelp/operations_client.go | 94 + .../operations_client_example_test.go | 66 + .../selfhelp/armselfhelp/response_types.go | 35 + .../selfhelp/armselfhelp/time_rfc3339.go | 87 + .../armservicefabric/assets.json | 6 + .../servicefabric/armservicefabric/go.mod | 8 + .../servicefabric/armservicefabric/go.sum | 17 + .../servicefabric_live_test.go | 235 + .../armservicenetworking/CHANGELOG.md | 20 + .../associationsinterface_client.go | 36 +- ...sociationsinterface_client_example_test.go | 70 +- .../armservicenetworking/autorest.md | 8 +- .../armservicenetworking/constants.go | 30 +- .../frontendsinterface_client.go | 36 +- .../frontendsinterface_client_example_test.go | 86 +- .../armservicenetworking/models.go | 57 +- .../armservicenetworking/models_serde.go | 125 +- .../armservicenetworking/operations_client.go | 4 +- .../operations_client_example_test.go | 4 +- .../trafficcontrollerinterface_client.go | 28 +- ...controllerinterface_client_example_test.go | 98 +- .../sphere/armsphere/CHANGELOG.md | 7 + .../sphere/armsphere/LICENSE.txt | 21 + .../sphere/armsphere/README.md | 85 + .../sphere/armsphere/autorest.md | 13 + sdk/resourcemanager/sphere/armsphere/build.go | 7 + .../sphere/armsphere/catalogs_client.go | 806 + .../armsphere/catalogs_client_example_test.go | 407 + .../sphere/armsphere/certificates_client.go | 317 + .../certificates_client_example_test.go | 122 + .../sphere/armsphere}/ci.yml | 9 +- .../sphere/armsphere/client_factory.go | 79 + .../sphere/armsphere/constants.go | 299 + .../sphere/armsphere/deployments_client.go | 383 + .../deployments_client_example_test.go | 173 + .../sphere/armsphere/devicegroups_client.go | 590 + .../devicegroups_client_example_test.go | 230 + .../sphere/armsphere/devices_client.go | 536 + .../armsphere/devices_client_example_test.go | 205 + sdk/resourcemanager/sphere/armsphere/go.mod | 21 + sdk/resourcemanager/sphere/armsphere/go.sum | 31 + .../sphere/armsphere/images_client.go | 334 + .../armsphere/images_client_example_test.go | 135 + .../sphere/armsphere/models.go | 873 + .../sphere/armsphere/models_serde.go | 1563 ++ .../sphere/armsphere/operations_client.go | 94 + .../operations_client_example_test.go | 64 + .../sphere/armsphere/products_client.go | 534 + .../armsphere/products_client_example_test.go | 235 + .../sphere/armsphere/response_types.go | 230 + .../sphere/armsphere/time_rfc3339.go | 87 + sdk/resourcemanager/sql/armsql/CHANGELOG.md | 249 + .../sql/armsql/agent_client.go | 30 +- .../sql/armsql/agent_client_example_test.go | 6 +- sdk/resourcemanager/sql/armsql/autorest.md | 7 +- ...backupshorttermretentionpolicies_client.go | 50 +- ...rmretentionpolicies_client_example_test.go | 8 +- .../sql/armsql/capabilities_client.go | 14 +- .../capabilities_client_example_test.go | 4 +- .../sql/armsql/client_factory.go | 452 +- sdk/resourcemanager/sql/armsql/constants.go | 510 +- ...advancedthreatprotectionsettings_client.go | 30 +- ...tprotectionsettings_client_example_test.go | 10 +- .../sql/armsql/databaseadvisors_client.go | 41 +- .../databaseadvisors_client_example_test.go | 10 +- .../armsql/databaseautomatictuning_client.go | 30 +- ...baseautomatictuning_client_example_test.go | 8 +- .../databaseblobauditingpolicies_client.go | 30 +- ...lobauditingpolicies_client_example_test.go | 12 +- .../sql/armsql/databasecolumns_client.go | 14 +- .../databasecolumns_client_example_test.go | 10 +- .../databaseencryptionprotectors_client.go | 204 + ...ncryptionprotectors_client_example_test.go | 60 + .../sql/armsql/databaseextensions_client.go | 29 +- .../databaseextensions_client_example_test.go | 8 +- .../sql/armsql/databaseoperations_client.go | 11 +- .../databaseoperations_client_example_test.go | 6 +- .../databaserecommendedactions_client.go | 41 +- ...erecommendedactions_client_example_test.go | 8 +- .../sql/armsql/databases_client.go | 250 +- .../armsql/databases_client_example_test.go | 1650 +- .../sql/armsql/databaseschemas_client.go | 14 +- .../databaseschemas_client_example_test.go | 6 +- .../databasesecurityalertpolicies_client.go | 30 +- ...curityalertpolicies_client_example_test.go | 10 +- ...vulnerabilityassessmentbaselines_client.go | 281 + ...assessmentbaselines_client_example_test.go | 324 + ...lnerabilityassessmentexecutescan_client.go | 122 + ...sessmentexecutescan_client_example_test.go | 39 + ...erabilityassessmentrulebaselines_client.go | 365 + ...ssmentrulebaselines_client_example_test.go | 186 + ...ulnerabilityassessmentscanresult_client.go | 212 + ...ssessmentscanresult_client_example_test.go | 213 + ...esqlvulnerabilityassessmentscans_client.go | 202 + ...lityassessmentscans_client_example_test.go | 158 + ...vulnerabilityassessmentssettings_client.go | 192 + ...assessmentssettings_client_example_test.go | 82 + .../sql/armsql/databasetables_client.go | 14 +- .../databasetables_client_example_test.go | 6 +- .../sql/armsql/databaseusages_client.go | 3 +- .../databaseusages_client_example_test.go | 4 +- ...erabilityassessmentrulebaselines_client.go | 38 +- ...ssmentrulebaselines_client_example_test.go | 8 +- ...databasevulnerabilityassessments_client.go | 38 +- ...rabilityassessments_client_example_test.go | 14 +- ...basevulnerabilityassessmentscans_client.go | 38 +- ...lityassessmentscans_client_example_test.go | 10 +- .../sql/armsql/datamaskingpolicies_client.go | 30 +- ...datamaskingpolicies_client_example_test.go | 8 +- .../sql/armsql/datamaskingrules_client.go | 19 +- .../datamaskingrules_client_example_test.go | 12 +- .../datawarehouseuseractivities_client.go | 14 +- ...houseuseractivities_client_example_test.go | 6 +- .../sql/armsql/deletedservers_client.go | 27 +- .../deletedservers_client_example_test.go | 10 +- .../distributedavailabilitygroups_client.go | 63 +- ...davailabilitygroups_client_example_test.go | 12 +- .../armsql/elasticpoolactivities_client.go | 3 +- ...asticpoolactivities_client_example_test.go | 4 +- .../elasticpooldatabaseactivities_client.go | 3 +- ...ldatabaseactivities_client_example_test.go | 4 +- .../armsql/elasticpooloperations_client.go | 11 +- ...asticpooloperations_client_example_test.go | 6 +- .../sql/armsql/elasticpools_client.go | 114 +- .../elasticpools_client_example_test.go | 414 +- .../sql/armsql/encryptionprotectors_client.go | 45 +- ...ncryptionprotectors_client_example_test.go | 12 +- .../sql/armsql/endpointcertificates_client.go | 14 +- ...ndpointcertificates_client_example_test.go | 6 +- ...ndeddatabaseblobauditingpolicies_client.go | 30 +- ...lobauditingpolicies_client_example_test.go | 12 +- ...tendedserverblobauditingpolicies_client.go | 32 +- ...lobauditingpolicies_client_example_test.go | 10 +- .../sql/armsql/failovergroups_client.go | 205 +- .../failovergroups_client_example_test.go | 214 +- .../sql/armsql/firewallrules_client.go | 54 +- .../firewallrules_client_example_test.go | 14 +- .../sql/armsql/geobackuppolicies_client.go | 30 +- .../geobackuppolicies_client_example_test.go | 8 +- sdk/resourcemanager/sql/armsql/go.mod | 20 +- sdk/resourcemanager/sql/armsql/go.sum | 36 +- .../armsql/instancefailovergroups_client.go | 103 +- ...tancefailovergroups_client_example_test.go | 187 +- .../sql/armsql/instancepools_client.go | 63 +- .../instancepools_client_example_test.go | 16 +- .../sql/armsql/ipv6firewallrules_client.go | 54 +- .../ipv6firewallrules_client_example_test.go | 12 +- .../sql/armsql/jobagents_client.go | 63 +- .../armsql/jobagents_client_example_test.go | 12 +- .../sql/armsql/jobcredentials_client.go | 38 +- .../jobcredentials_client_example_test.go | 10 +- .../sql/armsql/jobexecutions_client.go | 48 +- .../jobexecutions_client_example_test.go | 16 +- sdk/resourcemanager/sql/armsql/jobs_client.go | 38 +- .../sql/armsql/jobs_client_example_test.go | 12 +- .../sql/armsql/jobstepexecutions_client.go | 14 +- .../jobstepexecutions_client_example_test.go | 6 +- .../sql/armsql/jobsteps_client.go | 49 +- .../armsql/jobsteps_client_example_test.go | 16 +- .../sql/armsql/jobtargetexecutions_client.go | 14 +- ...jobtargetexecutions_client_example_test.go | 8 +- .../sql/armsql/jobtargetgroups_client.go | 38 +- .../jobtargetgroups_client_example_test.go | 12 +- .../sql/armsql/jobversions_client.go | 14 +- .../armsql/jobversions_client_example_test.go | 6 +- .../sql/armsql/ledgerdigestuploads_client.go | 45 +- ...ledgerdigestuploads_client_example_test.go | 10 +- .../armsql/longtermretentionbackups_client.go | 123 +- ...ermretentionbackups_client_example_test.go | 30 +- ...mretentionmanagedinstancebackups_client.go | 51 +- ...agedinstancebackups_client_example_test.go | 22 +- .../longtermretentionpolicies_client.go | 32 +- ...rmretentionpolicies_client_example_test.go | 8 +- .../armsql/maintenancewindowoptions_client.go | 14 +- ...enancewindowoptions_client_example_test.go | 4 +- .../sql/armsql/maintenancewindows_client.go | 27 +- .../maintenancewindows_client_example_test.go | 6 +- ...backupshorttermretentionpolicies_client.go | 50 +- ...rmretentionpolicies_client_example_test.go | 8 +- ...advancedthreatprotectionsettings_client.go | 268 + ...tprotectionsettings_client_example_test.go | 183 + .../armsql/manageddatabasecolumns_client.go | 14 +- ...ageddatabasecolumns_client_example_test.go | 10 +- .../manageddatabasemoveoperations_client.go | 183 + ...abasemoveoperations_client_example_test.go | 262 + .../armsql/manageddatabasequeries_client.go | 14 +- ...ageddatabasequeries_client_example_test.go | 10 +- ...baserecommendedsensitivitylabels_client.go | 16 +- ...edsensitivitylabels_client_example_test.go | 4 +- .../manageddatabaserestoredetails_client.go | 18 +- ...abaserestoredetails_client_example_test.go | 133 +- .../sql/armsql/manageddatabases_client.go | 348 +- .../manageddatabases_client_example_test.go | 273 +- .../armsql/manageddatabaseschemas_client.go | 14 +- ...ageddatabaseschemas_client_example_test.go | 6 +- ...geddatabasesecurityalertpolicies_client.go | 30 +- ...curityalertpolicies_client_example_test.go | 10 +- .../manageddatabasesecurityevents_client.go | 3 +- ...abasesecurityevents_client_example_test.go | 6 +- ...manageddatabasesensitivitylabels_client.go | 67 +- ...sesensitivitylabels_client_example_test.go | 18 +- .../armsql/manageddatabasetables_client.go | 14 +- ...nageddatabasetables_client_example_test.go | 6 +- ...atabasetransparentdataencryption_client.go | 30 +- ...arentdataencryption_client_example_test.go | 8 +- ...erabilityassessmentrulebaselines_client.go | 38 +- ...ssmentrulebaselines_client_example_test.go | 8 +- ...databasevulnerabilityassessments_client.go | 38 +- ...rabilityassessments_client_example_test.go | 12 +- ...basevulnerabilityassessmentscans_client.go | 38 +- ...lityassessmentscans_client_example_test.go | 10 +- .../managedinstanceadministrators_client.go | 45 +- ...tanceadministrators_client_example_test.go | 12 +- ...advancedthreatprotectionsettings_client.go | 260 + ...tprotectionsettings_client_example_test.go | 191 + ...stanceazureadonlyauthentications_client.go | 45 +- ...onlyauthentications_client_example_test.go | 10 +- .../sql/armsql/managedinstancedtcs_client.go | 259 + ...managedinstancedtcs_client_example_test.go | 233 + ...agedinstanceencryptionprotectors_client.go | 45 +- ...ncryptionprotectors_client_example_test.go | 12 +- .../sql/armsql/managedinstancekeys_client.go | 45 +- ...managedinstancekeys_client_example_test.go | 10 +- ...nstancelongtermretentionpolicies_client.go | 32 +- ...rmretentionpolicies_client_example_test.go | 8 +- .../managedinstanceoperations_client.go | 22 +- ...dinstanceoperations_client_example_test.go | 8 +- ...stanceprivateendpointconnections_client.go | 45 +- ...endpointconnections_client_example_test.go | 10 +- ...agedinstanceprivatelinkresources_client.go | 14 +- ...rivatelinkresources_client_example_test.go | 6 +- .../sql/armsql/managedinstances_client.go | 332 +- .../managedinstances_client_example_test.go | 389 +- .../managedinstancetdecertificates_client.go | 21 +- ...ancetdecertificates_client_example_test.go | 4 +- ...instancevulnerabilityassessments_client.go | 38 +- ...rabilityassessments_client_example_test.go | 14 +- .../managedledgerdigestuploads_client.go | 352 + ...ledgerdigestuploads_client_example_test.go | 154 + ...backupshorttermretentionpolicies_client.go | 50 +- ...rmretentionpolicies_client_example_test.go | 8 +- .../armsql/managedserverdnsaliases_client.go | 405 + ...gedserverdnsaliases_client_example_test.go | 181 + ...nagedserversecurityalertpolicies_client.go | 32 +- ...curityalertpolicies_client_example_test.go | 10 +- sdk/resourcemanager/sql/armsql/models.go | 7710 +++----- .../sql/armsql/models_serde.go | 16505 +++++++++------- .../sql/armsql/operations_client.go | 3 +- sdk/resourcemanager/sql/armsql/options.go | 3401 ++++ .../armsql/outboundfirewallrules_client.go | 45 +- ...tboundfirewallrules_client_example_test.go | 10 +- .../privateendpointconnections_client.go | 65 +- ...endpointconnections_client_example_test.go | 128 +- .../sql/armsql/privatelinkresources_client.go | 14 +- ...rivatelinkresources_client_example_test.go | 6 +- .../recommendedsensitivitylabels_client.go | 16 +- ...edsensitivitylabels_client_example_test.go | 4 +- .../sql/armsql/recoverabledatabases_client.go | 60 +- ...ecoverabledatabases_client_example_test.go | 113 +- .../recoverablemanageddatabases_client.go | 14 +- ...blemanageddatabases_client_example_test.go | 6 +- .../sql/armsql/replicationlinks_client.go | 108 +- .../replicationlinks_client_example_test.go | 22 +- .../sql/armsql/response_types.go | 778 +- .../restorabledroppeddatabases_client.go | 28 +- ...bledroppeddatabases_client_example_test.go | 58 +- ...estorabledroppedmanageddatabases_client.go | 14 +- ...pedmanageddatabases_client_example_test.go | 6 +- .../sql/armsql/restorepoints_client.go | 40 +- .../restorepoints_client_example_test.go | 14 +- .../sql/armsql/sensitivitylabels_client.go | 67 +- .../sensitivitylabels_client_example_test.go | 18 +- ...advancedthreatprotectionsettings_client.go | 32 +- ...tprotectionsettings_client_example_test.go | 10 +- .../sql/armsql/serveradvisors_client.go | 41 +- .../serveradvisors_client_example_test.go | 10 +- .../armsql/serverautomatictuning_client.go | 30 +- ...rverautomatictuning_client_example_test.go | 8 +- .../serverazureadadministrators_client.go | 45 +- ...ureadadministrators_client_example_test.go | 10 +- ...serverazureadonlyauthentications_client.go | 45 +- ...onlyauthentications_client_example_test.go | 10 +- .../serverblobauditingpolicies_client.go | 32 +- ...lobauditingpolicies_client_example_test.go | 10 +- .../armsql/servercommunicationlinks_client.go | 40 +- ...rcommunicationlinks_client_example_test.go | 10 +- .../serverconfigurationoptions_client.go | 260 + ...onfigurationoptions_client_example_test.go | 122 + .../armsql/serverconnectionpolicies_client.go | 32 +- ...rconnectionpolicies_client_example_test.go | 8 +- .../serverdevopsauditsettings_client.go | 62 +- ...devopsauditsettings_client_example_test.go | 106 +- .../sql/armsql/serverdnsaliases_client.go | 58 +- .../serverdnsaliases_client_example_test.go | 12 +- .../sql/armsql/serverkeys_client.go | 45 +- .../armsql/serverkeys_client_example_test.go | 10 +- .../sql/armsql/serveroperations_client.go | 3 +- .../serveroperations_client_example_test.go | 4 +- .../sql/armsql/servers_client.go | 208 +- .../sql/armsql/servers_client_example_test.go | 608 +- .../serversecurityalertpolicies_client.go | 32 +- ...curityalertpolicies_client_example_test.go | 10 +- .../armsql/servertrustcertificates_client.go | 45 +- ...ertrustcertificates_client_example_test.go | 10 +- .../sql/armsql/servertrustgroups_client.go | 45 +- .../servertrustgroups_client_example_test.go | 12 +- .../sql/armsql/serverusages_client.go | 3 +- .../serverusages_client_example_test.go | 4 +- .../servervulnerabilityassessments_client.go | 38 +- ...rabilityassessments_client_example_test.go | 14 +- .../sql/armsql/serviceobjectives_client.go | 14 +- .../serviceobjectives_client_example_test.go | 6 +- ...tartstopmanagedinstanceschedules_client.go | 309 + ...edinstanceschedules_client_example_test.go | 286 + .../sql/armsql/subscriptionusages_client.go | 14 +- .../subscriptionusages_client_example_test.go | 6 +- .../armsql/synapselinkworkspaces_client.go | 120 + ...napselinkworkspaces_client_example_test.go | 62 + .../sql/armsql/syncagents_client.go | 56 +- .../armsql/syncagents_client_example_test.go | 16 +- .../sql/armsql/syncgroups_client.go | 92 +- .../armsql/syncgroups_client_example_test.go | 26 +- .../sql/armsql/syncmembers_client.go | 76 +- .../armsql/syncmembers_client_example_test.go | 18 +- .../sql/armsql/tdecertificates_client.go | 21 +- .../tdecertificates_client_example_test.go | 4 +- .../sql/armsql/time_rfc3339.go | 3 +- .../sql/armsql/timezones_client.go | 14 +- .../armsql/timezones_client_example_test.go | 8 +- .../transparentdataencryptions_client.go | 79 +- ...rentdataencryptions_client_example_test.go | 86 +- .../sql/armsql/usages_client.go | 3 +- .../sql/armsql/usages_client_example_test.go | 6 +- .../sql/armsql/virtualclusters_client.go | 125 +- .../virtualclusters_client_example_test.go | 191 +- .../sql/armsql/virtualnetworkrules_client.go | 45 +- ...virtualnetworkrules_client_example_test.go | 10 +- .../vulnerabilityassessmentbaseline_client.go | 193 + ...yassessmentbaseline_client_example_test.go | 140 + ...vulnerabilityassessmentbaselines_client.go | 120 + ...assessmentbaselines_client_example_test.go | 136 + ...lnerabilityassessmentexecutescan_client.go | 118 + ...sessmentexecutescan_client_example_test.go | 39 + ...nerabilityassessmentrulebaseline_client.go | 283 + ...essmentrulebaseline_client_example_test.go | 169 + ...erabilityassessmentrulebaselines_client.go | 110 + ...ssmentrulebaselines_client_example_test.go | 35 + .../armsql/vulnerabilityassessments_client.go | 100 + ...rabilityassessments_client_example_test.go | 35 + ...ulnerabilityassessmentscanresult_client.go | 204 + ...ssessmentscanresult_client_example_test.go | 213 + .../vulnerabilityassessmentscans_client.go | 193 + ...lityassessmentscans_client_example_test.go | 158 + ...vulnerabilityassessmentssettings_client.go | 253 + ...assessmentssettings_client_example_test.go | 115 + .../sql/armsql/workloadclassifiers_client.go | 45 +- ...workloadclassifiers_client_example_test.go | 12 +- .../sql/armsql/workloadgroups_client.go | 45 +- .../workloadgroups_client_example_test.go | 12 +- .../armsqlvirtualmachine/CHANGELOG.md | 17 + .../armsqlvirtualmachine/autorest.md | 7 +- .../availabilitygrouplisteners_client.go | 29 +- ...ilitygrouplisteners_client_example_test.go | 10 +- .../armsqlvirtualmachine/client_factory.go | 5 + .../armsqlvirtualmachine/constants.go | 18 +- .../armsqlvirtualmachine/go.mod | 16 +- .../armsqlvirtualmachine/go.sum | 36 +- .../armsqlvirtualmachine/groups_client.go | 43 +- .../groups_client_example_test.go | 12 +- .../armsqlvirtualmachine/models.go | 429 +- .../armsqlvirtualmachine/models_serde.go | 179 + .../armsqlvirtualmachine/operations_client.go | 4 +- .../operations_client_example_test.go | 2 +- .../armsqlvirtualmachine/response_types.go | 5 + .../sqlvirtualmachines_client.go | 77 +- .../sqlvirtualmachines_client_example_test.go | 129 +- .../troubleshoot_client.go | 114 + .../troubleshoot_client_example_test.go | 64 + .../storage/armstorage/CHANGELOG.md | 12 + .../storage/armstorage/README.md | 25 + .../storage/armstorage/accounts_client.go | 256 +- .../storage/armstorage/autorest.md | 8 +- .../armstorage/blobcontainers_client.go | 234 +- .../blobinventorypolicies_client.go | 52 +- .../storage/armstorage/blobservices_client.go | 40 +- .../storage/armstorage/build.go | 2 +- .../storage/armstorage/client_factory.go | 77 +- .../storage/armstorage/constants.go | 45 +- .../armstorage/deletedaccounts_client.go | 20 +- .../armstorage/encryptionscopes_client.go | 60 +- .../armstorage/fake/accounts_server.go | 822 + .../armstorage/fake/blobcontainers_server.go | 780 + .../fake/blobinventorypolicies_server.go | 242 + .../armstorage/fake/blobservices_server.go | 191 + .../armstorage/fake/deletedaccounts_server.go | 144 + .../fake/encryptionscopes_server.go | 284 + .../armstorage/fake/fileservices_server.go | 182 + .../armstorage/fake/fileshares_server.go | 463 + .../storage/armstorage/fake/internal.go | 123 + .../armstorage/fake/localusers_server.go | 328 + .../fake/managementpolicies_server.go | 194 + .../fake/objectreplicationpolicies_server.go | 242 + .../armstorage/fake/operations_server.go | 92 + .../fake/privateendpointconnections_server.go | 242 + .../fake/privatelinkresources_server.go | 100 + .../storage/armstorage/fake/queue_server.go | 311 + .../armstorage/fake/queueservices_server.go | 182 + .../storage/armstorage/fake/skus_server.go | 99 + .../storage/armstorage/fake/table_server.go | 306 + .../armstorage/fake/tableservices_server.go | 182 + .../storage/armstorage/fake/time_rfc3339.go | 86 + .../storage/armstorage/fake/usages_server.go | 104 + .../storage/armstorage/fake_example_test.go | 79 + .../storage/armstorage/fileservices_client.go | 53 +- .../storage/armstorage/fileshares_client.go | 109 +- sdk/resourcemanager/storage/armstorage/go.mod | 10 +- sdk/resourcemanager/storage/armstorage/go.sum | 20 +- .../storage/armstorage/localusers_client.go | 82 +- .../armstorage/managementpolicies_client.go | 50 +- .../storage/armstorage/models.go | 1890 +- .../storage/armstorage/models_serde.go | 3 +- .../objectreplicationpolicies_client.go | 52 +- .../storage/armstorage/operations_client.go | 5 +- .../storage/armstorage/options.go | 564 + .../privateendpointconnections_client.go | 52 +- .../armstorage/privatelinkresources_client.go | 18 +- .../storage/armstorage/queue_client.go | 72 +- .../armstorage/queueservices_client.go | 53 +- .../storage/armstorage/response_types.go | 77 +- .../storage/armstorage/skus_client.go | 5 +- .../storage/armstorage/table_client.go | 72 +- .../armstorage/tableservices_client.go | 53 +- .../storage/armstorage/time_rfc3339.go | 3 +- .../storage/armstorage/usages_client.go | 5 +- .../storagecache/armstoragecache/CHANGELOG.md | 56 + .../armstoragecache/amlfilesystems_client.go | 531 + .../amlfilesystems_client_example_test.go | 733 + .../armstoragecache/ascoperations_client.go | 11 +- .../ascoperations_client_example_test.go | 2 +- .../armstoragecache/ascusages_client.go | 7 +- .../ascusages_client_example_test.go | 2 +- .../storagecache/armstoragecache/autorest.md | 8 +- .../armstoragecache/caches_client.go | 193 +- .../caches_client_example_test.go | 126 +- .../armstoragecache/client_factory.go | 13 +- .../storagecache/armstoragecache/constants.go | 144 +- .../storagecache/armstoragecache/go.mod | 16 +- .../storagecache/armstoragecache/go.sum | 36 +- .../armstoragecache/management_client.go | 138 + .../management_client_example_test.go | 66 + .../storagecache/armstoragecache/models.go | 888 +- .../armstoragecache/models_serde.go | 891 + .../armstoragecache/operations_client.go | 4 +- .../operations_client_example_test.go | 2 +- .../armstoragecache/response_types.go | 50 + .../armstoragecache/skus_client.go | 7 +- .../skus_client_example_test.go | 2 +- .../armstoragecache/storagetarget_client.go | 43 +- .../storagetarget_client_example_test.go | 8 +- .../armstoragecache/storagetargets_client.go | 83 +- .../storagetargets_client_example_test.go | 16 +- .../armstoragecache/usagemodels_client.go | 9 +- .../usagemodels_client_example_test.go | 2 +- .../storagemover/armstoragemover/CHANGELOG.md | 27 + .../armstoragemover/agents_client.go | 22 +- .../agents_client_example_test.go | 104 +- .../storagemover/armstoragemover/autorest.md | 8 +- .../storagemover/armstoragemover/constants.go | 20 +- .../armstoragemover/endpoints_client.go | 22 +- .../endpoints_client_example_test.go | 423 +- .../storagemover/armstoragemover/go.mod | 18 +- .../storagemover/armstoragemover/go.sum | 36 +- .../armstoragemover/jobdefinitions_client.go | 30 +- .../jobdefinitions_client_example_test.go | 84 +- .../armstoragemover/jobruns_client.go | 8 +- .../jobruns_client_example_test.go | 54 +- .../storagemover/armstoragemover/models.go | 200 +- .../armstoragemover/models_serde.go | 286 +- .../armstoragemover/operations_client.go | 4 +- .../operations_client_example_test.go | 4 +- .../armstoragemover/polymorphic_helpers.go | 28 + .../armstoragemover/projects_client.go | 22 +- .../projects_client_example_test.go | 24 +- .../armstoragemover/storagemovers_client.go | 26 +- .../storagemovers_client_example_test.go | 160 +- .../armstreamanalytics/assets.json | 6 + .../armstreamanalytics/clusters_live_test.go | 259 + .../armstreamanalytics/functions_live_test.go | 170 + .../streamanalytics/armstreamanalytics/go.mod | 10 +- .../streamanalytics/armstreamanalytics/go.sum | 17 + .../armstreamanalytics/inputs_live_test.go | 267 + .../armstreamanalytics/outputs_live_test.go | 265 + .../streamingjobs_live_test.go | 148 + .../subscriptions_live_test.go | 64 + .../transformations_live_test.go | 127 + .../armtrafficmanager/CHANGELOG.md | 9 + .../armtrafficmanager/autorest.md | 8 +- .../armtrafficmanager/client_factory.go | 3 +- .../armtrafficmanager/constants.go | 21 +- .../armtrafficmanager/endpoints_client.go | 27 +- .../endpoints_client_example_test.go | 61 +- .../geographichierarchies_client.go | 4 +- ...ographichierarchies_client_example_test.go | 2 +- .../trafficmanager/armtrafficmanager/go.mod | 16 +- .../trafficmanager/armtrafficmanager/go.sum | 36 +- .../armtrafficmanager/heatmap_client.go | 9 +- .../heatmap_client_example_test.go | 6 +- .../armtrafficmanager/models.go | 214 +- .../armtrafficmanager/models_serde.go | 4 + .../armtrafficmanager/profiles_client.go | 90 +- .../profiles_client_example_test.go | 88 +- .../armtrafficmanager/response_types.go | 5 + .../usermetricskeys_client.go | 15 +- .../usermetricskeys_client_example_test.go | 6 +- .../webpubsub/armwebpubsub/CHANGELOG.md | 23 + .../webpubsub/armwebpubsub/autorest.md | 8 +- .../webpubsub/armwebpubsub/client.go | 190 +- .../armwebpubsub/client_example_test.go | 353 +- .../webpubsub/armwebpubsub/client_factory.go | 8 +- .../webpubsub/armwebpubsub/constants.go | 18 +- .../armwebpubsub/customcertificates_client.go | 49 +- .../customcertificates_client_example_test.go | 8 +- .../armwebpubsub/customdomains_client.go | 51 +- .../customdomains_client_example_test.go | 8 +- .../webpubsub/armwebpubsub/go.mod | 16 +- .../webpubsub/armwebpubsub/go.sum | 36 +- .../webpubsub/armwebpubsub/hubs_client.go | 51 +- .../armwebpubsub/hubs_client_example_test.go | 8 +- .../webpubsub/armwebpubsub/models.go | 188 +- .../webpubsub/armwebpubsub/models_serde.go | 133 + .../armwebpubsub/operations_client.go | 4 +- .../operations_client_example_test.go | 2 +- .../privateendpointconnections_client.go | 51 +- ...endpointconnections_client_example_test.go | 60 +- .../privatelinkresources_client.go | 13 +- ...rivatelinkresources_client_example_test.go | 18 +- .../webpubsub/armwebpubsub/replicas_client.go | 427 + .../replicas_client_example_test.go | 279 + .../webpubsub/armwebpubsub/response_types.go | 35 + .../sharedprivatelinkresources_client.go | 51 +- ...rivatelinkresources_client_example_test.go | 8 +- .../webpubsub/armwebpubsub/usages_client.go | 10 +- .../usages_client_example_test.go | 2 +- .../managed-identity/functions/go.mod | 31 +- .../managed-identity/functions/go.sum | 78 +- .../managed-identity/functions/handler.go | 4 +- .../managed-identity/general/go.mod | 31 +- .../managed-identity/general/go.sum | 75 +- .../managed-identity/service-fabric/go.mod | 22 +- .../managed-identity/service-fabric/go.sum | 57 +- .../managed-identity/service-fabric/main.go | 9 +- sdk/security/keyvault/azadmin/CHANGELOG.md | 21 +- sdk/security/keyvault/azadmin/README.md | 2 +- sdk/security/keyvault/azadmin/assets.json | 2 +- .../keyvault/azadmin/backup/autorest.md | 13 +- .../keyvault/azadmin/backup/client.go | 6 +- .../keyvault/azadmin/backup/client_test.go | 6 +- .../keyvault/azadmin/backup/example_test.go | 10 +- .../keyvault/azadmin/backup/models.go | 8 +- .../keyvault/azadmin/backup/models_serde.go | 16 +- .../keyvault/azadmin/backup/utils_test.go | 67 +- sdk/security/keyvault/azadmin/go.mod | 4 +- sdk/security/keyvault/azadmin/go.sum | 15 +- .../keyvault/azadmin/internal/version.go | 2 +- .../keyvault/azadmin/rbac/utils_test.go | 46 +- .../keyvault/azadmin/settings/client_test.go | 4 - .../keyvault/azadmin/settings/utils_test.go | 45 +- .../keyvault/azadmin/test-resources.json | 4 + .../keyvault/azcertificates/CHANGELOG.md | 48 +- .../keyvault/azcertificates/README.md | 2 +- .../keyvault/azcertificates/assets.json | 2 +- .../keyvault/azcertificates/autorest.md | 154 +- .../keyvault/azcertificates/client.go | 664 +- .../keyvault/azcertificates/client_test.go | 88 +- .../keyvault/azcertificates/constants.go | 113 +- .../keyvault/azcertificates/example_test.go | 4 +- sdk/security/keyvault/azcertificates/go.mod | 4 +- sdk/security/keyvault/azcertificates/go.sum | 15 +- .../keyvault/azcertificates/models.go | 351 +- .../keyvault/azcertificates/models_serde.go | 644 +- .../keyvault/azcertificates/response_types.go | 90 +- .../azcertificates/testdata/perf/go.mod | 2 +- .../azcertificates/testdata/perf/go.sum | 6 +- .../keyvault/azcertificates/version.go | 2 +- sdk/security/keyvault/azkeys/CHANGELOG.md | 45 +- sdk/security/keyvault/azkeys/README.md | 2 +- sdk/security/keyvault/azkeys/assets.json | 2 +- sdk/security/keyvault/azkeys/autorest.md | 164 +- sdk/security/keyvault/azkeys/client.go | 464 +- sdk/security/keyvault/azkeys/client_test.go | 100 +- sdk/security/keyvault/azkeys/constants.go | 327 +- sdk/security/keyvault/azkeys/example_test.go | 18 +- sdk/security/keyvault/azkeys/go.mod | 4 +- sdk/security/keyvault/azkeys/go.sum | 15 +- sdk/security/keyvault/azkeys/models.go | 408 +- sdk/security/keyvault/azkeys/models_serde.go | 193 +- sdk/security/keyvault/azkeys/options.go | 131 + .../keyvault/azkeys/response_types.go | 48 +- .../keyvault/azkeys/testdata/perf/get_key.go | 7 +- .../keyvault/azkeys/testdata/perf/go.mod | 2 +- .../keyvault/azkeys/testdata/perf/go.sum | 6 +- sdk/security/keyvault/azkeys/time_unix.go | 3 +- sdk/security/keyvault/azkeys/utils_test.go | 25 + sdk/security/keyvault/azkeys/version.go | 2 +- sdk/security/keyvault/azsecrets/CHANGELOG.md | 31 +- sdk/security/keyvault/azsecrets/README.md | 2 +- sdk/security/keyvault/azsecrets/assets.json | 2 +- sdk/security/keyvault/azsecrets/autorest.md | 55 +- sdk/security/keyvault/azsecrets/build.go | 1 + sdk/security/keyvault/azsecrets/client.go | 187 +- .../keyvault/azsecrets/client_test.go | 57 +- sdk/security/keyvault/azsecrets/constants.go | 63 - .../keyvault/azsecrets/example_test.go | 16 +- sdk/security/keyvault/azsecrets/go.mod | 4 +- sdk/security/keyvault/azsecrets/go.sum | 15 +- sdk/security/keyvault/azsecrets/models.go | 115 +- .../keyvault/azsecrets/models_serde.go | 156 +- .../keyvault/azsecrets/response_types.go | 36 +- .../keyvault/azsecrets/testdata/perf/go.mod | 2 +- .../keyvault/azsecrets/testdata/perf/go.sum | 6 +- .../azsecrets/testdata/perf/list_secrets.go | 2 +- sdk/security/keyvault/azsecrets/utils_test.go | 45 + sdk/security/keyvault/azsecrets/version.go | 2 +- sdk/security/keyvault/internal/CHANGELOG.md | 10 +- sdk/security/keyvault/internal/constants.go | 2 +- sdk/security/keyvault/internal/go.mod | 10 +- sdk/security/keyvault/internal/go.sum | 27 +- sdk/storage/azblob/CHANGELOG.md | 42 + sdk/storage/azblob/README.md | 146 +- sdk/storage/azblob/appendblob/client.go | 41 +- sdk/storage/azblob/appendblob/client_test.go | 144 + sdk/storage/azblob/assets.json | 2 +- sdk/storage/azblob/blob/client.go | 39 +- sdk/storage/azblob/blob/client_test.go | 176 +- sdk/storage/azblob/blob/constants.go | 1 + sdk/storage/azblob/blob/models.go | 8 +- sdk/storage/azblob/bloberror/error_codes.go | 1 + sdk/storage/azblob/blockblob/client.go | 85 +- sdk/storage/azblob/blockblob/client_test.go | 766 +- sdk/storage/azblob/blockblob/constants.go | 13 + sdk/storage/azblob/blockblob/mmf_unix.go | 4 +- sdk/storage/azblob/blockblob/models.go | 25 +- sdk/storage/azblob/client_test.go | 154 + sdk/storage/azblob/container/client.go | 46 +- sdk/storage/azblob/container/client_test.go | 920 +- sdk/storage/azblob/container/models.go | 28 + sdk/storage/azblob/container/responses.go | 3 + sdk/storage/azblob/doc.go | 43 +- sdk/storage/azblob/go.mod | 26 +- sdk/storage/azblob/go.sum | 58 +- sdk/storage/azblob/internal/base/clients.go | 31 +- .../exported/shared_key_credential.go | 2 +- .../azblob/internal/exported/version.go | 2 +- .../internal/generated/appendblob_client.go | 19 +- .../azblob/internal/generated/autorest.md | 23 +- .../azblob/internal/generated/blob_client.go | 17 +- .../internal/generated/block_blob_client.go | 19 +- .../internal/generated/container_client.go | 19 +- .../azblob/internal/generated/models.go | 76 + .../internal/generated/pageblob_client.go | 19 +- .../internal/generated/service_client.go | 19 +- .../generated/zz_appendblob_client.go | 44 +- .../internal/generated/zz_blob_client.go | 185 +- .../internal/generated/zz_blockblob_client.go | 72 +- .../azblob/internal/generated/zz_constants.go | 124 +- .../internal/generated/zz_container_client.go | 203 +- .../azblob/internal/generated/zz_models.go | 48 +- .../internal/generated/zz_models_serde.go | 28 +- .../internal/generated/zz_pageblob_client.go | 74 +- .../internal/generated/zz_response_types.go | 19 + .../internal/generated/zz_service_client.go | 80 +- sdk/storage/azblob/internal/shared/shared.go | 60 +- .../azblob/internal/shared/shared_test.go | 59 +- .../internal/testcommon/clients_auth.go | 21 + sdk/storage/azblob/pageblob/client.go | 33 +- sdk/storage/azblob/pageblob/client_test.go | 27 + sdk/storage/azblob/sas/account.go | 29 +- sdk/storage/azblob/sas/query_params.go | 13 +- sdk/storage/azblob/sas/service.go | 58 +- sdk/storage/azblob/sas/service_test.go | 45 + sdk/storage/azblob/service/client.go | 33 +- sdk/storage/azblob/service/client_test.go | 100 + sdk/storage/azblob/service/models.go | 3 + sdk/storage/azblob/testdata/perf/go.mod | 8 +- sdk/storage/azblob/testdata/perf/go.sum | 35 +- sdk/storage/azfile/CHANGELOG.md | 15 +- sdk/storage/azfile/assets.json | 2 +- sdk/storage/azfile/directory/client.go | 5 +- sdk/storage/azfile/directory/client_test.go | 55 +- sdk/storage/azfile/file/client.go | 4 + sdk/storage/azfile/file/client_test.go | 36 + sdk/storage/azfile/file/mmf_unix.go | 4 +- sdk/storage/azfile/file/models.go | 7 + .../exported/shared_key_credential.go | 2 +- .../azfile/internal/exported/smb_property.go | 42 + .../azfile/internal/exported/version.go | 2 +- sdk/storage/azfile/migrationguide.md | 76 + sdk/storage/azfile/share/client.go | 3 +- sdk/storage/azqueue/CHANGELOG.md | 12 + .../exported/shared_key_credential.go | 2 +- .../azqueue/internal/exported/version.go | 2 +- sdk/storage/azqueue/internal/shared/shared.go | 52 +- .../azqueue/internal/shared/shared_test.go | 141 + sdk/storage/azqueue/queue_client_test.go | 71 + sdk/storage/azqueue/sas/service.go | 5 +- sdk/storage/azqueue/sas/service_test.go | 45 + sdk/tracing/azotel/CHANGELOG.md | 23 + sdk/tracing/azotel/LICENSE.txt | 21 + sdk/tracing/azotel/README.md | 47 + .../ci.keyvault.yml => tracing/azotel/ci.yml} | 8 +- sdk/tracing/azotel/examples_test.go | 75 + sdk/tracing/azotel/go.mod | 33 + sdk/tracing/azotel/go.sum | 58 + .../azotel/internal}/version.go | 7 +- sdk/tracing/azotel/otel.go | 113 + sdk/tracing/azotel/otel_test.go | 251 + 3486 files changed, 419380 insertions(+), 116592 deletions(-) delete mode 100644 eng/common/pipelines/templates/steps/docs-metadata-release.yml create mode 100644 eng/common/pipelines/templates/steps/docsms-ensure-validation.yml create mode 100644 eng/common/scripts/TypeSpec-Project-Process.ps1 create mode 100644 eng/common/scripts/X509Certificate2/README.md create mode 100644 eng/common/scripts/X509Certificate2/X509Certificate2.psm1 rename eng/common/testproxy/{transition-scripts/README.md => onboarding/README.me} (92%) rename eng/common/testproxy/{transition-scripts => onboarding}/generate-assets-json.ps1 (91%) create mode 100644 sdk/ai/azopenai/CHANGELOG.md create mode 100644 sdk/ai/azopenai/LICENSE.txt create mode 100644 sdk/ai/azopenai/README.md create mode 100644 sdk/ai/azopenai/assets.json create mode 100644 sdk/ai/azopenai/autorest.md create mode 100644 sdk/ai/azopenai/build.go create mode 100644 sdk/ai/azopenai/ci.yml create mode 100644 sdk/ai/azopenai/client.go create mode 100644 sdk/ai/azopenai/client_chat_completions_test.go create mode 100644 sdk/ai/azopenai/client_completions_test.go create mode 100644 sdk/ai/azopenai/client_embeddings_test.go create mode 100644 sdk/ai/azopenai/client_functions_test.go create mode 100644 sdk/ai/azopenai/client_rai_test.go create mode 100644 sdk/ai/azopenai/client_shared_test.go create mode 100644 sdk/ai/azopenai/client_test.go create mode 100644 sdk/ai/azopenai/constants.go create mode 100644 sdk/ai/azopenai/custom_client.go create mode 100644 sdk/ai/azopenai/custom_client_functions.go create mode 100644 sdk/ai/azopenai/custom_client_image.go create mode 100644 sdk/ai/azopenai/custom_client_image_test.go create mode 100644 sdk/ai/azopenai/custom_client_test.go create mode 100644 sdk/ai/azopenai/custom_models.go create mode 100644 sdk/ai/azopenai/custom_models_test.go create mode 100644 sdk/ai/azopenai/event_reader.go create mode 100644 sdk/ai/azopenai/event_reader_test.go create mode 100644 sdk/ai/azopenai/example_client_createimage_test.go create mode 100644 sdk/ai/azopenai/example_client_embeddings_test.go create mode 100644 sdk/ai/azopenai/example_client_getchatcompletions_test.go create mode 100644 sdk/ai/azopenai/example_client_getcompletions_test.go create mode 100644 sdk/ai/azopenai/example_client_test.go create mode 100644 sdk/ai/azopenai/genopenapi3.ps1 create mode 100644 sdk/ai/azopenai/go.mod create mode 100644 sdk/ai/azopenai/go.sum rename sdk/{keyvault/azsecrets/build.go => ai/azopenai/main_test.go} (58%) create mode 100644 sdk/ai/azopenai/models.go create mode 100644 sdk/ai/azopenai/models_serde.go create mode 100644 sdk/ai/azopenai/options.go create mode 100644 sdk/ai/azopenai/policy_apikey.go create mode 100644 sdk/ai/azopenai/policy_apikey_test.go create mode 100644 sdk/ai/azopenai/response_types.go create mode 100644 sdk/ai/azopenai/sample.env create mode 100644 sdk/ai/azopenai/testdata/.gitignore create mode 100644 sdk/ai/azopenai/testdata/content_filter_response_error.json create mode 100644 sdk/ai/azopenai/testdata/package-lock.json create mode 100644 sdk/ai/azopenai/testdata/package.json create mode 100644 sdk/ai/azopenai/testdata/tsp-location.yaml create mode 100644 sdk/ai/azopenai/testdata/tspconfig.yaml rename sdk/{keyvault/internal/doc.go => ai/azopenai/version.go} (80%) create mode 100644 sdk/azcore/fake/internal/exported/fake.go create mode 100644 sdk/azcore/fake/internal/exported/fake_test.go create mode 100644 sdk/azcore/fake/server/server.go create mode 100644 sdk/azcore/fake/server/server_test.go create mode 100644 sdk/azcore/messaging/cloud_event.go create mode 100644 sdk/azcore/messaging/cloud_event_test.go create mode 100644 sdk/azcore/messaging/example_usingcloudevent_test.go create mode 100644 sdk/azcore/messaging/testdata/cloudevent_binary_with_extensions.json create mode 100644 sdk/azcore/messaging/testdata/cloudevent_required_only.json create mode 100644 sdk/cognitiveservices/azopenai/CHANGELOG.md create mode 100644 sdk/cognitiveservices/azopenai/LICENSE.txt create mode 100644 sdk/cognitiveservices/azopenai/README.md create mode 100644 sdk/cognitiveservices/azopenai/assets.json create mode 100644 sdk/cognitiveservices/azopenai/autorest.md create mode 100644 sdk/cognitiveservices/azopenai/build.go create mode 100644 sdk/cognitiveservices/azopenai/ci.cognitiveservices.yml create mode 100644 sdk/cognitiveservices/azopenai/client.go create mode 100644 sdk/cognitiveservices/azopenai/client_chat_completions_test.go create mode 100644 sdk/cognitiveservices/azopenai/client_completions_test.go create mode 100644 sdk/cognitiveservices/azopenai/client_embeddings_test.go create mode 100644 sdk/cognitiveservices/azopenai/client_functions_test.go create mode 100644 sdk/cognitiveservices/azopenai/client_rai_test.go create mode 100644 sdk/cognitiveservices/azopenai/client_shared_test.go create mode 100644 sdk/cognitiveservices/azopenai/client_test.go create mode 100644 sdk/cognitiveservices/azopenai/constants.go create mode 100644 sdk/cognitiveservices/azopenai/custom_client.go create mode 100644 sdk/cognitiveservices/azopenai/custom_client_functions.go create mode 100644 sdk/cognitiveservices/azopenai/custom_client_image.go create mode 100644 sdk/cognitiveservices/azopenai/custom_client_image_test.go create mode 100644 sdk/cognitiveservices/azopenai/custom_client_test.go create mode 100644 sdk/cognitiveservices/azopenai/custom_models.go create mode 100644 sdk/cognitiveservices/azopenai/custom_models_test.go create mode 100644 sdk/cognitiveservices/azopenai/event_reader.go create mode 100644 sdk/cognitiveservices/azopenai/event_reader_test.go create mode 100644 sdk/cognitiveservices/azopenai/example_client_createimage_test.go create mode 100644 sdk/cognitiveservices/azopenai/example_client_embeddings_test.go create mode 100644 sdk/cognitiveservices/azopenai/example_client_getchatcompletions_test.go create mode 100644 sdk/cognitiveservices/azopenai/example_client_getcompletions_test.go create mode 100644 sdk/cognitiveservices/azopenai/example_client_test.go create mode 100644 sdk/cognitiveservices/azopenai/genopenapi3.ps1 create mode 100644 sdk/cognitiveservices/azopenai/go.mod create mode 100644 sdk/cognitiveservices/azopenai/go.sum create mode 100644 sdk/cognitiveservices/azopenai/main_test.go create mode 100644 sdk/cognitiveservices/azopenai/models.go create mode 100644 sdk/cognitiveservices/azopenai/models_serde.go create mode 100644 sdk/cognitiveservices/azopenai/options.go create mode 100644 sdk/cognitiveservices/azopenai/policy_apikey.go create mode 100644 sdk/cognitiveservices/azopenai/policy_apikey_test.go create mode 100644 sdk/cognitiveservices/azopenai/response_types.go create mode 100644 sdk/cognitiveservices/azopenai/sample.env create mode 100644 sdk/cognitiveservices/azopenai/testdata/.gitignore create mode 100644 sdk/cognitiveservices/azopenai/testdata/content_filter_response_error.json create mode 100644 sdk/cognitiveservices/azopenai/testdata/package-lock.json create mode 100644 sdk/cognitiveservices/azopenai/testdata/package.json create mode 100644 sdk/cognitiveservices/azopenai/testdata/tsp-location.yaml create mode 100644 sdk/cognitiveservices/azopenai/testdata/tspconfig.yaml rename sdk/{keyvault/azkeys => cognitiveservices/azopenai}/version.go (76%) create mode 100644 sdk/containers/azcontainerregistry/TROUBLESHOOTING.md create mode 100644 sdk/containers/azcontainerregistry/constants_test.go create mode 100644 sdk/containers/azcontainerregistry/digest_helper.go create mode 100644 sdk/containers/azcontainerregistry/digest_helper_test.go rename sdk/containers/azcontainerregistry/{blob_client_example_test.go => example_blob_client_test.go} (62%) rename sdk/containers/azcontainerregistry/{blob_custom_client_example_test.go => example_blob_custom_client_test.go} (59%) rename sdk/containers/azcontainerregistry/{client_example_test.go => example_client_test.go} (71%) rename sdk/containers/azcontainerregistry/{custom_client_example_test.go => example_custom_client_test.go} (100%) create mode 100644 sdk/containers/azcontainerregistry/example_download_image_test.go delete mode 100644 sdk/containers/azcontainerregistry/example_upload_download_blob_test.go rename sdk/containers/azcontainerregistry/{example_upload_manifest_test.go => example_upload_image_test.go} (82%) create mode 100644 sdk/containers/azcontainerregistry/time_rfc3339_test.go delete mode 100644 sdk/data/aztables/internal/connection.go delete mode 100644 sdk/data/aztables/internal/models_serde.go rename sdk/{keyvault/internal/constants.go => data/aztables/internal/version.go} (82%) rename sdk/data/aztables/internal/{constants.go => zz_constants.go} (60%) create mode 100644 sdk/data/aztables/internal/zz_models.go create mode 100644 sdk/data/aztables/internal/zz_models_serde.go rename sdk/data/aztables/internal/{models.go => zz_options.go} (54%) rename sdk/data/aztables/internal/{response_types.go => zz_response_types.go} (94%) create mode 100644 sdk/data/aztables/internal/zz_service_client.go create mode 100644 sdk/data/aztables/internal/zz_table_client.go rename sdk/data/aztables/internal/{time_rfc1123.go => zz_time_rfc1123.go} (92%) rename sdk/data/aztables/internal/{time_rfc3339.go => zz_time_rfc3339.go} (95%) create mode 100644 sdk/internal/recording/server.go create mode 100644 sdk/internal/recording/server_test.go rename sdk/internal/recording/testdata/recordings/{ => TestRecording}/TestBackwardSlashPath.json (100%) rename sdk/internal/recording/testdata/recordings/{ => TestRecording}/TestGenerateAlphaNumericID.json (59%) rename sdk/internal/recording/testdata/recordings/{ => TestRecording}/TestModeNotSetStartStop.json (100%) rename sdk/internal/recording/testdata/recordings/{ => TestRecording}/TestSetBodilessMatcherNilTest.json (100%) rename sdk/internal/recording/testdata/recordings/{ => TestRecording}/TestStartStop.json (100%) rename sdk/internal/recording/testdata/recordings/{ => TestRecordingSanitizer}/TestBodyKeySanitizer.json (100%) rename sdk/internal/recording/testdata/recordings/{ => TestRecordingSanitizer}/TestBodyRegexSanitizer.json (100%) rename sdk/internal/recording/testdata/recordings/{ => TestRecordingSanitizer}/TestContinuationSanitizer.json (100%) rename sdk/internal/recording/testdata/recordings/{ => TestRecordingSanitizer}/TestGeneralRegexSanitizer.json (100%) rename sdk/internal/recording/testdata/recordings/{ => TestRecordingSanitizer}/TestHeaderRegexSanitizer.json (100%) rename sdk/internal/recording/testdata/recordings/{ => TestRecordingSanitizer}/TestOAuthResponseSanitizer.json (100%) rename sdk/internal/recording/testdata/recordings/{ => TestRecordingSanitizer}/TestRemoveHeaderSanitizer.json (100%) rename sdk/internal/recording/testdata/recordings/{ => TestRecordingSanitizer}/TestResetSanitizers.json (100%) rename sdk/internal/recording/testdata/recordings/{TestSingleTestSanitizer => TestRecordingSanitizer/TestSingleTestSanitizer/TestRecordingSanitizer}/TestSingleTestSanitizer-0.json (100%) rename sdk/internal/recording/testdata/recordings/{TestSingleTestSanitizer => TestRecordingSanitizer/TestSingleTestSanitizer/TestRecordingSanitizer}/TestSingleTestSanitizer-1.json (100%) rename sdk/internal/recording/testdata/recordings/{ => TestRecordingSanitizer}/TestUriSanitizer.json (100%) rename sdk/internal/recording/testdata/recordings/{ => TestRecordingSanitizer}/TestUriSubscriptionIdSanitizer.json (100%) delete mode 100644 sdk/internal/recording/testdata/recordings/TestSetBodilessMatcher.json delete mode 100644 sdk/internal/recording/testdata/recordings/TestSetDefaultMatcher.json delete mode 100644 sdk/keyvault/TROUBLESHOOTING.md delete mode 100644 sdk/keyvault/azcertificates/CHANGELOG.md delete mode 100644 sdk/keyvault/azcertificates/LICENSE.txt delete mode 100644 sdk/keyvault/azcertificates/README.md delete mode 100644 sdk/keyvault/azcertificates/TROUBLESHOOTING.md delete mode 100644 sdk/keyvault/azcertificates/autorest.md delete mode 100644 sdk/keyvault/azcertificates/client.go delete mode 100644 sdk/keyvault/azcertificates/client_test.go delete mode 100644 sdk/keyvault/azcertificates/constants.go delete mode 100644 sdk/keyvault/azcertificates/custom_client.go delete mode 100644 sdk/keyvault/azcertificates/example_test.go delete mode 100644 sdk/keyvault/azcertificates/go.mod delete mode 100644 sdk/keyvault/azcertificates/models.go delete mode 100644 sdk/keyvault/azcertificates/models_serde.go delete mode 100644 sdk/keyvault/azcertificates/response_types.go delete mode 100644 sdk/keyvault/azcertificates/test-resources.json delete mode 100644 sdk/keyvault/azcertificates/testdata/ca.crt delete mode 100644 sdk/keyvault/azcertificates/testdata/ca.key delete mode 100644 sdk/keyvault/azcertificates/testdata/perf/get_certificate.go delete mode 100644 sdk/keyvault/azcertificates/testdata/perf/go.mod delete mode 100644 sdk/keyvault/azcertificates/testdata/perf/go.sum delete mode 100644 sdk/keyvault/azcertificates/testdata/perf/main.go delete mode 100644 sdk/keyvault/azcertificates/testdata/recordings/TestBackupRestore.json delete mode 100644 sdk/keyvault/azcertificates/testdata/recordings/TestCRUD.json delete mode 100644 sdk/keyvault/azcertificates/testdata/recordings/TestContactsCRUD.json delete mode 100644 sdk/keyvault/azcertificates/testdata/recordings/TestDeleteRecover.json delete mode 100644 sdk/keyvault/azcertificates/testdata/recordings/TestImportCertificate.json delete mode 100644 sdk/keyvault/azcertificates/testdata/recordings/TestIssuerCRUD.json delete mode 100644 sdk/keyvault/azcertificates/testdata/recordings/TestListCertificateVersions.json delete mode 100644 sdk/keyvault/azcertificates/testdata/recordings/TestListCertificates.json delete mode 100644 sdk/keyvault/azcertificates/testdata/recordings/TestMergeCertificate.json delete mode 100644 sdk/keyvault/azcertificates/testdata/recordings/TestOperationCRUD.json delete mode 100644 sdk/keyvault/azcertificates/testdata/recordings/TestUpdateCertificatePolicy.json delete mode 100644 sdk/keyvault/azcertificates/time_unix.go delete mode 100644 sdk/keyvault/azcertificates/utils_test.go delete mode 100644 sdk/keyvault/azcertificates/version.go delete mode 100644 sdk/keyvault/azkeys/CHANGELOG.md delete mode 100644 sdk/keyvault/azkeys/LICENSE.txt delete mode 100644 sdk/keyvault/azkeys/README.md delete mode 100644 sdk/keyvault/azkeys/TROUBLESHOOTING.md delete mode 100644 sdk/keyvault/azkeys/autorest.md delete mode 100644 sdk/keyvault/azkeys/client.go delete mode 100644 sdk/keyvault/azkeys/client_test.go delete mode 100644 sdk/keyvault/azkeys/constants.go delete mode 100644 sdk/keyvault/azkeys/custom_client.go delete mode 100644 sdk/keyvault/azkeys/example_test.go delete mode 100644 sdk/keyvault/azkeys/go.mod delete mode 100644 sdk/keyvault/azkeys/go.sum delete mode 100644 sdk/keyvault/azkeys/models.go delete mode 100644 sdk/keyvault/azkeys/models_serde.go delete mode 100644 sdk/keyvault/azkeys/platform-matrix.json delete mode 100644 sdk/keyvault/azkeys/response_types.go delete mode 100644 sdk/keyvault/azkeys/test-resources-post.ps1 delete mode 100644 sdk/keyvault/azkeys/test-resources.json delete mode 100644 sdk/keyvault/azkeys/testdata/perf/decrypt.go delete mode 100644 sdk/keyvault/azkeys/testdata/perf/get_key.go delete mode 100644 sdk/keyvault/azkeys/testdata/perf/go.mod delete mode 100644 sdk/keyvault/azkeys/testdata/perf/go.sum delete mode 100644 sdk/keyvault/azkeys/testdata/perf/main.go delete mode 100644 sdk/keyvault/azkeys/testdata/perf/sign.go delete mode 100644 sdk/keyvault/azkeys/testdata/perf/unwrap.go delete mode 100644 sdk/keyvault/azkeys/testdata/recordings/TestBackupRestore/KV.json delete mode 100644 sdk/keyvault/azkeys/testdata/recordings/TestBackupRestore/MHSM.json delete mode 100644 sdk/keyvault/azkeys/testdata/recordings/TestCRUD/EC.json delete mode 100644 sdk/keyvault/azkeys/testdata/recordings/TestCRUD/EC_MHSM.json delete mode 100644 sdk/keyvault/azkeys/testdata/recordings/TestCRUD/RSA.json delete mode 100644 sdk/keyvault/azkeys/testdata/recordings/TestCRUD/RSA_MHSM.json delete mode 100644 sdk/keyvault/azkeys/testdata/recordings/TestEncryptDecrypt/KV.json delete mode 100644 sdk/keyvault/azkeys/testdata/recordings/TestEncryptDecrypt/MHSM.json delete mode 100644 sdk/keyvault/azkeys/testdata/recordings/TestEncryptDecryptSymmetric.json delete mode 100644 sdk/keyvault/azkeys/testdata/recordings/TestGetRandomBytes.json delete mode 100644 sdk/keyvault/azkeys/testdata/recordings/TestImportKey/KV.json delete mode 100644 sdk/keyvault/azkeys/testdata/recordings/TestImportKey/MHSM.json delete mode 100644 sdk/keyvault/azkeys/testdata/recordings/TestListDeletedKeys/KV.json delete mode 100644 sdk/keyvault/azkeys/testdata/recordings/TestListDeletedKeys/MHSM.json delete mode 100644 sdk/keyvault/azkeys/testdata/recordings/TestListKeyVersions/KV.json delete mode 100644 sdk/keyvault/azkeys/testdata/recordings/TestListKeyVersions/MHSM.json delete mode 100644 sdk/keyvault/azkeys/testdata/recordings/TestListKeys/KV.json delete mode 100644 sdk/keyvault/azkeys/testdata/recordings/TestListKeys/MHSM.json delete mode 100644 sdk/keyvault/azkeys/testdata/recordings/TestRecoverDeletedKey/KV.json delete mode 100644 sdk/keyvault/azkeys/testdata/recordings/TestRecoverDeletedKey/MHSM.json delete mode 100644 sdk/keyvault/azkeys/testdata/recordings/TestReleaseKey/KV.json delete mode 100644 sdk/keyvault/azkeys/testdata/recordings/TestReleaseKey/MHSM.json delete mode 100644 sdk/keyvault/azkeys/testdata/recordings/TestRotateKey/KV.json delete mode 100644 sdk/keyvault/azkeys/testdata/recordings/TestRotateKey/MHSM.json delete mode 100644 sdk/keyvault/azkeys/testdata/recordings/TestSignVerify/KV.json delete mode 100644 sdk/keyvault/azkeys/testdata/recordings/TestSignVerify/MHSM.json delete mode 100644 sdk/keyvault/azkeys/testdata/recordings/TestWrapUnwrap/KV.json delete mode 100644 sdk/keyvault/azkeys/testdata/recordings/TestWrapUnwrap/MHSM.json delete mode 100644 sdk/keyvault/azkeys/utils_test.go delete mode 100644 sdk/keyvault/azsecrets/CHANGELOG.md delete mode 100644 sdk/keyvault/azsecrets/LICENSE.txt delete mode 100644 sdk/keyvault/azsecrets/README.md delete mode 100644 sdk/keyvault/azsecrets/TROUBLESHOOTING.md delete mode 100644 sdk/keyvault/azsecrets/autorest.md delete mode 100644 sdk/keyvault/azsecrets/client.go delete mode 100644 sdk/keyvault/azsecrets/client_test.go delete mode 100644 sdk/keyvault/azsecrets/constants.go delete mode 100644 sdk/keyvault/azsecrets/custom_client.go delete mode 100644 sdk/keyvault/azsecrets/example_test.go delete mode 100644 sdk/keyvault/azsecrets/go.mod delete mode 100644 sdk/keyvault/azsecrets/go.sum delete mode 100644 sdk/keyvault/azsecrets/models.go delete mode 100644 sdk/keyvault/azsecrets/models_serde.go delete mode 100644 sdk/keyvault/azsecrets/response_types.go delete mode 100644 sdk/keyvault/azsecrets/test-resources.json delete mode 100644 sdk/keyvault/azsecrets/testdata/perf/get_secret.go delete mode 100644 sdk/keyvault/azsecrets/testdata/perf/go.mod delete mode 100644 sdk/keyvault/azsecrets/testdata/perf/go.sum delete mode 100644 sdk/keyvault/azsecrets/testdata/perf/list_secrets.go delete mode 100644 sdk/keyvault/azsecrets/testdata/perf/main.go delete mode 100644 sdk/keyvault/azsecrets/testdata/recordings/TestBackupRestore.json delete mode 100644 sdk/keyvault/azsecrets/testdata/recordings/TestCRUD.json delete mode 100644 sdk/keyvault/azsecrets/testdata/recordings/TestListDeletedSecrets.json delete mode 100644 sdk/keyvault/azsecrets/testdata/recordings/TestListSecretVersions.json delete mode 100644 sdk/keyvault/azsecrets/testdata/recordings/TestListSecrets.json delete mode 100644 sdk/keyvault/azsecrets/testdata/recordings/TestRecover.json delete mode 100644 sdk/keyvault/azsecrets/time_unix.go delete mode 100644 sdk/keyvault/azsecrets/utils_test.go delete mode 100644 sdk/keyvault/internal/CHANGELOG.md delete mode 100644 sdk/keyvault/internal/LICENSE.txt delete mode 100644 sdk/keyvault/internal/README.md delete mode 100644 sdk/keyvault/internal/challenge_policy.go delete mode 100644 sdk/keyvault/internal/challenge_policy_test.go delete mode 100644 sdk/keyvault/internal/go.mod delete mode 100644 sdk/keyvault/internal/go.sum delete mode 100644 sdk/keyvault/internal/parse.go delete mode 100644 sdk/keyvault/internal/parse_test.go create mode 100644 sdk/messaging/azeventgrid/CHANGELOG.md create mode 100644 sdk/messaging/azeventgrid/LICENSE.txt create mode 100644 sdk/messaging/azeventgrid/NOTICE.txt create mode 100644 sdk/messaging/azeventgrid/README.md create mode 100644 sdk/messaging/azeventgrid/assets.json create mode 100644 sdk/messaging/azeventgrid/autorest.md rename sdk/{keyvault/azkeys => messaging/azeventgrid}/build.go (82%) create mode 100644 sdk/messaging/azeventgrid/ci.yml create mode 100644 sdk/messaging/azeventgrid/client.go create mode 100644 sdk/messaging/azeventgrid/client_custom.go create mode 100644 sdk/messaging/azeventgrid/client_test.go create mode 100644 sdk/messaging/azeventgrid/example_publish_and_receive_test.go create mode 100644 sdk/messaging/azeventgrid/example_test.go create mode 100644 sdk/messaging/azeventgrid/go.mod create mode 100644 sdk/messaging/azeventgrid/go.sum create mode 100644 sdk/messaging/azeventgrid/main_test.go create mode 100644 sdk/messaging/azeventgrid/models.go create mode 100644 sdk/messaging/azeventgrid/models_serde.go create mode 100644 sdk/messaging/azeventgrid/options.go create mode 100644 sdk/messaging/azeventgrid/response_types.go create mode 100644 sdk/messaging/azeventgrid/sample.env create mode 100644 sdk/messaging/azeventgrid/shared_test.go create mode 100644 sdk/messaging/azeventgrid/test-resources.bicep create mode 100644 sdk/messaging/azeventgrid/time_rfc3339.go create mode 100644 sdk/messaging/azeventgrid/version.go create mode 100644 sdk/messaging/azeventhubs/internal/amqpwrap/error.go create mode 100644 sdk/messaging/azeventhubs/internal/eh/stress/readme.md create mode 100644 sdk/messaging/azeventhubs/internal/links_recover.go rename sdk/messaging/azeventhubs/internal/{eh.go => namespace_eh.go} (100%) create mode 100644 sdk/messaging/azeventhubs/internal/test/mock_helpers.go create mode 100644 sdk/messaging/azservicebus/internal/stress/readme.md delete mode 100644 sdk/messaging/azservicebus/internal/utils/sync.go create mode 100644 sdk/monitor/azingest/CHANGELOG.md create mode 100644 sdk/monitor/azingest/LICENSE.txt create mode 100644 sdk/monitor/azingest/README.md create mode 100644 sdk/monitor/azingest/assets.json create mode 100644 sdk/monitor/azingest/autorest.md rename sdk/{keyvault/azcertificates => monitor/azingest}/build.go (75%) create mode 100644 sdk/monitor/azingest/ci.yml create mode 100644 sdk/monitor/azingest/client.go create mode 100644 sdk/monitor/azingest/client_test.go create mode 100644 sdk/monitor/azingest/custom_client.go create mode 100644 sdk/monitor/azingest/example_test.go create mode 100644 sdk/monitor/azingest/go.mod create mode 100644 sdk/monitor/azingest/go.sum create mode 100644 sdk/monitor/azingest/models.go create mode 100644 sdk/monitor/azingest/response_types.go create mode 100644 sdk/monitor/azingest/test-resources.bicep create mode 100644 sdk/monitor/azingest/utils_test.go create mode 100644 sdk/monitor/azingest/version.go create mode 100644 sdk/resourcemanager/advisor/armadvisor/advisor_live_test.go create mode 100644 sdk/resourcemanager/advisor/armadvisor/assets.json create mode 100644 sdk/resourcemanager/alertsmanagement/armalertsmanagement/alertsmanagement_live_test.go create mode 100644 sdk/resourcemanager/alertsmanagement/armalertsmanagement/assets.json create mode 100644 sdk/resourcemanager/analysisservices/armanalysisservices/analysisservices_live_test.go create mode 100644 sdk/resourcemanager/analysisservices/armanalysisservices/assets.json create mode 100644 sdk/resourcemanager/appcontainers/armappcontainers/availableworkloadprofiles_client.go create mode 100644 sdk/resourcemanager/appcontainers/armappcontainers/availableworkloadprofiles_client_example_test.go create mode 100644 sdk/resourcemanager/appcontainers/armappcontainers/billingmeters_client.go create mode 100644 sdk/resourcemanager/appcontainers/armappcontainers/billingmeters_client_example_test.go create mode 100644 sdk/resourcemanager/appcontainers/armappcontainers/connectedenvironments_client.go create mode 100644 sdk/resourcemanager/appcontainers/armappcontainers/connectedenvironments_client_example_test.go create mode 100644 sdk/resourcemanager/appcontainers/armappcontainers/connectedenvironmentscertificates_client.go create mode 100644 sdk/resourcemanager/appcontainers/armappcontainers/connectedenvironmentscertificates_client_example_test.go create mode 100644 sdk/resourcemanager/appcontainers/armappcontainers/connectedenvironmentsdaprcomponents_client.go create mode 100644 sdk/resourcemanager/appcontainers/armappcontainers/connectedenvironmentsdaprcomponents_client_example_test.go create mode 100644 sdk/resourcemanager/appcontainers/armappcontainers/connectedenvironmentsstorages_client.go create mode 100644 sdk/resourcemanager/appcontainers/armappcontainers/connectedenvironmentsstorages_client_example_test.go create mode 100644 sdk/resourcemanager/appcontainers/armappcontainers/containerappsdiagnostics_client.go create mode 100644 sdk/resourcemanager/appcontainers/armappcontainers/containerappsdiagnostics_client_example_test.go create mode 100644 sdk/resourcemanager/appcontainers/armappcontainers/jobs_client.go create mode 100644 sdk/resourcemanager/appcontainers/armappcontainers/jobs_client_example_test.go create mode 100644 sdk/resourcemanager/appcontainers/armappcontainers/jobsexecutions_client.go create mode 100644 sdk/resourcemanager/appcontainers/armappcontainers/jobsexecutions_client_example_test.go create mode 100644 sdk/resourcemanager/appcontainers/armappcontainers/managedcertificates_client.go create mode 100644 sdk/resourcemanager/appcontainers/armappcontainers/managedcertificates_client_example_test.go create mode 100644 sdk/resourcemanager/appcontainers/armappcontainers/managedenvironmentdiagnostics_client.go create mode 100644 sdk/resourcemanager/appcontainers/armappcontainers/managedenvironmentdiagnostics_client_example_test.go create mode 100644 sdk/resourcemanager/appcontainers/armappcontainers/managedenvironmentsdiagnostics_client.go create mode 100644 sdk/resourcemanager/appcontainers/armappcontainers/managedenvironmentsdiagnostics_client_example_test.go create mode 100644 sdk/resourcemanager/appplatform/armappplatform/appplatform_live_test.go create mode 100644 sdk/resourcemanager/appplatform/armappplatform/assets.json create mode 100644 sdk/resourcemanager/appplatform/armappplatform/configservices_live_test.go create mode 100644 sdk/resourcemanager/authorization/armauthorization/accessreviewdefaultsettings_client.go create mode 100644 sdk/resourcemanager/authorization/armauthorization/accessreviewhistorydefinition_client.go create mode 100644 sdk/resourcemanager/authorization/armauthorization/accessreviewhistorydefinitioninstance_client.go create mode 100644 sdk/resourcemanager/authorization/armauthorization/accessreviewhistorydefinitioninstances_client.go create mode 100644 sdk/resourcemanager/authorization/armauthorization/accessreviewhistorydefinitions_client.go create mode 100644 sdk/resourcemanager/authorization/armauthorization/accessreviewinstance_client.go create mode 100644 sdk/resourcemanager/authorization/armauthorization/accessreviewinstance_client_example_test.go create mode 100644 sdk/resourcemanager/authorization/armauthorization/accessreviewinstancecontactedreviewers_client.go create mode 100644 sdk/resourcemanager/authorization/armauthorization/accessreviewinstancedecisions_client.go create mode 100644 sdk/resourcemanager/authorization/armauthorization/accessreviewinstancemydecisions_client.go create mode 100644 sdk/resourcemanager/authorization/armauthorization/accessreviewinstancemydecisions_client_example_test.go create mode 100644 sdk/resourcemanager/authorization/armauthorization/accessreviewinstances_client.go create mode 100644 sdk/resourcemanager/authorization/armauthorization/accessreviewinstancesassignedformyapproval_client.go create mode 100644 sdk/resourcemanager/authorization/armauthorization/accessreviewinstancesassignedformyapproval_client_example_test.go create mode 100644 sdk/resourcemanager/authorization/armauthorization/accessreviewscheduledefinitions_client.go create mode 100644 sdk/resourcemanager/authorization/armauthorization/accessreviewscheduledefinitionsassignedformyapproval_client.go create mode 100644 sdk/resourcemanager/authorization/armauthorization/accessreviewscheduledefinitionsassignedformyapproval_client_example_test.go create mode 100644 sdk/resourcemanager/authorization/armauthorization/alertconfigurations_client.go create mode 100644 sdk/resourcemanager/authorization/armauthorization/alertconfigurations_client_example_test.go create mode 100644 sdk/resourcemanager/authorization/armauthorization/alertdefinitions_client.go create mode 100644 sdk/resourcemanager/authorization/armauthorization/alertdefinitions_client_example_test.go create mode 100644 sdk/resourcemanager/authorization/armauthorization/alertincidents_client.go create mode 100644 sdk/resourcemanager/authorization/armauthorization/alertincidents_client_example_test.go create mode 100644 sdk/resourcemanager/authorization/armauthorization/alertoperation_client.go create mode 100644 sdk/resourcemanager/authorization/armauthorization/alertoperation_client_example_test.go create mode 100644 sdk/resourcemanager/authorization/armauthorization/alerts_client.go create mode 100644 sdk/resourcemanager/authorization/armauthorization/alerts_client_example_test.go create mode 100644 sdk/resourcemanager/authorization/armauthorization/operations_client.go create mode 100644 sdk/resourcemanager/authorization/armauthorization/scopeaccessreviewdefaultsettings_client.go create mode 100644 sdk/resourcemanager/authorization/armauthorization/scopeaccessreviewdefaultsettings_client_example_test.go create mode 100644 sdk/resourcemanager/authorization/armauthorization/scopeaccessreviewhistorydefinition_client.go create mode 100644 sdk/resourcemanager/authorization/armauthorization/scopeaccessreviewhistorydefinition_client_example_test.go create mode 100644 sdk/resourcemanager/authorization/armauthorization/scopeaccessreviewhistorydefinitioninstance_client.go create mode 100644 sdk/resourcemanager/authorization/armauthorization/scopeaccessreviewhistorydefinitioninstance_client_example_test.go create mode 100644 sdk/resourcemanager/authorization/armauthorization/scopeaccessreviewhistorydefinitioninstances_client.go create mode 100644 sdk/resourcemanager/authorization/armauthorization/scopeaccessreviewhistorydefinitioninstances_client_example_test.go create mode 100644 sdk/resourcemanager/authorization/armauthorization/scopeaccessreviewhistorydefinitions_client.go create mode 100644 sdk/resourcemanager/authorization/armauthorization/scopeaccessreviewhistorydefinitions_client_example_test.go create mode 100644 sdk/resourcemanager/authorization/armauthorization/scopeaccessreviewinstance_client.go create mode 100644 sdk/resourcemanager/authorization/armauthorization/scopeaccessreviewinstance_client_example_test.go create mode 100644 sdk/resourcemanager/authorization/armauthorization/scopeaccessreviewinstancecontactedreviewers_client.go create mode 100644 sdk/resourcemanager/authorization/armauthorization/scopeaccessreviewinstancecontactedreviewers_client_example_test.go create mode 100644 sdk/resourcemanager/authorization/armauthorization/scopeaccessreviewinstancedecisions_client.go create mode 100644 sdk/resourcemanager/authorization/armauthorization/scopeaccessreviewinstancedecisions_client_example_test.go create mode 100644 sdk/resourcemanager/authorization/armauthorization/scopeaccessreviewinstances_client.go create mode 100644 sdk/resourcemanager/authorization/armauthorization/scopeaccessreviewinstances_client_example_test.go create mode 100644 sdk/resourcemanager/authorization/armauthorization/scopeaccessreviewscheduledefinitions_client.go create mode 100644 sdk/resourcemanager/authorization/armauthorization/scopeaccessreviewscheduledefinitions_client_example_test.go create mode 100644 sdk/resourcemanager/authorization/armauthorization/tenantlevelaccessreviewinstancecontactedreviewers_client.go create mode 100644 sdk/resourcemanager/authorization/armauthorization/tenantlevelaccessreviewinstancecontactedreviewers_client_example_test.go create mode 100644 sdk/resourcemanager/batch/armbatch/assets.json create mode 100644 sdk/resourcemanager/batch/armbatch/batchmanagement_live_test.go create mode 100644 sdk/resourcemanager/botservice/armbotservice/assets.json create mode 100644 sdk/resourcemanager/botservice/armbotservice/botservice_live_test.go rename sdk/resourcemanager/{containerservice/armcontainerservice/trustedaccessroles_client.go => cognitiveservices/armcognitiveservices/models_client.go} (52%) create mode 100644 sdk/resourcemanager/cognitiveservices/armcognitiveservices/models_client_example_test.go create mode 100644 sdk/resourcemanager/cognitiveservices/armcognitiveservices/usages_client.go create mode 100644 sdk/resourcemanager/cognitiveservices/armcognitiveservices/usages_client_example_test.go create mode 100644 sdk/resourcemanager/compute/armcompute/fake/availabilitysets_server.go create mode 100644 sdk/resourcemanager/compute/armcompute/fake/capacityreservationgroups_server.go create mode 100644 sdk/resourcemanager/compute/armcompute/fake/capacityreservations_server.go create mode 100644 sdk/resourcemanager/compute/armcompute/fake/cloudserviceoperatingsystems_server.go create mode 100644 sdk/resourcemanager/compute/armcompute/fake/cloudserviceroleinstances_server.go create mode 100644 sdk/resourcemanager/compute/armcompute/fake/cloudserviceroles_server.go create mode 100644 sdk/resourcemanager/compute/armcompute/fake/cloudservices_server.go create mode 100644 sdk/resourcemanager/compute/armcompute/fake/cloudservicesupdatedomain_server.go create mode 100644 sdk/resourcemanager/compute/armcompute/fake/communitygalleries_server.go create mode 100644 sdk/resourcemanager/compute/armcompute/fake/communitygalleryimages_server.go create mode 100644 sdk/resourcemanager/compute/armcompute/fake/communitygalleryimageversions_server.go create mode 100644 sdk/resourcemanager/compute/armcompute/fake/dedicatedhostgroups_server.go create mode 100644 sdk/resourcemanager/compute/armcompute/fake/dedicatedhosts_server.go create mode 100644 sdk/resourcemanager/compute/armcompute/fake/diskaccesses_server.go create mode 100644 sdk/resourcemanager/compute/armcompute/fake/diskencryptionsets_server.go create mode 100644 sdk/resourcemanager/compute/armcompute/fake/diskrestorepoint_server.go create mode 100644 sdk/resourcemanager/compute/armcompute/fake/disks_server.go create mode 100644 sdk/resourcemanager/compute/armcompute/fake/galleries_server.go create mode 100644 sdk/resourcemanager/compute/armcompute/fake/galleryapplications_server.go create mode 100644 sdk/resourcemanager/compute/armcompute/fake/galleryapplicationversions_server.go create mode 100644 sdk/resourcemanager/compute/armcompute/fake/galleryimages_server.go create mode 100644 sdk/resourcemanager/compute/armcompute/fake/galleryimageversions_server.go create mode 100644 sdk/resourcemanager/compute/armcompute/fake/gallerysharingprofile_server.go create mode 100644 sdk/resourcemanager/compute/armcompute/fake/images_server.go create mode 100644 sdk/resourcemanager/compute/armcompute/fake/internal.go create mode 100644 sdk/resourcemanager/compute/armcompute/fake/loganalytics_server.go create mode 100644 sdk/resourcemanager/compute/armcompute/fake/operations_server.go create mode 100644 sdk/resourcemanager/compute/armcompute/fake/proximityplacementgroups_server.go create mode 100644 sdk/resourcemanager/compute/armcompute/fake/resourceskus_server.go create mode 100644 sdk/resourcemanager/compute/armcompute/fake/restorepointcollections_server.go create mode 100644 sdk/resourcemanager/compute/armcompute/fake/restorepoints_server.go create mode 100644 sdk/resourcemanager/compute/armcompute/fake/sharedgalleries_server.go create mode 100644 sdk/resourcemanager/compute/armcompute/fake/sharedgalleryimages_server.go create mode 100644 sdk/resourcemanager/compute/armcompute/fake/sharedgalleryimageversions_server.go create mode 100644 sdk/resourcemanager/compute/armcompute/fake/snapshots_server.go create mode 100644 sdk/resourcemanager/compute/armcompute/fake/sshpublickeys_server.go create mode 100644 sdk/resourcemanager/compute/armcompute/fake/time_rfc3339.go create mode 100644 sdk/resourcemanager/compute/armcompute/fake/usage_server.go create mode 100644 sdk/resourcemanager/compute/armcompute/fake/virtualmachineextensionimages_server.go create mode 100644 sdk/resourcemanager/compute/armcompute/fake/virtualmachineextensions_server.go create mode 100644 sdk/resourcemanager/compute/armcompute/fake/virtualmachineimages_server.go create mode 100644 sdk/resourcemanager/compute/armcompute/fake/virtualmachineimagesedgezone_server.go create mode 100644 sdk/resourcemanager/compute/armcompute/fake/virtualmachineruncommands_server.go create mode 100644 sdk/resourcemanager/compute/armcompute/fake/virtualmachines_server.go create mode 100644 sdk/resourcemanager/compute/armcompute/fake/virtualmachinescalesetextensions_server.go create mode 100644 sdk/resourcemanager/compute/armcompute/fake/virtualmachinescalesetrollingupgrades_server.go create mode 100644 sdk/resourcemanager/compute/armcompute/fake/virtualmachinescalesets_server.go create mode 100644 sdk/resourcemanager/compute/armcompute/fake/virtualmachinescalesetvmextensions_server.go create mode 100644 sdk/resourcemanager/compute/armcompute/fake/virtualmachinescalesetvmruncommands_server.go create mode 100644 sdk/resourcemanager/compute/armcompute/fake/virtualmachinescalesetvms_server.go create mode 100644 sdk/resourcemanager/compute/armcompute/fake/virtualmachinesizes_server.go create mode 100644 sdk/resourcemanager/compute/armcompute/fake_example_test.go create mode 100644 sdk/resourcemanager/compute/armcompute/options.go create mode 100644 sdk/resourcemanager/containerregistry/armcontainerregistry/fake/agentpools_server.go create mode 100644 sdk/resourcemanager/containerregistry/armcontainerregistry/fake/cacherules_server.go create mode 100644 sdk/resourcemanager/containerregistry/armcontainerregistry/fake/connectedregistries_server.go create mode 100644 sdk/resourcemanager/containerregistry/armcontainerregistry/fake/credentialsets_server.go create mode 100644 sdk/resourcemanager/containerregistry/armcontainerregistry/fake/exportpipelines_server.go create mode 100644 sdk/resourcemanager/containerregistry/armcontainerregistry/fake/importpipelines_server.go create mode 100644 sdk/resourcemanager/containerregistry/armcontainerregistry/fake/internal.go create mode 100644 sdk/resourcemanager/containerregistry/armcontainerregistry/fake/operations_server.go create mode 100644 sdk/resourcemanager/containerregistry/armcontainerregistry/fake/pipelineruns_server.go create mode 100644 sdk/resourcemanager/containerregistry/armcontainerregistry/fake/polymorphic_helpers.go create mode 100644 sdk/resourcemanager/containerregistry/armcontainerregistry/fake/privateendpointconnections_server.go create mode 100644 sdk/resourcemanager/containerregistry/armcontainerregistry/fake/registries_server.go create mode 100644 sdk/resourcemanager/containerregistry/armcontainerregistry/fake/replications_server.go create mode 100644 sdk/resourcemanager/containerregistry/armcontainerregistry/fake/runs_server.go create mode 100644 sdk/resourcemanager/containerregistry/armcontainerregistry/fake/scopemaps_server.go create mode 100644 sdk/resourcemanager/containerregistry/armcontainerregistry/fake/taskruns_server.go create mode 100644 sdk/resourcemanager/containerregistry/armcontainerregistry/fake/tasks_server.go create mode 100644 sdk/resourcemanager/containerregistry/armcontainerregistry/fake/time_rfc3339.go create mode 100644 sdk/resourcemanager/containerregistry/armcontainerregistry/fake/tokens_server.go create mode 100644 sdk/resourcemanager/containerregistry/armcontainerregistry/fake/webhooks_server.go create mode 100644 sdk/resourcemanager/containerregistry/armcontainerregistry/fake_example_test.go create mode 100644 sdk/resourcemanager/containerregistry/armcontainerregistry/interfaces.go create mode 100644 sdk/resourcemanager/containerregistry/armcontainerregistry/options.go create mode 100644 sdk/resourcemanager/containerservice/armcontainerservice/fake/agentpools_server.go rename sdk/{keyvault/azkeys/time_unix.go => resourcemanager/containerservice/armcontainerservice/fake/date_type.go} (54%) create mode 100644 sdk/resourcemanager/containerservice/armcontainerservice/fake/internal.go create mode 100644 sdk/resourcemanager/containerservice/armcontainerservice/fake/maintenanceconfigurations_server.go create mode 100644 sdk/resourcemanager/containerservice/armcontainerservice/fake/managedclusters_server.go create mode 100644 sdk/resourcemanager/containerservice/armcontainerservice/fake/operations_server.go create mode 100644 sdk/resourcemanager/containerservice/armcontainerservice/fake/privateendpointconnections_server.go create mode 100644 sdk/resourcemanager/containerservice/armcontainerservice/fake/privatelinkresources_server.go create mode 100644 sdk/resourcemanager/containerservice/armcontainerservice/fake/resolveprivatelinkserviceid_server.go create mode 100644 sdk/resourcemanager/containerservice/armcontainerservice/fake/snapshots_server.go create mode 100644 sdk/resourcemanager/containerservice/armcontainerservice/fake/time_rfc3339.go create mode 100644 sdk/resourcemanager/containerservice/armcontainerservice/fake_example_test.go delete mode 100644 sdk/resourcemanager/containerservice/armcontainerservice/managedclustersnapshots_client.go delete mode 100644 sdk/resourcemanager/containerservice/armcontainerservice/managedclustersnapshots_client_example_test.go create mode 100644 sdk/resourcemanager/containerservice/armcontainerservice/options.go delete mode 100644 sdk/resourcemanager/containerservice/armcontainerservice/trustedaccessrolebindings_client.go delete mode 100644 sdk/resourcemanager/containerservice/armcontainerservice/trustedaccessrolebindings_client_example_test.go create mode 100644 sdk/resourcemanager/containerservicefleet/armcontainerservicefleet/CHANGELOG.md create mode 100644 sdk/resourcemanager/containerservicefleet/armcontainerservicefleet/LICENSE.txt create mode 100644 sdk/resourcemanager/containerservicefleet/armcontainerservicefleet/README.md create mode 100644 sdk/resourcemanager/containerservicefleet/armcontainerservicefleet/autorest.md create mode 100644 sdk/resourcemanager/containerservicefleet/armcontainerservicefleet/build.go rename sdk/{keyvault/azkeys => resourcemanager/containerservicefleet/armcontainerservicefleet}/ci.yml (56%) create mode 100644 sdk/resourcemanager/containerservicefleet/armcontainerservicefleet/client_factory.go create mode 100644 sdk/resourcemanager/containerservicefleet/armcontainerservicefleet/constants.go create mode 100644 sdk/resourcemanager/containerservicefleet/armcontainerservicefleet/fleetmembers_client.go create mode 100644 sdk/resourcemanager/containerservicefleet/armcontainerservicefleet/fleetmembers_client_example_test.go create mode 100644 sdk/resourcemanager/containerservicefleet/armcontainerservicefleet/fleets_client.go create mode 100644 sdk/resourcemanager/containerservicefleet/armcontainerservicefleet/fleets_client_example_test.go create mode 100644 sdk/resourcemanager/containerservicefleet/armcontainerservicefleet/go.mod create mode 100644 sdk/resourcemanager/containerservicefleet/armcontainerservicefleet/go.sum create mode 100644 sdk/resourcemanager/containerservicefleet/armcontainerservicefleet/models.go create mode 100644 sdk/resourcemanager/containerservicefleet/armcontainerservicefleet/models_serde.go create mode 100644 sdk/resourcemanager/containerservicefleet/armcontainerservicefleet/operations_client.go rename sdk/resourcemanager/{containerservice/armcontainerservice/trustedaccessroles_client_example_test.go => containerservicefleet/armcontainerservicefleet/operations_client_example_test.go} (52%) create mode 100644 sdk/resourcemanager/containerservicefleet/armcontainerservicefleet/response_types.go create mode 100644 sdk/resourcemanager/containerservicefleet/armcontainerservicefleet/time_rfc3339.go create mode 100644 sdk/resourcemanager/containerservicefleet/armcontainerservicefleet/updateruns_client.go create mode 100644 sdk/resourcemanager/containerservicefleet/armcontainerservicefleet/updateruns_client_example_test.go create mode 100644 sdk/resourcemanager/cosmos/armcosmos/datatransferjobs_client.go create mode 100644 sdk/resourcemanager/cosmos/armcosmos/datatransferjobs_client_example_test.go create mode 100644 sdk/resourcemanager/cosmos/armcosmos/graphresources_client.go create mode 100644 sdk/resourcemanager/cosmos/armcosmos/graphresources_client_example_test.go create mode 100644 sdk/resourcemanager/cosmos/armcosmos/mongoclusters_client.go create mode 100644 sdk/resourcemanager/cosmos/armcosmos/mongoclusters_client_example_test.go create mode 100644 sdk/resourcemanager/cosmosforpostgresql/armcosmosforpostgresql/CHANGELOG.md create mode 100644 sdk/resourcemanager/cosmosforpostgresql/armcosmosforpostgresql/LICENSE.txt create mode 100644 sdk/resourcemanager/cosmosforpostgresql/armcosmosforpostgresql/README.md create mode 100644 sdk/resourcemanager/cosmosforpostgresql/armcosmosforpostgresql/assets.json create mode 100644 sdk/resourcemanager/cosmosforpostgresql/armcosmosforpostgresql/autorest.md create mode 100644 sdk/resourcemanager/cosmosforpostgresql/armcosmosforpostgresql/build.go create mode 100644 sdk/resourcemanager/cosmosforpostgresql/armcosmosforpostgresql/ci.yml create mode 100644 sdk/resourcemanager/cosmosforpostgresql/armcosmosforpostgresql/client_factory.go create mode 100644 sdk/resourcemanager/cosmosforpostgresql/armcosmosforpostgresql/clusters_client.go create mode 100644 sdk/resourcemanager/cosmosforpostgresql/armcosmosforpostgresql/clusters_client_example_test.go create mode 100644 sdk/resourcemanager/cosmosforpostgresql/armcosmosforpostgresql/configurations_client.go create mode 100644 sdk/resourcemanager/cosmosforpostgresql/armcosmosforpostgresql/configurations_client_example_test.go create mode 100644 sdk/resourcemanager/cosmosforpostgresql/armcosmosforpostgresql/constants.go create mode 100644 sdk/resourcemanager/cosmosforpostgresql/armcosmosforpostgresql/firewallrules_client.go create mode 100644 sdk/resourcemanager/cosmosforpostgresql/armcosmosforpostgresql/firewallrules_client_example_test.go create mode 100644 sdk/resourcemanager/cosmosforpostgresql/armcosmosforpostgresql/go.mod create mode 100644 sdk/resourcemanager/cosmosforpostgresql/armcosmosforpostgresql/go.sum create mode 100644 sdk/resourcemanager/cosmosforpostgresql/armcosmosforpostgresql/models.go create mode 100644 sdk/resourcemanager/cosmosforpostgresql/armcosmosforpostgresql/models_serde.go create mode 100644 sdk/resourcemanager/cosmosforpostgresql/armcosmosforpostgresql/operations_client.go create mode 100644 sdk/resourcemanager/cosmosforpostgresql/armcosmosforpostgresql/operations_client_example_test.go create mode 100644 sdk/resourcemanager/cosmosforpostgresql/armcosmosforpostgresql/postgresqlhsc_live_test.go create mode 100644 sdk/resourcemanager/cosmosforpostgresql/armcosmosforpostgresql/privateendpointconnections_client.go create mode 100644 sdk/resourcemanager/cosmosforpostgresql/armcosmosforpostgresql/privateendpointconnections_client_example_test.go create mode 100644 sdk/resourcemanager/cosmosforpostgresql/armcosmosforpostgresql/privatelinkresources_client.go create mode 100644 sdk/resourcemanager/cosmosforpostgresql/armcosmosforpostgresql/privatelinkresources_client_example_test.go create mode 100644 sdk/resourcemanager/cosmosforpostgresql/armcosmosforpostgresql/readreplica_live_test.go create mode 100644 sdk/resourcemanager/cosmosforpostgresql/armcosmosforpostgresql/response_types.go create mode 100644 sdk/resourcemanager/cosmosforpostgresql/armcosmosforpostgresql/roles_client.go create mode 100644 sdk/resourcemanager/cosmosforpostgresql/armcosmosforpostgresql/roles_client_example_test.go create mode 100644 sdk/resourcemanager/cosmosforpostgresql/armcosmosforpostgresql/servers_client.go create mode 100644 sdk/resourcemanager/cosmosforpostgresql/armcosmosforpostgresql/servers_client_example_test.go create mode 100644 sdk/resourcemanager/cosmosforpostgresql/armcosmosforpostgresql/time_rfc3339.go create mode 100644 sdk/resourcemanager/costmanagement/armcostmanagement/benefitrecommendations_client.go create mode 100644 sdk/resourcemanager/costmanagement/armcostmanagement/benefitrecommendations_client_example_test.go create mode 100644 sdk/resourcemanager/costmanagement/armcostmanagement/benefitutilizationsummaries_client.go create mode 100644 sdk/resourcemanager/costmanagement/armcostmanagement/benefitutilizationsummaries_client_example_test.go create mode 100644 sdk/resourcemanager/costmanagement/armcostmanagement/generatecostdetailsreport_client.go create mode 100644 sdk/resourcemanager/costmanagement/armcostmanagement/generatecostdetailsreport_client_example_test.go create mode 100644 sdk/resourcemanager/costmanagement/armcostmanagement/polymorphic_helpers.go create mode 100644 sdk/resourcemanager/costmanagement/armcostmanagement/pricesheet_client.go create mode 100644 sdk/resourcemanager/costmanagement/armcostmanagement/pricesheet_client_example_test.go create mode 100644 sdk/resourcemanager/costmanagement/armcostmanagement/scheduledactions_client.go create mode 100644 sdk/resourcemanager/costmanagement/armcostmanagement/scheduledactions_client_example_test.go create mode 100644 sdk/resourcemanager/databricks/armdatabricks/assets.json create mode 100644 sdk/resourcemanager/databricks/armdatabricks/databricks_live_test.go create mode 100644 sdk/resourcemanager/databricks/armdatabricks/vnetpeering_live_test.go create mode 100644 sdk/resourcemanager/datafactory/armdatafactory/assets.json create mode 100644 sdk/resourcemanager/datafactory/armdatafactory/datafactory_live_test.go create mode 100644 sdk/resourcemanager/datalake-store/armdatalakestore/account_live_test.go create mode 100644 sdk/resourcemanager/datalake-store/armdatalakestore/assets.json create mode 100644 sdk/resourcemanager/dataprotection/armdataprotection/dppresourceguardproxy_client.go create mode 100644 sdk/resourcemanager/dataprotection/armdataprotection/dppresourceguardproxy_client_example_test.go create mode 100644 sdk/resourcemanager/devcenter/armdevcenter/assets.json create mode 100644 sdk/resourcemanager/devcenter/armdevcenter/devcenter_live_test.go create mode 100644 sdk/resourcemanager/elastic/armelastic/versions_client.go create mode 100644 sdk/resourcemanager/elastic/armelastic/versions_client_example_test.go create mode 100644 sdk/resourcemanager/elasticsan/armelasticsan/privateendpointconnections_client.go create mode 100644 sdk/resourcemanager/elasticsan/armelasticsan/privateendpointconnections_client_example_test.go create mode 100644 sdk/resourcemanager/elasticsan/armelasticsan/privatelinkresources_client.go create mode 100644 sdk/resourcemanager/elasticsan/armelasticsan/privatelinkresources_client_example_test.go create mode 100644 sdk/resourcemanager/eventgrid/armeventgrid/cacertificates_client.go create mode 100644 sdk/resourcemanager/eventgrid/armeventgrid/cacertificates_client_example_test.go create mode 100644 sdk/resourcemanager/eventgrid/armeventgrid/clientgroups_client.go create mode 100644 sdk/resourcemanager/eventgrid/armeventgrid/clientgroups_client_example_test.go create mode 100644 sdk/resourcemanager/eventgrid/armeventgrid/clients_client.go create mode 100644 sdk/resourcemanager/eventgrid/armeventgrid/clients_client_example_test.go create mode 100644 sdk/resourcemanager/eventgrid/armeventgrid/namespaces_client.go create mode 100644 sdk/resourcemanager/eventgrid/armeventgrid/namespaces_client_example_test.go create mode 100644 sdk/resourcemanager/eventgrid/armeventgrid/namespacetopiceventsubscriptions_client.go create mode 100644 sdk/resourcemanager/eventgrid/armeventgrid/namespacetopiceventsubscriptions_client_example_test.go create mode 100644 sdk/resourcemanager/eventgrid/armeventgrid/namespacetopics_client.go create mode 100644 sdk/resourcemanager/eventgrid/armeventgrid/namespacetopics_client_example_test.go create mode 100644 sdk/resourcemanager/eventgrid/armeventgrid/partnerdestinations_client.go create mode 100644 sdk/resourcemanager/eventgrid/armeventgrid/partnerdestinations_client_example_test.go create mode 100644 sdk/resourcemanager/eventgrid/armeventgrid/permissionbindings_client.go create mode 100644 sdk/resourcemanager/eventgrid/armeventgrid/permissionbindings_client_example_test.go create mode 100644 sdk/resourcemanager/eventgrid/armeventgrid/topicspaces_client.go create mode 100644 sdk/resourcemanager/eventgrid/armeventgrid/topicspaces_client_example_test.go create mode 100644 sdk/resourcemanager/extendedlocation/armextendedlocation/resourcesyncrules_client.go create mode 100644 sdk/resourcemanager/extendedlocation/armextendedlocation/resourcesyncrules_client_example_test.go delete mode 100644 sdk/resourcemanager/graphservices/armgraphservices/account_client.go delete mode 100644 sdk/resourcemanager/graphservices/armgraphservices/account_client_example_test.go rename sdk/resourcemanager/graphservices/armgraphservices/{operation_client.go => operations_client.go} (55%) rename sdk/resourcemanager/graphservices/armgraphservices/{operation_client_example_test.go => operations_client_example_test.go} (89%) create mode 100644 sdk/resourcemanager/hdinsight/armhdinsight/operations_client_example_test.go create mode 100644 sdk/resourcemanager/iotfirmwaredefense/armiotfirmwaredefense/CHANGELOG.md create mode 100644 sdk/resourcemanager/iotfirmwaredefense/armiotfirmwaredefense/LICENSE.txt create mode 100644 sdk/resourcemanager/iotfirmwaredefense/armiotfirmwaredefense/README.md create mode 100644 sdk/resourcemanager/iotfirmwaredefense/armiotfirmwaredefense/autorest.md create mode 100644 sdk/resourcemanager/iotfirmwaredefense/armiotfirmwaredefense/build.go create mode 100644 sdk/resourcemanager/iotfirmwaredefense/armiotfirmwaredefense/ci.yml create mode 100644 sdk/resourcemanager/iotfirmwaredefense/armiotfirmwaredefense/client_factory.go create mode 100644 sdk/resourcemanager/iotfirmwaredefense/armiotfirmwaredefense/constants.go create mode 100644 sdk/resourcemanager/iotfirmwaredefense/armiotfirmwaredefense/firmware_client.go create mode 100644 sdk/resourcemanager/iotfirmwaredefense/armiotfirmwaredefense/firmware_client_example_test.go create mode 100644 sdk/resourcemanager/iotfirmwaredefense/armiotfirmwaredefense/go.mod create mode 100644 sdk/resourcemanager/iotfirmwaredefense/armiotfirmwaredefense/go.sum create mode 100644 sdk/resourcemanager/iotfirmwaredefense/armiotfirmwaredefense/models.go create mode 100644 sdk/resourcemanager/iotfirmwaredefense/armiotfirmwaredefense/models_serde.go create mode 100644 sdk/resourcemanager/iotfirmwaredefense/armiotfirmwaredefense/operations_client.go create mode 100644 sdk/resourcemanager/iotfirmwaredefense/armiotfirmwaredefense/operations_client_example_test.go create mode 100644 sdk/resourcemanager/iotfirmwaredefense/armiotfirmwaredefense/response_types.go create mode 100644 sdk/resourcemanager/iotfirmwaredefense/armiotfirmwaredefense/time_rfc3339.go create mode 100644 sdk/resourcemanager/iotfirmwaredefense/armiotfirmwaredefense/workspaces_client.go create mode 100644 sdk/resourcemanager/iotfirmwaredefense/armiotfirmwaredefense/workspaces_client_example_test.go create mode 100644 sdk/resourcemanager/iothub/armiothub/assets.json create mode 100644 sdk/resourcemanager/iothub/armiothub/iothub_live_test.go create mode 100644 sdk/resourcemanager/kusto/armkusto/database_client.go create mode 100644 sdk/resourcemanager/kusto/armkusto/database_client_example_test.go create mode 100644 sdk/resourcemanager/logic/armlogic/assets.json create mode 100644 sdk/resourcemanager/logic/armlogic/integrationaccounts_live_test.go create mode 100644 sdk/resourcemanager/logic/armlogic/operations_live_test.go create mode 100644 sdk/resourcemanager/logic/armlogic/workflows_live_test.go create mode 100644 sdk/resourcemanager/managednetworkfabric/armmanagednetworkfabric/CHANGELOG.md create mode 100644 sdk/resourcemanager/managednetworkfabric/armmanagednetworkfabric/LICENSE.txt create mode 100644 sdk/resourcemanager/managednetworkfabric/armmanagednetworkfabric/README.md create mode 100644 sdk/resourcemanager/managednetworkfabric/armmanagednetworkfabric/accesscontrollists_client.go create mode 100644 sdk/resourcemanager/managednetworkfabric/armmanagednetworkfabric/accesscontrollists_client_example_test.go create mode 100644 sdk/resourcemanager/managednetworkfabric/armmanagednetworkfabric/autorest.md create mode 100644 sdk/resourcemanager/managednetworkfabric/armmanagednetworkfabric/build.go create mode 100644 sdk/resourcemanager/managednetworkfabric/armmanagednetworkfabric/ci.yml create mode 100644 sdk/resourcemanager/managednetworkfabric/armmanagednetworkfabric/client_factory.go create mode 100644 sdk/resourcemanager/managednetworkfabric/armmanagednetworkfabric/constants.go create mode 100644 sdk/resourcemanager/managednetworkfabric/armmanagednetworkfabric/externalnetworks_client.go create mode 100644 sdk/resourcemanager/managednetworkfabric/armmanagednetworkfabric/externalnetworks_client_example_test.go create mode 100644 sdk/resourcemanager/managednetworkfabric/armmanagednetworkfabric/go.mod create mode 100644 sdk/resourcemanager/managednetworkfabric/armmanagednetworkfabric/go.sum create mode 100644 sdk/resourcemanager/managednetworkfabric/armmanagednetworkfabric/internalnetworks_client.go create mode 100644 sdk/resourcemanager/managednetworkfabric/armmanagednetworkfabric/internalnetworks_client_example_test.go create mode 100644 sdk/resourcemanager/managednetworkfabric/armmanagednetworkfabric/internetgatewayrules_client.go create mode 100644 sdk/resourcemanager/managednetworkfabric/armmanagednetworkfabric/internetgatewayrules_client_example_test.go create mode 100644 sdk/resourcemanager/managednetworkfabric/armmanagednetworkfabric/internetgateways_client.go create mode 100644 sdk/resourcemanager/managednetworkfabric/armmanagednetworkfabric/internetgateways_client_example_test.go create mode 100644 sdk/resourcemanager/managednetworkfabric/armmanagednetworkfabric/ipcommunities_client.go create mode 100644 sdk/resourcemanager/managednetworkfabric/armmanagednetworkfabric/ipcommunities_client_example_test.go create mode 100644 sdk/resourcemanager/managednetworkfabric/armmanagednetworkfabric/ipextendedcommunities_client.go create mode 100644 sdk/resourcemanager/managednetworkfabric/armmanagednetworkfabric/ipextendedcommunities_client_example_test.go create mode 100644 sdk/resourcemanager/managednetworkfabric/armmanagednetworkfabric/ipprefixes_client.go create mode 100644 sdk/resourcemanager/managednetworkfabric/armmanagednetworkfabric/ipprefixes_client_example_test.go create mode 100644 sdk/resourcemanager/managednetworkfabric/armmanagednetworkfabric/l2isolationdomains_client.go create mode 100644 sdk/resourcemanager/managednetworkfabric/armmanagednetworkfabric/l2isolationdomains_client_example_test.go create mode 100644 sdk/resourcemanager/managednetworkfabric/armmanagednetworkfabric/l3isolationdomains_client.go create mode 100644 sdk/resourcemanager/managednetworkfabric/armmanagednetworkfabric/l3isolationdomains_client_example_test.go create mode 100644 sdk/resourcemanager/managednetworkfabric/armmanagednetworkfabric/models.go create mode 100644 sdk/resourcemanager/managednetworkfabric/armmanagednetworkfabric/models_serde.go create mode 100644 sdk/resourcemanager/managednetworkfabric/armmanagednetworkfabric/neighborgroups_client.go create mode 100644 sdk/resourcemanager/managednetworkfabric/armmanagednetworkfabric/neighborgroups_client_example_test.go create mode 100644 sdk/resourcemanager/managednetworkfabric/armmanagednetworkfabric/networkdevices_client.go create mode 100644 sdk/resourcemanager/managednetworkfabric/armmanagednetworkfabric/networkdevices_client_example_test.go create mode 100644 sdk/resourcemanager/managednetworkfabric/armmanagednetworkfabric/networkdeviceskus_client.go create mode 100644 sdk/resourcemanager/managednetworkfabric/armmanagednetworkfabric/networkdeviceskus_client_example_test.go create mode 100644 sdk/resourcemanager/managednetworkfabric/armmanagednetworkfabric/networkfabriccontrollers_client.go create mode 100644 sdk/resourcemanager/managednetworkfabric/armmanagednetworkfabric/networkfabriccontrollers_client_example_test.go create mode 100644 sdk/resourcemanager/managednetworkfabric/armmanagednetworkfabric/networkfabrics_client.go create mode 100644 sdk/resourcemanager/managednetworkfabric/armmanagednetworkfabric/networkfabrics_client_example_test.go create mode 100644 sdk/resourcemanager/managednetworkfabric/armmanagednetworkfabric/networkfabricskus_client.go create mode 100644 sdk/resourcemanager/managednetworkfabric/armmanagednetworkfabric/networkfabricskus_client_example_test.go create mode 100644 sdk/resourcemanager/managednetworkfabric/armmanagednetworkfabric/networkinterfaces_client.go create mode 100644 sdk/resourcemanager/managednetworkfabric/armmanagednetworkfabric/networkinterfaces_client_example_test.go create mode 100644 sdk/resourcemanager/managednetworkfabric/armmanagednetworkfabric/networkpacketbrokers_client.go create mode 100644 sdk/resourcemanager/managednetworkfabric/armmanagednetworkfabric/networkpacketbrokers_client_example_test.go create mode 100644 sdk/resourcemanager/managednetworkfabric/armmanagednetworkfabric/networkracks_client.go create mode 100644 sdk/resourcemanager/managednetworkfabric/armmanagednetworkfabric/networkracks_client_example_test.go create mode 100644 sdk/resourcemanager/managednetworkfabric/armmanagednetworkfabric/networktaprules_client.go create mode 100644 sdk/resourcemanager/managednetworkfabric/armmanagednetworkfabric/networktaprules_client_example_test.go create mode 100644 sdk/resourcemanager/managednetworkfabric/armmanagednetworkfabric/networktaps_client.go create mode 100644 sdk/resourcemanager/managednetworkfabric/armmanagednetworkfabric/networktaps_client_example_test.go create mode 100644 sdk/resourcemanager/managednetworkfabric/armmanagednetworkfabric/networktonetworkinterconnects_client.go create mode 100644 sdk/resourcemanager/managednetworkfabric/armmanagednetworkfabric/networktonetworkinterconnects_client_example_test.go create mode 100644 sdk/resourcemanager/managednetworkfabric/armmanagednetworkfabric/operations_client.go create mode 100644 sdk/resourcemanager/managednetworkfabric/armmanagednetworkfabric/operations_client_example_test.go create mode 100644 sdk/resourcemanager/managednetworkfabric/armmanagednetworkfabric/response_types.go create mode 100644 sdk/resourcemanager/managednetworkfabric/armmanagednetworkfabric/routepolicies_client.go create mode 100644 sdk/resourcemanager/managednetworkfabric/armmanagednetworkfabric/routepolicies_client_example_test.go create mode 100644 sdk/resourcemanager/managednetworkfabric/armmanagednetworkfabric/time_rfc3339.go create mode 100644 sdk/resourcemanager/managementgroups/armmanagementgroups/assets.json create mode 100644 sdk/resourcemanager/managementgroups/armmanagementgroups/management_live_test.go create mode 100644 sdk/resourcemanager/marketplaceordering/armmarketplaceordering/fake/internal.go create mode 100644 sdk/resourcemanager/marketplaceordering/armmarketplaceordering/fake/marketplaceagreements_server.go create mode 100644 sdk/resourcemanager/marketplaceordering/armmarketplaceordering/fake/operations_server.go create mode 100644 sdk/resourcemanager/marketplaceordering/armmarketplaceordering/fake/time_rfc3339.go create mode 100644 sdk/resourcemanager/marketplaceordering/armmarketplaceordering/fake_example_test.go create mode 100644 sdk/resourcemanager/marketplaceordering/armmarketplaceordering/options.go create mode 100644 sdk/resourcemanager/mediaservices/armmediaservices/accounts_live_test.go create mode 100644 sdk/resourcemanager/mediaservices/armmediaservices/assets.json create mode 100644 sdk/resourcemanager/mediaservices/armmediaservices/encoding_live_test.go create mode 100644 sdk/resourcemanager/mediaservices/armmediaservices/metadata_live_test.go create mode 100644 sdk/resourcemanager/mediaservices/armmediaservices/streamingservice_live_test.go create mode 100644 sdk/resourcemanager/mobilenetwork/armmobilenetwork/diagnosticspackages_client.go create mode 100644 sdk/resourcemanager/mobilenetwork/armmobilenetwork/diagnosticspackages_client_example_test.go create mode 100644 sdk/resourcemanager/mobilenetwork/armmobilenetwork/options.go create mode 100644 sdk/resourcemanager/mobilenetwork/armmobilenetwork/packetcaptures_client.go create mode 100644 sdk/resourcemanager/mobilenetwork/armmobilenetwork/packetcaptures_client_example_test.go create mode 100644 sdk/resourcemanager/monitor/armmonitor/fake/actiongroups_server.go create mode 100644 sdk/resourcemanager/monitor/armmonitor/fake/activitylogalerts_server.go create mode 100644 sdk/resourcemanager/monitor/armmonitor/fake/activitylogs_server.go create mode 100644 sdk/resourcemanager/monitor/armmonitor/fake/alertruleincidents_server.go create mode 100644 sdk/resourcemanager/monitor/armmonitor/fake/alertrules_server.go create mode 100644 sdk/resourcemanager/monitor/armmonitor/fake/autoscalesettings_server.go create mode 100644 sdk/resourcemanager/monitor/armmonitor/fake/azuremonitorworkspaces_server.go create mode 100644 sdk/resourcemanager/monitor/armmonitor/fake/baselines_server.go create mode 100644 sdk/resourcemanager/monitor/armmonitor/fake/datacollectionendpoints_server.go create mode 100644 sdk/resourcemanager/monitor/armmonitor/fake/datacollectionruleassociations_server.go create mode 100644 sdk/resourcemanager/monitor/armmonitor/fake/datacollectionrules_server.go create mode 100644 sdk/resourcemanager/monitor/armmonitor/fake/diagnosticsettings_server.go create mode 100644 sdk/resourcemanager/monitor/armmonitor/fake/diagnosticsettingscategory_server.go create mode 100644 sdk/resourcemanager/monitor/armmonitor/fake/eventcategories_server.go create mode 100644 sdk/resourcemanager/monitor/armmonitor/fake/internal.go create mode 100644 sdk/resourcemanager/monitor/armmonitor/fake/logprofiles_server.go create mode 100644 sdk/resourcemanager/monitor/armmonitor/fake/metricalerts_server.go create mode 100644 sdk/resourcemanager/monitor/armmonitor/fake/metricalertsstatus_server.go create mode 100644 sdk/resourcemanager/monitor/armmonitor/fake/metricdefinitions_server.go create mode 100644 sdk/resourcemanager/monitor/armmonitor/fake/metricnamespaces_server.go create mode 100644 sdk/resourcemanager/monitor/armmonitor/fake/metrics_server.go create mode 100644 sdk/resourcemanager/monitor/armmonitor/fake/operations_server.go create mode 100644 sdk/resourcemanager/monitor/armmonitor/fake/operationsformonitor_server.go create mode 100644 sdk/resourcemanager/monitor/armmonitor/fake/polymorphic_helpers.go create mode 100644 sdk/resourcemanager/monitor/armmonitor/fake/predictivemetric_server.go create mode 100644 sdk/resourcemanager/monitor/armmonitor/fake/privateendpointconnections_server.go create mode 100644 sdk/resourcemanager/monitor/armmonitor/fake/privatelinkresources_server.go create mode 100644 sdk/resourcemanager/monitor/armmonitor/fake/privatelinkscopedresources_server.go create mode 100644 sdk/resourcemanager/monitor/armmonitor/fake/privatelinkscopeoperationstatus_server.go create mode 100644 sdk/resourcemanager/monitor/armmonitor/fake/privatelinkscopes_server.go create mode 100644 sdk/resourcemanager/monitor/armmonitor/fake/scheduledqueryrules_server.go create mode 100644 sdk/resourcemanager/monitor/armmonitor/fake/tenantactiongroups_server.go create mode 100644 sdk/resourcemanager/monitor/armmonitor/fake/tenantactivitylogs_server.go create mode 100644 sdk/resourcemanager/monitor/armmonitor/fake/time_rfc3339.go create mode 100644 sdk/resourcemanager/monitor/armmonitor/fake/vminsights_server.go create mode 100644 sdk/resourcemanager/monitor/armmonitor/fake_example_test.go create mode 100644 sdk/resourcemanager/monitor/armmonitor/interfaces.go create mode 100644 sdk/resourcemanager/monitor/armmonitor/options.go create mode 100644 sdk/resourcemanager/mysql/armmysqlflexibleservers/azureadadministrators_client.go create mode 100644 sdk/resourcemanager/mysql/armmysqlflexibleservers/azureadadministrators_client_example_test.go create mode 100644 sdk/resourcemanager/mysql/armmysqlflexibleservers/backupandexport_client.go create mode 100644 sdk/resourcemanager/mysql/armmysqlflexibleservers/backupandexport_client_example_test.go create mode 100644 sdk/resourcemanager/mysql/armmysqlflexibleservers/checknameavailabilitywithoutlocation_client.go create mode 100644 sdk/resourcemanager/mysql/armmysqlflexibleservers/checknameavailabilitywithoutlocation_client_example_test.go create mode 100644 sdk/resourcemanager/mysql/armmysqlflexibleservers/logfiles_client.go create mode 100644 sdk/resourcemanager/mysql/armmysqlflexibleservers/logfiles_client_example_test.go create mode 100644 sdk/resourcemanager/mysql/armmysqlflexibleservers/polymorphic_helpers.go create mode 100644 sdk/resourcemanager/network/armnetwork/fake/adminrulecollections_server.go create mode 100644 sdk/resourcemanager/network/armnetwork/fake/adminrules_server.go create mode 100644 sdk/resourcemanager/network/armnetwork/fake/applicationgatewayprivateendpointconnections_server.go create mode 100644 sdk/resourcemanager/network/armnetwork/fake/applicationgatewayprivatelinkresources_server.go create mode 100644 sdk/resourcemanager/network/armnetwork/fake/applicationgateways_server.go create mode 100644 sdk/resourcemanager/network/armnetwork/fake/applicationgatewaywafdynamicmanifests_server.go create mode 100644 sdk/resourcemanager/network/armnetwork/fake/applicationgatewaywafdynamicmanifestsdefault_server.go create mode 100644 sdk/resourcemanager/network/armnetwork/fake/applicationsecuritygroups_server.go create mode 100644 sdk/resourcemanager/network/armnetwork/fake/availabledelegations_server.go create mode 100644 sdk/resourcemanager/network/armnetwork/fake/availableendpointservices_server.go create mode 100644 sdk/resourcemanager/network/armnetwork/fake/availableprivateendpointtypes_server.go create mode 100644 sdk/resourcemanager/network/armnetwork/fake/availableresourcegroupdelegations_server.go create mode 100644 sdk/resourcemanager/network/armnetwork/fake/availableservicealiases_server.go create mode 100644 sdk/resourcemanager/network/armnetwork/fake/azurefirewallfqdntags_server.go create mode 100644 sdk/resourcemanager/network/armnetwork/fake/azurefirewalls_server.go create mode 100644 sdk/resourcemanager/network/armnetwork/fake/bastionhosts_server.go create mode 100644 sdk/resourcemanager/network/armnetwork/fake/bgpservicecommunities_server.go create mode 100644 sdk/resourcemanager/network/armnetwork/fake/configurationpolicygroups_server.go create mode 100644 sdk/resourcemanager/network/armnetwork/fake/connectionmonitors_server.go create mode 100644 sdk/resourcemanager/network/armnetwork/fake/connectivityconfigurations_server.go create mode 100644 sdk/resourcemanager/network/armnetwork/fake/customipprefixes_server.go create mode 100644 sdk/resourcemanager/network/armnetwork/fake/ddoscustompolicies_server.go create mode 100644 sdk/resourcemanager/network/armnetwork/fake/ddosprotectionplans_server.go create mode 100644 sdk/resourcemanager/network/armnetwork/fake/defaultsecurityrules_server.go create mode 100644 sdk/resourcemanager/network/armnetwork/fake/dscpconfiguration_server.go create mode 100644 sdk/resourcemanager/network/armnetwork/fake/expressroutecircuitauthorizations_server.go create mode 100644 sdk/resourcemanager/network/armnetwork/fake/expressroutecircuitconnections_server.go create mode 100644 sdk/resourcemanager/network/armnetwork/fake/expressroutecircuitpeerings_server.go create mode 100644 sdk/resourcemanager/network/armnetwork/fake/expressroutecircuits_server.go create mode 100644 sdk/resourcemanager/network/armnetwork/fake/expressrouteconnections_server.go create mode 100644 sdk/resourcemanager/network/armnetwork/fake/expressroutecrossconnectionpeerings_server.go create mode 100644 sdk/resourcemanager/network/armnetwork/fake/expressroutecrossconnections_server.go create mode 100644 sdk/resourcemanager/network/armnetwork/fake/expressroutegateways_server.go create mode 100644 sdk/resourcemanager/network/armnetwork/fake/expressroutelinks_server.go create mode 100644 sdk/resourcemanager/network/armnetwork/fake/expressrouteportauthorizations_server.go create mode 100644 sdk/resourcemanager/network/armnetwork/fake/expressrouteports_server.go create mode 100644 sdk/resourcemanager/network/armnetwork/fake/expressrouteportslocations_server.go create mode 100644 sdk/resourcemanager/network/armnetwork/fake/expressrouteproviderportslocation_server.go create mode 100644 sdk/resourcemanager/network/armnetwork/fake/expressrouteserviceproviders_server.go create mode 100644 sdk/resourcemanager/network/armnetwork/fake/firewallpolicies_server.go create mode 100644 sdk/resourcemanager/network/armnetwork/fake/firewallpolicyidpssignatures_server.go create mode 100644 sdk/resourcemanager/network/armnetwork/fake/firewallpolicyidpssignaturesfiltervalues_server.go create mode 100644 sdk/resourcemanager/network/armnetwork/fake/firewallpolicyidpssignaturesoverrides_server.go create mode 100644 sdk/resourcemanager/network/armnetwork/fake/firewallpolicyrulecollectiongroups_server.go create mode 100644 sdk/resourcemanager/network/armnetwork/fake/flowlogs_server.go create mode 100644 sdk/resourcemanager/network/armnetwork/fake/groups_server.go create mode 100644 sdk/resourcemanager/network/armnetwork/fake/hubroutetables_server.go create mode 100644 sdk/resourcemanager/network/armnetwork/fake/hubvirtualnetworkconnections_server.go create mode 100644 sdk/resourcemanager/network/armnetwork/fake/inboundnatrules_server.go create mode 100644 sdk/resourcemanager/network/armnetwork/fake/inboundsecurityrule_server.go create mode 100644 sdk/resourcemanager/network/armnetwork/fake/interfaceipconfigurations_server.go create mode 100644 sdk/resourcemanager/network/armnetwork/fake/interfaceloadbalancers_server.go create mode 100644 sdk/resourcemanager/network/armnetwork/fake/interfaces_server.go create mode 100644 sdk/resourcemanager/network/armnetwork/fake/interfacetapconfigurations_server.go create mode 100644 sdk/resourcemanager/network/armnetwork/fake/internal.go create mode 100644 sdk/resourcemanager/network/armnetwork/fake/ipallocations_server.go create mode 100644 sdk/resourcemanager/network/armnetwork/fake/ipgroups_server.go create mode 100644 sdk/resourcemanager/network/armnetwork/fake/loadbalancerbackendaddresspools_server.go create mode 100644 sdk/resourcemanager/network/armnetwork/fake/loadbalancerfrontendipconfigurations_server.go create mode 100644 sdk/resourcemanager/network/armnetwork/fake/loadbalancerloadbalancingrules_server.go create mode 100644 sdk/resourcemanager/network/armnetwork/fake/loadbalancernetworkinterfaces_server.go create mode 100644 sdk/resourcemanager/network/armnetwork/fake/loadbalanceroutboundrules_server.go create mode 100644 sdk/resourcemanager/network/armnetwork/fake/loadbalancerprobes_server.go create mode 100644 sdk/resourcemanager/network/armnetwork/fake/loadbalancers_server.go create mode 100644 sdk/resourcemanager/network/armnetwork/fake/localnetworkgateways_server.go create mode 100644 sdk/resourcemanager/network/armnetwork/fake/management_server.go create mode 100644 sdk/resourcemanager/network/armnetwork/fake/managementgroupnetworkmanagerconnections_server.go create mode 100644 sdk/resourcemanager/network/armnetwork/fake/managercommits_server.go create mode 100644 sdk/resourcemanager/network/armnetwork/fake/managerdeploymentstatus_server.go create mode 100644 sdk/resourcemanager/network/armnetwork/fake/managers_server.go create mode 100644 sdk/resourcemanager/network/armnetwork/fake/natgateways_server.go create mode 100644 sdk/resourcemanager/network/armnetwork/fake/natrules_server.go create mode 100644 sdk/resourcemanager/network/armnetwork/fake/operations_server.go create mode 100644 sdk/resourcemanager/network/armnetwork/fake/p2svpngateways_server.go create mode 100644 sdk/resourcemanager/network/armnetwork/fake/packetcaptures_server.go create mode 100644 sdk/resourcemanager/network/armnetwork/fake/peerexpressroutecircuitconnections_server.go create mode 100644 sdk/resourcemanager/network/armnetwork/fake/polymorphic_helpers.go create mode 100644 sdk/resourcemanager/network/armnetwork/fake/privatednszonegroups_server.go create mode 100644 sdk/resourcemanager/network/armnetwork/fake/privateendpoints_server.go create mode 100644 sdk/resourcemanager/network/armnetwork/fake/privatelinkservices_server.go create mode 100644 sdk/resourcemanager/network/armnetwork/fake/profiles_server.go create mode 100644 sdk/resourcemanager/network/armnetwork/fake/publicipaddresses_server.go create mode 100644 sdk/resourcemanager/network/armnetwork/fake/publicipprefixes_server.go create mode 100644 sdk/resourcemanager/network/armnetwork/fake/resourcenavigationlinks_server.go create mode 100644 sdk/resourcemanager/network/armnetwork/fake/routefilterrules_server.go create mode 100644 sdk/resourcemanager/network/armnetwork/fake/routefilters_server.go create mode 100644 sdk/resourcemanager/network/armnetwork/fake/routemaps_server.go create mode 100644 sdk/resourcemanager/network/armnetwork/fake/routes_server.go create mode 100644 sdk/resourcemanager/network/armnetwork/fake/routetables_server.go create mode 100644 sdk/resourcemanager/network/armnetwork/fake/routingintent_server.go create mode 100644 sdk/resourcemanager/network/armnetwork/fake/scopeconnections_server.go create mode 100644 sdk/resourcemanager/network/armnetwork/fake/securityadminconfigurations_server.go create mode 100644 sdk/resourcemanager/network/armnetwork/fake/securitygroups_server.go create mode 100644 sdk/resourcemanager/network/armnetwork/fake/securitypartnerproviders_server.go create mode 100644 sdk/resourcemanager/network/armnetwork/fake/securityrules_server.go create mode 100644 sdk/resourcemanager/network/armnetwork/fake/serviceassociationlinks_server.go create mode 100644 sdk/resourcemanager/network/armnetwork/fake/serviceendpointpolicies_server.go create mode 100644 sdk/resourcemanager/network/armnetwork/fake/serviceendpointpolicydefinitions_server.go create mode 100644 sdk/resourcemanager/network/armnetwork/fake/servicetaginformation_server.go create mode 100644 sdk/resourcemanager/network/armnetwork/fake/servicetags_server.go create mode 100644 sdk/resourcemanager/network/armnetwork/fake/staticmembers_server.go create mode 100644 sdk/resourcemanager/network/armnetwork/fake/subnets_server.go create mode 100644 sdk/resourcemanager/network/armnetwork/fake/subscriptionnetworkmanagerconnections_server.go create mode 100644 sdk/resourcemanager/network/armnetwork/fake/time_rfc3339.go create mode 100644 sdk/resourcemanager/network/armnetwork/fake/usages_server.go create mode 100644 sdk/resourcemanager/network/armnetwork/fake/vipswap_server.go create mode 100644 sdk/resourcemanager/network/armnetwork/fake/virtualapplianceconnections_server.go create mode 100644 sdk/resourcemanager/network/armnetwork/fake/virtualappliances_server.go create mode 100644 sdk/resourcemanager/network/armnetwork/fake/virtualappliancesites_server.go create mode 100644 sdk/resourcemanager/network/armnetwork/fake/virtualapplianceskus_server.go create mode 100644 sdk/resourcemanager/network/armnetwork/fake/virtualhubbgpconnection_server.go create mode 100644 sdk/resourcemanager/network/armnetwork/fake/virtualhubbgpconnections_server.go create mode 100644 sdk/resourcemanager/network/armnetwork/fake/virtualhubipconfiguration_server.go create mode 100644 sdk/resourcemanager/network/armnetwork/fake/virtualhubroutetablev2s_server.go create mode 100644 sdk/resourcemanager/network/armnetwork/fake/virtualhubs_server.go create mode 100644 sdk/resourcemanager/network/armnetwork/fake/virtualnetworkgatewayconnections_server.go create mode 100644 sdk/resourcemanager/network/armnetwork/fake/virtualnetworkgatewaynatrules_server.go create mode 100644 sdk/resourcemanager/network/armnetwork/fake/virtualnetworkgateways_server.go create mode 100644 sdk/resourcemanager/network/armnetwork/fake/virtualnetworkpeerings_server.go create mode 100644 sdk/resourcemanager/network/armnetwork/fake/virtualnetworks_server.go create mode 100644 sdk/resourcemanager/network/armnetwork/fake/virtualnetworktaps_server.go create mode 100644 sdk/resourcemanager/network/armnetwork/fake/virtualrouterpeerings_server.go create mode 100644 sdk/resourcemanager/network/armnetwork/fake/virtualrouters_server.go create mode 100644 sdk/resourcemanager/network/armnetwork/fake/virtualwans_server.go create mode 100644 sdk/resourcemanager/network/armnetwork/fake/vpnconnections_server.go create mode 100644 sdk/resourcemanager/network/armnetwork/fake/vpngateways_server.go create mode 100644 sdk/resourcemanager/network/armnetwork/fake/vpnlinkconnections_server.go create mode 100644 sdk/resourcemanager/network/armnetwork/fake/vpnserverconfigurations_server.go create mode 100644 sdk/resourcemanager/network/armnetwork/fake/vpnserverconfigurationsassociatedwithvirtualwan_server.go create mode 100644 sdk/resourcemanager/network/armnetwork/fake/vpnsitelinkconnections_server.go create mode 100644 sdk/resourcemanager/network/armnetwork/fake/vpnsitelinks_server.go create mode 100644 sdk/resourcemanager/network/armnetwork/fake/vpnsites_server.go create mode 100644 sdk/resourcemanager/network/armnetwork/fake/vpnsitesconfiguration_server.go create mode 100644 sdk/resourcemanager/network/armnetwork/fake/watchers_server.go create mode 100644 sdk/resourcemanager/network/armnetwork/fake/webapplicationfirewallpolicies_server.go create mode 100644 sdk/resourcemanager/network/armnetwork/fake/webcategories_server.go create mode 100644 sdk/resourcemanager/network/armnetwork/fake_example_test.go create mode 100644 sdk/resourcemanager/network/armnetwork/interfaces.go create mode 100644 sdk/resourcemanager/network/armnetwork/options.go create mode 100644 sdk/resourcemanager/network/armnetwork/virtualapplianceconnections_client.go create mode 100644 sdk/resourcemanager/network/armnetwork/virtualapplianceconnections_client_example_test.go create mode 100644 sdk/resourcemanager/networkcloud/armnetworkcloud/CHANGELOG.md create mode 100644 sdk/resourcemanager/networkcloud/armnetworkcloud/LICENSE.txt create mode 100644 sdk/resourcemanager/networkcloud/armnetworkcloud/README.md create mode 100644 sdk/resourcemanager/networkcloud/armnetworkcloud/agentpools_client.go create mode 100644 sdk/resourcemanager/networkcloud/armnetworkcloud/agentpools_client_example_test.go create mode 100644 sdk/resourcemanager/networkcloud/armnetworkcloud/autorest.md create mode 100644 sdk/resourcemanager/networkcloud/armnetworkcloud/baremetalmachinekeysets_client.go create mode 100644 sdk/resourcemanager/networkcloud/armnetworkcloud/baremetalmachinekeysets_client_example_test.go create mode 100644 sdk/resourcemanager/networkcloud/armnetworkcloud/baremetalmachines_client.go create mode 100644 sdk/resourcemanager/networkcloud/armnetworkcloud/baremetalmachines_client_example_test.go create mode 100644 sdk/resourcemanager/networkcloud/armnetworkcloud/bmckeysets_client.go create mode 100644 sdk/resourcemanager/networkcloud/armnetworkcloud/bmckeysets_client_example_test.go create mode 100644 sdk/resourcemanager/networkcloud/armnetworkcloud/build.go create mode 100644 sdk/resourcemanager/networkcloud/armnetworkcloud/ci.yml create mode 100644 sdk/resourcemanager/networkcloud/armnetworkcloud/client_factory.go create mode 100644 sdk/resourcemanager/networkcloud/armnetworkcloud/cloudservicesnetworks_client.go create mode 100644 sdk/resourcemanager/networkcloud/armnetworkcloud/cloudservicesnetworks_client_example_test.go create mode 100644 sdk/resourcemanager/networkcloud/armnetworkcloud/clustermanagers_client.go create mode 100644 sdk/resourcemanager/networkcloud/armnetworkcloud/clustermanagers_client_example_test.go create mode 100644 sdk/resourcemanager/networkcloud/armnetworkcloud/clusters_client.go create mode 100644 sdk/resourcemanager/networkcloud/armnetworkcloud/clusters_client_example_test.go create mode 100644 sdk/resourcemanager/networkcloud/armnetworkcloud/consoles_client.go create mode 100644 sdk/resourcemanager/networkcloud/armnetworkcloud/consoles_client_example_test.go create mode 100644 sdk/resourcemanager/networkcloud/armnetworkcloud/constants.go create mode 100644 sdk/resourcemanager/networkcloud/armnetworkcloud/go.mod create mode 100644 sdk/resourcemanager/networkcloud/armnetworkcloud/go.sum create mode 100644 sdk/resourcemanager/networkcloud/armnetworkcloud/kubernetesclusters_client.go create mode 100644 sdk/resourcemanager/networkcloud/armnetworkcloud/kubernetesclusters_client_example_test.go create mode 100644 sdk/resourcemanager/networkcloud/armnetworkcloud/l2networks_client.go create mode 100644 sdk/resourcemanager/networkcloud/armnetworkcloud/l2networks_client_example_test.go create mode 100644 sdk/resourcemanager/networkcloud/armnetworkcloud/l3networks_client.go create mode 100644 sdk/resourcemanager/networkcloud/armnetworkcloud/l3networks_client_example_test.go create mode 100644 sdk/resourcemanager/networkcloud/armnetworkcloud/metricsconfigurations_client.go create mode 100644 sdk/resourcemanager/networkcloud/armnetworkcloud/metricsconfigurations_client_example_test.go create mode 100644 sdk/resourcemanager/networkcloud/armnetworkcloud/models.go create mode 100644 sdk/resourcemanager/networkcloud/armnetworkcloud/models_serde.go create mode 100644 sdk/resourcemanager/networkcloud/armnetworkcloud/operations_client.go create mode 100644 sdk/resourcemanager/networkcloud/armnetworkcloud/operations_client_example_test.go create mode 100644 sdk/resourcemanager/networkcloud/armnetworkcloud/racks_client.go create mode 100644 sdk/resourcemanager/networkcloud/armnetworkcloud/racks_client_example_test.go create mode 100644 sdk/resourcemanager/networkcloud/armnetworkcloud/rackskus_client.go create mode 100644 sdk/resourcemanager/networkcloud/armnetworkcloud/rackskus_client_example_test.go create mode 100644 sdk/resourcemanager/networkcloud/armnetworkcloud/response_types.go create mode 100644 sdk/resourcemanager/networkcloud/armnetworkcloud/storageappliances_client.go create mode 100644 sdk/resourcemanager/networkcloud/armnetworkcloud/storageappliances_client_example_test.go create mode 100644 sdk/resourcemanager/networkcloud/armnetworkcloud/time_rfc3339.go create mode 100644 sdk/resourcemanager/networkcloud/armnetworkcloud/trunkednetworks_client.go create mode 100644 sdk/resourcemanager/networkcloud/armnetworkcloud/trunkednetworks_client_example_test.go create mode 100644 sdk/resourcemanager/networkcloud/armnetworkcloud/virtualmachines_client.go create mode 100644 sdk/resourcemanager/networkcloud/armnetworkcloud/virtualmachines_client_example_test.go create mode 100644 sdk/resourcemanager/networkcloud/armnetworkcloud/volumes_client.go create mode 100644 sdk/resourcemanager/networkcloud/armnetworkcloud/volumes_client_example_test.go create mode 100644 sdk/resourcemanager/notificationhubs/armnotificationhubs/assets.json create mode 100644 sdk/resourcemanager/notificationhubs/armnotificationhubs/notificationhubs_live_test.go create mode 100644 sdk/resourcemanager/postgresql/armpostgresqlflexibleservers/flexibleserver_client.go create mode 100644 sdk/resourcemanager/postgresql/armpostgresqlflexibleservers/flexibleserver_client_example_test.go create mode 100644 sdk/resourcemanager/postgresql/armpostgresqlflexibleservers/logfiles_client.go create mode 100644 sdk/resourcemanager/postgresql/armpostgresqlflexibleservers/logfiles_client_example_test.go create mode 100644 sdk/resourcemanager/postgresql/armpostgresqlflexibleservers/ltrbackupoperations_client.go create mode 100644 sdk/resourcemanager/postgresql/armpostgresqlflexibleservers/ltrbackupoperations_client_example_test.go create mode 100644 sdk/resourcemanager/postgresql/armpostgresqlflexibleservers/migrations_client.go create mode 100644 sdk/resourcemanager/postgresql/armpostgresqlflexibleservers/migrations_client_example_test.go create mode 100644 sdk/resourcemanager/postgresql/armpostgresqlflexibleservers/postgresqlmanagement_client.go create mode 100644 sdk/resourcemanager/postgresql/armpostgresqlflexibleservers/postgresqlmanagement_client_example_test.go create mode 100644 sdk/resourcemanager/postgresql/armpostgresqlflexibleservers/servercapabilities_client.go create mode 100644 sdk/resourcemanager/postgresql/armpostgresqlflexibleservers/servercapabilities_client_example_test.go create mode 100644 sdk/resourcemanager/recoveryservices/armrecoveryservices/assets.json create mode 100644 sdk/resourcemanager/recoveryservices/armrecoveryservices/recoveryservices_live_test.go create mode 100644 sdk/resourcemanager/relay/armrelay/assets.json create mode 100644 sdk/resourcemanager/relay/armrelay/hybridconnections_live_test.go create mode 100644 sdk/resourcemanager/relay/armrelay/namespaces_live_test.go create mode 100644 sdk/resourcemanager/relay/armrelay/operations_live_test.go create mode 100644 sdk/resourcemanager/relay/armrelay/wcfrelays_live_test.go create mode 100644 sdk/resourcemanager/resourcegraph/armresourcegraph/fake/internal.go create mode 100644 sdk/resourcemanager/resourcegraph/armresourcegraph/fake/operations_server.go create mode 100644 sdk/resourcemanager/resourcegraph/armresourcegraph/fake/polymorphic_helpers.go create mode 100644 sdk/resourcemanager/resourcegraph/armresourcegraph/fake/server.go create mode 100644 sdk/resourcemanager/resourcegraph/armresourcegraph/fake/time_rfc3339.go create mode 100644 sdk/resourcemanager/resourcegraph/armresourcegraph/fake_example_test.go create mode 100644 sdk/resourcemanager/resourcegraph/armresourcegraph/interfaces.go create mode 100644 sdk/resourcemanager/resourcegraph/armresourcegraph/options.go create mode 100644 sdk/resourcemanager/resourcehealth/armresourcehealth/childavailabilitystatuses_client.go create mode 100644 sdk/resourcemanager/resourcehealth/armresourcehealth/childavailabilitystatuses_client_example_test.go create mode 100644 sdk/resourcemanager/resourcehealth/armresourcehealth/childresources_client.go create mode 100644 sdk/resourcemanager/resourcehealth/armresourcehealth/childresources_client_example_test.go create mode 100644 sdk/resourcemanager/resourcehealth/armresourcehealth/emergingissues_client.go create mode 100644 sdk/resourcemanager/resourcehealth/armresourcehealth/emergingissues_client_example_test.go create mode 100644 sdk/resourcemanager/resourcehealth/armresourcehealth/event_client.go create mode 100644 sdk/resourcemanager/resourcehealth/armresourcehealth/event_client_example_test.go create mode 100644 sdk/resourcemanager/resourcehealth/armresourcehealth/events_client.go create mode 100644 sdk/resourcemanager/resourcehealth/armresourcehealth/events_client_example_test.go create mode 100644 sdk/resourcemanager/resourcehealth/armresourcehealth/impactedresources_client.go create mode 100644 sdk/resourcemanager/resourcehealth/armresourcehealth/impactedresources_client_example_test.go create mode 100644 sdk/resourcemanager/resourcehealth/armresourcehealth/metadata_client.go create mode 100644 sdk/resourcemanager/resourcehealth/armresourcehealth/metadata_client_example_test.go create mode 100644 sdk/resourcemanager/resourcehealth/armresourcehealth/securityadvisoryimpactedresources_client.go create mode 100644 sdk/resourcemanager/resourcehealth/armresourcehealth/securityadvisoryimpactedresources_client_example_test.go create mode 100644 sdk/resourcemanager/resources/armresources/fake/deploymentoperations_server.go create mode 100644 sdk/resourcemanager/resources/armresources/fake/deployments_server.go create mode 100644 sdk/resourcemanager/resources/armresources/fake/internal.go create mode 100644 sdk/resourcemanager/resources/armresources/fake/operations_server.go create mode 100644 sdk/resourcemanager/resources/armresources/fake/providerresourcetypes_server.go create mode 100644 sdk/resourcemanager/resources/armresources/fake/providers_server.go create mode 100644 sdk/resourcemanager/resources/armresources/fake/resourcegroups_server.go create mode 100644 sdk/resourcemanager/resources/armresources/fake/server.go create mode 100644 sdk/resourcemanager/resources/armresources/fake/tags_server.go create mode 100644 sdk/resourcemanager/resources/armresources/fake/time_rfc3339.go create mode 100644 sdk/resourcemanager/resources/armresources/fake_example_test.go create mode 100644 sdk/resourcemanager/resources/armresources/options.go create mode 100644 sdk/resourcemanager/resources/armsubscriptions/fake/internal.go create mode 100644 sdk/resourcemanager/resources/armsubscriptions/fake/operations_server.go create mode 100644 sdk/resourcemanager/resources/armsubscriptions/fake/server.go create mode 100644 sdk/resourcemanager/resources/armsubscriptions/fake/subscription_server.go create mode 100644 sdk/resourcemanager/resources/armsubscriptions/fake/tenants_server.go create mode 100644 sdk/resourcemanager/resources/armsubscriptions/fake_example_test.go create mode 100644 sdk/resourcemanager/resources/armsubscriptions/operations_client.go create mode 100644 sdk/resourcemanager/resources/armsubscriptions/options.go create mode 100644 sdk/resourcemanager/search/armsearch/assets.json create mode 100644 sdk/resourcemanager/search/armsearch/search_live_test.go create mode 100644 sdk/resourcemanager/selfhelp/armselfhelp/CHANGELOG.md create mode 100644 sdk/resourcemanager/selfhelp/armselfhelp/LICENSE.txt create mode 100644 sdk/resourcemanager/selfhelp/armselfhelp/README.md create mode 100644 sdk/resourcemanager/selfhelp/armselfhelp/assets.json create mode 100644 sdk/resourcemanager/selfhelp/armselfhelp/autorest.md create mode 100644 sdk/resourcemanager/selfhelp/armselfhelp/build.go rename sdk/{keyvault/azcertificates => resourcemanager/selfhelp/armselfhelp}/ci.yml (68%) create mode 100644 sdk/resourcemanager/selfhelp/armselfhelp/client_factory.go create mode 100644 sdk/resourcemanager/selfhelp/armselfhelp/constants.go create mode 100644 sdk/resourcemanager/selfhelp/armselfhelp/diagnostics_client.go create mode 100644 sdk/resourcemanager/selfhelp/armselfhelp/diagnostics_client_example_test.go create mode 100644 sdk/resourcemanager/selfhelp/armselfhelp/discoverysolution_client.go create mode 100644 sdk/resourcemanager/selfhelp/armselfhelp/discoverysolution_client_example_test.go create mode 100644 sdk/resourcemanager/selfhelp/armselfhelp/go.mod rename sdk/{keyvault/azcertificates => resourcemanager/selfhelp/armselfhelp}/go.sum (51%) create mode 100644 sdk/resourcemanager/selfhelp/armselfhelp/help_live_test.go create mode 100644 sdk/resourcemanager/selfhelp/armselfhelp/models.go create mode 100644 sdk/resourcemanager/selfhelp/armselfhelp/models_serde.go create mode 100644 sdk/resourcemanager/selfhelp/armselfhelp/operations_client.go create mode 100644 sdk/resourcemanager/selfhelp/armselfhelp/operations_client_example_test.go create mode 100644 sdk/resourcemanager/selfhelp/armselfhelp/response_types.go create mode 100644 sdk/resourcemanager/selfhelp/armselfhelp/time_rfc3339.go create mode 100644 sdk/resourcemanager/servicefabric/armservicefabric/assets.json create mode 100644 sdk/resourcemanager/servicefabric/armservicefabric/servicefabric_live_test.go create mode 100644 sdk/resourcemanager/sphere/armsphere/CHANGELOG.md create mode 100644 sdk/resourcemanager/sphere/armsphere/LICENSE.txt create mode 100644 sdk/resourcemanager/sphere/armsphere/README.md create mode 100644 sdk/resourcemanager/sphere/armsphere/autorest.md create mode 100644 sdk/resourcemanager/sphere/armsphere/build.go create mode 100644 sdk/resourcemanager/sphere/armsphere/catalogs_client.go create mode 100644 sdk/resourcemanager/sphere/armsphere/catalogs_client_example_test.go create mode 100644 sdk/resourcemanager/sphere/armsphere/certificates_client.go create mode 100644 sdk/resourcemanager/sphere/armsphere/certificates_client_example_test.go rename sdk/{keyvault/azsecrets => resourcemanager/sphere/armsphere}/ci.yml (70%) create mode 100644 sdk/resourcemanager/sphere/armsphere/client_factory.go create mode 100644 sdk/resourcemanager/sphere/armsphere/constants.go create mode 100644 sdk/resourcemanager/sphere/armsphere/deployments_client.go create mode 100644 sdk/resourcemanager/sphere/armsphere/deployments_client_example_test.go create mode 100644 sdk/resourcemanager/sphere/armsphere/devicegroups_client.go create mode 100644 sdk/resourcemanager/sphere/armsphere/devicegroups_client_example_test.go create mode 100644 sdk/resourcemanager/sphere/armsphere/devices_client.go create mode 100644 sdk/resourcemanager/sphere/armsphere/devices_client_example_test.go create mode 100644 sdk/resourcemanager/sphere/armsphere/go.mod create mode 100644 sdk/resourcemanager/sphere/armsphere/go.sum create mode 100644 sdk/resourcemanager/sphere/armsphere/images_client.go create mode 100644 sdk/resourcemanager/sphere/armsphere/images_client_example_test.go create mode 100644 sdk/resourcemanager/sphere/armsphere/models.go create mode 100644 sdk/resourcemanager/sphere/armsphere/models_serde.go create mode 100644 sdk/resourcemanager/sphere/armsphere/operations_client.go create mode 100644 sdk/resourcemanager/sphere/armsphere/operations_client_example_test.go create mode 100644 sdk/resourcemanager/sphere/armsphere/products_client.go create mode 100644 sdk/resourcemanager/sphere/armsphere/products_client_example_test.go create mode 100644 sdk/resourcemanager/sphere/armsphere/response_types.go create mode 100644 sdk/resourcemanager/sphere/armsphere/time_rfc3339.go create mode 100644 sdk/resourcemanager/sql/armsql/databaseencryptionprotectors_client.go create mode 100644 sdk/resourcemanager/sql/armsql/databaseencryptionprotectors_client_example_test.go create mode 100644 sdk/resourcemanager/sql/armsql/databasesqlvulnerabilityassessmentbaselines_client.go create mode 100644 sdk/resourcemanager/sql/armsql/databasesqlvulnerabilityassessmentbaselines_client_example_test.go create mode 100644 sdk/resourcemanager/sql/armsql/databasesqlvulnerabilityassessmentexecutescan_client.go create mode 100644 sdk/resourcemanager/sql/armsql/databasesqlvulnerabilityassessmentexecutescan_client_example_test.go create mode 100644 sdk/resourcemanager/sql/armsql/databasesqlvulnerabilityassessmentrulebaselines_client.go create mode 100644 sdk/resourcemanager/sql/armsql/databasesqlvulnerabilityassessmentrulebaselines_client_example_test.go create mode 100644 sdk/resourcemanager/sql/armsql/databasesqlvulnerabilityassessmentscanresult_client.go create mode 100644 sdk/resourcemanager/sql/armsql/databasesqlvulnerabilityassessmentscanresult_client_example_test.go create mode 100644 sdk/resourcemanager/sql/armsql/databasesqlvulnerabilityassessmentscans_client.go create mode 100644 sdk/resourcemanager/sql/armsql/databasesqlvulnerabilityassessmentscans_client_example_test.go create mode 100644 sdk/resourcemanager/sql/armsql/databasesqlvulnerabilityassessmentssettings_client.go create mode 100644 sdk/resourcemanager/sql/armsql/databasesqlvulnerabilityassessmentssettings_client_example_test.go create mode 100644 sdk/resourcemanager/sql/armsql/manageddatabaseadvancedthreatprotectionsettings_client.go create mode 100644 sdk/resourcemanager/sql/armsql/manageddatabaseadvancedthreatprotectionsettings_client_example_test.go create mode 100644 sdk/resourcemanager/sql/armsql/manageddatabasemoveoperations_client.go create mode 100644 sdk/resourcemanager/sql/armsql/manageddatabasemoveoperations_client_example_test.go create mode 100644 sdk/resourcemanager/sql/armsql/managedinstanceadvancedthreatprotectionsettings_client.go create mode 100644 sdk/resourcemanager/sql/armsql/managedinstanceadvancedthreatprotectionsettings_client_example_test.go create mode 100644 sdk/resourcemanager/sql/armsql/managedinstancedtcs_client.go create mode 100644 sdk/resourcemanager/sql/armsql/managedinstancedtcs_client_example_test.go create mode 100644 sdk/resourcemanager/sql/armsql/managedledgerdigestuploads_client.go create mode 100644 sdk/resourcemanager/sql/armsql/managedledgerdigestuploads_client_example_test.go create mode 100644 sdk/resourcemanager/sql/armsql/managedserverdnsaliases_client.go create mode 100644 sdk/resourcemanager/sql/armsql/managedserverdnsaliases_client_example_test.go create mode 100644 sdk/resourcemanager/sql/armsql/options.go create mode 100644 sdk/resourcemanager/sql/armsql/serverconfigurationoptions_client.go create mode 100644 sdk/resourcemanager/sql/armsql/serverconfigurationoptions_client_example_test.go create mode 100644 sdk/resourcemanager/sql/armsql/startstopmanagedinstanceschedules_client.go create mode 100644 sdk/resourcemanager/sql/armsql/startstopmanagedinstanceschedules_client_example_test.go create mode 100644 sdk/resourcemanager/sql/armsql/synapselinkworkspaces_client.go create mode 100644 sdk/resourcemanager/sql/armsql/synapselinkworkspaces_client_example_test.go create mode 100644 sdk/resourcemanager/sql/armsql/vulnerabilityassessmentbaseline_client.go create mode 100644 sdk/resourcemanager/sql/armsql/vulnerabilityassessmentbaseline_client_example_test.go create mode 100644 sdk/resourcemanager/sql/armsql/vulnerabilityassessmentbaselines_client.go create mode 100644 sdk/resourcemanager/sql/armsql/vulnerabilityassessmentbaselines_client_example_test.go create mode 100644 sdk/resourcemanager/sql/armsql/vulnerabilityassessmentexecutescan_client.go create mode 100644 sdk/resourcemanager/sql/armsql/vulnerabilityassessmentexecutescan_client_example_test.go create mode 100644 sdk/resourcemanager/sql/armsql/vulnerabilityassessmentrulebaseline_client.go create mode 100644 sdk/resourcemanager/sql/armsql/vulnerabilityassessmentrulebaseline_client_example_test.go create mode 100644 sdk/resourcemanager/sql/armsql/vulnerabilityassessmentrulebaselines_client.go create mode 100644 sdk/resourcemanager/sql/armsql/vulnerabilityassessmentrulebaselines_client_example_test.go create mode 100644 sdk/resourcemanager/sql/armsql/vulnerabilityassessments_client.go create mode 100644 sdk/resourcemanager/sql/armsql/vulnerabilityassessments_client_example_test.go create mode 100644 sdk/resourcemanager/sql/armsql/vulnerabilityassessmentscanresult_client.go create mode 100644 sdk/resourcemanager/sql/armsql/vulnerabilityassessmentscanresult_client_example_test.go create mode 100644 sdk/resourcemanager/sql/armsql/vulnerabilityassessmentscans_client.go create mode 100644 sdk/resourcemanager/sql/armsql/vulnerabilityassessmentscans_client_example_test.go create mode 100644 sdk/resourcemanager/sql/armsql/vulnerabilityassessmentssettings_client.go create mode 100644 sdk/resourcemanager/sql/armsql/vulnerabilityassessmentssettings_client_example_test.go create mode 100644 sdk/resourcemanager/sqlvirtualmachine/armsqlvirtualmachine/troubleshoot_client.go create mode 100644 sdk/resourcemanager/sqlvirtualmachine/armsqlvirtualmachine/troubleshoot_client_example_test.go create mode 100644 sdk/resourcemanager/storage/armstorage/fake/accounts_server.go create mode 100644 sdk/resourcemanager/storage/armstorage/fake/blobcontainers_server.go create mode 100644 sdk/resourcemanager/storage/armstorage/fake/blobinventorypolicies_server.go create mode 100644 sdk/resourcemanager/storage/armstorage/fake/blobservices_server.go create mode 100644 sdk/resourcemanager/storage/armstorage/fake/deletedaccounts_server.go create mode 100644 sdk/resourcemanager/storage/armstorage/fake/encryptionscopes_server.go create mode 100644 sdk/resourcemanager/storage/armstorage/fake/fileservices_server.go create mode 100644 sdk/resourcemanager/storage/armstorage/fake/fileshares_server.go create mode 100644 sdk/resourcemanager/storage/armstorage/fake/internal.go create mode 100644 sdk/resourcemanager/storage/armstorage/fake/localusers_server.go create mode 100644 sdk/resourcemanager/storage/armstorage/fake/managementpolicies_server.go create mode 100644 sdk/resourcemanager/storage/armstorage/fake/objectreplicationpolicies_server.go create mode 100644 sdk/resourcemanager/storage/armstorage/fake/operations_server.go create mode 100644 sdk/resourcemanager/storage/armstorage/fake/privateendpointconnections_server.go create mode 100644 sdk/resourcemanager/storage/armstorage/fake/privatelinkresources_server.go create mode 100644 sdk/resourcemanager/storage/armstorage/fake/queue_server.go create mode 100644 sdk/resourcemanager/storage/armstorage/fake/queueservices_server.go create mode 100644 sdk/resourcemanager/storage/armstorage/fake/skus_server.go create mode 100644 sdk/resourcemanager/storage/armstorage/fake/table_server.go create mode 100644 sdk/resourcemanager/storage/armstorage/fake/tableservices_server.go create mode 100644 sdk/resourcemanager/storage/armstorage/fake/time_rfc3339.go create mode 100644 sdk/resourcemanager/storage/armstorage/fake/usages_server.go create mode 100644 sdk/resourcemanager/storage/armstorage/fake_example_test.go create mode 100644 sdk/resourcemanager/storage/armstorage/options.go create mode 100644 sdk/resourcemanager/storagecache/armstoragecache/amlfilesystems_client.go create mode 100644 sdk/resourcemanager/storagecache/armstoragecache/amlfilesystems_client_example_test.go create mode 100644 sdk/resourcemanager/storagecache/armstoragecache/management_client.go create mode 100644 sdk/resourcemanager/storagecache/armstoragecache/management_client_example_test.go create mode 100644 sdk/resourcemanager/streamanalytics/armstreamanalytics/assets.json create mode 100644 sdk/resourcemanager/streamanalytics/armstreamanalytics/clusters_live_test.go create mode 100644 sdk/resourcemanager/streamanalytics/armstreamanalytics/functions_live_test.go create mode 100644 sdk/resourcemanager/streamanalytics/armstreamanalytics/inputs_live_test.go create mode 100644 sdk/resourcemanager/streamanalytics/armstreamanalytics/outputs_live_test.go create mode 100644 sdk/resourcemanager/streamanalytics/armstreamanalytics/streamingjobs_live_test.go create mode 100644 sdk/resourcemanager/streamanalytics/armstreamanalytics/subscriptions_live_test.go create mode 100644 sdk/resourcemanager/streamanalytics/armstreamanalytics/transformations_live_test.go create mode 100644 sdk/resourcemanager/webpubsub/armwebpubsub/replicas_client.go create mode 100644 sdk/resourcemanager/webpubsub/armwebpubsub/replicas_client_example_test.go create mode 100644 sdk/security/keyvault/azkeys/options.go delete mode 100644 sdk/security/keyvault/azsecrets/constants.go create mode 100644 sdk/storage/azfile/migrationguide.md create mode 100644 sdk/storage/azqueue/internal/shared/shared_test.go create mode 100644 sdk/tracing/azotel/CHANGELOG.md create mode 100644 sdk/tracing/azotel/LICENSE.txt create mode 100644 sdk/tracing/azotel/README.md rename sdk/{keyvault/internal/ci.keyvault.yml => tracing/azotel/ci.yml} (77%) create mode 100644 sdk/tracing/azotel/examples_test.go create mode 100644 sdk/tracing/azotel/go.mod create mode 100644 sdk/tracing/azotel/go.sum rename sdk/{keyvault/azsecrets => tracing/azotel/internal}/version.go (63%) create mode 100644 sdk/tracing/azotel/otel.go create mode 100644 sdk/tracing/azotel/otel_test.go diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 8b6f0882c0f6..a5017250d06e 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -16,7 +16,10 @@ /sdk/azcore/ @rickwinter @chlowell @jhendrixMSFT @richardpark-msft # PRLabel: %Azure.Identity -/sdk/azidentity/ @chlowell @jhendrixMSFT @rickwinter +/sdk/azidentity/ @chlowell @jhendrixMSFT @rickwinter @Azure/azure-sdk-write-identity + +# PRLable: %OpenAI +/sdk/ai @richardpark-msft @jhendrixMSFT # PRLabel: %Internal /sdk/internal/ @chlowell @jhendrixMSFT @richardpark-msft @rickwinter @@ -30,20 +33,20 @@ # PRLabel: %Tables /sdk/data/aztables/ @jhendrixMSFT -# PRLabel: %KeyVault -/sdk/keyvault/ @chlowell @jhendrixMSFT - # PRLabel: %KeyVault /sdk/security/keyvault/ @chlowell @jhendrixMSFT @gracewilcox # PRLabel: %Service Bus /sdk/messaging/azservicebus/ @richardpark-msft @jhendrixMSFT +# PRLabel: %Event Grid +/sdk/messaging/azeventgrid/ @richardpark-msft @jhendrixMSFT + # PRLabel: %Event Hubs /sdk/messaging/azeventhubs/ @richardpark-msft @jhendrixMSFT # PRLabel: %Monitor -/sdk/monitor/ @gracewilcox @chlowell @jhendrixMSFT +/sdk/monitor/ @gracewilcox @chlowell @jhendrixMSFT @Azure/azure-sdk-write-monitor-data-plane # PRLabel: %Mgmt /sdk/resourcemanager/ @ArcturusZhang @lirenhe @tadelesh @@ -51,6 +54,9 @@ # PRLabel: %Storage /sdk/storage/ @siminsavani-msft @souravgupta-msft @tasherif-msft @jhendrixMSFT @gapra-msft @vibhansa-msft +# PRLabel: %Open Telemetry +/sdk/tracing/azotel @jhendrixMSFT @rickwinter + ################ # Automation ################ @@ -65,3 +71,549 @@ # PRLabel: %EngSys /sdk/template/ @benbp @weshaggard + +# ServiceLabel: %AAD +#// @adamedx + +# ServiceLabel: %AKS +#// @Azure/aks-pm + +# ServiceLabel: %Alerts Management +#// @liadtal @yairgil + +# ServiceLabel: %ARM +#// @armleads-azure + +# ServiceLabel: %ARM - Templates +#// @armleads-azure + +# ServiceLabel: %ARM - Tags +#// @armleads-azure + +# ServiceLabel: %ARM - Core +#// @armleads-azure + +# ServiceLabel: %ARM - Managed Applications +#// @armleads-azure + +# ServiceLabel: %ARM - Service Catalog +#// @armleads-azure + +# ServiceLabel: %ARM - RBAC +#// @armleads-azure + +# ServiceLabel: %Advisor +#// @mojayara @Prasanna-Padmanabhan + +# ServiceLabel: %Analysis Services +#// @athipp @taiwu @minghan + +# ServiceLabel: %API Management +#// @miaojiang + +# ServiceLabel: %Application Insights +#// @azmonapplicationinsights + +# ServiceLabel: %App Services +#// @antcp @AzureAppServiceCLI + +# ServiceLabel: %App Configuration +#// @shenmuxiaosen @avanigupta + +# ServiceLabel: %ARO +#// @mjudeikis @jim-minter @julienstroheker @amanohar + +# ServiceLabel: %Attestation +#// @anilba06 + +# ServiceLabel: %Authorization +#// @darshanhs90 @AshishGargMicrosoft + +# ServiceLabel: %Automation +#// @zjalexander + +# ServiceLabel: %AVS +#// @divka78 @amitchat @aishu + +# ServiceLabel: %Azure Stack +#// @sijuman @sarathys @bganapa @rakku-ms + +# ServiceLabel: %Batch +#// @mksuni @bgklein @mscurrell @dpwatrous @gingi @paterasMSFT @cRui861 + +# ServiceLabel: %BatchAI +#// @matthchr + +# ServiceLabel: %Billing +#// @cabbpt + +# ServiceLabel: %Blueprint +#// @alex-frankel @filizt + +# ServiceLabel: %Bot Service +#// @sgellock + +# ServiceLabel: %Cloud Shell +#// @maertendMSFT + +# ServiceLabel: %Cognitive - Text Analytics +#// @assafi + +# ServiceLabel: %Cognitive - Form Recognizer +#// @ctstone @anrothMSFT + +# ServiceLabel: %Cognitive - Anomaly Detector +#// @yingqunpku @bowgong + +# ServiceLabel: %Cognitive - Custom Vision +#// @areddish @tburns10 + +# ServiceLabel: %Cognitive - Computer Vision +#// @ryogok @TFR258 @tburns10 + +# ServiceLabel: %Cognitive - Face +#// @JinyuID @dipidoo @SteveMSFT + +# ServiceLabel: %Cognitive - QnA Maker +#// @bingisbestest @nerajput1607 + +# ServiceLabel: %Cognitive - Translator +#// @swmachan + +# ServiceLabel: %Cognitive - Speech +#// @robch @oscholz + +# ServiceLabel: %Cognitive - LUIS +#// @cahann @kayousef + +# ServiceLabel: %Cognitive - Content Moderator +#// @swiftarrow11 + +# ServiceLabel: %Cognitive - Personalizer +#// @dwaijam + +# ServiceLabel: %Cognitive - Immersive Reader +#// @metanMSFT + +# ServiceLabel: %Cognitive - Ink Recognizer +#// @olduroja + +# ServiceLabel: %Cognitive - Bing +#// @jaggerbodas-ms @arwong + +# ServiceLabel: %Cognitive - Mgmt +#// @yangyuan + +# ServiceLabel: %Commerce +#// @ms-premp @qiaozha + +# ServiceLabel: %Compute +#// @Drewm3 @avirishuv @vaibhav-agar @amjads1 + +# ServiceLabel: %Compute - Extensions +#// @Drewm3 @amjads1 + +# ServiceLabel: %Compute - Images +#// @Drewm3 @vaibhav-agar + +# ServiceLabel: %Compute - Managed Disks +#// @Drewm3 @vaibhav-agar + +# ServiceLabel: %Compute - RDFE +#// @Drewm3 @avirishuv + +# ServiceLabel: %Compute - VM +#// @Drewm3 @avirishuv + +# ServiceLabel: %Compute - VMSS +#// @Drewm3 @avirishuv + +# ServiceLabel: %Connected Kubernetes +#// @akashkeshari + +# ServiceLabel: %Container Instances +#// @macolso + +# ServiceLabel: %Container Registry +#// @toddysm @northtyphoon + +# ServiceLabel: %Container Service +#// @qike-ms @jwilder @thomas1206 @seanmck + +# ServiceLabel: %Cosmos +#// @Wmengmsft @MehaKaushik + +# ServiceLabel: %Customer Insights +#// @shefymk + +# ServiceLabel: %Custom Providers +#// @manoharp @MSEvanhi + +# ServiceLabel: %CycleCloud +#// @adriankjohnson + +# ServiceLabel: %Data Bricks +#// @arindamc + +# ServiceLabel: %DataBox +#// @tmvishwajit @matdickson @manuaery @madhurinms + +# ServiceLabel: %DataBox Edge +#// @a-t-mason @ganzee @manuaery + +# ServiceLabel: %Data Catalog +#// @ingave + +# ServiceLabel: %Data Factory +#// @Jingshu923 @zhangyd2015 @Frey-Wang + +# ServiceLabel: %Data Lake +#// @sumantmehtams + +# ServiceLabel: %Data Lake Storage Gen1 +#// @sumantmehtams + +# ServiceLabel: %Data Lake Storage Gen2 +#// @sumantmehtams + +# ServiceLabel: %Data Lake Analytics +#// @idear1203 + +# ServiceLabel: %Data Lake Store +#// @sumantmehtams + +# ServiceLabel: %Data Migration +#// @radjaram @kavitham10 + +# ServiceLabel: %Data Share +#// @raedJarrar @jifems + +# ServiceLabel: %DevOps +#// @narula0781 @ashishonce @romil07 + +# ServiceLabel: %Dev Spaces +#// @yuzorMa @johnsta @greenie-msft + +# ServiceLabel: %Devtestlab +#// @Tanmayeekamath + +# ServiceLabel: %Device Provisioning Service +#// @nberdy + +# ServiceLabel: %Digital Twins +#// @sourabhguha @inesk-vt + +# ServiceLabel: %Event Grid +#// @jfggdl + +# ServiceLabel: %Event Hubs +#// @jfggdl + +# ServiceLabel: %Functions +#// @ahmedelnably @fabiocav + +# ServiceLabel: %Graph.Microsoft +#// @dkershaw10 @baywet + +# ServiceLabel: %Guest Configuration +#// @mgreenegit @vivlingaiah + +# ServiceLabel: %HDInsight +#// @aim-for-better @idear1203 @deshriva + +# ServiceLabel: %HPC Cache +#// @romahamu @omzevall + +# ServiceLabel: %Import Export +#// @madhurinms + +# ServiceLabel: %KeyVault +#// @RandalliLama @schaabs @jlichwa + +# ServiceLabel: %Kubernetes Configuration +#// @NarayanThiru + +# ServiceLabel: %Azure Data Explorer +#// @ilayrn @orhasban @zoharHenMicrosoft @sagivf @Aviv-Yaniv + +# ServiceLabel: %Lab Services +#// @Tanmayeekamath + +# ServiceLabel: %Logic App +#// @Azure/azure-logicapps-team + +# ServiceLabel: %LOUIS +#// @minamnmik + +# ServiceLabel: %Managed Identity +#// @varunkch + +# ServiceLabel: %Machine Learning +#// @azureml-github + +# ServiceLabel: %Machine Learning Compute +#// @azureml-github + +# ServiceLabel: %Machine Learning Experimentation +#// @aashishb + +# ServiceLabel: %Managed Services +#// @Lighthouse-Azure + +# ServiceLabel: %MariaDB +#// @ambhatna @savjani + +# ServiceLabel: %Marketplace Ordering +#// @prbansa + +# ServiceLabel: %Media Services +#// @akucer + +# ServiceLabel: %Migrate +#// @shijojoy + +# ServiceLabel: %Mobile Engagement +#// @kpiteira + +# ServiceLabel: %Monitor +#// @SameergMS @dadunl + +# ServiceLabel: %Monitor - Autoscale +#// @AzMonEssential + +# ServiceLabel: %Monitor - ActivityLogs +#// @AzMonEssential + +# ServiceLabel: %Monitor - Metrics +#// @AzMonEssential + +# ServiceLabel: %Monitor - Diagnostic Settings +#// @AzMonEssential + +# ServiceLabel: %Monitor - Alerts +#// @AzmonAlerts + +# ServiceLabel: %Monitor - ActionGroups +#// @AzmonActionG + +# ServiceLabel: %Monitor - LogAnalytics +#// @AzmonLogA + +# ServiceLabel: %Monitor - ApplicationInsights +#// @azmonapplicationinsights + +# ServiceLabel: %MySQL +#// @ambhatna @savjani + +# ServiceLabel: %Network +#// @aznetsuppgithub + +# ServiceLabel: %Network - Application Gateway +#// @appgwsuppgithub + +# ServiceLabel: %Network - CDN +#// @cdnfdsuppgithub + +# ServiceLabel: %Network - DDOS Protection +#// @ddossuppgithub + +# ServiceLabel: %Network - ExpressRoute +#// @exrsuppgithub + +# ServiceLabel: %Network - Firewall +#// @fwsuppgithub + +# ServiceLabel: %Network - Front Door +#// @cdnfdsuppgithub + +# ServiceLabel: %Network - Load Balancer +#// @slbsupportgithub + +# ServiceLabel: %Network - Virtual Network NAT +#// @vnetsuppgithub + +# ServiceLabel: %Network - Network Watcher +#// @netwatchsuppgithub + +# ServiceLabel: %Network - DNS +#// @dnssuppgithub + +# ServiceLabel: %Network - Traffic Manager +#// @tmsuppgithub + +# ServiceLabel: %Network - VPN Gateway +#// @vpngwsuppgithub + +# ServiceLabel: %Notification Hub +#// @tjsomasundaram + +# ServiceLabel: %Operational Insights +#// @AzmonLogA + +# ServiceLabel: %Policy +#// @aperezcloud @kenieva + +# ServiceLabel: %Policy Insights +#// @kenieva + +# ServiceLabel: %PostgreSQL +#// @sunilagarwal @lfittl-msft @sr-msft @niklarin + +# ServiceLabel: %Recovery Services Backup +#// @pvrk @adityabalaji-msft + +# ServiceLabel: %Recovery Services Site-Recovery +#// @Sharmistha-Rai + +# ServiceLabel: %Redis Cache +#// @yegu-ms + +# ServiceLabel: %Relay +#// @jfggdl + +# ServiceLabel: %Reservations +#// @Rkapso + +# ServiceLabel: %Resource Authorization +#// @darshanhs90 @AshishGargMicrosoft + +# ServiceLabel: %Resource Graph +#// @chiragg4u + +# ServiceLabel: %Resource Health +#// @stephbaron + +# ServiceLabel: %Scheduler +#// @derek1ee + +# ServiceLabel: %Search +#// @brjohnstmsft @bleroy @tjacobhi @markheff @miwelsh + +# ServiceLabel: %Security +#// @chlahav + +# ServiceLabel: %Service Bus +#// @jfggdl @EldertGrootenboer + +# ServiceLabel: %Service Fabric +#// @QingChenmsft @vaishnavk @juhacket + +# ServiceLabel: %Schema Registry +#// @arerlend @alzimmermsft + +# ServiceLabel: %SignalR +#// @sffamily @chenkennt + +# ServiceLabel: %SQL +#// @azureSQLGitHub + +# ServiceLabel: %SQL - VM +#// @azureSQLGitHub + +# ServiceLabel: %SQL - Backup & Restore +#// @azureSQLGitHub + +# ServiceLabel: %SQL - Data Security +#// @azureSQLGitHub + +# ServiceLabel: %SQL - Elastic Jobs +#// @azureSQLGitHub + +# ServiceLabel: %SQL - Managed Instance +#// @azureSQLGitHub + +# ServiceLabel: %SQL - Replication & Failover +#// @azureSQLGitHub + +# ServiceLabel: %Storage +#// @xgithubtriage + +# ServiceLabel: %Storsimple +#// @anoobbacker @ganzee @manuaery @patelkunal + +# ServiceLabel: %Stream Analytics +#// @atpham256 + +# ServiceLabel: %Subscription +#// @anuragdalmia @shilpigautam @ramaganesan-rg + +# ServiceLabel: %Support +#// @shahbj79 @mit2nil @aygoya @ganganarayanan + +# ServiceLabel: %Synapse +#// @wonner @zesluo + +# ServiceLabel: %Tables +#// @klaaslanghout + +# ServiceLabel: %TimeseriesInsights +#// @Shipra1Mishra + +# ServiceLabel: %vFXT +#// @zhusijia26 + +# ServiceLabel: %Web Apps +#// @AzureAppServiceCLI @antcp + +# ServiceLabel: %Network - Virtual Network +#// @vnetsuppgithub + +# ServiceLabel: %Network - Virtual WAN +#// @vwansuppgithub + +# ServiceLabel: %Network - Network Virtual Appliance +#// @nvasuppgithub + +# ServiceLabel: %Network - Bastion +#// @bastionsuppgithub + +# ServiceLabel: %Azure.Spring - Cosmos +#// @kushagraThapar + +# ServiceLabel: %Network - Private Link +#// @privlinksuppgithub + +# ServiceLabel: %Azure Arc enabled servers +#// @rpsqrd @edyoung + +# ServiceLabel: %SecurityInsights +#// @amirkeren + +# ServiceLabel: %IoT - CLI +#// @Azure/azure-iot-cli-triage + +# ServiceLabel: %Communication +#// @acsdevx-msft + +# ServiceLabel: %Cost Management - Budget +#// @ccmaxpcrew + +# ServiceLabel: %Consumption - Budget +#// @ccmaxpcrew + +# ServiceLabel: %Cost Management - Query +#// @ccmixpdevs + +# ServiceLabel: %Consumption - Query +#// @ccmixpdevs + +# ServiceLabel: %Cost Management - Billing +#// @ccmbpxpcrew + +# ServiceLabel: %Consumption - Billing +#// @ccmbpxpcrew + +# ServiceLabel: %Cost Management - UsageDetailsAndExport +#// @TiagoCrewGitHubIssues + +# ServiceLabel: %Consumption - UsageDetailsAndExport +#// @TiagoCrewGitHubIssues + +# ServiceLabel: %Cost Management - RIandShowBack +#// @ccmshowbackdevs + +# ServiceLabel: %Consumption - RIandShowBack +#// @ccmshowbackdevs + +# ServiceLabel: %Monitor - Exporter +#// @cijothomas @reyang @rajkumar-rangaraj @TimothyMothra @vishweshbankwar diff --git a/.github/workflows/event-processor.yml b/.github/workflows/event-processor.yml index befc1d9a2e31..c1b818d7d904 100644 --- a/.github/workflows/event-processor.yml +++ b/.github/workflows/event-processor.yml @@ -55,7 +55,7 @@ jobs: run: > dotnet tool install Azure.Sdk.Tools.GitHubEventProcessor - --version 1.0.0-dev.20230505.2 + --version 1.0.0-dev.20230713.2 --add-source https://pkgs.dev.azure.com/azure-sdk/public/_packaging/azure-sdk-for-net/nuget/v3/index.json --global shell: bash @@ -84,11 +84,12 @@ jobs: - name: Process Action Event run: | - echo $GITHUB_PAYLOAD > payload.json + cat > payload.json << 'EOF' + ${{ toJson(github.event) }} + EOF github-event-processor ${{ github.event_name }} payload.json shell: bash env: - GITHUB_PAYLOAD: ${{ toJson(github.event) }} # This is a temporary secret generated by github # https://docs.github.com/en/actions/security-guides/automatic-token-authentication#about-the-github_token-secret GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/scheduled-event-processor.yml b/.github/workflows/scheduled-event-processor.yml index 53181c5a418c..547a5ce2ca0f 100644 --- a/.github/workflows/scheduled-event-processor.yml +++ b/.github/workflows/scheduled-event-processor.yml @@ -34,7 +34,7 @@ jobs: run: > dotnet tool install Azure.Sdk.Tools.GitHubEventProcessor - --version 1.0.0-dev.20230505.2 + --version 1.0.0-dev.20230713.2 --add-source https://pkgs.dev.azure.com/azure-sdk/public/_packaging/azure-sdk-for-net/nuget/v3/index.json --global shell: bash @@ -64,59 +64,65 @@ jobs: - name: Close Stale Issues Scheduled Event if: github.event.schedule == '0 1 * * *' run: | - echo $GITHUB_PAYLOAD > payload.json + cat > payload.json << 'EOF' + ${{ toJson(github.event) }} + EOF github-event-processor ${{ github.event_name }} payload.json CloseStaleIssues shell: bash env: - GITHUB_PAYLOAD: ${{ toJson(github.event) }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - name: Identify Stale PullRequests Scheduled Event if: github.event.schedule == '0 5 * * FRI' run: | - echo $GITHUB_PAYLOAD > payload.json + cat > payload.json << 'EOF' + ${{ toJson(github.event) }} + EOF github-event-processor ${{ github.event_name }} payload.json IdentifyStalePullRequests shell: bash env: - GITHUB_PAYLOAD: ${{ toJson(github.event) }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - name: Close Stale PullRequests Scheduled Event if: github.event.schedule == '30 2,8,14,20 * * *' run: | - echo $GITHUB_PAYLOAD > payload.json + cat > payload.json << 'EOF' + ${{ toJson(github.event) }} + EOF github-event-processor ${{ github.event_name }} payload.json CloseStalePullRequests shell: bash env: - GITHUB_PAYLOAD: ${{ toJson(github.event) }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - name: Identify Stale Issues Scheduled Event if: github.event.schedule == '30 3,9,15,21 * * *' run: | - echo $GITHUB_PAYLOAD > payload.json + cat > payload.json << 'EOF' + ${{ toJson(github.event) }} + EOF github-event-processor ${{ github.event_name }} payload.json IdentifyStaleIssues shell: bash env: - GITHUB_PAYLOAD: ${{ toJson(github.event) }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - name: Close Addressed Issues Scheduled Event if: github.event.schedule == '30 4,10,16,22 * * *' run: | - echo $GITHUB_PAYLOAD > payload.json + cat > payload.json << 'EOF' + ${{ toJson(github.event) }} + EOF github-event-processor ${{ github.event_name }} payload.json CloseAddressedIssues shell: bash env: - GITHUB_PAYLOAD: ${{ toJson(github.event) }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - name: Lock Closed Issues Scheduled Event if: github.event.schedule == '30 5,11,17,23 * * *' run: | - echo $GITHUB_PAYLOAD > payload.json + cat > payload.json << 'EOF' + ${{ toJson(github.event) }} + EOF github-event-processor ${{ github.event_name }} payload.json LockClosedIssues shell: bash env: - GITHUB_PAYLOAD: ${{ toJson(github.event) }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.gitignore b/.gitignore index 61f01a7c59cf..d33a9a16046a 100644 --- a/.gitignore +++ b/.gitignore @@ -53,3 +53,6 @@ vendor/ # Default Test Proxy Assets restore directory .assets + +# Default Test Proxy tools install directory +.proxy diff --git a/documentation/developer_setup.md b/documentation/developer_setup.md index 6476b9e431a5..2cf8f1fdcc20 100644 --- a/documentation/developer_setup.md +++ b/documentation/developer_setup.md @@ -106,7 +106,7 @@ export-clients: true go: true input-file: license-header: MICROSOFT_MIT_NO_VERSION -module: (e.g. github.com/Azure/azure-sdk-for-go/sdk/keyvault/azkeys) +module: (e.g. github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azkeys) openapi-type: "data-plane" output-folder: use: "@autorest/go@4.0.0-preview.44" @@ -135,7 +135,7 @@ Testing is built into the Go toolchain as well with the `testing` library. The t | playback | `$ENV:AZURE_RECORD_MODE="playback"` | Running tests against recording HTTP interactiosn | | live | `$ENV:AZURE_RECORD_MODE="live"` | Bypassing test proxy, running against live service, and not recording HTTP interactions (used by live pipelines) | -To get started first [install test-proxy][test_proxy_install] via the standalone executable. Then to start the proxy, from the root of the repository, run the command `test-proxy start`. +By default the [recording](recording_package) package will automatically install and run the test proxy server. If there are issues with auto-install or the proxy needs to be run standalone, it can be run manually instead. To get started first [install test-proxy][test_proxy_install] via the standalone executable, then to start the proxy, from the root of the repository, run the command `test-proxy start`. When invoking tests, set the environment variable `PROXY_MANUAL_START` to `true`. ### Test Mode Options @@ -370,7 +370,7 @@ This creates the pipelines that will verify future PRs. The `azure-sdk-for-go` i [directory_structure]: https://azure.github.io/azure-sdk/golang_introduction.html [module_design]: https://azure.github.io/azure-sdk/golang_introduction.html#azure-sdk-module-design [type_declarations]: https://go.dev/ref/spec#Type_declarations -[azkeys_directory]: https://github.com/Azure/azure-sdk-for-go/tree/sdk/keyvault/azkeys/v0.9.0/sdk/keyvault/azkeys +[azkeys_directory]: https://github.com/Azure/azure-sdk-for-go/tree/main/sdk/security/keyvault/azkeys [aztables_directory]: https://github.com/Azure/azure-sdk-for-go/tree/sdk/data/aztables/v1.0.1/sdk/data/aztables [aztemplate]: https://github.com/Azure/azure-sdk-for-go/tree/main/sdk/template/aztemplate [api_design]: https://azure.github.io/azure-sdk/golang_introduction.html#azure-sdk-module-design @@ -380,3 +380,4 @@ This creates the pipelines that will verify future PRs. The `azure-sdk-for-go` i [autorest_intro]: https://github.com/Azure/autorest/blob/main/docs/readme.md [autorest_directives]: https://github.com/Azure/autorest/blob/main/docs/generate/directives.md [test_resources]: https://github.com/Azure/azure-sdk-tools/tree/main/eng/common/TestResources +[recording_package]: https://github.com/Azure/azure-sdk-for-go/tree/main/sdk/internal/recording diff --git a/eng/common/TestResources/README.md b/eng/common/TestResources/README.md index 757c7c337ac5..b63307e24530 100644 --- a/eng/common/TestResources/README.md +++ b/eng/common/TestResources/README.md @@ -89,6 +89,7 @@ Below is an example of how `$templateFileParameters` can be used to pass data fr **Snippet from `test-resources-pre.ps1`** ```powershell +Import-Module -Name ./eng/common/scripts/X509Certificate2 $cert = New-X509Certificate2 -SubjectName 'E=opensource@microsoft.com, CN=Azure SDK, OU=Azure SDK, O=Microsoft, L=Frisco, S=TX, C=US' -ValidDays 3652 # Create new entries in $templateFileParameters $templateFileParameters['ConfidentialLedgerPrincipalPEM'] = Format-X509Certificate2 -Certificate $cert diff --git a/eng/common/pipelines/templates/steps/create-pull-request.yml b/eng/common/pipelines/templates/steps/create-pull-request.yml index df364d447862..57e413c2db78 100644 --- a/eng/common/pipelines/templates/steps/create-pull-request.yml +++ b/eng/common/pipelines/templates/steps/create-pull-request.yml @@ -13,9 +13,9 @@ parameters: PRTitle: not-specified PRBody: '' ScriptDirectory: eng/common/scripts - GHReviewersVariable: '' - GHTeamReviewersVariable: '' - GHAssignessVariable: '' + GHReviewers: '' + GHTeamReviewers: '' + GHAssignees: '' # Multiple labels seperated by comma, e.g. "bug, APIView" PRLabels: '' SkipCheckingForChanges: false @@ -52,8 +52,8 @@ steps: -PRTitle "${{ parameters.PRTitle }}" -PRBody "${{ coalesce(parameters.PRBody, parameters.CommitMsg, parameters.PRTitle) }}" -PRLabels "${{ parameters.PRLabels }}" - -UserReviewers "$(${{ parameters.GHReviewersVariable }})" - -TeamReviewers "$(${{ parameters.GHTeamReviewersVariable }})" - -Assignees "$(${{ parameters.GHAssignessVariable }})" + -UserReviewers "${{ parameters.GHReviewers }}" + -TeamReviewers "${{ parameters.GHTeamReviewers }}" + -Assignees "${{ parameters.GHAssignees }}" -CloseAfterOpenForTesting $${{ coalesce(parameters.CloseAfterOpenForTesting, 'false') }} -OpenAsDraft $${{ parameters.OpenAsDraft }} diff --git a/eng/common/pipelines/templates/steps/docs-metadata-release.yml b/eng/common/pipelines/templates/steps/docs-metadata-release.yml deleted file mode 100644 index 7b6fb183a54e..000000000000 --- a/eng/common/pipelines/templates/steps/docs-metadata-release.yml +++ /dev/null @@ -1,119 +0,0 @@ -# intended to be used as part of a release process -parameters: - - name: ArtifactLocation - type: string - default: 'not-specified' - - name: PackageRepository - type: string - default: 'not-specified' - - name: ReleaseSha - type: string - default: 'not-specified' - - name: RepoId - type: string - default: $(Build.Repository.Name) - - name: WorkingDirectory - type: string - default: '' - - name: ScriptDirectory - type: string - default: eng/common/scripts - - name: TargetDocRepoName - type: string - default: '' - - name: TargetDocRepoOwner - type: string - default: '' - - name: PRBranchName - type: string - default: 'main-rdme' - - name: PRLabels - type: string - default: 'auto-merge' - - name: ArtifactName - type: string - default: '' - - name: Language - type: string - default: '' - - name: DocRepoDestinationPath - type: string - default: '' #usually docs-ref-services/ - - name: CIConfigs - type: string - default: '[]' - - name: GHReviewersVariable - type: string - default: '' - - name: GHTeamReviewersVariable - type: string - default: '' # externally set, as eng-common does not have the identity-resolver. Run as pre-step - - name: OnboardingBranch - type: string - default: '' - - name: CloseAfterOpenForTesting - type: boolean - default: false - - name: SkipPackageJson - type: object - default: false - - name: SparseCheckoutPaths - type: object - default: null - -steps: -- pwsh: | - if ($IsWindows) { - REG ADD HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\FileSystem /f /v LongPathsEnabled /t REG_DWORD /d 1 - git config --system core.longpaths true - } - else { - Write-Host "This script is not executing on Windows, skipping registry modification." - } - displayName: Enable Long Paths if Necessary - -- ${{ if not(parameters.SparseCheckoutPaths) }}: - - pwsh: | - git clone https://github.com/${{ parameters.TargetDocRepoOwner }}/${{ parameters.TargetDocRepoName }} ${{ parameters.WorkingDirectory }}/repo - displayName: Clone Documentation Repository - ignoreLASTEXITCODE: false - -- ${{ if parameters.SparseCheckoutPaths }}: - - template: /eng/common/pipelines/templates/steps/sparse-checkout.yml - parameters: - SkipCheckoutNone: true - Repositories: - - Name: ${{ parameters.TargetDocRepoOwner }}/${{ parameters.TargetDocRepoName }} - WorkingDirectory: ${{ parameters.WorkingDirectory }}/repo - Paths: ${{ parameters.SparseCheckoutPaths }} - -- template: /eng/common/pipelines/templates/steps/set-default-branch.yml - parameters: - WorkingDirectory: ${{ parameters.WorkingDirectory }}/repo -- task: PowerShell@2 - displayName: 'Apply Documentation Updates From Artifact' - inputs: - targetType: filePath - filePath: ${{ parameters.ScriptDirectory }}/update-docs-metadata.ps1 - arguments: > - -ArtifactLocation ${{ parameters.ArtifactLocation }} - -Repository ${{ parameters.PackageRepository }} - -ReleaseSHA ${{ parameters.ReleaseSha }} - -RepoId ${{ parameters.RepoId }} - -WorkDirectory "${{ parameters.WorkingDirectory }}" - -DocRepoLocation "${{ parameters.WorkingDirectory }}/repo" - -Language "${{parameters.Language}}" - -Configs "${{ parameters.CIConfigs }}" - pwsh: true - env: - GH_TOKEN: $(azuresdk-github-pat) - -- template: /eng/common/pipelines/templates/steps/git-push-changes.yml - parameters: - BaseRepoBranch: $(DefaultBranch) - BaseRepoOwner: ${{ parameters.TargetDocRepoOwner }} - CommitMsg: "Update docs metadata and targeting for release of ${{ parameters.ArtifactName }}" - TargetRepoName: ${{ parameters.TargetDocRepoName }} - TargetRepoOwner: ${{ parameters.TargetDocRepoOwner }} - WorkingDirectory: ${{ parameters.WorkingDirectory }}/repo - ScriptDirectory: ${{ parameters.WorkingDirectory }}/${{ parameters.ScriptDirectory }} diff --git a/eng/common/pipelines/templates/steps/docsms-ensure-validation.yml b/eng/common/pipelines/templates/steps/docsms-ensure-validation.yml new file mode 100644 index 000000000000..135352fc3d63 --- /dev/null +++ b/eng/common/pipelines/templates/steps/docsms-ensure-validation.yml @@ -0,0 +1,11 @@ +steps: +# Fail the build if any of the packages failed validation. Valid values are +# "true" or "false" +- pwsh: | + if ('$(DocsMsPackagesAllValid)' -eq 'true') { + Write-Host "All packages passed validation." + } else { + Write-Error "Some packages failed validation." + exit 1 + } + displayName: Check package validation results diff --git a/eng/common/pipelines/templates/steps/sparse-checkout.yml b/eng/common/pipelines/templates/steps/sparse-checkout.yml index cee1fbb2d58e..ab95453954cb 100644 --- a/eng/common/pipelines/templates/steps/sparse-checkout.yml +++ b/eng/common/pipelines/templates/steps/sparse-checkout.yml @@ -46,6 +46,10 @@ steps: git clone --no-checkout --filter=tree:0 https://github.com/$($repository.Name) . } + # Turn off git GC for sparse checkout. Note: The devops checkout task does this by default + Write-Host "git config gc.auto 0" + git config gc.auto 0 + Write-Host "git sparse-checkout init" git sparse-checkout init diff --git a/eng/common/scripts/Delete-RemoteBranches.ps1 b/eng/common/scripts/Delete-RemoteBranches.ps1 index 49cc85cbe909..c79ff03bd983 100644 --- a/eng/common/scripts/Delete-RemoteBranches.ps1 +++ b/eng/common/scripts/Delete-RemoteBranches.ps1 @@ -1,11 +1,9 @@ [CmdletBinding(SupportsShouldProcess)] param( - # The repo owner: e.g. Azure - $RepoOwner, - # The repo name. E.g. azure-sdk-for-java - $RepoName, # Please use the RepoOwner/RepoName format: e.g. Azure/azure-sdk-for-java - $RepoId="$RepoOwner/$RepoName", + $RepoId = "$RepoOwner/$RepoName", + # Upstream repo to check and see if there are existing open PRs from before deleting branch + $UpstreamRepoId, # CentralRepoId the original PR to generate sync PR. E.g Azure/azure-sdk-tools for eng/common $CentralRepoId, # We start from the sync PRs, use the branch name to get the PR number of central repo. E.g. sync-eng/common-()-(). Have group name on PR number. @@ -15,9 +13,11 @@ param( # Date format: e.g. Tuesday, April 12, 2022 1:36:02 PM. Allow to use other date format. [AllowNull()] [DateTime]$LastCommitOlderThan, + [Switch]$DeleteBranchesEvenIfThereIsOpenPR = $false, [Parameter(Mandatory = $true)] $AuthToken ) +Set-StrictMode -version 3 . (Join-Path $PSScriptRoot common.ps1) @@ -44,26 +44,9 @@ foreach ($res in $responses) continue } - # Get all open sync PRs associate with branch. - try { - $head = "${RepoId}:${branchName}" - LogDebug "Operating on branch [ $branchName ]" - $pullRequests = Get-GitHubPullRequests -RepoId $RepoId -State "all" -Head $head -AuthToken $AuthToken - } - catch + # If we have a central PR that created this branch still open still don't delete the branch + if ($CentralRepoId) { - LogError "Get-GitHubPullRequests failed with exception:`n$_" - exit 1 - } - $openPullRequests = $pullRequests | ? { $_.State -eq "open" } - - if (!$CentralRepoId -and $openPullRequests.Count -gt 0) { - LogDebug "CentralRepoId is not configured and found open PRs associate with branch [ $branchName ]. Skipping..." - continue - } - - # check central PR - if ($CentralRepoId) { $pullRequestNumber = $Matches["PrNumber"] # If central PR number found, then skip if (!$pullRequestNumber) { @@ -88,12 +71,33 @@ foreach ($res in $responses) } } - foreach ($openPullRequest in $openPullRequests) { - Write-Host "Open pull Request [ $($openPullRequest.html_url) ] will be closed after branch deletion." + # If this branch has an open PR in the repo or the upstream repo then don't delete + try + { + $head = "${RepoId}:${branchName}" + LogDebug "Operating on branch [ $branchName ]" + $pullRequests = Get-GitHubPullRequests -RepoId $RepoId -State "all" -Head $head -AuthToken $AuthToken + + # check to see if there are any PR's open in the main central repo as well. + if ($UpstreamRepoId) { + $pullRequests += Get-GitHubPullRequests -RepoId $UpstreamRepoId -State "all" -Head $head -AuthToken $AuthToken + } + } + catch + { + LogError "Get-GitHubPullRequests failed with exception:`n$_" + exit 1 + } + $openPullRequests = @($pullRequests | Where-Object { $_.State -eq "open" }) + + if ($openPullRequests.Count -gt 0 -and !$DeleteBranchesEvenIfThereIsOpenPR) { + LogDebug "CentralRepoId is not configured and found open PRs associate with branch [ $branchName ]. Skipping..." + continue } # If there is date filter, then check if branch last commit older than the date. - if ($LastCommitOlderThan) { + if ($LastCommitOlderThan) + { if (!$res.object -or !$res.object.url) { LogWarning "No commit url returned from response. Skipping... " continue @@ -117,10 +121,15 @@ foreach ($res in $responses) } } - try { + foreach ($openPullRequest in $openPullRequests) { + Write-Host "Open pull Request [ $($openPullRequest.html_url) ] will be closed after branch deletion." + } + + try + { if ($PSCmdlet.ShouldProcess("[ $branchName ] in [ $RepoId ]", "Deleting branches on cleanup script")) { Remove-GitHubSourceReferences -RepoId $RepoId -Ref $branch -AuthToken $AuthToken - Write-Host "The branch [ $branchName ] with sha [$($res.object.sha)] in [ $RepoId ] has been deleted." + Write-Host "The branch [ $branchName ] with sha [ $($res.object.sha) ] in [ $RepoId ] has been deleted." } } catch { diff --git a/eng/common/scripts/Helpers/DevOps-WorkItem-Helpers.ps1 b/eng/common/scripts/Helpers/DevOps-WorkItem-Helpers.ps1 index ba299856b2dc..fc0d3497c06a 100644 --- a/eng/common/scripts/Helpers/DevOps-WorkItem-Helpers.ps1 +++ b/eng/common/scripts/Helpers/DevOps-WorkItem-Helpers.ps1 @@ -836,6 +836,15 @@ function UpdatePackageVersions($pkgWorkItem, $plannedVersions, $shippedVersions) $shippedVersionSet[$version.Version] = $version $updateShipped = $true } + else + { + # Check for any date update, general case would from be previous Unknown to date + if ($shippedVersionSet[$version.Version].Date -ne $version.Date) + { + $shippedVersionSet[$version.Version] = $version + $updateShipped = $true + } + } } $versionSet = @{} @@ -889,11 +898,11 @@ function UpdatePackageVersions($pkgWorkItem, $plannedVersions, $shippedVersions) # If we shipped a version after we set "In Release" state then reset the state to "Next Release Unknown" if ($pkgWorkItem.fields["System.State"] -eq "In Release") { - $lastShippedDate = [DateTime]$newShippedVersions[0].Date + $lastShippedDate = $newShippedVersions[0].Date -as [DateTime] $markedInReleaseDate = ([DateTime]$pkgWorkItem.fields["Microsoft.VSTS.Common.StateChangeDate"]) # We just shipped so lets set the state to "Next Release Unknown" - if ($markedInReleaseDate -le $lastShippedDate) + if ($lastShippedDate -and $markedInReleaseDate -le $lastShippedDate) { $fieldUpdates += @' { diff --git a/eng/common/scripts/Helpers/PSModule-Helpers.ps1 b/eng/common/scripts/Helpers/PSModule-Helpers.ps1 index d9a5afaab1b3..bfca8a4154d8 100644 --- a/eng/common/scripts/Helpers/PSModule-Helpers.ps1 +++ b/eng/common/scripts/Helpers/PSModule-Helpers.ps1 @@ -47,6 +47,7 @@ function Update-PSModulePathForCI() } } +# Manual test at eng/common-tests/psmodule-helpers/Install-Module-Parallel.ps1 # If we want to use another default repository other then PSGallery we can update the default parameters function Install-ModuleIfNotInstalled() { @@ -65,35 +66,53 @@ function Install-ModuleIfNotInstalled() if ($modules.Count -eq 0) { - $repositories = (Get-PSRepository).Where({ $_.SourceLocation -eq $repositoryUrl }) - if ($repositories.Count -eq 0) - { - Register-PSRepository -Name $repositoryUrl -SourceLocation $repositoryUrl -InstallationPolicy Trusted - $repositories = (Get-PSRepository).Where({ $_.SourceLocation -eq $repositoryUrl }) - if ($repositories.Count -eq 0) { - Write-Error "Failed to registory package repository $repositoryUrl." - return + # Use double-checked locking to avoid locking when module is already installed + $mutex = New-Object System.Threading.Mutex($false, "Install-ModuleIfNotInstalled") + $null = $mutex.WaitOne() + + try { + # Check installed modules again after acquiring lock + $modules = (Get-Module -ListAvailable $moduleName) + if ($version -as [Version]) { + $modules = $modules.Where({ [Version]$_.Version -ge [Version]$version }) } - } - $repository = $repositories[0] - - if ($repository.InstallationPolicy -ne "Trusted") { - Set-PSRepository -Name $repository.Name -InstallationPolicy "Trusted" - } - Write-Host "Installing module $moduleName with min version $version from $repositoryUrl" - # Install under CurrentUser scope so that the end up under $CurrentUserModulePath for caching - Install-Module $moduleName -MinimumVersion $version -Repository $repository.Name -Scope CurrentUser -Force - - # Ensure module installed - $modules = (Get-Module -ListAvailable $moduleName) - if ($version -as [Version]) { - $modules = $modules.Where({ [Version]$_.Version -ge [Version]$version }) + if ($modules.Count -eq 0) + { + $repositories = (Get-PSRepository).Where({ $_.SourceLocation -eq $repositoryUrl }) + if ($repositories.Count -eq 0) + { + Register-PSRepository -Name $repositoryUrl -SourceLocation $repositoryUrl -InstallationPolicy Trusted + $repositories = (Get-PSRepository).Where({ $_.SourceLocation -eq $repositoryUrl }) + if ($repositories.Count -eq 0) { + Write-Error "Failed to register package repository $repositoryUrl." + return + } + } + $repository = $repositories[0] + + if ($repository.InstallationPolicy -ne "Trusted") { + Set-PSRepository -Name $repository.Name -InstallationPolicy "Trusted" + } + + Write-Host "Installing module $moduleName with min version $version from $repositoryUrl" + # Install under CurrentUser scope so that the end up under $CurrentUserModulePath for caching + Install-Module $moduleName -MinimumVersion $version -Repository $repository.Name -Scope CurrentUser -Force + + # Ensure module installed + $modules = (Get-Module -ListAvailable $moduleName) + if ($version -as [Version]) { + $modules = $modules.Where({ [Version]$_.Version -ge [Version]$version }) + } + + if ($modules.Count -eq 0) { + Write-Error "Failed to install module $moduleName with version $version" + return + } + } } - - if ($modules.Count -eq 0) { - Write-Error "Failed to install module $moduleName with version $version" - return + finally { + $mutex.ReleaseMutex() } } diff --git a/eng/common/scripts/Helpers/Resource-Helpers.ps1 b/eng/common/scripts/Helpers/Resource-Helpers.ps1 index cbeee3bc65c6..6c02e9150e24 100644 --- a/eng/common/scripts/Helpers/Resource-Helpers.ps1 +++ b/eng/common/scripts/Helpers/Resource-Helpers.ps1 @@ -49,7 +49,7 @@ function Get-PurgeableResources { Write-Verbose "Retrieving deleted Managed HSMs from subscription $subscriptionId" # Get deleted Managed HSMs for the current subscription. - $response = Invoke-AzRestMethod -Method GET -Path "/subscriptions/$subscriptionId/providers/Microsoft.KeyVault/deletedManagedHSMs?api-version=2021-04-01-preview" -ErrorAction Ignore + $response = Invoke-AzRestMethod -Method GET -Path "/subscriptions/$subscriptionId/providers/Microsoft.KeyVault/deletedManagedHSMs?api-version=2023-02-01" -ErrorAction Ignore if ($response.StatusCode -ge 200 -and $response.StatusCode -lt 300 -and $response.Content) { $content = $response.Content | ConvertFrom-Json @@ -123,7 +123,7 @@ filter Remove-PurgeableResources { 'Key Vault' { if ($r.EnablePurgeProtection) { # We will try anyway but will ignore errors. - Write-Warning "Key Vault '$($r.VaultName)' has purge protection enabled and may not be purged for $($r.SoftDeleteRetentionInDays) days" + Write-Warning "Key Vault '$($r.VaultName)' has purge protection enabled and may not be purged until $($r.ScheduledPurgeDate)" } # Use `-AsJob` to start a lightweight, cancellable job and pass to `Wait-PurgeableResoruceJob` for consistent behavior. @@ -134,11 +134,11 @@ filter Remove-PurgeableResources { 'Managed HSM' { if ($r.EnablePurgeProtection) { # We will try anyway but will ignore errors. - Write-Warning "Managed HSM '$($r.Name)' has purge protection enabled and may not be purged for $($r.SoftDeleteRetentionInDays) days" + Write-Warning "Managed HSM '$($r.Name)' has purge protection enabled and may not be purged until $($r.ScheduledPurgeDate)" } # Use `GetNewClosure()` on the `-Action` ScriptBlock to make sure variables are captured. - Invoke-AzRestMethod -Method POST -Path "/subscriptions/$subscriptionId/providers/Microsoft.KeyVault/locations/$($r.Location)/deletedManagedHSMs/$($r.Name)/purge?api-version=2021-04-01-preview" -ErrorAction Ignore -AsJob ` + Invoke-AzRestMethod -Method POST -Path "/subscriptions/$subscriptionId/providers/Microsoft.KeyVault/locations/$($r.Location)/deletedManagedHSMs/$($r.Name)/purge?api-version=2023-02-01" -ErrorAction Ignore -AsJob ` | Wait-PurgeableResourceJob -Resource $r -Timeout $Timeout -PassThru:$PassThru -Action { param ( $response ) if ($response.StatusCode -ge 200 -and $response.StatusCode -lt 300) { diff --git a/eng/common/scripts/Save-Package-Properties.ps1 b/eng/common/scripts/Save-Package-Properties.ps1 index 6fb9e61ee0f2..44f622357753 100644 --- a/eng/common/scripts/Save-Package-Properties.ps1 +++ b/eng/common/scripts/Save-Package-Properties.ps1 @@ -10,6 +10,10 @@ an artifact name property is available in the package properties. Can optionally add a dev version property which can be used logic for daily builds. +In cases of collisions where track 2 packages (IsNewSdk = true) have the same +filename as track 1 packages (e.g. same artifact name or package name), the +track 2 package properties will be written. + .PARAMETER serviceDirectory Service directory in which to search for packages @@ -87,6 +91,7 @@ function GetRelativePath($path) { return $relativePath } +$exportedPaths = @{} $allPackageProperties = Get-AllPkgProperties $serviceDirectory if ($allPackageProperties) { @@ -114,6 +119,15 @@ if ($allPackageProperties) Write-Host "Creating directory $($outDir) for json property file" New-Item -ItemType Directory -Path $outDir } + + # If package properties for a track 2 (IsNewSdk = true) package has + # already been written, skip writing to that same path. + if ($exportedPaths.ContainsKey($outputPath) -and $exportedPaths[$outputPath].IsNewSdk -eq $true) { + Write-Host "Track 2 package info with file name $($outputPath) already exported. Skipping export." + continue + } + $exportedPaths[$outputPath] = $pkg + SetOutput $outputPath $pkg } diff --git a/eng/common/scripts/Test-SampleMetadata.ps1 b/eng/common/scripts/Test-SampleMetadata.ps1 index c20396b0a96b..d0a4670113a8 100644 --- a/eng/common/scripts/Test-SampleMetadata.ps1 +++ b/eng/common/scripts/Test-SampleMetadata.ps1 @@ -247,6 +247,7 @@ begin { "azure-network-watcher", "azure-notebooks", "azure-notification-hubs", + "azure-openai", "azure-open-datasets", "azure-personalizer", "azure-pipelines", diff --git a/eng/common/scripts/TypeSpec-Project-Generate.ps1 b/eng/common/scripts/TypeSpec-Project-Generate.ps1 index feba00d37ed8..418221982a36 100644 --- a/eng/common/scripts/TypeSpec-Project-Generate.ps1 +++ b/eng/common/scripts/TypeSpec-Project-Generate.ps1 @@ -5,8 +5,8 @@ param ( [Parameter(Position=0)] [ValidateNotNullOrEmpty()] [string] $ProjectDirectory, - [Parameter(Position=1)] - [string] $typespecAdditionalOptions ## addtional typespec emitter options, separated by semicolon if more than one, e.g. option1=value1;option2=value2 + [string] $TypespecAdditionalOptions = $null, ## addtional typespec emitter options, separated by semicolon if more than one, e.g. option1=value1;option2=value2 + [switch] $SaveInputs = $false ## saves the temporary files during execution, default false ) $ErrorActionPreference = "Stop" @@ -38,13 +38,21 @@ function NpmInstallForProject([string]$workingDirectory) { #default to root/eng/emitter-package.json but you can override by writing #Get-${Language}-EmitterPackageJsonPath in your Language-Settings.ps1 - $replacementPackageJson = "$PSScriptRoot/../../emitter-package.json" + $replacementPackageJson = Join-Path $PSScriptRoot "../../emitter-package.json" if (Test-Path "Function:$GetEmitterPackageJsonPathFn") { $replacementPackageJson = &$GetEmitterPackageJsonPathFn } Write-Host("Copying package.json from $replacementPackageJson") Copy-Item -Path $replacementPackageJson -Destination "package.json" -Force + + $useAlphaNpmRegistry = (Get-Content $replacementPackageJson -Raw).Contains("-alpha.") + + if($useAlphaNpmRegistry) { + Write-Host "Package.json contains '-alpha.' in the version, Creating .npmrc using public/azure-sdk-for-js-test-autorest feed." + "registry=https://pkgs.dev.azure.com/azure-sdk/public/_packaging/azure-sdk-for-js-test-autorest/npm/registry/ `n`nalways-auth=true" | Out-File '.npmrc' + } + npm install --no-lock-file if ($LASTEXITCODE) { exit $LASTEXITCODE } } @@ -80,12 +88,17 @@ try { } } $typespecCompileCommand = "npx tsp compile $mainTypeSpecFile --emit $emitterName$emitterAdditionalOptions" - if ($typespecAdditionalOptions) { - $options = $typespecAdditionalOptions.Split(";"); + if ($TypespecAdditionalOptions) { + $options = $TypespecAdditionalOptions.Split(";"); foreach ($option in $options) { $typespecCompileCommand += " --option $emitterName.$option" } } + + if ($SaveInputs) { + $typespecCompileCommand += " --option $emitterName.save-inputs=true" + } + Write-Host($typespecCompileCommand) Invoke-Expression $typespecCompileCommand @@ -95,7 +108,8 @@ finally { Pop-Location } -$shouldCleanUp = $configuration["cleanup"] ?? $true +$shouldCleanUp = !$SaveInputs if ($shouldCleanUp) { Remove-Item $tempFolder -Recurse -Force } +exit 0 diff --git a/eng/common/scripts/TypeSpec-Project-Process.ps1 b/eng/common/scripts/TypeSpec-Project-Process.ps1 new file mode 100644 index 000000000000..7b894379e925 --- /dev/null +++ b/eng/common/scripts/TypeSpec-Project-Process.ps1 @@ -0,0 +1,228 @@ +# For details see https://github.com/Azure/azure-sdk-tools/blob/main/doc/common/TypeSpec-Project-Scripts.md + +[CmdletBinding()] +param ( + [Parameter(Position = 0)] + [ValidateNotNullOrEmpty()] + [string] $TypeSpecProjectDirectory, # A directory of `tspconfig.yaml` or a remoteUrl of `tspconfig.yaml` + [Parameter(Position = 1)] + [string] $CommitHash, + [Parameter(Position = 2)] + [string] $RepoUrl, + [switch] $SkipSyncAndGenerate +) + +. $PSScriptRoot/common.ps1 +. $PSScriptRoot/Helpers/PSModule-Helpers.ps1 +Install-ModuleIfNotInstalled "powershell-yaml" "0.4.1" | Import-Module + +function CreateUpdate-TspLocation([System.Object]$tspConfig, [string]$TypeSpecProjectDirectory, [string]$CommitHash, [string]$repo, [string]$repoRoot, [ref]$isNewSdkProject) { + $additionalDirs = @() + if ($tspConfig["parameters"]["dependencies"] -and $tspConfig["parameters"]["dependencies"]["additionalDirectories"]) { + $additionalDirs = $tspConfig["parameters"]["dependencies"]["additionalDirectories"]; + } + + # Create service-dir if not exist + $serviceDir = Get-ServiceDir $tspConfig $repoRoot + if (!(Test-Path -Path $serviceDir)) { + New-Item -Path $serviceDir -ItemType Directory | Out-Null + Write-Host "created service folder $serviceDir" + } + + # Create package-dir if not exist + $packageDir = Get-PackageDir $tspConfig + $packageDir = Join-Path $serviceDir $packageDir + if (!(Test-Path -Path $packageDir)) { + New-Item -Path $packageDir -ItemType Directory | Out-Null + Write-Host "created package folder $packageDir" + $isNewSdkProject.Value = $true + } + + # Load tsp-location.yaml if exist + $tspLocationYamlPath = Join-Path $packageDir "tsp-location.yaml" + $tspLocationYaml = @{} + if (Test-Path -Path $tspLocationYamlPath) { + $tspLocationYaml = Get-Content -Path $tspLocationYamlPath -Raw | ConvertFrom-Yaml + } + else { + Write-Host "creating tsp-location.yaml in $packageDir" + } + + # Update tsp-location.yaml + $tspLocationYaml["commit"] = $CommitHash + Write-Host "updated tsp-location.yaml commit to $CommitHash" + $tspLocationYaml["repo"] = $repo + Write-Host "updated tsp-location.yaml repo to $repo" + $tspLocationYaml["directory"] = $TypeSpecProjectDirectory + Write-Host "updated tsp-location.yaml directory to $TypeSpecProjectDirectory" + $tspLocationYaml["additionalDirectories"] = $additionalDirs + Write-Host "updated tsp-location.yaml additionalDirectories to $additionalDirs" + $tspLocationYaml |ConvertTo-Yaml | Out-File $tspLocationYamlPath + Write-Host "finished updating tsp-location.yaml in $packageDir" + return $packageDir +} + +function Get-ServiceDir([System.Object]$tspConfig, [string]$repoRoot) { + $serviceDir = "" + if ($tspConfig["parameters"] -and $tspConfig["parameters"]["service-dir"]) { + $serviceDir = $tspConfig["parameters"]["service-dir"]["default"]; + } + else { + Write-Error "Missing service-dir in parameters section of tspconfig.yaml. Please refer to https://github.com/Azure/azure-rest-api-specs/blob/main/specification/contosowidgetmanager/Contoso.WidgetManager/tspconfig.yaml for the right schema." + exit 1 + } + + # Create service-dir if not exist + $serviceDir = Join-Path $repoRoot $serviceDir + return $serviceDir +} +function Get-PackageDir([System.Object]$tspConfig) { + $emitterName = "" + if (Test-Path "Function:$GetEmitterNameFn") { + $emitterName = &$GetEmitterNameFn + } + else { + Write-Error "Missing $GetEmitterNameFn function in {$Language} SDK repo script." + exit 1 + } + $packageDir = "" + if ($tspConfig["options"] -and $tspConfig["options"]["$emitterName"] -and $tspConfig["options"]["$emitterName"]["package-dir"]) { + $packageDir = $tspConfig["options"]["$emitterName"]["package-dir"] + } + else { + Write-Error "Missing package-dir in $emitterName options of tspconfig.yaml. Please refer to https://github.com/Azure/azure-rest-api-specs/blob/main/specification/contosowidgetmanager/Contoso.WidgetManager/tspconfig.yaml for the right schema." + exit 1 + } + return $packageDir +} + +function Get-TspLocationFolder([System.Object]$tspConfig, [string]$repoRoot) { + $serviceDir = Get-ServiceDir $tspConfig $repoRoot + $packageDir = Get-PackageDir $tspConfig + $packageDir = Join-Path $serviceDir $packageDir + return $packageDir +} + +$sdkRepoRootPath = (Join-Path $PSScriptRoot .. .. ..) +$sdkRepoRootPath = Resolve-Path $sdkRepoRootPath +$sdkRepoRootPath = $sdkRepoRootPath -replace "\\", "/" +$tspConfigPath = Join-Path $sdkRepoRootPath 'tspconfig.yaml' +$tmpTspConfigPath = $tspConfigPath +$repo = "" +$specRepoRoot = "" +$generateFromLocalTypeSpec = $false +$isNewSdkProject = $false +# remote url scenario +# example url of tspconfig.yaml: https://github.com/Azure/azure-rest-api-specs-pr/blob/724ccc4d7ef7655c0b4d5c5ac4a5513f19bbef35/specification/containerservice/Fleet.Management/tspconfig.yaml +if ($TypeSpecProjectDirectory -match '^https://github.com/(?[^/]*/azure-rest-api-specs(-pr)?)/blob/(?[0-9a-f]{40})/(?.*)/tspconfig.yaml$') { + try { + $TypeSpecProjectDirectory = $TypeSpecProjectDirectory -replace "https://github.com/(.*)/(tree|blob)", "https://raw.githubusercontent.com/`$1" + Invoke-WebRequest $TypeSpecProjectDirectory -OutFile $tspConfigPath -MaximumRetryCount 3 + } + catch { + Write-Host "Failed to download '$TypeSpecProjectDirectory'" + Write-Error $_.Exception.Message + return + } + $repo = $Matches["repo"] + $TypeSpecProjectDirectory = $Matches["path"] + $CommitHash = $Matches["commit"] + # TODO support the branch name in url then get the commithash from branch name +} else { + # local path scenario + $tspConfigPath = Join-Path $TypeSpecProjectDirectory "tspconfig.yaml" + if (!(Test-Path $tspConfigPath)) { + Write-Error "Failed to find tspconfig.yaml in '$TypeSpecProjectDirectory'" + exit 1 + } + $TypeSpecProjectDirectory = $TypeSpecProjectDirectory.Replace("\", "/") + if ($TypeSpecProjectDirectory -match "(?^.*)/(?specification/.*)$") { + $TypeSpecProjectDirectory = $Matches["path"] + $specRepoRoot = $Matches["repoRoot"] + } else { + Write-Error "$TypeSpecProjectDirectory doesn't have 'specification' in path." + exit 1 + } + if (!$CommitHash -or !$RepoUrl) { + Write-Warning "Parameter of Commithash or RepoUrl are not provided along with the local path of tspconfig.yaml, trying to re-generate sdk code based on the local type specs." + $generateFromLocalTypeSpec = $true + } + + if ($RepoUrl) { + if ($RepoUrl -match "^(https://github.com/|git@github.com:)(?[^/]*/azure-rest-api-specs(-pr)?).*") { + $repo = $Matches["repo"] + } + else { + Write-Error "Parameter 'RepoUrl' has incorrect value:$RepoUrl. It should be similar like 'https://github.com/Azure/azure-rest-api-specs'" + exit 1 + } + } +} + +$tspConfigYaml = Get-Content $tspConfigPath -Raw | ConvertFrom-Yaml + +# delete the tmporary tspconfig.yaml downloaded from github +if (Test-Path $tmpTspConfigPath) { + Remove-Item $tspConfigPath +} + +$sdkProjectFolder = "" +if ($generateFromLocalTypeSpec) { + Write-Host "Generating sdk code based on local type specs at specRepoRoot: $specRepoRoot." + $sdkProjectFolder = Get-TspLocationFolder $tspConfigYaml $sdkRepoRootPath + $tspLocationYamlPath = Join-Path $sdkProjectFolder "tsp-location.yaml" + if (!(Test-Path -Path $tspLocationYamlPath)) { + # try to create tsp-location.yaml using HEAD commit of the local spec repo + Write-Warning "Failed to find tsp-location.yaml in '$sdkProjectFolder'. Trying to create tsp-location.yaml using HEAD commit of the local spec repo then proceed the sdk generation based upon local typespecs at $specRepoRoot. Alternatively, please make sure to provide CommitHash and RepoUrl parameters when running this script." + # set default repo to Azure/azure-rest-api-specs + $repo = "Azure/azure-rest-api-specs" + try { + Push-Location $specRepoRoot + $CommitHash = $(git rev-parse HEAD) + $gitOriginUrl = (git remote get-url origin) + if ($gitOriginUrl -and $gitOriginUrl -match '(.*)?github.com:(?[^/]*/azure-rest-api-specs(-pr)?)(.git)?') { + $repo = $Matches["repo"] + Write-Host "Found git origin repo: $repo" + } + else { + Write-Warning "Failed to find git origin repo of the local spec repo at specRepoRoot: $specRepoRoot. Using default repo: $repo" + } + } + catch { + Write-Error "Failed to get HEAD commit or remote origin of the local spec repo at specRepoRoot: $specRepoRoot." + exit 1 + } + finally { + Pop-Location + } + $sdkProjectFolder = CreateUpdate-TspLocation $tspConfigYaml $TypeSpecProjectDirectory $CommitHash $repo $sdkRepoRootPath -isNewSdkProject ([ref]$isNewSdkProject) + } +} else { + # call CreateUpdate-TspLocation function + $sdkProjectFolder = CreateUpdate-TspLocation $tspConfigYaml $TypeSpecProjectDirectory $CommitHash $repo $sdkRepoRootPath -isNewSdkProject ([ref]$isNewSdkProject) +} + +# checking skip switch, only skip when it's not a new sdk project as project scaffolding is supported by emitter +if ($SkipSyncAndGenerate -and !$isNewSdkProject) { + Write-Host "Skip calling TypeSpec-Project-Sync.ps1 and TypeSpec-Project-Generate.ps1." +} else { + # call TypeSpec-Project-Sync.ps1 + $syncScript = Join-Path $PSScriptRoot TypeSpec-Project-Sync.ps1 + Write-Host "Calling TypeSpec-Project-Sync.ps1" + & $syncScript $sdkProjectFolder $specRepoRoot | Out-Null + if ($LASTEXITCODE) { + Write-Error "Failed to sync sdk project from $specRepoRoot to $sdkProjectFolder" + exit $LASTEXITCODE + } + + # call TypeSpec-Project-Generate.ps1 + Write-Host "Calling TypeSpec-Project-Generate.ps1" + $generateScript = Join-Path $PSScriptRoot TypeSpec-Project-Generate.ps1 + & $generateScript $sdkProjectFolder | Out-Null + if ($LASTEXITCODE) { + Write-Error "Failed to generate sdk project at $sdkProjectFolder" + exit $LASTEXITCODE + } +} + +return $sdkProjectFolder \ No newline at end of file diff --git a/eng/common/scripts/TypeSpec-Project-Sync.ps1 b/eng/common/scripts/TypeSpec-Project-Sync.ps1 index 0cf2700e6810..0c7427af4ce5 100644 --- a/eng/common/scripts/TypeSpec-Project-Sync.ps1 +++ b/eng/common/scripts/TypeSpec-Project-Sync.ps1 @@ -2,9 +2,11 @@ [CmdletBinding()] param ( - [Parameter(Position=0)] - [ValidateNotNullOrEmpty()] - [string] $ProjectDirectory + [Parameter(Position = 0)] + [ValidateNotNullOrEmpty()] + [string] $ProjectDirectory, + [Parameter(Position = 1)] + [string] $LocalSpecRepoPath ) $ErrorActionPreference = "Stop" @@ -13,115 +15,133 @@ Install-ModuleIfNotInstalled "powershell-yaml" "0.4.1" | Import-Module $sparseCheckoutFile = ".git/info/sparse-checkout" function AddSparseCheckoutPath([string]$subDirectory) { - if (!(Test-Path $sparseCheckoutFile) -or !((Get-Content $sparseCheckoutFile).Contains($subDirectory))) { - Write-Output $subDirectory >> .git/info/sparse-checkout - } + if (!(Test-Path $sparseCheckoutFile) -or !((Get-Content $sparseCheckoutFile).Contains($subDirectory))) { + Write-Output $subDirectory >> .git/info/sparse-checkout + } } function CopySpecToProjectIfNeeded([string]$specCloneRoot, [string]$mainSpecDir, [string]$dest, [string[]]$specAdditionalSubDirectories) { - $source = "$specCloneRoot/$mainSpecDir" - Copy-Item -Path $source -Destination $dest -Recurse -Force - Write-Host "Copying spec from $source to $dest" + $source = Join-Path $specCloneRoot $mainSpecDir + Copy-Item -Path $source -Destination $dest -Recurse -Force + Write-Host "Copying spec from $source to $dest" - foreach ($additionalDir in $specAdditionalSubDirectories) { - $source = "$specCloneRoot/$additionalDir" - Write-Host "Copying spec from $source to $dest" - Copy-Item -Path $source -Destination $dest -Recurse -Force - } + foreach ($additionalDir in $specAdditionalSubDirectories) { + $source = Join-Path $specCloneRoot $additionalDir + Write-Host "Copying spec from $source to $dest" + Copy-Item -Path $source -Destination $dest -Recurse -Force + } } function UpdateSparseCheckoutFile([string]$mainSpecDir, [string[]]$specAdditionalSubDirectories) { - AddSparseCheckoutPath $mainSpecDir - foreach ($subDir in $specAdditionalSubDirectories) { - AddSparseCheckoutPath $subDir - } + AddSparseCheckoutPath $mainSpecDir + foreach ($subDir in $specAdditionalSubDirectories) { + Write-Host "Adding $subDir to sparse checkout" + AddSparseCheckoutPath $subDir + } } function GetGitRemoteValue([string]$repo) { - Push-Location $ProjectDirectory - $result = "" - try { - $gitRemotes = (git remote -v) - foreach ($remote in $gitRemotes) { - if ($remote.StartsWith("origin")) { - if ($remote -match 'https://github.com/\S+') { - $result = "https://github.com/$repo.git" - break - } elseif ($remote -match "git@github.com:\S+"){ - $result = "git@github.com:$repo.git" - break - } else { - throw "Unknown git remote format found: $remote" - } - } + Push-Location $ProjectDirectory + $result = "" + try { + $gitRemotes = (git remote -v) + foreach ($remote in $gitRemotes) { + Write-Host "Checking remote $remote" + if ($remote.StartsWith("origin") -or $remote.StartsWith("main")) { + if ($remote -match 'https://(.*)?github.com/\S+') { + $result = "https://github.com/$repo.git" + break } + elseif ($remote -match "(.*)?git@github.com:\S+") { + $result = "git@github.com:$repo.git" + break + } + else { + throw "Unknown git remote format found: $remote" + } + } } - finally { - Pop-Location - } - - return $result + } + finally { + Pop-Location + } + Write-Host "Found git remote $result" + return $result } function InitializeSparseGitClone([string]$repo) { - git clone --no-checkout --filter=tree:0 $repo . - if ($LASTEXITCODE) { exit $LASTEXITCODE } - git sparse-checkout init - if ($LASTEXITCODE) { exit $LASTEXITCODE } - Remove-Item $sparseCheckoutFile -Force + git clone --no-checkout --filter=tree:0 $repo . + if ($LASTEXITCODE) { exit $LASTEXITCODE } + git sparse-checkout init + if ($LASTEXITCODE) { exit $LASTEXITCODE } + Remove-Item $sparseCheckoutFile -Force } function GetSpecCloneDir([string]$projectName) { - Push-Location $ProjectDirectory - try { - $root = git rev-parse --show-toplevel - } - finally { - Pop-Location - } - - $sparseSpecCloneDir = "$root/../sparse-spec/$projectName" - New-Item $sparseSpecCloneDir -Type Directory -Force | Out-Null - $createResult = Resolve-Path $sparseSpecCloneDir - return $createResult + Push-Location $ProjectDirectory + try { + $root = git rev-parse --show-toplevel + } + finally { + Pop-Location + } + + $sparseSpecCloneDir = "$root/../sparse-spec/$projectName" + New-Item $sparseSpecCloneDir -Type Directory -Force | Out-Null + $createResult = Resolve-Path $sparseSpecCloneDir + return $createResult } $typespecConfigurationFile = Resolve-Path "$ProjectDirectory/tsp-location.yaml" Write-Host "Reading configuration from $typespecConfigurationFile" $configuration = Get-Content -Path $typespecConfigurationFile -Raw | ConvertFrom-Yaml -$pieces = $typespecConfigurationFile.Path.Replace("\","/").Split("/") +$pieces = $typespecConfigurationFile.Path.Replace("\", "/").Split("/") $projectName = $pieces[$pieces.Count - 2] $specSubDirectory = $configuration["directory"] -if ( $configuration["repo"] -and $configuration["commit"]) { - $specCloneDir = GetSpecCloneDir $projectName - $gitRemoteValue = GetGitRemoteValue $configuration["repo"] - - Write-Host "Setting up sparse clone for $projectName at $specCloneDir" - - Push-Location $specCloneDir.Path - try { - if (!(Test-Path ".git")) { - InitializeSparseGitClone $gitRemoteValue - } - UpdateSparseCheckoutFile $specSubDirectory $configuration["additionalDirectories"] - git checkout $configuration["commit"] - if ($LASTEXITCODE) { exit $LASTEXITCODE } - } - finally { - Pop-Location +# use local spec repo if provided +if ($LocalSpecRepoPath) { + $specCloneDir = $LocalSpecRepoPath +} +elseif ($configuration["repo"] -and $configuration["commit"]) { + # use sparse clone if repo and commit are provided + $specCloneDir = GetSpecCloneDir $projectName + $gitRemoteValue = GetGitRemoteValue $configuration["repo"] + + Write-Host "from tsplocation.yaml 'repo' is:"$configuration["repo"] + Write-Host "Setting up sparse clone for $projectName at $specCloneDir" + + Push-Location $specCloneDir.Path + try { + if (!(Test-Path ".git")) { + Write-Host "Initializing sparse clone for repo: $gitRemoteValue" + InitializeSparseGitClone $gitRemoteValue } -} elseif ( $configuration["spec-root-dir"] ) { - $specCloneDir = $configuration["spec-root-dir"] + Write-Host "Updating sparse checkout file with directory:$specSubDirectory" + UpdateSparseCheckoutFile $specSubDirectory $configuration["additionalDirectories"] + $commit = $configuration["commit"] + Write-Host "git checkout commit: $commit" + git checkout $configuration["commit"] + if ($LASTEXITCODE) { exit $LASTEXITCODE } + } + finally { + Pop-Location + } +} +else { + # write error if neither local spec repo nor repo and commit are provided + Write-Error "Must contain both 'repo' and 'commit' in tsp-location.yaml or input 'localSpecRepoPath' parameter." + exit 1 } - $tempTypeSpecDir = "$ProjectDirectory/TempTypeSpecFiles" New-Item $tempTypeSpecDir -Type Directory -Force | Out-Null CopySpecToProjectIfNeeded ` - -specCloneRoot $specCloneDir ` - -mainSpecDir $specSubDirectory ` - -dest $tempTypeSpecDir ` - -specAdditionalSubDirectories $configuration["additionalDirectories"] + -specCloneRoot $specCloneDir ` + -mainSpecDir $specSubDirectory ` + -dest $tempTypeSpecDir ` + -specAdditionalSubDirectories $configuration["additionalDirectories"] + +exit 0 diff --git a/eng/common/scripts/Update-DocsMsMetadata.ps1 b/eng/common/scripts/Update-DocsMsMetadata.ps1 index 8026a5a6e08d..94aa8c1efe1b 100644 --- a/eng/common/scripts/Update-DocsMsMetadata.ps1 +++ b/eng/common/scripts/Update-DocsMsMetadata.ps1 @@ -230,17 +230,40 @@ function UpdateDocsMsMetadataForPackage($packageInfoJsonLocation) { Set-Content -Path $readmeLocation -Value $outputReadmeContent } -# For daily update and release, validate DocsMS publishing using the language-specific validation function -if ($ValidateDocsMsPackagesFn -and (Test-Path "Function:$ValidateDocsMsPackagesFn")) { - Write-Host "Validating the packages..." - - $packageInfos = @($PackageInfoJsonLocations | ForEach-Object { GetPackageInfoJson $_ }) +$allSucceeded = $true +foreach ($packageInfoLocation in $PackageInfoJsonLocations) { - &$ValidateDocsMsPackagesFn -PackageInfos $packageInfos -PackageSourceOverride $PackageSourceOverride -DocValidationImageId $DocValidationImageId -DocRepoLocation $DocRepoLocation -} + if ($ValidateDocsMsPackagesFn -and (Test-Path "Function:$ValidateDocsMsPackagesFn")) { + Write-Host "Validating the packages..." + + $packageInfo = GetPackageInfoJson $packageInfoLocation + # This calls a function named "Validate-${Language}-DocMsPackages" + # declared in common.ps1, implemented in Language-Settings.ps1 + $isValid = &$ValidateDocsMsPackagesFn ` + -PackageInfos $packageInfo ` + -PackageSourceOverride $PackageSourceOverride ` + -DocValidationImageId $DocValidationImageId ` + -DocRepoLocation $DocRepoLocation + + if (!$isValid) { + Write-Host "Package validation failed for package: $packageInfoLocation" + $allSucceeded = $false + + # Skip the later call to UpdateDocsMsMetadataForPackage because this + # package has not passed validation + continue + } + } -foreach ($packageInfoLocation in $PackageInfoJsonLocations) { Write-Host "Updating metadata for package: $packageInfoLocation" # Convert package metadata json file to metadata json property. UpdateDocsMsMetadataForPackage $packageInfoLocation } + +# Set a variable which will be used by the pipeline later to fail the build if +# any packages failed validation +if ($allSucceeded) { + Write-Host "##vso[task.setvariable variable=DocsMsPackagesAllValid;]$true" +} else { + Write-Host "##vso[task.setvariable variable=DocsMsPackagesAllValid;]$false" +} diff --git a/eng/common/scripts/Update-DocsMsPackages.ps1 b/eng/common/scripts/Update-DocsMsPackages.ps1 index ccd531d3bd40..e84c1d56658a 100644 --- a/eng/common/scripts/Update-DocsMsPackages.ps1 +++ b/eng/common/scripts/Update-DocsMsPackages.ps1 @@ -3,16 +3,12 @@ Update docs.microsoft.com CI configuration with provided metadata .DESCRIPTION -Update docs.microsoft.com CI configuration with metadata in the Azure/azure-sdk -metadata CSV file and information in the docs.microsoft.com repo's own /metadata -folder. The docs.microsoft.com repo's /metadata folder allows onboarding of +Update docs.microsoft.com CI configuration with metadata in the docs.microsoft.com repo's +/metadata folder. The docs.microsoft.com repo's /metadata folder allows onboarding of packages which have not released to a central package manager. -* Use packages in the Azure/azure-sdk metadata CSV where New == true and - Hide != true -* Add metadata from files in the metadata/ folder to the CSV metadata * Onboard new packages, update existing tracked packages, leave other packages - in place. (This is implemented on a per-language basis by + in place. (This is implemented on a per-language basis by $UpdateDocsMsPackagesFn) .PARAMETER DocRepoLocation @@ -25,7 +21,7 @@ variable is meant to be used in the domain-specific business logic in &$UpdateDocsMsPackagesFn .PARAMETER ImageId -Optional The docker image for package validation in format of '$containerRegistry/$imageName:$tag'. +Optional The docker image for package validation in format of '$containerRegistry/$imageName:$tag'. e.g. azuresdkimages.azurecr.io/jsrefautocr:latest #> @@ -42,27 +38,27 @@ param ( . (Join-Path $PSScriptRoot common.ps1) -function GetDocsMetadataForMoniker($moniker) { +function GetDocsMetadataForMoniker($moniker) { $searchPath = Join-Path $DocRepoLocation 'metadata' $moniker - if (!(Test-Path $searchPath)) { - return @() + if (!(Test-Path $searchPath)) { + return @() } $paths = Get-ChildItem -Path $searchPath -Filter *.json - $metadata = @() - foreach ($path in $paths) { + $metadata = @() + foreach ($path in $paths) { $fileContents = Get-Content $path -Raw $fileObject = ConvertFrom-Json -InputObject $fileContents $versionGa = '' - $versionPreview = '' - if ($moniker -eq 'latest') { + $versionPreview = '' + if ($moniker -eq 'latest') { $versionGa = $fileObject.Version - } else { + } else { $versionPreview = $fileObject.Version } $entry = @{ - Package = $fileObject.Name; + Package = $fileObject.Name; VersionGA = $versionGa; VersionPreview = $versionPreview; RepoPath = $fileObject.ServiceDirectory; @@ -78,14 +74,12 @@ function GetDocsMetadataForMoniker($moniker) { return $metadata } -function GetDocsMetadata() { - # Read metadata from CSV - $csvMetadata = (Get-CSVMetadata).Where({ ($_.New -eq 'true' -or $_.MSDocService -ne '') -and $_.Hide -ne 'true'}) +function GetDocsMetadata() { # Read metadata from docs repo $metadataByPackage = @{} - foreach ($package in GetDocsMetadataForMoniker 'latest') { - if ($metadataByPackage.ContainsKey($package.Package)) { + foreach ($package in GetDocsMetadataForMoniker 'latest') { + if ($metadataByPackage.ContainsKey($package.Package)) { LogWarning "Duplicate package in latest metadata: $($package.Package)" } Write-Host "Adding latest package: $($package.Package)" @@ -103,37 +97,9 @@ function GetDocsMetadata() { } } - # Override CSV metadata version information before returning - $outputMetadata = @() - foreach ($item in $csvMetadata) { - if ($metadataByPackage.ContainsKey($item.Package)) { - Write-Host "Overriding CSV metadata from docs repo for $($item.Package)" - $matchingPackage = $metadataByPackage[$item.Package] - - # Only update the version from metadata present in the docs repo IF there - # is a specified version. The absence of package metadata in the docs repo - # (e.g. no GA version) does not imply that the CSV metadata is incorrect. - if ($matchingPackage.VersionGA) { - $item.VersionGA = $matchingPackage.VersionGA - } - if ($matchingPackage.VersionPreview) { - $item.VersionPreview = $matchingPackage.VersionPreview - } - } - $outputMetadata += $item - } - - # Add entries present in the docs repo which are not present in CSV. These are - # usually packages which have not yet published a preview or GA version. - foreach ($item in $metadataByPackage.Values) { - $matchingPackagesInCsvMetadata = $csvMetadata.Where({ $_.Package -eq $item.Package }) - if (!$matchingPackagesInCsvMetadata) { - Write-Host "Adding package from docs metadata that is not found in CSV metadata: $($item.Package)" - $outputMetadata += $item - } - } + # TODO - Add a call to GetDocsMetadataForMoniker for 'legacy' when that is implemented - return $outputMetadata + return $metadataByPackage.Values } if ($UpdateDocsMsPackagesFn -and (Test-Path "Function:$UpdateDocsMsPackagesFn")) { @@ -141,13 +107,13 @@ if ($UpdateDocsMsPackagesFn -and (Test-Path "Function:$UpdateDocsMsPackagesFn")) try { $docsMetadata = GetDocsMetadata &$UpdateDocsMsPackagesFn -DocsRepoLocation $DocRepoLocation -DocsMetadata $docsMetadata -PackageSourceOverride $PackageSourceOverride -DocValidationImageId $ImageId - } catch { + } catch { LogError "Exception while updating docs.ms packages" - LogError $_ + LogError $_ LogError $_.ScriptStackTrace exit 1 } - + } else { LogError "The function for '$UpdateFn' was not found.` Make sure it is present in eng/scripts/Language-Settings.ps1 and referenced in eng/common/scripts/common.ps1.` diff --git a/eng/common/scripts/X509Certificate2/README.md b/eng/common/scripts/X509Certificate2/README.md new file mode 100644 index 000000000000..9941994c1c99 --- /dev/null +++ b/eng/common/scripts/X509Certificate2/README.md @@ -0,0 +1,24 @@ +Powershell module for generating self-signed x509 certificates + +Usage: + +```powershell +Import-Module -Name ./eng/common/scripts/X509Certificate2 # assumes $PWD is repo root + +$cert1 = New-X509Certificate2 -SubjectName 'E=opensource@microsoft.com, CN=Azure SDK, OU=Azure SDK, O=Microsoft, L=Redmond, S=WA, C=US' -ValidDays 3652 + +$CaPublicKeyBase64 = $cert1 | Format-X509Certificate2 -Type CertificateBase64 +$CaPrivateKeyPem = $cert1 | Format-X509Certificate2 -Type Pkcs1 +$CaKeyPairPkcs12Base64 = $cert1 | Format-X509Certificate2 -Type Pkcs12Base64 +``` + +With V3 extensions + +```powershell +Import-Module -Name eng/scripts/X509Certificate2.psm1 # assumes $PWD is repo root + +$cert2 = New-X509Certificate2 -SubjectName 'CN=Azure SDK' -SubjectAlternativeNames (New-X509Certificate2SubjectAlternativeNames -EmailAddress azuresdk@microsoft.com) -KeyUsageFlags KeyEncipherment, NonRepudiation, DigitalSignature -CA -TLS -ValidDays 3652 + +$PemCertificateWithV3Extensions = ($cert2 | Format-X509Certificate2 -Type Certificate) + "`n" + ($cert2 | Format-X509Certificate2 -Type Pkcs8) +$CertificateWithV3ExtensionsBase64 = $cert2 | Format-X509Certificate2 -Type CertificateBase64 + ``` diff --git a/eng/common/scripts/X509Certificate2/X509Certificate2.psm1 b/eng/common/scripts/X509Certificate2/X509Certificate2.psm1 new file mode 100644 index 000000000000..f37ba1d58406 --- /dev/null +++ b/eng/common/scripts/X509Certificate2/X509Certificate2.psm1 @@ -0,0 +1,339 @@ +#Requires -Version 6.0 + +using namespace System.Security.Cryptography +using namespace System.Security.Cryptography.X509Certificates +using namespace System.Text + +<# +.Synopsis +Generate an X509 v3 certificate. + +.Description +Generates an [X509Certificate2] from either a subject name, or individual X500 distinguished names. + +.Parameter SubjectName +The entire X500 subject name. + +.Parameter Country +The country e.g., "US". + +.Parameter State +The state or province e.g., "WA". + +.Parameter City +The city or locality e.g., "Redmond". + +.Parameter Organization +The organization e.g., "Microsoft". + +.Parameter Department +The department e.g., "Azure SDK". + +.Parameter CommonName +A common name e.g., "www.microsoft.com". + +.Parameter SubjectAlternativeNames +Additional subject names from New-X509Certificate2SubjectAlternativeNames. + +.Parameter KeySize +Size of the RSA key. + +.Parameter KeyUsageFlags +Additional key usage flags. + +.Parameter CA +Create self-signed certificate authority. + +.Parameter TLS +Create self-signed certificate suitable for TLS. + +.Parameter NotBefore +The start date when the certificate is valid. The default is the current time. + +.Parameter ValidDays +How many days from NotBefore until the certificate expires. + +.Example +New-X509Certificate2 -SubjectName 'E=opensource@microsoft.com, CN=Azure SDK, OU=Azure SDK, O=Microsoft, L=Redmond, S=WA, C=US' -ValidDays 3652 + +Create a self-signed certificate valid for 10 years from now. + +.Example +New-X509Certificate2 -SubjectName 'CN=Azure SDK' -SubjectAlternativeNames (New-X509Certificate2SubjectAlternativeNames -EmailAddress azuresdk@microsoft.com) -KeyUsageFlags KeyEncipherment, NonRepudiation, DigitalSignature -CA -TLS -ValidDays 3652 + +Create a self-signed certificate valid for 10 years from now with an alternative name, additional key usages including TLS connections, and that can sign other certificate requests. +#> +function New-X509Certificate2 { + [CmdletBinding(DefaultParameterSetName='SubjectName')] + [OutputType([System.Security.Cryptography.X509Certificates.X509Certificate2])] + param ( + [Parameter(ParameterSetName='SubjectName', Mandatory=$true, Position=0)] + [string] $SubjectName, + + [Parameter(ParameterSetName='Builder', HelpMessage='Country Name (2 letter code)')] + [Alias('C')] + [string] $Country, + + [Parameter(ParameterSetName='Builder', HelpMessage='State or Province Name (full name)')] + [Alias('S', 'Province')] + [string] $State, + + [Parameter(ParameterSetName='Builder', HelpMessage='Locality Name (eg, city)')] + [Alias('L', 'Locality')] + [string] $City, + + [Parameter(ParameterSetName='Builder', HelpMessage='Organization Name (eg, company)')] + [Alias('O')] + [string] $Organization, + + [Parameter(ParameterSetName='Builder', HelpMessage='Organizational Unit Name (eg, section)')] + [Alias('OU')] + [string] $Department, + + [Parameter(ParameterSetName='Builder', HelpMessage='Common Name (e.g. server FQDN or YOUR name)')] + [Alias('CN')] + [string] $CommonName, + + [Parameter()] + [ValidateNotNull()] + [SubjectAlternativeNameBuilder] $SubjectAlternativeNames, + + [Parameter()] + [ValidateSet(1024, 2048, 4096)] + [int] $KeySize = 2048, + + [Parameter()] + [X509KeyUsageFlags] $KeyUsageFlags, + + [Parameter()] + [switch] $CA, + + [Parameter()] + [switch] $TLS, + + [Parameter()] + [ValidateNotNullOrEmpty()] + [DateTimeOffset] $NotBefore = [DateTimeOffset]::Now, + + [Parameter()] + [ValidateRange(1, [int]::MaxValue)] + [int] $ValidDays = 365 + ) + + if ($PSCmdlet.ParameterSetName -eq 'Builder') { + $sb = [StringBuilder]::new() + if ($Country) { $null = $sb.Append("C=$Country,") } + if ($State) { $null = $sb.Append("S=$State, ") } + if ($City) { $null = $sb.Append("L=$City, ") } + if ($Organization) { $null = $sb.Append("O=$Organization, ") } + if ($Department) { $null = $sb.Append("OU=$Department, ") } + if ($CommonName) { $null = $sb.Append("CN=$CommonName, ") } + + $SubjectName = [X500DistinguishedName]::new($sb.ToString()).Format($false) + } + + $rsa = [RSA]::Create($KeySize) + try { + $req = [CertificateRequest]::new( + [string] $SubjectName, + $rsa, + [HashAlgorithmName]::SHA256, + [RSASignaturePadding]::Pkcs1 + ) + + $req.CertificateExtensions.Add( + [X509BasicConstraintsExtension]::new( + $CA, + $false, + 0, + $true + ) + ) + + if ($SubjectAlternativeNames) { + $req.CertificateExtensions.Add( + $SubjectAlternativeNames.Build($false) + ) + } + + if ($KeyUsageFlags) { + $req.CertificateExtensions.Add( + [X509KeyUsageExtension]::new( + $KeyUsageFlags, + $true + ) + ) + } + + if ($TLS) { + $oids = [OidCollection]::new() + $null = $oids.Add([Oid]::new('1.3.6.1.5.5.7.3.1')) + + $req.CertificateExtensions.Add( + [X509EnhancedKeyUsageExtension]::new( + $oids, + $false + ) + ) + } + + $req.CreateSelfSigned($NotBefore, $NotBefore.AddDays($ValidDays)) + } + finally { + $rsa.Dispose() + } +} + +<# +.Synopsis +Create subject alternative names for New-X509Certificate2. + +.Description +Subject alternative names include DNS names, email addresses, and IP addresses for which a certificate may also authenticate connections. + +.Parameter DnsName +One or more DNS names e.g., "www.microsoft.com". + +.Parameter EmailAddress +One or more email addresses e.g., "opensource@microsoft.com". + +.Parameter IpAddress +One or more IP addresses. + +.Parameter Uri +Additional URIs not covered by other options. + +.Parameter UserPrincipalName +Additional user names not covered by other options. +#> +function New-X509Certificate2SubjectAlternativeNames { + [CmdletBinding()] + [OutputType([System.Security.Cryptography.X509Certificates.SubjectAlternativeNameBuilder])] + param ( + [Parameter()] + [ValidateNotNullOrEmpty()] + [string[]] $DnsName, + + [Parameter()] + [ValidateNotNullOrEmpty()] + [string[]] $EmailAddress, + + [Parameter()] + [ValidateScript({[System.Net.IPAddress]::TryParse($_, [ref] $null)})] + [string[]] $IpAddress, + + [Parameter()] + [ValidateScript({[System.Uri]::TryParse($_, [ref] $null)})] + [string[]] $Uri, + + [Parameter()] + [ValidateNotNullOrEmpty()] + [string[]] $UserPrincipalName + ) + + $subjectAlternativeNames = [SubjectAlternativeNameBuilder]::new() + + foreach ($value in $DnsName) { + $subjectAlternativeNames.AddDnsName($value) + } + + foreach ($value in $EmailAddress) { + $subjectAlternativeNames.AddEmailAddress($value) + } + + foreach ($value in $IpAddress) { + $subjectAlternativeNames.AddIpAddress($value) + } + + foreach ($value in $Uri) { + $subjectAlternativeNames.AddUri($value) + } + + foreach ($value in $UserPrincipalName) { + $subjectAlternativeNames.AddUserPrincipalName($value) + } + + $subjectAlternativeNames +} + +<# +.Synopsis +Exports a certificate to a file. + +.Description +Exports an X509Certificate2 to a file in one of the given formats. + +.Parameter Path +The path to the file to save. + +.Parameter Type +The type of encoding for the file to save. + +.Parameter Certificate +The certificate to save. +#> +function Export-X509Certificate2 { + [CmdletBinding()] + param ( + [Parameter(Mandatory=$true, Position=0)] + [string] $Path, + + [Parameter(Position=1)] + [ValidateSet('Certificate', 'CertificateBase64', 'Pfx', 'Pkcs1', 'Pkcs12', 'Pkcs12Base64', 'Pkcs8', 'PrivateKey')] + [string] $Type = 'Pfx', + + [Parameter(Mandatory=$true, ValueFromPipeline=$true)] + [X509Certificate2] $Certificate + ) + + if ($Type -in 'Pfx', 'Pkcs12') { + $Certificate.Export([X509ContentType]::Pfx) | Set-Content $Path -AsByteStream + } else { + Format-X509Certificate2 -Type $Type -Certificate $Certificate | Set-Content $Path -Encoding ASCII + } +} + +<# +.Synopsis +Formats a certificate. + +.Description +Formats a certificate and prints it to the output buffer e.g., console. Useful for piping to clip.exe in Windows and pasting into code (additional formatting may be required). + +.Parameter Type +The type of encoding for the output. + +.Parameter Certificate +The certificate to format. +#> +function Format-X509Certificate2 { + [CmdletBinding()] + param ( + [Parameter(Position=0)] + [ValidateSet('Certificate', 'CertificateBase64', 'Pkcs1', 'Pkcs12Base64', 'Pkcs8', 'PrivateKey')] + [string] $Type = 'Certificate', + + [Parameter(Mandatory=$true, ValueFromPipeline=$true)] + [X509Certificate2] $Certificate + ) + + function ConvertTo-Pem($tag, $data) { + @" +-----BEGIN $tag----- +$([Convert]::ToBase64String($data, 'InsertLineBreaks')) +-----END $tag----- +"@ + } + + if ($Type -eq 'Certificate') { + ConvertTo-Pem 'CERTIFICATE' $Certificate.RawData + } elseif ($Type -eq 'CertificateBase64') { + [Convert]::ToBase64String($Certificate.RawData, 'InsertLineBreaks') + } elseif ($Type -eq 'Pkcs1') { + ConvertTo-Pem 'RSA PRIVATE KEY' $Certificate.PrivateKey.ExportRSAPrivateKey() + } elseif ($Type -eq 'Pkcs12Base64') { + [Convert]::ToBase64String($Certificate.Export([X509ContentType]::Pfx), 'InsertLineBreaks') + } elseif ($Type -in 'Pkcs8', 'PrivateKey') { + ConvertTo-Pem 'PRIVATE KEY' $Certificate.PrivateKey.ExportPkcs8PrivateKey() + } +} diff --git a/eng/common/scripts/get-codeowners.lib.ps1 b/eng/common/scripts/get-codeowners.lib.ps1 index c34f28bb225b..2fc31e3be091 100644 --- a/eng/common/scripts/get-codeowners.lib.ps1 +++ b/eng/common/scripts/get-codeowners.lib.ps1 @@ -1,6 +1,7 @@ function Get-CodeownersTool([string] $ToolPath, [string] $DevOpsFeed, [string] $ToolVersion) { $codeownersToolCommand = Join-Path $ToolPath "retrieve-codeowners" + Write-Host "Checking for retrieve-codeowners in $ToolPath ..." # Check if the retrieve-codeowners tool exists or not. if (Get-Command $codeownersToolCommand -errorAction SilentlyContinue) { return $codeownersToolCommand @@ -10,15 +11,16 @@ function Get-CodeownersTool([string] $ToolPath, [string] $DevOpsFeed, [string] $ } Write-Host "Installing the retrieve-codeowners tool under tool path: $ToolPath ..." - # Run command under tool path to avoid dotnet tool install command checking .csproj files. + # Run command under tool path to avoid dotnet tool install command checking .csproj files. # This is a bug for dotnet tool command. Issue: https://github.com/dotnet/sdk/issues/9623 Push-Location $ToolPath + Write-Host "Executing: dotnet tool install --tool-path $ToolPath --add-source $DevOpsFeed --version $ToolVersion" dotnet tool install --tool-path $ToolPath --add-source $DevOpsFeed --version $ToolVersion "Azure.Sdk.Tools.RetrieveCodeOwners" | Out-Null Pop-Location # Test to see if the tool properly installed. if (!(Get-Command $codeownersToolCommand -errorAction SilentlyContinue)) { Write-Error "The retrieve-codeowners tool is not properly installed. Please check your tool path: $ToolPath" - return + return } return $codeownersToolCommand } @@ -30,7 +32,7 @@ of that path, as determined by CODEOWNERS file passed in $CodeownersFileLocation param. .PARAMETER TargetPath -Required*. Path to file or directory whose owners are to be determined from a +Required*. Path to file or directory whose owners are to be determined from a CODEOWNERS file. e.g. sdk/core/azure-amqp/ or sdk/core/foo.txt. *for backward compatibility, you might provide $TargetDirectory instead. @@ -45,7 +47,7 @@ Optional. An absolute path to the CODEOWNERS file against which the $TargetPath will be checked to determine its owners. .PARAMETER ToolVersion -Optional. The NuGet package version of the package containing the "retrieve-codeowners" +Optional. The NuGet package version of the package containing the "retrieve-codeowners" tool, around which this script is a wrapper. .PARAMETER ToolPath @@ -60,8 +62,8 @@ https://dev.azure.com/azure-sdk/public/_artifacts/feed/azure-sdk-for-net/NuGet/A Pipeline publishing the NuGet package to the feed, "tools - code-owners-parser": https://dev.azure.com/azure-sdk/internal/_build?definitionId=3188 -.PARAMETER VsoVariable -Optional. If provided, the determined owners, based on $TargetPath matched against CODEOWNERS file at $CodeownersFileLocation, +.PARAMETER VsoVariable +Optional. If provided, the determined owners, based on $TargetPath matched against CODEOWNERS file at $CodeownersFileLocation, will be output to Azure DevOps pipeline log as variable named $VsoVariable. Reference: @@ -80,7 +82,7 @@ function Get-Codeowners( [string] $TargetDirectory, [string] $ToolPath = (Join-Path ([System.IO.Path]::GetTempPath()) "codeowners-tool"), [string] $DevOpsFeed = "https://pkgs.dev.azure.com/azure-sdk/public/_packaging/azure-sdk-for-net/nuget/v3/index.json", - [string] $ToolVersion = "1.0.0-dev.20230306.3", + [string] $ToolVersion = "1.0.0-dev.20230629.2", [string] $VsoVariable = "", [string] $CodeownersFileLocation = "", [switch] $IncludeNonUserAliases @@ -100,12 +102,14 @@ function Get-Codeowners( return ,@() } + $jsonOutputFile = New-TemporaryFile $codeownersToolCommand = Get-CodeownersTool -ToolPath $ToolPath -DevOpsFeed $DevOpsFeed -ToolVersion $ToolVersion - Write-Host "Executing: & $codeownersToolCommand --target-path $TargetPath --codeowners-file-path-or-url $CodeownersFileLocation --exclude-non-user-aliases:$(!$IncludeNonUserAliases)" + Write-Host "Executing: & $codeownersToolCommand --target-path $TargetPath --codeowners-file-path-or-url $CodeownersFileLocation --exclude-non-user-aliases:$(!$IncludeNonUserAliases) --owners-data-output-file $jsonOutputFile" $commandOutput = & $codeownersToolCommand ` --target-path $TargetPath ` --codeowners-file-path-or-url $CodeownersFileLocation ` --exclude-non-user-aliases:$(!$IncludeNonUserAliases) ` + --owners-data-output-file $jsonOutputFile ` 2>&1 if ($LASTEXITCODE -ne 0) { @@ -116,14 +120,15 @@ function Get-Codeowners( Write-Host "Command $codeownersToolCommand executed successfully (exit code = 0). Command output string length: $($commandOutput.length)" } -# Assert: $commandOutput is a valid JSON representing: -# - a single CodeownersEntry, if the $TargetPath was a single path -# - or a dictionary of CodeownerEntries, keyes by each path resolved from a $TargetPath glob path. -# -# For implementation details, see Azure.Sdk.Tools.RetrieveCodeOwners.Program.Main + # Assert: $commandOutput is a valid JSON representing: + # - a single CodeownersEntry, if the $TargetPath was a single path + # - or a dictionary of CodeownerEntries, keyes by each path resolved from a $TargetPath glob path. + # + # For implementation details, see Azure.Sdk.Tools.RetrieveCodeOwners.Program.Main + + $fileContents = Get-Content $jsonOutputFile -Raw + $codeownersJson = ConvertFrom-Json -InputObject $fileContents -$codeownersJson = $commandOutput | ConvertFrom-Json - if ($VsoVariable) { $codeowners = $codeownersJson.Owners -join "," Write-Host "##vso[task.setvariable variable=$VsoVariable;]$codeowners" diff --git a/eng/common/scripts/stress-testing/deploy-stress-tests.ps1 b/eng/common/scripts/stress-testing/deploy-stress-tests.ps1 index bc028f26aa10..8abaa40d0cb4 100644 --- a/eng/common/scripts/stress-testing/deploy-stress-tests.ps1 +++ b/eng/common/scripts/stress-testing/deploy-stress-tests.ps1 @@ -1,16 +1,14 @@ -# Set a default parameter set here so we can call this script without requiring -Login and -Subscription, -# but if it IS called with either of those, then both parameters need to be required. Not defining a -# default parameter set makes Login/Subscription required all the time. +# Not defining a default parameter set makes SkipLogin/Subscription required all the time. [CmdletBinding(DefaultParameterSetName = 'Default')] param( [string]$SearchDirectory, [hashtable]$Filters, [string]$Environment, [string]$Repository, - [switch]$PushImages, + [switch]$SkipPushImages, [string]$ClusterGroup, [string]$DeployId, - [switch]$Login, + [switch]$SkipLogin, [string]$Subscription, # Default to true in Azure Pipelines environments diff --git a/eng/common/scripts/stress-testing/stress-test-deployment-lib.ps1 b/eng/common/scripts/stress-testing/stress-test-deployment-lib.ps1 index 5ad163c6a848..0f5ae468a98c 100644 --- a/eng/common/scripts/stress-testing/stress-test-deployment-lib.ps1 +++ b/eng/common/scripts/stress-testing/stress-test-deployment-lib.ps1 @@ -43,7 +43,7 @@ function RunOrExitOnFailure() } } -function Login([string]$subscription, [string]$clusterGroup, [switch]$pushImages) +function Login([string]$subscription, [string]$clusterGroup, [switch]$skipPushImages) { Write-Host "Logging in to subscription, cluster and container registry" az account show *> $null @@ -73,10 +73,10 @@ function Login([string]$subscription, [string]$clusterGroup, [switch]$pushImages RunOrExitOnFailure kubectl config set-context $clusterName --namespace $defaultNamespace } - if ($pushImages) { + if (!$skipPushImages) { $registry = RunOrExitOnFailure az acr list -g $clusterGroup --subscription $subscription -o json $registryName = ($registry | ConvertFrom-Json).name - RunOrExitOnFailure az acr login -n $registryName + RunOrExitOnFailure az acr login -n $registryName --subscription $subscription } } @@ -86,10 +86,10 @@ function DeployStressTests( # Default to playground environment [string]$environment = 'pg', [string]$repository = '', - [switch]$pushImages, + [switch]$skipPushImages, [string]$clusterGroup = '', [string]$deployId = '', - [switch]$login, + [switch]$skipLogin, [string]$subscription = '', [switch]$CI, [string]$Namespace, @@ -125,8 +125,8 @@ function DeployStressTests( throw "clusterGroup and subscription parameters must be specified when deploying to an environment that is not pg or prod." } - if ($login) { - Login -subscription $subscription -clusterGroup $clusterGroup -pushImages:$pushImages + if (!$skipLogin) { + Login -subscription $subscription -clusterGroup $clusterGroup -skipPushImages:$skipPushImages } $chartRepoName = 'stress-test-charts' @@ -162,8 +162,8 @@ function DeployStressTests( -deployId $deployer ` -environment $environment ` -repositoryBase $repository ` - -pushImages:$pushImages ` - -login:$login ` + -skipPushImages:$skipPushImages ` + -skipLogin:$skipLogin ` -clusterGroup $clusterGroup ` -subscription $subscription } @@ -189,8 +189,8 @@ function DeployStressPackage( [string]$deployId, [string]$environment, [string]$repositoryBase, - [switch]$pushImages, - [switch]$login, + [switch]$skipPushImages, + [switch]$skipLogin, [string]$clusterGroup, [string]$subscription ) { @@ -267,10 +267,13 @@ function DeployStressPackage( } $dockerfileName = ($dockerFilePath -split { $_ -in '\', '/' })[-1].ToLower() $imageTag = $imageTagBase + "/${dockerfileName}:${deployId}" - if ($pushImages) { + if (!$skipPushImages) { Write-Host "Building and pushing stress test docker image '$imageTag'" $dockerFile = Get-ChildItem $dockerFilePath + Write-Host "Setting DOCKER_BUILDKIT=1" + $env:DOCKER_BUILDKIT = 1 + $dockerBuildCmd = "docker", "build", "-t", $imageTag, "-f", $dockerFile foreach ($buildArg in $dockerBuildConfig.scenario.GetEnumerator()) { $dockerBuildCmd += "--build-arg" @@ -290,8 +293,8 @@ function DeployStressPackage( Run docker push $imageTag if ($LASTEXITCODE) { - if ($login) { - Write-Warning "If docker push is failing due to authentication issues, try calling this script with '-Login'" + if (!$skipLogin) { + Write-Warning "If docker push is failing due to authentication issues, try calling this script without '-SkipLogin'" } } } @@ -387,6 +390,21 @@ function CheckDependencies() throw "Please update helm to version >= $MIN_HELM_VERSION (current version: $helmVersionString)`nAdditional information for updating helm version can be found here: https://helm.sh/docs/intro/install/" } + # Ensure docker is running via command and handle command hangs + if (!$skipPushImages) { + $LastErrorActionPreference = $ErrorActionPreference + $ErrorActionPreference = 'Continue' + $job = Start-Job { docker ps; return $LASTEXITCODE } + $result = $job | Wait-Job -Timeout 5 | Receive-Job + + $ErrorActionPreference = $LastErrorActionPreference + $job | Remove-Job -Force + + if (($result -eq $null -and $job.State -ne "Completed") -or ($result | Select -Last 1) -ne 0) { + throw "Docker does not appear to be running. Start/restart docker." + } + } + if ($shouldError) { exit 1 } diff --git a/eng/common/spelling/package-lock.json b/eng/common/spelling/package-lock.json index 73aa96879e91..a98640c417bd 100644 --- a/eng/common/spelling/package-lock.json +++ b/eng/common/spelling/package-lock.json @@ -15,30 +15,30 @@ } }, "node_modules/@babel/code-frame": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.18.6.tgz", - "integrity": "sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.5.tgz", + "integrity": "sha512-Xmwn266vad+6DAqEB2A6V/CcZVp62BbwVmcOJc2RPuwih1kw02TjQvWVWlcKGbBPd+8/0V5DEkOcizRGYsspYQ==", "dependencies": { - "@babel/highlight": "^7.18.6" + "@babel/highlight": "^7.22.5" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.19.1", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz", - "integrity": "sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.5.tgz", + "integrity": "sha512-aJXu+6lErq8ltp+JhkJUfk1MTGyuA4v7f3pA+BJ5HLfNC6nAQ0Cpi9uOquUj8Hehg0aUiHzWQbOVJGao6ztBAQ==", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/highlight": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz", - "integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.5.tgz", + "integrity": "sha512-BSKlD1hgnedS5XRnGOljZawtag7H1yPfQp0tdNJCHoH6AZ+Pcm9VvkrK59/Yy593Ypg0zMxH2BxD1VPYUQ7UIw==", "dependencies": { - "@babel/helper-validator-identifier": "^7.18.6", + "@babel/helper-validator-identifier": "^7.22.5", "chalk": "^2.0.0", "js-tokens": "^4.0.0" }, @@ -103,150 +103,164 @@ } }, "node_modules/@cspell/cspell-bundled-dicts": { - "version": "6.12.0", - "resolved": "https://registry.npmjs.org/@cspell/cspell-bundled-dicts/-/cspell-bundled-dicts-6.12.0.tgz", - "integrity": "sha512-myfsDwSJcAMjKbztKBG424wIp/YV9/lvxsgHFKxBGPi+nNx1p7TbOjAAO9EWk0mZVHyGKZwCFJS2ohkoqxJWoQ==", - "dependencies": { - "@cspell/dict-ada": "^2.0.1", - "@cspell/dict-aws": "^2.0.0", - "@cspell/dict-bash": "^2.0.4", - "@cspell/dict-companies": "^2.0.14", - "@cspell/dict-cpp": "^3.2.1", - "@cspell/dict-cryptocurrencies": "^2.0.0", - "@cspell/dict-csharp": "^3.0.1", - "@cspell/dict-css": "^2.1.0", - "@cspell/dict-dart": "^1.1.1", - "@cspell/dict-django": "^2.0.0", - "@cspell/dict-docker": "^1.1.1", - "@cspell/dict-dotnet": "^2.0.1", - "@cspell/dict-elixir": "^2.0.1", - "@cspell/dict-en_us": "^2.3.3", - "@cspell/dict-en-gb": "^1.1.33", - "@cspell/dict-filetypes": "^2.1.1", - "@cspell/dict-fonts": "^2.1.0", - "@cspell/dict-fullstack": "^2.0.6", - "@cspell/dict-git": "^1.0.1", - "@cspell/dict-golang": "^3.0.1", - "@cspell/dict-haskell": "^2.0.1", - "@cspell/dict-html": "^3.3.2", - "@cspell/dict-html-symbol-entities": "^3.0.0", - "@cspell/dict-java": "^3.0.7", - "@cspell/dict-latex": "^2.0.9", - "@cspell/dict-lorem-ipsum": "^2.0.1", - "@cspell/dict-lua": "^2.0.0", - "@cspell/dict-node": "^3.0.1", - "@cspell/dict-npm": "^3.1.2", - "@cspell/dict-php": "^2.0.0", - "@cspell/dict-powershell": "^2.0.0", - "@cspell/dict-public-licenses": "^1.0.6", - "@cspell/dict-python": "^3.0.6", - "@cspell/dict-r": "^1.0.3", - "@cspell/dict-ruby": "^2.0.2", - "@cspell/dict-rust": "^2.0.1", - "@cspell/dict-scala": "^2.0.0", - "@cspell/dict-software-terms": "^2.2.11", - "@cspell/dict-sql": "^1.0.4", - "@cspell/dict-swift": "^1.0.3", - "@cspell/dict-typescript": "^2.0.2", - "@cspell/dict-vue": "^2.0.2" + "version": "6.31.2", + "resolved": "https://registry.npmjs.org/@cspell/cspell-bundled-dicts/-/cspell-bundled-dicts-6.31.2.tgz", + "integrity": "sha512-rQ5y/U1Ah5AaduIh3NU2z371hRrOr1cmNdhhP8oiuz2E4VqmcoVHflXIct9DgY8uIJpwsSCdR6ypOQWZYXYnwA==", + "dependencies": { + "@cspell/dict-ada": "^4.0.1", + "@cspell/dict-aws": "^3.0.0", + "@cspell/dict-bash": "^4.1.1", + "@cspell/dict-companies": "^3.0.9", + "@cspell/dict-cpp": "^5.0.2", + "@cspell/dict-cryptocurrencies": "^3.0.1", + "@cspell/dict-csharp": "^4.0.2", + "@cspell/dict-css": "^4.0.5", + "@cspell/dict-dart": "^2.0.2", + "@cspell/dict-django": "^4.0.2", + "@cspell/dict-docker": "^1.1.6", + "@cspell/dict-dotnet": "^5.0.0", + "@cspell/dict-elixir": "^4.0.2", + "@cspell/dict-en_us": "^4.3.2", + "@cspell/dict-en-common-misspellings": "^1.0.2", + "@cspell/dict-en-gb": "1.1.33", + "@cspell/dict-filetypes": "^3.0.0", + "@cspell/dict-fonts": "^3.0.2", + "@cspell/dict-fullstack": "^3.1.5", + "@cspell/dict-gaming-terms": "^1.0.4", + "@cspell/dict-git": "^2.0.0", + "@cspell/dict-golang": "^6.0.1", + "@cspell/dict-haskell": "^4.0.1", + "@cspell/dict-html": "^4.0.3", + "@cspell/dict-html-symbol-entities": "^4.0.0", + "@cspell/dict-java": "^5.0.5", + "@cspell/dict-k8s": "^1.0.1", + "@cspell/dict-latex": "^4.0.0", + "@cspell/dict-lorem-ipsum": "^3.0.0", + "@cspell/dict-lua": "^4.0.1", + "@cspell/dict-node": "^4.0.2", + "@cspell/dict-npm": "^5.0.5", + "@cspell/dict-php": "^4.0.1", + "@cspell/dict-powershell": "^5.0.1", + "@cspell/dict-public-licenses": "^2.0.2", + "@cspell/dict-python": "^4.0.2", + "@cspell/dict-r": "^2.0.1", + "@cspell/dict-ruby": "^5.0.0", + "@cspell/dict-rust": "^4.0.1", + "@cspell/dict-scala": "^5.0.0", + "@cspell/dict-software-terms": "^3.1.6", + "@cspell/dict-sql": "^2.1.0", + "@cspell/dict-svelte": "^1.0.2", + "@cspell/dict-swift": "^2.0.1", + "@cspell/dict-typescript": "^3.1.1", + "@cspell/dict-vue": "^3.0.0" }, "engines": { "node": ">=14" } }, "node_modules/@cspell/cspell-pipe": { - "version": "6.12.0", - "resolved": "https://registry.npmjs.org/@cspell/cspell-pipe/-/cspell-pipe-6.12.0.tgz", - "integrity": "sha512-Nkm+tIJ5k+jZPovZCdmZhrWrwRFwnDq+7yCxhov0C7UX3hsSNtTJIpFuaCNEQJ+Whpvxdh1YKflvHiHYygEgTg==", + "version": "6.31.1", + "resolved": "https://registry.npmjs.org/@cspell/cspell-pipe/-/cspell-pipe-6.31.1.tgz", + "integrity": "sha512-zk1olZi4dr6GLm5PAjvsiZ01HURNSruUYFl1qSicGnTwYN8GaN4RhAwannAytcJ7zJPIcyXlid0YsB58nJf3wQ==", "engines": { "node": ">=14" } }, "node_modules/@cspell/cspell-service-bus": { - "version": "6.12.0", - "resolved": "https://registry.npmjs.org/@cspell/cspell-service-bus/-/cspell-service-bus-6.12.0.tgz", - "integrity": "sha512-GgvciSeMUekl8z8vP8//cs5/qRQJSLz9IVREf6fxQW4upjw6zXZ1KonwPqOF5uLocIMAr8eCdrJzHKuKvigJIA==", + "version": "6.31.1", + "resolved": "https://registry.npmjs.org/@cspell/cspell-service-bus/-/cspell-service-bus-6.31.1.tgz", + "integrity": "sha512-YyBicmJyZ1uwKVxujXw7sgs9x+Eps43OkWmCtDZmZlnq489HdTSuhF1kTbVi2yeFSeaXIS87+uHo12z97KkQpg==", "engines": { "node": ">=14" } }, "node_modules/@cspell/cspell-types": { - "version": "6.12.0", - "resolved": "https://registry.npmjs.org/@cspell/cspell-types/-/cspell-types-6.12.0.tgz", - "integrity": "sha512-BcZTt05fNy9SGXfbPgUyxS4FfIaUpcVq8IOJ0noN+jsKsmlbssOUgJOB2ApN1h66FfWcKuFy/uNrjfcrQ7PTqg==", + "version": "6.31.1", + "resolved": "https://registry.npmjs.org/@cspell/cspell-types/-/cspell-types-6.31.1.tgz", + "integrity": "sha512-1KeTQFiHMssW1eRoF2NZIEg4gPVIfXLsL2+VSD/AV6YN7lBcuf6gRRgV5KWYarhxtEfjxhDdDTmu26l/iJEUtw==", "engines": { "node": ">=14" } }, "node_modules/@cspell/dict-ada": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@cspell/dict-ada/-/dict-ada-2.0.1.tgz", - "integrity": "sha512-vopTJ1oHrrFYV5GU55Sr+AzItR78Uj5YbCaspYABmYKlq4NRrcUAUsr4bWgymDcspMIHO7e7IFcj48OKs1fndA==" + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@cspell/dict-ada/-/dict-ada-4.0.1.tgz", + "integrity": "sha512-/E9o3nHrXOhYmQE43deKbxZcR3MIJAsa+66IzP9TXGHheKEx8b9dVMVVqydDDH8oom1H0U20NRPtu6KRVbT9xw==" }, "node_modules/@cspell/dict-aws": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@cspell/dict-aws/-/dict-aws-2.0.0.tgz", - "integrity": "sha512-NKz7pDZ7pwj/b33i3f4WLpC1rOOUMmENwYgftxU+giU2YBeKM2wZbMTSEIzsrel56r0UlQYmdIVlP/B4nnVaoQ==" + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@cspell/dict-aws/-/dict-aws-3.0.0.tgz", + "integrity": "sha512-O1W6nd5y3Z00AMXQMzfiYrIJ1sTd9fB1oLr+xf/UD7b3xeHeMeYE2OtcWbt9uyeHim4tk+vkSTcmYEBKJgS5bQ==" }, "node_modules/@cspell/dict-bash": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@cspell/dict-bash/-/dict-bash-2.0.4.tgz", - "integrity": "sha512-uK/ehmp5LYrmRH2Gv3nbvdPswpkybJUn34WYKLpeuYHQktmi+pOI1A9uPdBPnSbMDffSvwQlQohIyKawz+X8Ag==" + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/@cspell/dict-bash/-/dict-bash-4.1.1.tgz", + "integrity": "sha512-8czAa/Mh96wu2xr0RXQEGMTBUGkTvYn/Pb0o+gqOO1YW+poXGQc3gx0YPqILDryP/KCERrNvkWUJz3iGbvwC2A==" }, "node_modules/@cspell/dict-companies": { - "version": "2.0.14", - "resolved": "https://registry.npmjs.org/@cspell/dict-companies/-/dict-companies-2.0.14.tgz", - "integrity": "sha512-Sq1X29Z05OZ/UNqTwVhf3/WaqvJQy4/S6gS8qYI5AQRX45gVe8CPhNBLmZOTC6z8m716bfQCxa5rRT9YNSdTZg==" + "version": "3.0.17", + "resolved": "https://registry.npmjs.org/@cspell/dict-companies/-/dict-companies-3.0.17.tgz", + "integrity": "sha512-vo1jbozgZWSzz2evIL26kLd35tVb+5kW/UTvTzAwaWutSWRloRyKx38nj2CaLJ2IFxBdiATteCFGTzKCvJJl6A==" }, "node_modules/@cspell/dict-cpp": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/@cspell/dict-cpp/-/dict-cpp-3.2.1.tgz", - "integrity": "sha512-XcmzrKIghqFfrYLLaHtWKOp9rupiuGdc5ODONk+emsq0W5CIc3Abn27IQHwUzxzF+Cm5IfKAIJ5Kpe6hkzm0HQ==" + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/@cspell/dict-cpp/-/dict-cpp-5.0.3.tgz", + "integrity": "sha512-7sx/RFsf0hB3q8chx8OHYl9Kd+g0pqA1laphwaAQ+/jPwoAreYT3kNQWbJ3bIt/rMoORetFSQxckSbaJXwwqpw==" }, "node_modules/@cspell/dict-cryptocurrencies": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@cspell/dict-cryptocurrencies/-/dict-cryptocurrencies-2.0.0.tgz", - "integrity": "sha512-nREysmmfOp7L2YCRAUufQahwD5/Punzb5AZ6eyg4zUamdRWHgBFphb5/9h2flt1vgdUfhc6hZcML21Ci7iXjaA==" + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@cspell/dict-cryptocurrencies/-/dict-cryptocurrencies-3.0.1.tgz", + "integrity": "sha512-Tdlr0Ahpp5yxtwM0ukC13V6+uYCI0p9fCRGMGZt36rWv8JQZHIuHfehNl7FB/Qc09NCF7p5ep0GXbL+sVTd/+w==" }, "node_modules/@cspell/dict-csharp": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@cspell/dict-csharp/-/dict-csharp-3.0.1.tgz", - "integrity": "sha512-xkfQu03F388w4sdVQSSjrVMkxAxpTYB2yW7nw0XYtTjl3L/jBgvTr/j1BTjdFbQhdNf10Lg0Ak1kXOjmHodVqA==" + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@cspell/dict-csharp/-/dict-csharp-4.0.2.tgz", + "integrity": "sha512-1JMofhLK+4p4KairF75D3A924m5ERMgd1GvzhwK2geuYgd2ZKuGW72gvXpIV7aGf52E3Uu1kDXxxGAiZ5uVG7g==" }, "node_modules/@cspell/dict-css": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@cspell/dict-css/-/dict-css-2.1.0.tgz", - "integrity": "sha512-glASAELcGhh4Ru0rTQ4G9mTQxSyPwsZOON/5BYflB6Kks8YC8nUvKrtMCoo5W7CPKPfSEa8zUNctFQ1+IUYDHA==" + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/@cspell/dict-css/-/dict-css-4.0.6.tgz", + "integrity": "sha512-2Lo8W2ezHmGgY8cWFr4RUwnjbndna5mokpCK/DuxGILQnuajR0J31ANQOXj/8iZM2phFB93ZzMNk/0c04TDfSQ==" }, "node_modules/@cspell/dict-dart": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@cspell/dict-dart/-/dict-dart-1.1.1.tgz", - "integrity": "sha512-XBOCpezXrgFN18kGEwqMpTUGZdw4BjCoJrNOo6qBdcdZySCrEHLwELraLOkcSba2kM4stmTp0t59FkwtP8TKOA==" + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@cspell/dict-dart/-/dict-dart-2.0.2.tgz", + "integrity": "sha512-jigcODm7Z4IFZ4vParwwP3IT0fIgRq/9VoxkXfrxBMsLBGGM2QltHBj7pl+joX+c4cOHxfyZktGJK1B1wFtR4Q==" + }, + "node_modules/@cspell/dict-data-science": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/@cspell/dict-data-science/-/dict-data-science-1.0.7.tgz", + "integrity": "sha512-Q9VUFaarUpqM6CAmR8peP4o9alk0XQ4rgVoE2R2XalpC2cqPI8Hmg6QwMU2UPioSUcWMJCqLc/KzJti0gBMuxA==" }, "node_modules/@cspell/dict-django": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@cspell/dict-django/-/dict-django-2.0.0.tgz", - "integrity": "sha512-GkJdJv6cmzrKcmq2/oxTXjKF5uv71r4eTqnFmgPbNBW1t+G4VYpzOf0QrVQrhx2RC4DdW5XfcTf+iS0FxHOTmw==" + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@cspell/dict-django/-/dict-django-4.1.0.tgz", + "integrity": "sha512-bKJ4gPyrf+1c78Z0Oc4trEB9MuhcB+Yg+uTTWsvhY6O2ncFYbB/LbEZfqhfmmuK/XJJixXfI1laF2zicyf+l0w==" }, "node_modules/@cspell/dict-docker": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@cspell/dict-docker/-/dict-docker-1.1.1.tgz", - "integrity": "sha512-UEYoeRDm7oUN9yz1mYSozz6D4+2N14S/cd2Re9et6Xzq6yi62s4ky3knF92Of2weelADjnN41UA22VBhRAf7Sw==" + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/@cspell/dict-docker/-/dict-docker-1.1.6.tgz", + "integrity": "sha512-zCCiRTZ6EOQpBnSOm0/3rnKW1kCcAUDUA7SxJG3SuH6iZvKi3I8FEg8+O83WQUeXg0SyPNerD9F40JLnnJjJig==" }, "node_modules/@cspell/dict-dotnet": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@cspell/dict-dotnet/-/dict-dotnet-2.0.1.tgz", - "integrity": "sha512-b1n4crJRW0WZVf9Gp/52j/tDtjYiZ3N81fIyfqPlBrjsh/5AivfA697DYwQ2mr8ngNX7RsqRtYNQjealA1rEnQ==" + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@cspell/dict-dotnet/-/dict-dotnet-5.0.0.tgz", + "integrity": "sha512-EOwGd533v47aP5QYV8GlSSKkmM9Eq8P3G/eBzSpH3Nl2+IneDOYOBLEUraHuiCtnOkNsz0xtZHArYhAB2bHWAw==" }, "node_modules/@cspell/dict-elixir": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@cspell/dict-elixir/-/dict-elixir-2.0.1.tgz", - "integrity": "sha512-eTTTxZt1FqGkM780yFDxsGHvTbWqvlK8YISSccK8FyrB6ULW+uflQlNS5AnWg3uWKC48b7pQott+odYCsPJ+Ow==" + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/@cspell/dict-elixir/-/dict-elixir-4.0.3.tgz", + "integrity": "sha512-g+uKLWvOp9IEZvrIvBPTr/oaO6619uH/wyqypqvwpmnmpjcfi8+/hqZH8YNKt15oviK8k4CkINIqNhyndG9d9Q==" }, "node_modules/@cspell/dict-en_us": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/@cspell/dict-en_us/-/dict-en_us-2.3.3.tgz", - "integrity": "sha512-csyKeaNktfpvMkmE2GOPTwsrQm3wWhLKVaDRaGU0qTcIjDiCvqv/iYgrVrKRkoddA3kdNTZ8YNCcix7lb6VkOg==" + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/@cspell/dict-en_us/-/dict-en_us-4.3.4.tgz", + "integrity": "sha512-mR2yqWmFip1zTKja2SqyVMbzuqEThqkEJk9M32bMDziPJpEyOIPvLA0UPmj3cyRKJkRuVF0bhDCE33O+at38hw==" + }, + "node_modules/@cspell/dict-en-common-misspellings": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@cspell/dict-en-common-misspellings/-/dict-en-common-misspellings-1.0.2.tgz", + "integrity": "sha512-jg7ZQZpZH7+aAxNBlcAG4tGhYF6Ksy+QS5Df73Oo+XyckBjC9QS+PrRwLTeYoFIgXy5j3ICParK5r3MSSoL4gw==" }, "node_modules/@cspell/dict-en-gb": { "version": "1.1.33", @@ -254,144 +268,208 @@ "integrity": "sha512-tKSSUf9BJEV+GJQAYGw5e+ouhEe2ZXE620S7BLKe3ZmpnjlNG9JqlnaBhkIMxKnNFkLY2BP/EARzw31AZnOv4g==" }, "node_modules/@cspell/dict-filetypes": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@cspell/dict-filetypes/-/dict-filetypes-2.1.1.tgz", - "integrity": "sha512-Oo0/mUbFHzsaATqRLdkV1RMoYns3aGzeKFIpVJg415GYtJ8EABXtEArYTXeMwlboyGTPvEk+PR2hBSTSfQTqmg==" + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@cspell/dict-filetypes/-/dict-filetypes-3.0.1.tgz", + "integrity": "sha512-8z8mY1IbrTyTRumx2vvD9yzRhNMk9SajM/GtI5hdMM2pPpNSp25bnuauzjRf300eqlqPY2MNb5MmhBFO014DJw==" }, "node_modules/@cspell/dict-fonts": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@cspell/dict-fonts/-/dict-fonts-2.1.0.tgz", - "integrity": "sha512-hk7xsbfWEUhc136Xj7I2TD7ouKAfWwzCVAQaHBxcVXAsVxu7bDOGj4FvE2jBzlkSUY8A9Ww8qS0GOFvowJshVg==" + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@cspell/dict-fonts/-/dict-fonts-3.0.2.tgz", + "integrity": "sha512-Z5QdbgEI7DV+KPXrAeDA6dDm/vTzyaW53SGlKqz6PI5VhkOjgkBXv3YtZjnxMZ4dY2ZIqq+RUK6qa9Pi8rQdGQ==" }, "node_modules/@cspell/dict-fullstack": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/@cspell/dict-fullstack/-/dict-fullstack-2.0.6.tgz", - "integrity": "sha512-R2E2xvbHvvRwwurxfpBJDRIJjXBMfEPF5WNV3LTOEMRqkZtoYCeJK9aqc8LHlmJMtAbnN1cx//BCDIyTJ0rO0A==" + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/@cspell/dict-fullstack/-/dict-fullstack-3.1.5.tgz", + "integrity": "sha512-6ppvo1dkXUZ3fbYn/wwzERxCa76RtDDl5Afzv2lijLoijGGUw5yYdLBKJnx8PJBGNLh829X352ftE7BElG4leA==" + }, + "node_modules/@cspell/dict-gaming-terms": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@cspell/dict-gaming-terms/-/dict-gaming-terms-1.0.4.tgz", + "integrity": "sha512-hbDduNXlk4AOY0wFxcDMWBPpm34rpqJBeqaySeoUH70eKxpxm+dvjpoRLJgyu0TmymEICCQSl6lAHTHSDiWKZg==" }, "node_modules/@cspell/dict-git": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@cspell/dict-git/-/dict-git-1.0.1.tgz", - "integrity": "sha512-Rk+eTof/9inF11lvxmkCRK+gODatA3qai8kSASv6OG/JfPvpj7fTHErx/rdgPw/LOTDUafnoTjTYmj7B2MOQXg==" + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@cspell/dict-git/-/dict-git-2.0.0.tgz", + "integrity": "sha512-n1AxyX5Kgxij/sZFkxFJlzn3K9y/sCcgVPg/vz4WNJ4K9YeTsUmyGLA2OQI7d10GJeiuAo2AP1iZf2A8j9aj2w==" }, "node_modules/@cspell/dict-golang": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@cspell/dict-golang/-/dict-golang-3.0.1.tgz", - "integrity": "sha512-0KNfXTbxHW2l8iVjxeOf+KFv9Qrw3z5cyKnkuYJWlBTSB5KcUBfeKCb4fsds26VdANqiy6U91b4gDx5kNEmBjQ==" + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/@cspell/dict-golang/-/dict-golang-6.0.2.tgz", + "integrity": "sha512-5pyZn4AAiYukAW+gVMIMVmUSkIERFrDX2vtPDjg8PLQUhAHWiVeQSDjuOhq9/C5GCCEZU/zWSONkGiwLBBvV9A==" }, "node_modules/@cspell/dict-haskell": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@cspell/dict-haskell/-/dict-haskell-2.0.1.tgz", - "integrity": "sha512-ooA23qIG7InOOxlLm67CNH5O2J85QsPHEAzEU9KEqVfYG5ovFs5tx6n9pHekDVk3MpQULpqfNUYDR0KigPLg5g==" + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@cspell/dict-haskell/-/dict-haskell-4.0.1.tgz", + "integrity": "sha512-uRrl65mGrOmwT7NxspB4xKXFUenNC7IikmpRZW8Uzqbqcu7ZRCUfstuVH7T1rmjRgRkjcIjE4PC11luDou4wEQ==" }, "node_modules/@cspell/dict-html": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/@cspell/dict-html/-/dict-html-3.3.2.tgz", - "integrity": "sha512-cM5pQSEiqjrdk6cRFLrlLdWNT/J8399f/A6DjwjfYhHrGy0e/Rsjv76HZT0GlE1OqMoq9eG9jdQsfoYYgWTIpQ==" + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/@cspell/dict-html/-/dict-html-4.0.3.tgz", + "integrity": "sha512-Gae8i8rrArT0UyG1I6DHDK62b7Be6QEcBSIeWOm4VIIW1CASkN9B0qFgSVnkmfvnu1Y3H7SSaaEynKjdj3cs8w==" }, "node_modules/@cspell/dict-html-symbol-entities": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@cspell/dict-html-symbol-entities/-/dict-html-symbol-entities-3.0.0.tgz", - "integrity": "sha512-04K7cPTcbYXmHICfiob4gZA1yaj4hpfM+Nl5WIJ1EAZsSGHdqmGEF28GuCjyQ8ZeKiJAsPt/vXuLBbjxkHqZyQ==" + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@cspell/dict-html-symbol-entities/-/dict-html-symbol-entities-4.0.0.tgz", + "integrity": "sha512-HGRu+48ErJjoweR5IbcixxETRewrBb0uxQBd6xFGcxbEYCX8CnQFTAmKI5xNaIt2PKaZiJH3ijodGSqbKdsxhw==" }, "node_modules/@cspell/dict-java": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/@cspell/dict-java/-/dict-java-3.0.7.tgz", - "integrity": "sha512-IL7ubsRvKX6dZSx++TplJCfhiS7kkEGpbTPG0gMEP50DTNAVM4icZS8zmer2UBCU5PTwF85abJjdX7mRADWKVg==" + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/@cspell/dict-java/-/dict-java-5.0.5.tgz", + "integrity": "sha512-X19AoJgWIBwJBSWGFqSgHaBR/FEykBHTMjL6EqOnhIGEyE9nvuo32tsSHjXNJ230fQxQptEvRZoaldNLtKxsRg==" + }, + "node_modules/@cspell/dict-k8s": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@cspell/dict-k8s/-/dict-k8s-1.0.1.tgz", + "integrity": "sha512-gc5y4Nm3hVdMZNBZfU2M1AsAmObZsRWjCUk01NFPfGhFBXyVne41T7E62rpnzu5330FV/6b/TnFcPgRmak9lLw==" }, "node_modules/@cspell/dict-latex": { - "version": "2.0.9", - "resolved": "https://registry.npmjs.org/@cspell/dict-latex/-/dict-latex-2.0.9.tgz", - "integrity": "sha512-d1kTK6dJb5z6UcfASQWjqQlsjZvnoVOvMWxYtLpGksYf6gM4IgqoPVNMLYYK6xBS4T/uAnLIj975A6YuAeyZpg==" + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@cspell/dict-latex/-/dict-latex-4.0.0.tgz", + "integrity": "sha512-LPY4y6D5oI7D3d+5JMJHK/wxYTQa2lJMSNxps2JtuF8hbAnBQb3igoWEjEbIbRRH1XBM0X8dQqemnjQNCiAtxQ==" }, "node_modules/@cspell/dict-lorem-ipsum": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@cspell/dict-lorem-ipsum/-/dict-lorem-ipsum-2.0.1.tgz", - "integrity": "sha512-s7Ft8UiloUJwgz4z8uLeFvCkeTcZ43HQl7mSAlZd76eW+keLSsdeGmLDx2zaciqo+MftPGyzygVCwaJjTGxiew==" + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@cspell/dict-lorem-ipsum/-/dict-lorem-ipsum-3.0.0.tgz", + "integrity": "sha512-msEV24qEpzWZs2kcEicqYlhyBpR0amfDkJOs+iffC07si9ftqtQ+yP3lf1VFLpgqw3SQh1M1vtU7RD4sPrNlcQ==" }, "node_modules/@cspell/dict-lua": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@cspell/dict-lua/-/dict-lua-2.0.0.tgz", - "integrity": "sha512-7WUEBEspSKtsq104WdIys1+DLqAxpJPzw74Py1TuE3fI5GvlzeSZkRFP2ya54GB2lCO4C3mq4M8EnitpibVDfw==" + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@cspell/dict-lua/-/dict-lua-4.0.1.tgz", + "integrity": "sha512-j0MFmeCouSoC6EdZTbvGe1sJ9V+ruwKSeF+zRkNNNload7R72Co5kX1haW2xLHGdlq0kqSy1ODRZKdVl0e+7hg==" }, "node_modules/@cspell/dict-node": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@cspell/dict-node/-/dict-node-3.0.1.tgz", - "integrity": "sha512-sK2cpuV0EAc43Amd5xeQXkI9MeRTECMw+yjap06gKSModbgI7BqJUHeKZed+0Hii+LpaJ4TYpLGiRVsO+qSk0w==" + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@cspell/dict-node/-/dict-node-4.0.2.tgz", + "integrity": "sha512-FEQJ4TnMcXEFslqBQkXa5HposMoCGsiBv2ux4IZuIXgadXeHKHUHk60iarWpjhzNzQLyN2GD7NoRMd12bK3Llw==" }, "node_modules/@cspell/dict-npm": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/@cspell/dict-npm/-/dict-npm-3.1.3.tgz", - "integrity": "sha512-xnGp+TMpArdMLBUSG+ZrbEuhvY016rb76Yh35/OPDDEEz4ulENxLSZJxtN2/A0tZ9FJngDNSdFh7eJsOFmciZQ==" + "version": "5.0.7", + "resolved": "https://registry.npmjs.org/@cspell/dict-npm/-/dict-npm-5.0.7.tgz", + "integrity": "sha512-6SegF0HsVaBTl6PlHjeErG8Av+tRYkUG1yaXUQIGWXU0A8oxhI0o4PuL65UWH5lkCKhJyGai69Cd0iytL0oVFg==" }, "node_modules/@cspell/dict-php": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@cspell/dict-php/-/dict-php-2.0.0.tgz", - "integrity": "sha512-29WgU77eTO985LvMHwPi1pcpfopfCWfTdffDyqya0JIfOSaFUrlYKzGPkE4mRxcz2G3hXsaM0SRvBNdIRwEdUg==" + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@cspell/dict-php/-/dict-php-4.0.1.tgz", + "integrity": "sha512-XaQ/JkSyq2c07MfRG54DjLi2CV+HHwS99DDCAao9Fq2JfkWroTQsUeek7wYZXJATrJVOULoV3HKih12x905AtQ==" }, "node_modules/@cspell/dict-powershell": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@cspell/dict-powershell/-/dict-powershell-2.0.0.tgz", - "integrity": "sha512-6uvEhLiGmG3u9TFkM1TYcky6aL9Yk7Sk3KJwoTYBaQJY2KqrprgyQtW6yxIw9oU52VRHlq3KKvSAA9Q26+SIkQ==" + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/@cspell/dict-powershell/-/dict-powershell-5.0.2.tgz", + "integrity": "sha512-IHfWLme3FXE7vnOmMncSBxOsMTdNWd1Vcyhag03WS8oANSgX8IZ+4lMI00mF0ptlgchf16/OU8WsV4pZfikEFw==" }, "node_modules/@cspell/dict-public-licenses": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/@cspell/dict-public-licenses/-/dict-public-licenses-1.0.6.tgz", - "integrity": "sha512-Z9IUFPkkOpOsEdgPUfQOJNQ+qU6+iBAZWS/CR5sUqTX+s5VkPNVwQyVC2kdmgmE2U5qwzAPewG6nVKr2MVogwg==" + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@cspell/dict-public-licenses/-/dict-public-licenses-2.0.2.tgz", + "integrity": "sha512-baKkbs/WGEV2lCWZoL0KBPh3uiPcul5GSDwmXEBAsR5McEW52LF94/b7xWM0EmSAc/y8ODc5LnPYC7RDRLi6LQ==" }, "node_modules/@cspell/dict-python": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/@cspell/dict-python/-/dict-python-3.0.6.tgz", - "integrity": "sha512-tzxJ4sd9ZGhAUKg/WJJpQGDNtoHvM8Wn+iS2+PnQj2/LTHBW4mnaCogsGsBtYu8C4b2+BEQs+tc5808AeEfLug==" + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/@cspell/dict-python/-/dict-python-4.1.2.tgz", + "integrity": "sha512-Whcn4K8R0Ux/hcx/P9Fbx6i29GwTaXgT3LTt95AuCnV5RRLrzsqoyZkz851hcg5z4kjUQVMduDl3HECGgW/FNw==", + "dependencies": { + "@cspell/dict-data-science": "^1.0.0" + } }, "node_modules/@cspell/dict-r": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@cspell/dict-r/-/dict-r-1.0.3.tgz", - "integrity": "sha512-u2qeXd4cx/TvTVcmkvA+sK6f4K1uMAMO6QPMSr1pSvqGElPRP1mIBXmuiSuBzLO3LbsJuUEHw5Cp3/bxIB6rNA==" + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@cspell/dict-r/-/dict-r-2.0.1.tgz", + "integrity": "sha512-KCmKaeYMLm2Ip79mlYPc8p+B2uzwBp4KMkzeLd5E6jUlCL93Y5Nvq68wV5fRLDRTf7N1LvofkVFWfDcednFOgA==" }, "node_modules/@cspell/dict-ruby": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@cspell/dict-ruby/-/dict-ruby-2.0.2.tgz", - "integrity": "sha512-vVnUpSmGDbPjs7MHq741DsLHhQcoA4CnUCM9wsTorQ9AQRDAkDTbK/LcY8nM19MoXCb3eF8PFku5Jq+gqH0u7w==" + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@cspell/dict-ruby/-/dict-ruby-5.0.0.tgz", + "integrity": "sha512-ssb96QxLZ76yPqFrikWxItnCbUKhYXJ2owkoIYzUGNFl2CHSoHCb5a6Zetum9mQ/oUA3gNeUhd28ZUlXs0la2A==" }, "node_modules/@cspell/dict-rust": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@cspell/dict-rust/-/dict-rust-2.0.1.tgz", - "integrity": "sha512-ATDpIh0VWpQdUIZa8zqqJY4wQz3q00BTXlQCodeOmObYSb23+L6KWWzJ8mKLgpbc1lqTkogWrqxiCxlrCmqNmg==" + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@cspell/dict-rust/-/dict-rust-4.0.1.tgz", + "integrity": "sha512-xJSSzHDK2z6lSVaOmMxl3PTOtfoffaxMo7fTcbZUF+SCJzfKbO6vnN9TCGX2sx1RHFDz66Js6goz6SAZQdOwaw==" }, "node_modules/@cspell/dict-scala": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@cspell/dict-scala/-/dict-scala-2.0.0.tgz", - "integrity": "sha512-MUwA2YKpqaQOSR4V1/CVGRNk8Ii5kf6I8Ch+4/BhRZRQXuwWbi21rDRYWPqdQWps7VNzAbbMA+PQDWsD5YY38g==" + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@cspell/dict-scala/-/dict-scala-5.0.0.tgz", + "integrity": "sha512-ph0twaRoV+ylui022clEO1dZ35QbeEQaKTaV2sPOsdwIokABPIiK09oWwGK9qg7jRGQwVaRPEq0Vp+IG1GpqSQ==" }, "node_modules/@cspell/dict-software-terms": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@cspell/dict-software-terms/-/dict-software-terms-2.3.0.tgz", - "integrity": "sha512-rl+quUw68IxjWgeX/QDMgQsImZ1DaKzFyYMSGrCNcNPp4b4SMLwHCKoJ97/uOnUnw0jaBxueXoqp2iyN/QiOVw==" + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@cspell/dict-software-terms/-/dict-software-terms-3.2.0.tgz", + "integrity": "sha512-RI6sv4Bc4i42YH/ofVelv8lXpJRhCyS9IhI2BtejUoMXKhKA9gC01ATXOylx+oaQmj3t5ark4R50xKFRvC7ENA==" }, "node_modules/@cspell/dict-sql": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@cspell/dict-sql/-/dict-sql-1.0.4.tgz", - "integrity": "sha512-+9nMcwsCzdYH0tyv2LeuVvQ+DdecS2C1N+hw6sl0FTHWI5GwULHAGW840RBwcKw0s+dl7sc0WpZhS1EW7b0pXg==" + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@cspell/dict-sql/-/dict-sql-2.1.0.tgz", + "integrity": "sha512-Bb+TNWUrTNNABO0bmfcYXiTlSt0RD6sB2MIY+rNlaMyIwug43jUjeYmkLz2tPkn3+2uvySeFEOMVYhMVfcuDKg==" + }, + "node_modules/@cspell/dict-svelte": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@cspell/dict-svelte/-/dict-svelte-1.0.2.tgz", + "integrity": "sha512-rPJmnn/GsDs0btNvrRBciOhngKV98yZ9SHmg8qI6HLS8hZKvcXc0LMsf9LLuMK1TmS2+WQFAan6qeqg6bBxL2Q==" }, "node_modules/@cspell/dict-swift": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@cspell/dict-swift/-/dict-swift-1.0.3.tgz", - "integrity": "sha512-yOBLSaRD0AnkkkndJ8PuB82Evp6lA2xItf2AWsnPfCCgxp5Ojk6uUBC/WQBSkzkCAOGbXyHsu9D97tsOx2c6cw==" + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@cspell/dict-swift/-/dict-swift-2.0.1.tgz", + "integrity": "sha512-gxrCMUOndOk7xZFmXNtkCEeroZRnS2VbeaIPiymGRHj5H+qfTAzAKxtv7jJbVA3YYvEzWcVE2oKDP4wcbhIERw==" }, "node_modules/@cspell/dict-typescript": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@cspell/dict-typescript/-/dict-typescript-2.0.2.tgz", - "integrity": "sha512-OIoSJsCw9WHX4eDikoF5/0QbptMPZjElOcMYdYCyV03nqV5n4ot72ysTexW95yW4+fQU6uDPNQvnrUnhXXEkTA==" + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@cspell/dict-typescript/-/dict-typescript-3.1.1.tgz", + "integrity": "sha512-N9vNJZoOXmmrFPR4ir3rGvnqqwmQGgOYoL1+y6D4oIhyr7FhaYiyF/d7QT61RmjZQcATMa6PSL+ZisCeRLx9+A==" }, "node_modules/@cspell/dict-vue": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@cspell/dict-vue/-/dict-vue-2.0.2.tgz", - "integrity": "sha512-/MB0RS0Gn01s4pgmjy0FvsLfr3RRMrRphEuvTRserNcM8XVtoIVAtrjig/Gg0DPwDrN8Clm0L1j7iQay6S8D0g==" + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@cspell/dict-vue/-/dict-vue-3.0.0.tgz", + "integrity": "sha512-niiEMPWPV9IeRBRzZ0TBZmNnkK3olkOPYxC1Ny2AX4TGlYRajcW0WUtoSHmvvjZNfWLSg2L6ruiBeuPSbjnG6A==" }, - "node_modules/@types/parse-json": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz", - "integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==" + "node_modules/@cspell/dynamic-import": { + "version": "6.31.1", + "resolved": "https://registry.npmjs.org/@cspell/dynamic-import/-/dynamic-import-6.31.1.tgz", + "integrity": "sha512-uliIUv9uZlnyYmjUlcw/Dm3p0xJOEnWJNczHAfqAl4Ytg6QZktw0GtUA9b1umbRXLv0KRTPtSC6nMq3cR7rRmQ==", + "dependencies": { + "import-meta-resolve": "^2.2.2" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/@cspell/strong-weak-map": { + "version": "6.31.1", + "resolved": "https://registry.npmjs.org/@cspell/strong-weak-map/-/strong-weak-map-6.31.1.tgz", + "integrity": "sha512-z8AuWvUuSnugFKJOA9Ke0aiFuehcqLFqia9bk8XaQNEWr44ahPVn3sEWnAncTxPbpWuUw5UajoJa0egRAE1CCg==", + "engines": { + "node": ">=14.6" + } + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } }, "node_modules/ansi-regex": { "version": "5.0.1", @@ -415,6 +493,11 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" + }, "node_modules/array-timsort": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/array-timsort/-/array-timsort-1.0.3.tgz", @@ -426,11 +509,12 @@ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" }, "node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dependencies": { - "balanced-match": "^1.0.0" + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" } }, "node_modules/braces": { @@ -499,11 +583,11 @@ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" }, "node_modules/commander": { - "version": "9.4.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-9.4.1.tgz", - "integrity": "sha512-5EEkTNyHNGFPD2H+c/dXXfQZYa/scCKasxWcXJaWnNJ99pnQN9Vnmqow+p+PlFPE63Q6mThaZws1T+HxfpgtPw==", + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz", + "integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==", "engines": { - "node": "^12.20.0 || >=14" + "node": ">=14" } }, "node_modules/comment-json": { @@ -548,18 +632,17 @@ "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" }, "node_modules/cosmiconfig": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.0.1.tgz", - "integrity": "sha512-a1YWNUV2HwGimB7dU2s1wUMurNKjpx60HxBB6xUM8Re+2s1g1IIfJvFR0/iCF+XHdE0GMTKTuLR32UQff4TEyQ==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.0.0.tgz", + "integrity": "sha512-da1EafcpH6b/TD8vDRaWV7xFINlHlF6zKsGwS1TsuVJTZRkquaS5HTMq7uq6h31619QjbsYl21gVDOm32KM1vQ==", "dependencies": { - "@types/parse-json": "^4.0.0", "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", "parse-json": "^5.0.0", - "path-type": "^4.0.0", - "yaml": "^1.10.0" + "path-type": "^4.0.0" }, "engines": { - "node": ">=10" + "node": ">=14" } }, "node_modules/crypto-random-string": { @@ -571,28 +654,31 @@ } }, "node_modules/cspell": { - "version": "6.12.0", - "resolved": "https://registry.npmjs.org/cspell/-/cspell-6.12.0.tgz", - "integrity": "sha512-ny4xVEPYFP2jVf5w71Mnk4HKj6RbPH+CMSzUrOMbYVVNnQUj3GLfzy5DrSFLG0zGa353ZRC4/s9MsEvnAL8mkA==", + "version": "6.31.2", + "resolved": "https://registry.npmjs.org/cspell/-/cspell-6.31.2.tgz", + "integrity": "sha512-HJcQ8jqL/1N3Mj5dufFnIZCX3ACuRoFTSVY6h3Bo5wBqd2iiJTyeQ1SY9Zymlxtb2KyJ6jQRiFmkWeFx2HVs7w==", "dependencies": { - "@cspell/cspell-pipe": "^6.12.0", + "@cspell/cspell-pipe": "6.31.1", + "@cspell/cspell-types": "6.31.1", + "@cspell/dynamic-import": "6.31.1", "chalk": "^4.1.2", - "commander": "^9.4.0", - "cspell-gitignore": "^6.12.0", - "cspell-glob": "^6.12.0", - "cspell-lib": "^6.12.0", + "commander": "^10.0.0", + "cspell-gitignore": "6.31.2", + "cspell-glob": "6.31.2", + "cspell-io": "6.31.2", + "cspell-lib": "6.31.2", + "fast-glob": "^3.2.12", "fast-json-stable-stringify": "^2.1.0", "file-entry-cache": "^6.0.1", - "fs-extra": "^10.1.0", "get-stdin": "^8.0.0", - "glob": "^8.0.3", "imurmurhash": "^0.1.4", - "semver": "^7.3.7", + "semver": "^7.3.8", "strip-ansi": "^6.0.1", - "vscode-uri": "^3.0.6" + "vscode-uri": "^3.0.7" }, "bin": { - "cspell": "bin.js" + "cspell": "bin.js", + "cspell-esm": "bin.mjs" }, "engines": { "node": ">=14" @@ -602,39 +688,39 @@ } }, "node_modules/cspell-dictionary": { - "version": "6.12.0", - "resolved": "https://registry.npmjs.org/cspell-dictionary/-/cspell-dictionary-6.12.0.tgz", - "integrity": "sha512-I2cXSdXndt9H7yXmJzLTjgui/SAPGghXwxFeibTbvF68gyQYD5fUXvOygEIPrOEySKlAIb+aouV77SgoURxMHw==", + "version": "6.31.1", + "resolved": "https://registry.npmjs.org/cspell-dictionary/-/cspell-dictionary-6.31.1.tgz", + "integrity": "sha512-7+K7aQGarqbpucky26wled7QSCJeg6VkLUWS+hLjyf0Cqc9Zew5xsLa4QjReExWUJx+a97jbiflITZNuWxgMrg==", "dependencies": { - "@cspell/cspell-pipe": "^6.12.0", - "@cspell/cspell-types": "^6.12.0", - "cspell-trie-lib": "^6.12.0", + "@cspell/cspell-pipe": "6.31.1", + "@cspell/cspell-types": "6.31.1", + "cspell-trie-lib": "6.31.1", "fast-equals": "^4.0.3", - "gensequence": "^4.0.2" + "gensequence": "^5.0.2" }, "engines": { "node": ">=14" } }, "node_modules/cspell-gitignore": { - "version": "6.12.0", - "resolved": "https://registry.npmjs.org/cspell-gitignore/-/cspell-gitignore-6.12.0.tgz", - "integrity": "sha512-gtsN2AAvqdE8CHVzpxsQcd/Wn5GAMTjzHpDXX71g/k8IJn743poGU06O0O1WSVAgK0fWTRsfg+V5OegA1TAo7A==", + "version": "6.31.2", + "resolved": "https://registry.npmjs.org/cspell-gitignore/-/cspell-gitignore-6.31.2.tgz", + "integrity": "sha512-B1i8aiXCIbb/08u0K3xnDyXtg0qD+lb5B2itOOXi7KXlPkKvIuN4hWyXxhVDweWyYWEzyXD5wBpPrqICVrStHQ==", "dependencies": { - "cspell-glob": "^6.12.0", + "cspell-glob": "6.31.2", "find-up": "^5.0.0" }, "bin": { - "cspell-gitignore": "bin.js" + "cspell-gitignore": "bin.mjs" }, "engines": { "node": ">=14" } }, "node_modules/cspell-glob": { - "version": "6.12.0", - "resolved": "https://registry.npmjs.org/cspell-glob/-/cspell-glob-6.12.0.tgz", - "integrity": "sha512-Q0rMGTxDyFFPm1LmHYM0ziuxQt2aXgr8Oi1glA2s0dBs0hg1DexlAEoLwLiMDUwSTvibEKIidPzlrmZ1AUDWEg==", + "version": "6.31.2", + "resolved": "https://registry.npmjs.org/cspell-glob/-/cspell-glob-6.31.2.tgz", + "integrity": "sha512-ceTjHM4HaBgvG5S3oiB+PTPYq58EQYG6MmYpycDHzpR5I2H1NurK9lxWHfANmLbi0DsHn58tIZNDMUnnQj19Jw==", "dependencies": { "micromatch": "^4.0.5" }, @@ -643,72 +729,71 @@ } }, "node_modules/cspell-grammar": { - "version": "6.12.0", - "resolved": "https://registry.npmjs.org/cspell-grammar/-/cspell-grammar-6.12.0.tgz", - "integrity": "sha512-WXcDiWJ2pTW0jHY0Bf0DW5s8A9S0a+2tsVZsNxE/0CR5P/8yDSnznE+59uok/JN+GXOKQ6VIaqAZA3/XjDZuuA==", + "version": "6.31.1", + "resolved": "https://registry.npmjs.org/cspell-grammar/-/cspell-grammar-6.31.1.tgz", + "integrity": "sha512-AsRVP0idcNFVSb9+p9XjMumFj3BUV67WIPWApaAzJl/dYyiIygQObRE+si0/QtFWGNw873b7hNhWZiKjqIdoaQ==", "dependencies": { - "@cspell/cspell-pipe": "^6.12.0", - "@cspell/cspell-types": "^6.12.0" + "@cspell/cspell-pipe": "6.31.1", + "@cspell/cspell-types": "6.31.1" }, "bin": { - "cspell-grammar": "bin.js" + "cspell-grammar": "bin.mjs" }, "engines": { "node": ">=14" } }, "node_modules/cspell-io": { - "version": "6.12.0", - "resolved": "https://registry.npmjs.org/cspell-io/-/cspell-io-6.12.0.tgz", - "integrity": "sha512-1faxDj2OMgq61w7GaiXZD7ytks6PksJlG484LMl2USv58jDky4i2lujJs1C/+aP97Box9EcdwzydHX9GpnqqCw==", + "version": "6.31.2", + "resolved": "https://registry.npmjs.org/cspell-io/-/cspell-io-6.31.2.tgz", + "integrity": "sha512-Lp7LsF/f35LaOneROb/9mWiprShz2ONxjYFAt3bYP7gIxq41lWi8QhO+SN6spoqPp/wQXjSqJ7MuTZsemxPRnA==", "dependencies": { - "@cspell/cspell-service-bus": "^6.12.0", - "node-fetch": "^2.6.7" + "@cspell/cspell-service-bus": "6.31.1", + "node-fetch": "^2.6.9" }, "engines": { "node": ">=14" } }, "node_modules/cspell-lib": { - "version": "6.12.0", - "resolved": "https://registry.npmjs.org/cspell-lib/-/cspell-lib-6.12.0.tgz", - "integrity": "sha512-IKd2MzH/zoiXohc26Lqb1b8i+41Y2xGreyAe9ihv/7Z2dscGGVy7F/2taZvZK9kJIhaz33Yatxfx3htT6w0hqg==", - "dependencies": { - "@cspell/cspell-bundled-dicts": "^6.12.0", - "@cspell/cspell-pipe": "^6.12.0", - "@cspell/cspell-types": "^6.12.0", + "version": "6.31.2", + "resolved": "https://registry.npmjs.org/cspell-lib/-/cspell-lib-6.31.2.tgz", + "integrity": "sha512-LqaB2ZfVfQHKL5aZzYoKU6/UxxAtWeXAYwpC9l+satXmajYyXtAh4kWmuW+y7kKRH2jA79rJQS3QE6ToeSqgQQ==", + "dependencies": { + "@cspell/cspell-bundled-dicts": "6.31.2", + "@cspell/cspell-pipe": "6.31.1", + "@cspell/cspell-types": "6.31.1", + "@cspell/strong-weak-map": "6.31.1", "clear-module": "^4.1.2", "comment-json": "^4.2.3", "configstore": "^5.0.1", - "cosmiconfig": "^7.0.1", - "cspell-dictionary": "^6.12.0", - "cspell-glob": "^6.12.0", - "cspell-grammar": "^6.12.0", - "cspell-io": "^6.12.0", - "cspell-trie-lib": "^6.12.0", + "cosmiconfig": "8.0.0", + "cspell-dictionary": "6.31.1", + "cspell-glob": "6.31.2", + "cspell-grammar": "6.31.1", + "cspell-io": "6.31.2", + "cspell-trie-lib": "6.31.1", "fast-equals": "^4.0.3", "find-up": "^5.0.0", - "fs-extra": "^10.1.0", - "gensequence": "^4.0.2", + "gensequence": "^5.0.2", "import-fresh": "^3.3.0", "resolve-from": "^5.0.0", "resolve-global": "^1.0.0", - "vscode-languageserver-textdocument": "^1.0.7", - "vscode-uri": "^3.0.6" + "vscode-languageserver-textdocument": "^1.0.8", + "vscode-uri": "^3.0.7" }, "engines": { - "node": ">=14" + "node": ">=14.6" } }, "node_modules/cspell-trie-lib": { - "version": "6.12.0", - "resolved": "https://registry.npmjs.org/cspell-trie-lib/-/cspell-trie-lib-6.12.0.tgz", - "integrity": "sha512-SJOdb51Wy3ewaKfttZwc9NYOIXaKlhyr+ykYKBExj3qMfV1J4d4iDLE95FriaRcqnq6X/qEM9jUvZHlvadDk3A==", + "version": "6.31.1", + "resolved": "https://registry.npmjs.org/cspell-trie-lib/-/cspell-trie-lib-6.31.1.tgz", + "integrity": "sha512-MtYh7s4Sbr1rKT31P2BK6KY+YfOy3dWsuusq9HnqCXmq6aZ1HyFgjH/9p9uvqGi/TboMqn1KOV8nifhXK3l3jg==", "dependencies": { - "@cspell/cspell-pipe": "^6.12.0", - "@cspell/cspell-types": "^6.12.0", - "fs-extra": "^10.1.0", - "gensequence": "^4.0.2" + "@cspell/cspell-pipe": "6.31.1", + "@cspell/cspell-types": "6.31.1", + "gensequence": "^5.0.2" }, "engines": { "node": ">=14" @@ -758,11 +843,34 @@ "resolved": "https://registry.npmjs.org/fast-equals/-/fast-equals-4.0.3.tgz", "integrity": "sha512-G3BSX9cfKttjr+2o1O22tYMLq0DPluZnYtq1rXumE1SpL/F/SLIfHx08WYQoWSIpeMYf8sRbJ8++71+v6Pnxfg==" }, + "node_modules/fast-glob": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.0.tgz", + "integrity": "sha512-ChDuvbOypPuNjO8yIDf36x7BlZX1smcUMTTcyoIjycexOxd6DFsKsg21qVBzEmr3G7fUKIRy2/psii+CIUt7FA==", + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "engines": { + "node": ">=8.6.0" + } + }, "node_modules/fast-json-stable-stringify": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" }, + "node_modules/fastq": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", + "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==", + "dependencies": { + "reusify": "^1.0.4" + } + }, "node_modules/file-entry-cache": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", @@ -817,28 +925,15 @@ "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz", "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==" }, - "node_modules/fs-extra": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", - "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=12" - } - }, "node_modules/fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" }, "node_modules/gensequence": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/gensequence/-/gensequence-4.0.2.tgz", - "integrity": "sha512-mQiFskYFPFDSUpBJ/n3ebAV2Ufu6DZGvUPXzyWYzFfJr6/DyOOZVnjx6VTWE4y0RLvYWnc5tZq5sCjzEWhRjqQ==", + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/gensequence/-/gensequence-5.0.2.tgz", + "integrity": "sha512-JlKEZnFc6neaeSVlkzBGGgkIoIaSxMgvdamRoPN8r3ozm2r9dusqxeKqYQ7lhzmj2UhFQP8nkyfCaiLQxiLrDA==", "engines": { "node": ">=14" } @@ -855,23 +950,35 @@ } }, "node_modules/glob": { - "version": "8.0.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-8.0.3.tgz", - "integrity": "sha512-ull455NHSHI/Y1FqGaaYFaLGkNMMJbavMrEGFXG/PGrg6y7sutWHUHrz6gy6WEBH6akM1M414dWKCNs+IhKdiQ==", + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", - "minimatch": "^5.0.1", - "once": "^1.3.0" + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" }, "engines": { - "node": ">=12" + "node": "*" }, "funding": { "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/global-dirs": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-0.1.1.tgz", @@ -884,9 +991,9 @@ } }, "node_modules/graceful-fs": { - "version": "4.2.10", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", - "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" }, "node_modules/has-flag": { "version": "4.0.0", @@ -938,6 +1045,15 @@ "node": ">=4" } }, + "node_modules/import-meta-resolve": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/import-meta-resolve/-/import-meta-resolve-2.2.2.tgz", + "integrity": "sha512-f8KcQ1D80V7RnqVm+/lirO9zkOxjGxhaTC1IPrBGd3MEfNgmNG67tSUO9gTi2F3Blr2Az6g1vocaxzkVnWl9MA==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/imurmurhash": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", @@ -970,6 +1086,25 @@ "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==" }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/is-number": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", @@ -996,22 +1131,22 @@ "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" }, + "node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, "node_modules/json-parse-even-better-errors": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==" }, - "node_modules/jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", - "dependencies": { - "universalify": "^2.0.0" - }, - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, "node_modules/lines-and-columns": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", @@ -1057,13 +1192,21 @@ } }, "node_modules/make-dir/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "bin": { "semver": "bin/semver.js" } }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "engines": { + "node": ">= 8" + } + }, "node_modules/micromatch": { "version": "4.0.5", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", @@ -1077,20 +1220,20 @@ } }, "node_modules/minimatch": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.0.tgz", - "integrity": "sha512-9TPBGGak4nHfGZsPBohm9AWg6NoT7QTCehS3BIJABslyZbzxfV78QM2Y6+i741OPZIafFAaiiEMh5OyIrJPgtg==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dependencies": { - "brace-expansion": "^2.0.1" + "brace-expansion": "^1.1.7" }, "engines": { - "node": ">=10" + "node": "*" } }, "node_modules/node-fetch": { - "version": "2.6.7", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", - "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", + "version": "2.6.12", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.12.tgz", + "integrity": "sha512-C/fGU2E8ToujUivIO0H+tpQ6HWo4eEmchoPIoXtxCrVghxdKq+QOHqEZW7tuP3KlV3bC8FRMO5nMCC7Zm1VP6g==", "dependencies": { "whatwg-url": "^5.0.0" }, @@ -1205,6 +1348,25 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, "node_modules/repeat-string": { "version": "1.6.1", "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", @@ -1232,6 +1394,15 @@ "node": ">=8" } }, + "node_modules/reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, "node_modules/rimraf": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", @@ -1246,49 +1417,32 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/rimraf/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/rimraf/node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/rimraf/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" + "queue-microtask": "^1.2.2" } }, "node_modules/semver": { - "version": "7.3.8", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", - "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", "dependencies": { "lru-cache": "^6.0.0" }, @@ -1361,23 +1515,15 @@ "node": ">=8" } }, - "node_modules/universalify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", - "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", - "engines": { - "node": ">= 10.0.0" - } - }, "node_modules/vscode-languageserver-textdocument": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/vscode-languageserver-textdocument/-/vscode-languageserver-textdocument-1.0.7.tgz", - "integrity": "sha512-bFJH7UQxlXT8kKeyiyu41r22jCZXG8kuuVVA33OEJn1diWOZK5n8zBSPZFHVBOu8kXZ6h0LIRhf5UnCo61J4Hg==" + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/vscode-languageserver-textdocument/-/vscode-languageserver-textdocument-1.0.8.tgz", + "integrity": "sha512-1bonkGqQs5/fxGT5UchTgjGVnfysL0O8v1AYMBjqTbWQTFn721zaPGDYFkOKtfDgFiSgXM3KwaG3FMGfW4Ed9Q==" }, "node_modules/vscode-uri": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-3.0.6.tgz", - "integrity": "sha512-fmL7V1eiDBFRRnu+gfRWTzyPpNIHJTc4mWnFkwBUmO9U3KPgJAmTx7oxi2bl/Rh6HLdU7+4C9wlj0k2E4AdKFQ==" + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-3.0.7.tgz", + "integrity": "sha512-eOpPHogvorZRobNqJGhapa0JdwaxpjVvyBp0QIUMRMSf8ZAlqOdEquKuRmw9Qwu0qXtJIWqFtMkmvJjUZmMjVA==" }, "node_modules/webidl-conversions": { "version": "3.0.1", @@ -1422,14 +1568,6 @@ "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" }, - "node_modules/yaml": { - "version": "1.10.2", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", - "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", - "engines": { - "node": ">= 6" - } - }, "node_modules/yocto-queue": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", @@ -1444,24 +1582,24 @@ }, "dependencies": { "@babel/code-frame": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.18.6.tgz", - "integrity": "sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.5.tgz", + "integrity": "sha512-Xmwn266vad+6DAqEB2A6V/CcZVp62BbwVmcOJc2RPuwih1kw02TjQvWVWlcKGbBPd+8/0V5DEkOcizRGYsspYQ==", "requires": { - "@babel/highlight": "^7.18.6" + "@babel/highlight": "^7.22.5" } }, "@babel/helper-validator-identifier": { - "version": "7.19.1", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz", - "integrity": "sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==" + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.5.tgz", + "integrity": "sha512-aJXu+6lErq8ltp+JhkJUfk1MTGyuA4v7f3pA+BJ5HLfNC6nAQ0Cpi9uOquUj8Hehg0aUiHzWQbOVJGao6ztBAQ==" }, "@babel/highlight": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz", - "integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.5.tgz", + "integrity": "sha512-BSKlD1hgnedS5XRnGOljZawtag7H1yPfQp0tdNJCHoH6AZ+Pcm9VvkrK59/Yy593Ypg0zMxH2BxD1VPYUQ7UIw==", "requires": { - "@babel/helper-validator-identifier": "^7.18.6", + "@babel/helper-validator-identifier": "^7.22.5", "chalk": "^2.0.0", "js-tokens": "^4.0.0" }, @@ -1513,138 +1651,152 @@ } }, "@cspell/cspell-bundled-dicts": { - "version": "6.12.0", - "resolved": "https://registry.npmjs.org/@cspell/cspell-bundled-dicts/-/cspell-bundled-dicts-6.12.0.tgz", - "integrity": "sha512-myfsDwSJcAMjKbztKBG424wIp/YV9/lvxsgHFKxBGPi+nNx1p7TbOjAAO9EWk0mZVHyGKZwCFJS2ohkoqxJWoQ==", + "version": "6.31.2", + "resolved": "https://registry.npmjs.org/@cspell/cspell-bundled-dicts/-/cspell-bundled-dicts-6.31.2.tgz", + "integrity": "sha512-rQ5y/U1Ah5AaduIh3NU2z371hRrOr1cmNdhhP8oiuz2E4VqmcoVHflXIct9DgY8uIJpwsSCdR6ypOQWZYXYnwA==", "requires": { - "@cspell/dict-ada": "^2.0.1", - "@cspell/dict-aws": "^2.0.0", - "@cspell/dict-bash": "^2.0.4", - "@cspell/dict-companies": "^2.0.14", - "@cspell/dict-cpp": "^3.2.1", - "@cspell/dict-cryptocurrencies": "^2.0.0", - "@cspell/dict-csharp": "^3.0.1", - "@cspell/dict-css": "^2.1.0", - "@cspell/dict-dart": "^1.1.1", - "@cspell/dict-django": "^2.0.0", - "@cspell/dict-docker": "^1.1.1", - "@cspell/dict-dotnet": "^2.0.1", - "@cspell/dict-elixir": "^2.0.1", - "@cspell/dict-en_us": "^2.3.3", - "@cspell/dict-en-gb": "^1.1.33", - "@cspell/dict-filetypes": "^2.1.1", - "@cspell/dict-fonts": "^2.1.0", - "@cspell/dict-fullstack": "^2.0.6", - "@cspell/dict-git": "^1.0.1", - "@cspell/dict-golang": "^3.0.1", - "@cspell/dict-haskell": "^2.0.1", - "@cspell/dict-html": "^3.3.2", - "@cspell/dict-html-symbol-entities": "^3.0.0", - "@cspell/dict-java": "^3.0.7", - "@cspell/dict-latex": "^2.0.9", - "@cspell/dict-lorem-ipsum": "^2.0.1", - "@cspell/dict-lua": "^2.0.0", - "@cspell/dict-node": "^3.0.1", - "@cspell/dict-npm": "^3.1.2", - "@cspell/dict-php": "^2.0.0", - "@cspell/dict-powershell": "^2.0.0", - "@cspell/dict-public-licenses": "^1.0.6", - "@cspell/dict-python": "^3.0.6", - "@cspell/dict-r": "^1.0.3", - "@cspell/dict-ruby": "^2.0.2", - "@cspell/dict-rust": "^2.0.1", - "@cspell/dict-scala": "^2.0.0", - "@cspell/dict-software-terms": "^2.2.11", - "@cspell/dict-sql": "^1.0.4", - "@cspell/dict-swift": "^1.0.3", - "@cspell/dict-typescript": "^2.0.2", - "@cspell/dict-vue": "^2.0.2" + "@cspell/dict-ada": "^4.0.1", + "@cspell/dict-aws": "^3.0.0", + "@cspell/dict-bash": "^4.1.1", + "@cspell/dict-companies": "^3.0.9", + "@cspell/dict-cpp": "^5.0.2", + "@cspell/dict-cryptocurrencies": "^3.0.1", + "@cspell/dict-csharp": "^4.0.2", + "@cspell/dict-css": "^4.0.5", + "@cspell/dict-dart": "^2.0.2", + "@cspell/dict-django": "^4.0.2", + "@cspell/dict-docker": "^1.1.6", + "@cspell/dict-dotnet": "^5.0.0", + "@cspell/dict-elixir": "^4.0.2", + "@cspell/dict-en_us": "^4.3.2", + "@cspell/dict-en-common-misspellings": "^1.0.2", + "@cspell/dict-en-gb": "1.1.33", + "@cspell/dict-filetypes": "^3.0.0", + "@cspell/dict-fonts": "^3.0.2", + "@cspell/dict-fullstack": "^3.1.5", + "@cspell/dict-gaming-terms": "^1.0.4", + "@cspell/dict-git": "^2.0.0", + "@cspell/dict-golang": "^6.0.1", + "@cspell/dict-haskell": "^4.0.1", + "@cspell/dict-html": "^4.0.3", + "@cspell/dict-html-symbol-entities": "^4.0.0", + "@cspell/dict-java": "^5.0.5", + "@cspell/dict-k8s": "^1.0.1", + "@cspell/dict-latex": "^4.0.0", + "@cspell/dict-lorem-ipsum": "^3.0.0", + "@cspell/dict-lua": "^4.0.1", + "@cspell/dict-node": "^4.0.2", + "@cspell/dict-npm": "^5.0.5", + "@cspell/dict-php": "^4.0.1", + "@cspell/dict-powershell": "^5.0.1", + "@cspell/dict-public-licenses": "^2.0.2", + "@cspell/dict-python": "^4.0.2", + "@cspell/dict-r": "^2.0.1", + "@cspell/dict-ruby": "^5.0.0", + "@cspell/dict-rust": "^4.0.1", + "@cspell/dict-scala": "^5.0.0", + "@cspell/dict-software-terms": "^3.1.6", + "@cspell/dict-sql": "^2.1.0", + "@cspell/dict-svelte": "^1.0.2", + "@cspell/dict-swift": "^2.0.1", + "@cspell/dict-typescript": "^3.1.1", + "@cspell/dict-vue": "^3.0.0" } }, "@cspell/cspell-pipe": { - "version": "6.12.0", - "resolved": "https://registry.npmjs.org/@cspell/cspell-pipe/-/cspell-pipe-6.12.0.tgz", - "integrity": "sha512-Nkm+tIJ5k+jZPovZCdmZhrWrwRFwnDq+7yCxhov0C7UX3hsSNtTJIpFuaCNEQJ+Whpvxdh1YKflvHiHYygEgTg==" + "version": "6.31.1", + "resolved": "https://registry.npmjs.org/@cspell/cspell-pipe/-/cspell-pipe-6.31.1.tgz", + "integrity": "sha512-zk1olZi4dr6GLm5PAjvsiZ01HURNSruUYFl1qSicGnTwYN8GaN4RhAwannAytcJ7zJPIcyXlid0YsB58nJf3wQ==" }, "@cspell/cspell-service-bus": { - "version": "6.12.0", - "resolved": "https://registry.npmjs.org/@cspell/cspell-service-bus/-/cspell-service-bus-6.12.0.tgz", - "integrity": "sha512-GgvciSeMUekl8z8vP8//cs5/qRQJSLz9IVREf6fxQW4upjw6zXZ1KonwPqOF5uLocIMAr8eCdrJzHKuKvigJIA==" + "version": "6.31.1", + "resolved": "https://registry.npmjs.org/@cspell/cspell-service-bus/-/cspell-service-bus-6.31.1.tgz", + "integrity": "sha512-YyBicmJyZ1uwKVxujXw7sgs9x+Eps43OkWmCtDZmZlnq489HdTSuhF1kTbVi2yeFSeaXIS87+uHo12z97KkQpg==" }, "@cspell/cspell-types": { - "version": "6.12.0", - "resolved": "https://registry.npmjs.org/@cspell/cspell-types/-/cspell-types-6.12.0.tgz", - "integrity": "sha512-BcZTt05fNy9SGXfbPgUyxS4FfIaUpcVq8IOJ0noN+jsKsmlbssOUgJOB2ApN1h66FfWcKuFy/uNrjfcrQ7PTqg==" + "version": "6.31.1", + "resolved": "https://registry.npmjs.org/@cspell/cspell-types/-/cspell-types-6.31.1.tgz", + "integrity": "sha512-1KeTQFiHMssW1eRoF2NZIEg4gPVIfXLsL2+VSD/AV6YN7lBcuf6gRRgV5KWYarhxtEfjxhDdDTmu26l/iJEUtw==" }, "@cspell/dict-ada": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@cspell/dict-ada/-/dict-ada-2.0.1.tgz", - "integrity": "sha512-vopTJ1oHrrFYV5GU55Sr+AzItR78Uj5YbCaspYABmYKlq4NRrcUAUsr4bWgymDcspMIHO7e7IFcj48OKs1fndA==" + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@cspell/dict-ada/-/dict-ada-4.0.1.tgz", + "integrity": "sha512-/E9o3nHrXOhYmQE43deKbxZcR3MIJAsa+66IzP9TXGHheKEx8b9dVMVVqydDDH8oom1H0U20NRPtu6KRVbT9xw==" }, "@cspell/dict-aws": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@cspell/dict-aws/-/dict-aws-2.0.0.tgz", - "integrity": "sha512-NKz7pDZ7pwj/b33i3f4WLpC1rOOUMmENwYgftxU+giU2YBeKM2wZbMTSEIzsrel56r0UlQYmdIVlP/B4nnVaoQ==" + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@cspell/dict-aws/-/dict-aws-3.0.0.tgz", + "integrity": "sha512-O1W6nd5y3Z00AMXQMzfiYrIJ1sTd9fB1oLr+xf/UD7b3xeHeMeYE2OtcWbt9uyeHim4tk+vkSTcmYEBKJgS5bQ==" }, "@cspell/dict-bash": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@cspell/dict-bash/-/dict-bash-2.0.4.tgz", - "integrity": "sha512-uK/ehmp5LYrmRH2Gv3nbvdPswpkybJUn34WYKLpeuYHQktmi+pOI1A9uPdBPnSbMDffSvwQlQohIyKawz+X8Ag==" + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/@cspell/dict-bash/-/dict-bash-4.1.1.tgz", + "integrity": "sha512-8czAa/Mh96wu2xr0RXQEGMTBUGkTvYn/Pb0o+gqOO1YW+poXGQc3gx0YPqILDryP/KCERrNvkWUJz3iGbvwC2A==" }, "@cspell/dict-companies": { - "version": "2.0.14", - "resolved": "https://registry.npmjs.org/@cspell/dict-companies/-/dict-companies-2.0.14.tgz", - "integrity": "sha512-Sq1X29Z05OZ/UNqTwVhf3/WaqvJQy4/S6gS8qYI5AQRX45gVe8CPhNBLmZOTC6z8m716bfQCxa5rRT9YNSdTZg==" + "version": "3.0.17", + "resolved": "https://registry.npmjs.org/@cspell/dict-companies/-/dict-companies-3.0.17.tgz", + "integrity": "sha512-vo1jbozgZWSzz2evIL26kLd35tVb+5kW/UTvTzAwaWutSWRloRyKx38nj2CaLJ2IFxBdiATteCFGTzKCvJJl6A==" }, "@cspell/dict-cpp": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/@cspell/dict-cpp/-/dict-cpp-3.2.1.tgz", - "integrity": "sha512-XcmzrKIghqFfrYLLaHtWKOp9rupiuGdc5ODONk+emsq0W5CIc3Abn27IQHwUzxzF+Cm5IfKAIJ5Kpe6hkzm0HQ==" + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/@cspell/dict-cpp/-/dict-cpp-5.0.3.tgz", + "integrity": "sha512-7sx/RFsf0hB3q8chx8OHYl9Kd+g0pqA1laphwaAQ+/jPwoAreYT3kNQWbJ3bIt/rMoORetFSQxckSbaJXwwqpw==" }, "@cspell/dict-cryptocurrencies": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@cspell/dict-cryptocurrencies/-/dict-cryptocurrencies-2.0.0.tgz", - "integrity": "sha512-nREysmmfOp7L2YCRAUufQahwD5/Punzb5AZ6eyg4zUamdRWHgBFphb5/9h2flt1vgdUfhc6hZcML21Ci7iXjaA==" + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@cspell/dict-cryptocurrencies/-/dict-cryptocurrencies-3.0.1.tgz", + "integrity": "sha512-Tdlr0Ahpp5yxtwM0ukC13V6+uYCI0p9fCRGMGZt36rWv8JQZHIuHfehNl7FB/Qc09NCF7p5ep0GXbL+sVTd/+w==" }, "@cspell/dict-csharp": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@cspell/dict-csharp/-/dict-csharp-3.0.1.tgz", - "integrity": "sha512-xkfQu03F388w4sdVQSSjrVMkxAxpTYB2yW7nw0XYtTjl3L/jBgvTr/j1BTjdFbQhdNf10Lg0Ak1kXOjmHodVqA==" + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@cspell/dict-csharp/-/dict-csharp-4.0.2.tgz", + "integrity": "sha512-1JMofhLK+4p4KairF75D3A924m5ERMgd1GvzhwK2geuYgd2ZKuGW72gvXpIV7aGf52E3Uu1kDXxxGAiZ5uVG7g==" }, "@cspell/dict-css": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@cspell/dict-css/-/dict-css-2.1.0.tgz", - "integrity": "sha512-glASAELcGhh4Ru0rTQ4G9mTQxSyPwsZOON/5BYflB6Kks8YC8nUvKrtMCoo5W7CPKPfSEa8zUNctFQ1+IUYDHA==" + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/@cspell/dict-css/-/dict-css-4.0.6.tgz", + "integrity": "sha512-2Lo8W2ezHmGgY8cWFr4RUwnjbndna5mokpCK/DuxGILQnuajR0J31ANQOXj/8iZM2phFB93ZzMNk/0c04TDfSQ==" }, "@cspell/dict-dart": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@cspell/dict-dart/-/dict-dart-1.1.1.tgz", - "integrity": "sha512-XBOCpezXrgFN18kGEwqMpTUGZdw4BjCoJrNOo6qBdcdZySCrEHLwELraLOkcSba2kM4stmTp0t59FkwtP8TKOA==" + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@cspell/dict-dart/-/dict-dart-2.0.2.tgz", + "integrity": "sha512-jigcODm7Z4IFZ4vParwwP3IT0fIgRq/9VoxkXfrxBMsLBGGM2QltHBj7pl+joX+c4cOHxfyZktGJK1B1wFtR4Q==" + }, + "@cspell/dict-data-science": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/@cspell/dict-data-science/-/dict-data-science-1.0.7.tgz", + "integrity": "sha512-Q9VUFaarUpqM6CAmR8peP4o9alk0XQ4rgVoE2R2XalpC2cqPI8Hmg6QwMU2UPioSUcWMJCqLc/KzJti0gBMuxA==" }, "@cspell/dict-django": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@cspell/dict-django/-/dict-django-2.0.0.tgz", - "integrity": "sha512-GkJdJv6cmzrKcmq2/oxTXjKF5uv71r4eTqnFmgPbNBW1t+G4VYpzOf0QrVQrhx2RC4DdW5XfcTf+iS0FxHOTmw==" + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@cspell/dict-django/-/dict-django-4.1.0.tgz", + "integrity": "sha512-bKJ4gPyrf+1c78Z0Oc4trEB9MuhcB+Yg+uTTWsvhY6O2ncFYbB/LbEZfqhfmmuK/XJJixXfI1laF2zicyf+l0w==" }, "@cspell/dict-docker": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@cspell/dict-docker/-/dict-docker-1.1.1.tgz", - "integrity": "sha512-UEYoeRDm7oUN9yz1mYSozz6D4+2N14S/cd2Re9et6Xzq6yi62s4ky3knF92Of2weelADjnN41UA22VBhRAf7Sw==" + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/@cspell/dict-docker/-/dict-docker-1.1.6.tgz", + "integrity": "sha512-zCCiRTZ6EOQpBnSOm0/3rnKW1kCcAUDUA7SxJG3SuH6iZvKi3I8FEg8+O83WQUeXg0SyPNerD9F40JLnnJjJig==" }, "@cspell/dict-dotnet": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@cspell/dict-dotnet/-/dict-dotnet-2.0.1.tgz", - "integrity": "sha512-b1n4crJRW0WZVf9Gp/52j/tDtjYiZ3N81fIyfqPlBrjsh/5AivfA697DYwQ2mr8ngNX7RsqRtYNQjealA1rEnQ==" + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@cspell/dict-dotnet/-/dict-dotnet-5.0.0.tgz", + "integrity": "sha512-EOwGd533v47aP5QYV8GlSSKkmM9Eq8P3G/eBzSpH3Nl2+IneDOYOBLEUraHuiCtnOkNsz0xtZHArYhAB2bHWAw==" }, "@cspell/dict-elixir": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@cspell/dict-elixir/-/dict-elixir-2.0.1.tgz", - "integrity": "sha512-eTTTxZt1FqGkM780yFDxsGHvTbWqvlK8YISSccK8FyrB6ULW+uflQlNS5AnWg3uWKC48b7pQott+odYCsPJ+Ow==" + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/@cspell/dict-elixir/-/dict-elixir-4.0.3.tgz", + "integrity": "sha512-g+uKLWvOp9IEZvrIvBPTr/oaO6619uH/wyqypqvwpmnmpjcfi8+/hqZH8YNKt15oviK8k4CkINIqNhyndG9d9Q==" }, "@cspell/dict-en_us": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/@cspell/dict-en_us/-/dict-en_us-2.3.3.tgz", - "integrity": "sha512-csyKeaNktfpvMkmE2GOPTwsrQm3wWhLKVaDRaGU0qTcIjDiCvqv/iYgrVrKRkoddA3kdNTZ8YNCcix7lb6VkOg==" + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/@cspell/dict-en_us/-/dict-en_us-4.3.4.tgz", + "integrity": "sha512-mR2yqWmFip1zTKja2SqyVMbzuqEThqkEJk9M32bMDziPJpEyOIPvLA0UPmj3cyRKJkRuVF0bhDCE33O+at38hw==" + }, + "@cspell/dict-en-common-misspellings": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@cspell/dict-en-common-misspellings/-/dict-en-common-misspellings-1.0.2.tgz", + "integrity": "sha512-jg7ZQZpZH7+aAxNBlcAG4tGhYF6Ksy+QS5Df73Oo+XyckBjC9QS+PrRwLTeYoFIgXy5j3ICParK5r3MSSoL4gw==" }, "@cspell/dict-en-gb": { "version": "1.1.33", @@ -1652,144 +1804,193 @@ "integrity": "sha512-tKSSUf9BJEV+GJQAYGw5e+ouhEe2ZXE620S7BLKe3ZmpnjlNG9JqlnaBhkIMxKnNFkLY2BP/EARzw31AZnOv4g==" }, "@cspell/dict-filetypes": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@cspell/dict-filetypes/-/dict-filetypes-2.1.1.tgz", - "integrity": "sha512-Oo0/mUbFHzsaATqRLdkV1RMoYns3aGzeKFIpVJg415GYtJ8EABXtEArYTXeMwlboyGTPvEk+PR2hBSTSfQTqmg==" + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@cspell/dict-filetypes/-/dict-filetypes-3.0.1.tgz", + "integrity": "sha512-8z8mY1IbrTyTRumx2vvD9yzRhNMk9SajM/GtI5hdMM2pPpNSp25bnuauzjRf300eqlqPY2MNb5MmhBFO014DJw==" }, "@cspell/dict-fonts": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@cspell/dict-fonts/-/dict-fonts-2.1.0.tgz", - "integrity": "sha512-hk7xsbfWEUhc136Xj7I2TD7ouKAfWwzCVAQaHBxcVXAsVxu7bDOGj4FvE2jBzlkSUY8A9Ww8qS0GOFvowJshVg==" + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@cspell/dict-fonts/-/dict-fonts-3.0.2.tgz", + "integrity": "sha512-Z5QdbgEI7DV+KPXrAeDA6dDm/vTzyaW53SGlKqz6PI5VhkOjgkBXv3YtZjnxMZ4dY2ZIqq+RUK6qa9Pi8rQdGQ==" }, "@cspell/dict-fullstack": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/@cspell/dict-fullstack/-/dict-fullstack-2.0.6.tgz", - "integrity": "sha512-R2E2xvbHvvRwwurxfpBJDRIJjXBMfEPF5WNV3LTOEMRqkZtoYCeJK9aqc8LHlmJMtAbnN1cx//BCDIyTJ0rO0A==" + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/@cspell/dict-fullstack/-/dict-fullstack-3.1.5.tgz", + "integrity": "sha512-6ppvo1dkXUZ3fbYn/wwzERxCa76RtDDl5Afzv2lijLoijGGUw5yYdLBKJnx8PJBGNLh829X352ftE7BElG4leA==" + }, + "@cspell/dict-gaming-terms": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@cspell/dict-gaming-terms/-/dict-gaming-terms-1.0.4.tgz", + "integrity": "sha512-hbDduNXlk4AOY0wFxcDMWBPpm34rpqJBeqaySeoUH70eKxpxm+dvjpoRLJgyu0TmymEICCQSl6lAHTHSDiWKZg==" }, "@cspell/dict-git": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@cspell/dict-git/-/dict-git-1.0.1.tgz", - "integrity": "sha512-Rk+eTof/9inF11lvxmkCRK+gODatA3qai8kSASv6OG/JfPvpj7fTHErx/rdgPw/LOTDUafnoTjTYmj7B2MOQXg==" + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@cspell/dict-git/-/dict-git-2.0.0.tgz", + "integrity": "sha512-n1AxyX5Kgxij/sZFkxFJlzn3K9y/sCcgVPg/vz4WNJ4K9YeTsUmyGLA2OQI7d10GJeiuAo2AP1iZf2A8j9aj2w==" }, "@cspell/dict-golang": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@cspell/dict-golang/-/dict-golang-3.0.1.tgz", - "integrity": "sha512-0KNfXTbxHW2l8iVjxeOf+KFv9Qrw3z5cyKnkuYJWlBTSB5KcUBfeKCb4fsds26VdANqiy6U91b4gDx5kNEmBjQ==" + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/@cspell/dict-golang/-/dict-golang-6.0.2.tgz", + "integrity": "sha512-5pyZn4AAiYukAW+gVMIMVmUSkIERFrDX2vtPDjg8PLQUhAHWiVeQSDjuOhq9/C5GCCEZU/zWSONkGiwLBBvV9A==" }, "@cspell/dict-haskell": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@cspell/dict-haskell/-/dict-haskell-2.0.1.tgz", - "integrity": "sha512-ooA23qIG7InOOxlLm67CNH5O2J85QsPHEAzEU9KEqVfYG5ovFs5tx6n9pHekDVk3MpQULpqfNUYDR0KigPLg5g==" + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@cspell/dict-haskell/-/dict-haskell-4.0.1.tgz", + "integrity": "sha512-uRrl65mGrOmwT7NxspB4xKXFUenNC7IikmpRZW8Uzqbqcu7ZRCUfstuVH7T1rmjRgRkjcIjE4PC11luDou4wEQ==" }, "@cspell/dict-html": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/@cspell/dict-html/-/dict-html-3.3.2.tgz", - "integrity": "sha512-cM5pQSEiqjrdk6cRFLrlLdWNT/J8399f/A6DjwjfYhHrGy0e/Rsjv76HZT0GlE1OqMoq9eG9jdQsfoYYgWTIpQ==" + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/@cspell/dict-html/-/dict-html-4.0.3.tgz", + "integrity": "sha512-Gae8i8rrArT0UyG1I6DHDK62b7Be6QEcBSIeWOm4VIIW1CASkN9B0qFgSVnkmfvnu1Y3H7SSaaEynKjdj3cs8w==" }, "@cspell/dict-html-symbol-entities": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@cspell/dict-html-symbol-entities/-/dict-html-symbol-entities-3.0.0.tgz", - "integrity": "sha512-04K7cPTcbYXmHICfiob4gZA1yaj4hpfM+Nl5WIJ1EAZsSGHdqmGEF28GuCjyQ8ZeKiJAsPt/vXuLBbjxkHqZyQ==" + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@cspell/dict-html-symbol-entities/-/dict-html-symbol-entities-4.0.0.tgz", + "integrity": "sha512-HGRu+48ErJjoweR5IbcixxETRewrBb0uxQBd6xFGcxbEYCX8CnQFTAmKI5xNaIt2PKaZiJH3ijodGSqbKdsxhw==" }, "@cspell/dict-java": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/@cspell/dict-java/-/dict-java-3.0.7.tgz", - "integrity": "sha512-IL7ubsRvKX6dZSx++TplJCfhiS7kkEGpbTPG0gMEP50DTNAVM4icZS8zmer2UBCU5PTwF85abJjdX7mRADWKVg==" + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/@cspell/dict-java/-/dict-java-5.0.5.tgz", + "integrity": "sha512-X19AoJgWIBwJBSWGFqSgHaBR/FEykBHTMjL6EqOnhIGEyE9nvuo32tsSHjXNJ230fQxQptEvRZoaldNLtKxsRg==" + }, + "@cspell/dict-k8s": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@cspell/dict-k8s/-/dict-k8s-1.0.1.tgz", + "integrity": "sha512-gc5y4Nm3hVdMZNBZfU2M1AsAmObZsRWjCUk01NFPfGhFBXyVne41T7E62rpnzu5330FV/6b/TnFcPgRmak9lLw==" }, "@cspell/dict-latex": { - "version": "2.0.9", - "resolved": "https://registry.npmjs.org/@cspell/dict-latex/-/dict-latex-2.0.9.tgz", - "integrity": "sha512-d1kTK6dJb5z6UcfASQWjqQlsjZvnoVOvMWxYtLpGksYf6gM4IgqoPVNMLYYK6xBS4T/uAnLIj975A6YuAeyZpg==" + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@cspell/dict-latex/-/dict-latex-4.0.0.tgz", + "integrity": "sha512-LPY4y6D5oI7D3d+5JMJHK/wxYTQa2lJMSNxps2JtuF8hbAnBQb3igoWEjEbIbRRH1XBM0X8dQqemnjQNCiAtxQ==" }, "@cspell/dict-lorem-ipsum": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@cspell/dict-lorem-ipsum/-/dict-lorem-ipsum-2.0.1.tgz", - "integrity": "sha512-s7Ft8UiloUJwgz4z8uLeFvCkeTcZ43HQl7mSAlZd76eW+keLSsdeGmLDx2zaciqo+MftPGyzygVCwaJjTGxiew==" + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@cspell/dict-lorem-ipsum/-/dict-lorem-ipsum-3.0.0.tgz", + "integrity": "sha512-msEV24qEpzWZs2kcEicqYlhyBpR0amfDkJOs+iffC07si9ftqtQ+yP3lf1VFLpgqw3SQh1M1vtU7RD4sPrNlcQ==" }, "@cspell/dict-lua": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@cspell/dict-lua/-/dict-lua-2.0.0.tgz", - "integrity": "sha512-7WUEBEspSKtsq104WdIys1+DLqAxpJPzw74Py1TuE3fI5GvlzeSZkRFP2ya54GB2lCO4C3mq4M8EnitpibVDfw==" + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@cspell/dict-lua/-/dict-lua-4.0.1.tgz", + "integrity": "sha512-j0MFmeCouSoC6EdZTbvGe1sJ9V+ruwKSeF+zRkNNNload7R72Co5kX1haW2xLHGdlq0kqSy1ODRZKdVl0e+7hg==" }, "@cspell/dict-node": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@cspell/dict-node/-/dict-node-3.0.1.tgz", - "integrity": "sha512-sK2cpuV0EAc43Amd5xeQXkI9MeRTECMw+yjap06gKSModbgI7BqJUHeKZed+0Hii+LpaJ4TYpLGiRVsO+qSk0w==" + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@cspell/dict-node/-/dict-node-4.0.2.tgz", + "integrity": "sha512-FEQJ4TnMcXEFslqBQkXa5HposMoCGsiBv2ux4IZuIXgadXeHKHUHk60iarWpjhzNzQLyN2GD7NoRMd12bK3Llw==" }, "@cspell/dict-npm": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/@cspell/dict-npm/-/dict-npm-3.1.3.tgz", - "integrity": "sha512-xnGp+TMpArdMLBUSG+ZrbEuhvY016rb76Yh35/OPDDEEz4ulENxLSZJxtN2/A0tZ9FJngDNSdFh7eJsOFmciZQ==" + "version": "5.0.7", + "resolved": "https://registry.npmjs.org/@cspell/dict-npm/-/dict-npm-5.0.7.tgz", + "integrity": "sha512-6SegF0HsVaBTl6PlHjeErG8Av+tRYkUG1yaXUQIGWXU0A8oxhI0o4PuL65UWH5lkCKhJyGai69Cd0iytL0oVFg==" }, "@cspell/dict-php": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@cspell/dict-php/-/dict-php-2.0.0.tgz", - "integrity": "sha512-29WgU77eTO985LvMHwPi1pcpfopfCWfTdffDyqya0JIfOSaFUrlYKzGPkE4mRxcz2G3hXsaM0SRvBNdIRwEdUg==" + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@cspell/dict-php/-/dict-php-4.0.1.tgz", + "integrity": "sha512-XaQ/JkSyq2c07MfRG54DjLi2CV+HHwS99DDCAao9Fq2JfkWroTQsUeek7wYZXJATrJVOULoV3HKih12x905AtQ==" }, "@cspell/dict-powershell": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@cspell/dict-powershell/-/dict-powershell-2.0.0.tgz", - "integrity": "sha512-6uvEhLiGmG3u9TFkM1TYcky6aL9Yk7Sk3KJwoTYBaQJY2KqrprgyQtW6yxIw9oU52VRHlq3KKvSAA9Q26+SIkQ==" + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/@cspell/dict-powershell/-/dict-powershell-5.0.2.tgz", + "integrity": "sha512-IHfWLme3FXE7vnOmMncSBxOsMTdNWd1Vcyhag03WS8oANSgX8IZ+4lMI00mF0ptlgchf16/OU8WsV4pZfikEFw==" }, "@cspell/dict-public-licenses": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/@cspell/dict-public-licenses/-/dict-public-licenses-1.0.6.tgz", - "integrity": "sha512-Z9IUFPkkOpOsEdgPUfQOJNQ+qU6+iBAZWS/CR5sUqTX+s5VkPNVwQyVC2kdmgmE2U5qwzAPewG6nVKr2MVogwg==" + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@cspell/dict-public-licenses/-/dict-public-licenses-2.0.2.tgz", + "integrity": "sha512-baKkbs/WGEV2lCWZoL0KBPh3uiPcul5GSDwmXEBAsR5McEW52LF94/b7xWM0EmSAc/y8ODc5LnPYC7RDRLi6LQ==" }, "@cspell/dict-python": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/@cspell/dict-python/-/dict-python-3.0.6.tgz", - "integrity": "sha512-tzxJ4sd9ZGhAUKg/WJJpQGDNtoHvM8Wn+iS2+PnQj2/LTHBW4mnaCogsGsBtYu8C4b2+BEQs+tc5808AeEfLug==" + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/@cspell/dict-python/-/dict-python-4.1.2.tgz", + "integrity": "sha512-Whcn4K8R0Ux/hcx/P9Fbx6i29GwTaXgT3LTt95AuCnV5RRLrzsqoyZkz851hcg5z4kjUQVMduDl3HECGgW/FNw==", + "requires": { + "@cspell/dict-data-science": "^1.0.0" + } }, "@cspell/dict-r": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@cspell/dict-r/-/dict-r-1.0.3.tgz", - "integrity": "sha512-u2qeXd4cx/TvTVcmkvA+sK6f4K1uMAMO6QPMSr1pSvqGElPRP1mIBXmuiSuBzLO3LbsJuUEHw5Cp3/bxIB6rNA==" + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@cspell/dict-r/-/dict-r-2.0.1.tgz", + "integrity": "sha512-KCmKaeYMLm2Ip79mlYPc8p+B2uzwBp4KMkzeLd5E6jUlCL93Y5Nvq68wV5fRLDRTf7N1LvofkVFWfDcednFOgA==" }, "@cspell/dict-ruby": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@cspell/dict-ruby/-/dict-ruby-2.0.2.tgz", - "integrity": "sha512-vVnUpSmGDbPjs7MHq741DsLHhQcoA4CnUCM9wsTorQ9AQRDAkDTbK/LcY8nM19MoXCb3eF8PFku5Jq+gqH0u7w==" + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@cspell/dict-ruby/-/dict-ruby-5.0.0.tgz", + "integrity": "sha512-ssb96QxLZ76yPqFrikWxItnCbUKhYXJ2owkoIYzUGNFl2CHSoHCb5a6Zetum9mQ/oUA3gNeUhd28ZUlXs0la2A==" }, "@cspell/dict-rust": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@cspell/dict-rust/-/dict-rust-2.0.1.tgz", - "integrity": "sha512-ATDpIh0VWpQdUIZa8zqqJY4wQz3q00BTXlQCodeOmObYSb23+L6KWWzJ8mKLgpbc1lqTkogWrqxiCxlrCmqNmg==" + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@cspell/dict-rust/-/dict-rust-4.0.1.tgz", + "integrity": "sha512-xJSSzHDK2z6lSVaOmMxl3PTOtfoffaxMo7fTcbZUF+SCJzfKbO6vnN9TCGX2sx1RHFDz66Js6goz6SAZQdOwaw==" }, "@cspell/dict-scala": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@cspell/dict-scala/-/dict-scala-2.0.0.tgz", - "integrity": "sha512-MUwA2YKpqaQOSR4V1/CVGRNk8Ii5kf6I8Ch+4/BhRZRQXuwWbi21rDRYWPqdQWps7VNzAbbMA+PQDWsD5YY38g==" + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@cspell/dict-scala/-/dict-scala-5.0.0.tgz", + "integrity": "sha512-ph0twaRoV+ylui022clEO1dZ35QbeEQaKTaV2sPOsdwIokABPIiK09oWwGK9qg7jRGQwVaRPEq0Vp+IG1GpqSQ==" }, "@cspell/dict-software-terms": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@cspell/dict-software-terms/-/dict-software-terms-2.3.0.tgz", - "integrity": "sha512-rl+quUw68IxjWgeX/QDMgQsImZ1DaKzFyYMSGrCNcNPp4b4SMLwHCKoJ97/uOnUnw0jaBxueXoqp2iyN/QiOVw==" + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@cspell/dict-software-terms/-/dict-software-terms-3.2.0.tgz", + "integrity": "sha512-RI6sv4Bc4i42YH/ofVelv8lXpJRhCyS9IhI2BtejUoMXKhKA9gC01ATXOylx+oaQmj3t5ark4R50xKFRvC7ENA==" }, "@cspell/dict-sql": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@cspell/dict-sql/-/dict-sql-1.0.4.tgz", - "integrity": "sha512-+9nMcwsCzdYH0tyv2LeuVvQ+DdecS2C1N+hw6sl0FTHWI5GwULHAGW840RBwcKw0s+dl7sc0WpZhS1EW7b0pXg==" + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@cspell/dict-sql/-/dict-sql-2.1.0.tgz", + "integrity": "sha512-Bb+TNWUrTNNABO0bmfcYXiTlSt0RD6sB2MIY+rNlaMyIwug43jUjeYmkLz2tPkn3+2uvySeFEOMVYhMVfcuDKg==" + }, + "@cspell/dict-svelte": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@cspell/dict-svelte/-/dict-svelte-1.0.2.tgz", + "integrity": "sha512-rPJmnn/GsDs0btNvrRBciOhngKV98yZ9SHmg8qI6HLS8hZKvcXc0LMsf9LLuMK1TmS2+WQFAan6qeqg6bBxL2Q==" }, "@cspell/dict-swift": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@cspell/dict-swift/-/dict-swift-1.0.3.tgz", - "integrity": "sha512-yOBLSaRD0AnkkkndJ8PuB82Evp6lA2xItf2AWsnPfCCgxp5Ojk6uUBC/WQBSkzkCAOGbXyHsu9D97tsOx2c6cw==" + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@cspell/dict-swift/-/dict-swift-2.0.1.tgz", + "integrity": "sha512-gxrCMUOndOk7xZFmXNtkCEeroZRnS2VbeaIPiymGRHj5H+qfTAzAKxtv7jJbVA3YYvEzWcVE2oKDP4wcbhIERw==" }, "@cspell/dict-typescript": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@cspell/dict-typescript/-/dict-typescript-2.0.2.tgz", - "integrity": "sha512-OIoSJsCw9WHX4eDikoF5/0QbptMPZjElOcMYdYCyV03nqV5n4ot72ysTexW95yW4+fQU6uDPNQvnrUnhXXEkTA==" + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@cspell/dict-typescript/-/dict-typescript-3.1.1.tgz", + "integrity": "sha512-N9vNJZoOXmmrFPR4ir3rGvnqqwmQGgOYoL1+y6D4oIhyr7FhaYiyF/d7QT61RmjZQcATMa6PSL+ZisCeRLx9+A==" }, "@cspell/dict-vue": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@cspell/dict-vue/-/dict-vue-2.0.2.tgz", - "integrity": "sha512-/MB0RS0Gn01s4pgmjy0FvsLfr3RRMrRphEuvTRserNcM8XVtoIVAtrjig/Gg0DPwDrN8Clm0L1j7iQay6S8D0g==" + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@cspell/dict-vue/-/dict-vue-3.0.0.tgz", + "integrity": "sha512-niiEMPWPV9IeRBRzZ0TBZmNnkK3olkOPYxC1Ny2AX4TGlYRajcW0WUtoSHmvvjZNfWLSg2L6ruiBeuPSbjnG6A==" }, - "@types/parse-json": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz", - "integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==" + "@cspell/dynamic-import": { + "version": "6.31.1", + "resolved": "https://registry.npmjs.org/@cspell/dynamic-import/-/dynamic-import-6.31.1.tgz", + "integrity": "sha512-uliIUv9uZlnyYmjUlcw/Dm3p0xJOEnWJNczHAfqAl4Ytg6QZktw0GtUA9b1umbRXLv0KRTPtSC6nMq3cR7rRmQ==", + "requires": { + "import-meta-resolve": "^2.2.2" + } + }, + "@cspell/strong-weak-map": { + "version": "6.31.1", + "resolved": "https://registry.npmjs.org/@cspell/strong-weak-map/-/strong-weak-map-6.31.1.tgz", + "integrity": "sha512-z8AuWvUuSnugFKJOA9Ke0aiFuehcqLFqia9bk8XaQNEWr44ahPVn3sEWnAncTxPbpWuUw5UajoJa0egRAE1CCg==" + }, + "@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "requires": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + } + }, + "@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==" + }, + "@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "requires": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + } }, "ansi-regex": { "version": "5.0.1", @@ -1804,6 +2005,11 @@ "color-convert": "^2.0.1" } }, + "argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" + }, "array-timsort": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/array-timsort/-/array-timsort-1.0.3.tgz", @@ -1815,11 +2021,12 @@ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" }, "brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "requires": { - "balanced-match": "^1.0.0" + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" } }, "braces": { @@ -1867,9 +2074,9 @@ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" }, "commander": { - "version": "9.4.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-9.4.1.tgz", - "integrity": "sha512-5EEkTNyHNGFPD2H+c/dXXfQZYa/scCKasxWcXJaWnNJ99pnQN9Vnmqow+p+PlFPE63Q6mThaZws1T+HxfpgtPw==" + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz", + "integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==" }, "comment-json": { "version": "4.2.3", @@ -1907,15 +2114,14 @@ "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" }, "cosmiconfig": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.0.1.tgz", - "integrity": "sha512-a1YWNUV2HwGimB7dU2s1wUMurNKjpx60HxBB6xUM8Re+2s1g1IIfJvFR0/iCF+XHdE0GMTKTuLR32UQff4TEyQ==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.0.0.tgz", + "integrity": "sha512-da1EafcpH6b/TD8vDRaWV7xFINlHlF6zKsGwS1TsuVJTZRkquaS5HTMq7uq6h31619QjbsYl21gVDOm32KM1vQ==", "requires": { - "@types/parse-json": "^4.0.0", "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", "parse-json": "^5.0.0", - "path-type": "^4.0.0", - "yaml": "^1.10.0" + "path-type": "^4.0.0" } }, "crypto-random-string": { @@ -1924,111 +2130,112 @@ "integrity": "sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==" }, "cspell": { - "version": "6.12.0", - "resolved": "https://registry.npmjs.org/cspell/-/cspell-6.12.0.tgz", - "integrity": "sha512-ny4xVEPYFP2jVf5w71Mnk4HKj6RbPH+CMSzUrOMbYVVNnQUj3GLfzy5DrSFLG0zGa353ZRC4/s9MsEvnAL8mkA==", + "version": "6.31.2", + "resolved": "https://registry.npmjs.org/cspell/-/cspell-6.31.2.tgz", + "integrity": "sha512-HJcQ8jqL/1N3Mj5dufFnIZCX3ACuRoFTSVY6h3Bo5wBqd2iiJTyeQ1SY9Zymlxtb2KyJ6jQRiFmkWeFx2HVs7w==", "requires": { - "@cspell/cspell-pipe": "^6.12.0", + "@cspell/cspell-pipe": "6.31.1", + "@cspell/cspell-types": "6.31.1", + "@cspell/dynamic-import": "6.31.1", "chalk": "^4.1.2", - "commander": "^9.4.0", - "cspell-gitignore": "^6.12.0", - "cspell-glob": "^6.12.0", - "cspell-lib": "^6.12.0", + "commander": "^10.0.0", + "cspell-gitignore": "6.31.2", + "cspell-glob": "6.31.2", + "cspell-io": "6.31.2", + "cspell-lib": "6.31.2", + "fast-glob": "^3.2.12", "fast-json-stable-stringify": "^2.1.0", "file-entry-cache": "^6.0.1", - "fs-extra": "^10.1.0", "get-stdin": "^8.0.0", - "glob": "^8.0.3", "imurmurhash": "^0.1.4", - "semver": "^7.3.7", + "semver": "^7.3.8", "strip-ansi": "^6.0.1", - "vscode-uri": "^3.0.6" + "vscode-uri": "^3.0.7" } }, "cspell-dictionary": { - "version": "6.12.0", - "resolved": "https://registry.npmjs.org/cspell-dictionary/-/cspell-dictionary-6.12.0.tgz", - "integrity": "sha512-I2cXSdXndt9H7yXmJzLTjgui/SAPGghXwxFeibTbvF68gyQYD5fUXvOygEIPrOEySKlAIb+aouV77SgoURxMHw==", + "version": "6.31.1", + "resolved": "https://registry.npmjs.org/cspell-dictionary/-/cspell-dictionary-6.31.1.tgz", + "integrity": "sha512-7+K7aQGarqbpucky26wled7QSCJeg6VkLUWS+hLjyf0Cqc9Zew5xsLa4QjReExWUJx+a97jbiflITZNuWxgMrg==", "requires": { - "@cspell/cspell-pipe": "^6.12.0", - "@cspell/cspell-types": "^6.12.0", - "cspell-trie-lib": "^6.12.0", + "@cspell/cspell-pipe": "6.31.1", + "@cspell/cspell-types": "6.31.1", + "cspell-trie-lib": "6.31.1", "fast-equals": "^4.0.3", - "gensequence": "^4.0.2" + "gensequence": "^5.0.2" } }, "cspell-gitignore": { - "version": "6.12.0", - "resolved": "https://registry.npmjs.org/cspell-gitignore/-/cspell-gitignore-6.12.0.tgz", - "integrity": "sha512-gtsN2AAvqdE8CHVzpxsQcd/Wn5GAMTjzHpDXX71g/k8IJn743poGU06O0O1WSVAgK0fWTRsfg+V5OegA1TAo7A==", + "version": "6.31.2", + "resolved": "https://registry.npmjs.org/cspell-gitignore/-/cspell-gitignore-6.31.2.tgz", + "integrity": "sha512-B1i8aiXCIbb/08u0K3xnDyXtg0qD+lb5B2itOOXi7KXlPkKvIuN4hWyXxhVDweWyYWEzyXD5wBpPrqICVrStHQ==", "requires": { - "cspell-glob": "^6.12.0", + "cspell-glob": "6.31.2", "find-up": "^5.0.0" } }, "cspell-glob": { - "version": "6.12.0", - "resolved": "https://registry.npmjs.org/cspell-glob/-/cspell-glob-6.12.0.tgz", - "integrity": "sha512-Q0rMGTxDyFFPm1LmHYM0ziuxQt2aXgr8Oi1glA2s0dBs0hg1DexlAEoLwLiMDUwSTvibEKIidPzlrmZ1AUDWEg==", + "version": "6.31.2", + "resolved": "https://registry.npmjs.org/cspell-glob/-/cspell-glob-6.31.2.tgz", + "integrity": "sha512-ceTjHM4HaBgvG5S3oiB+PTPYq58EQYG6MmYpycDHzpR5I2H1NurK9lxWHfANmLbi0DsHn58tIZNDMUnnQj19Jw==", "requires": { "micromatch": "^4.0.5" } }, "cspell-grammar": { - "version": "6.12.0", - "resolved": "https://registry.npmjs.org/cspell-grammar/-/cspell-grammar-6.12.0.tgz", - "integrity": "sha512-WXcDiWJ2pTW0jHY0Bf0DW5s8A9S0a+2tsVZsNxE/0CR5P/8yDSnznE+59uok/JN+GXOKQ6VIaqAZA3/XjDZuuA==", + "version": "6.31.1", + "resolved": "https://registry.npmjs.org/cspell-grammar/-/cspell-grammar-6.31.1.tgz", + "integrity": "sha512-AsRVP0idcNFVSb9+p9XjMumFj3BUV67WIPWApaAzJl/dYyiIygQObRE+si0/QtFWGNw873b7hNhWZiKjqIdoaQ==", "requires": { - "@cspell/cspell-pipe": "^6.12.0", - "@cspell/cspell-types": "^6.12.0" + "@cspell/cspell-pipe": "6.31.1", + "@cspell/cspell-types": "6.31.1" } }, "cspell-io": { - "version": "6.12.0", - "resolved": "https://registry.npmjs.org/cspell-io/-/cspell-io-6.12.0.tgz", - "integrity": "sha512-1faxDj2OMgq61w7GaiXZD7ytks6PksJlG484LMl2USv58jDky4i2lujJs1C/+aP97Box9EcdwzydHX9GpnqqCw==", + "version": "6.31.2", + "resolved": "https://registry.npmjs.org/cspell-io/-/cspell-io-6.31.2.tgz", + "integrity": "sha512-Lp7LsF/f35LaOneROb/9mWiprShz2ONxjYFAt3bYP7gIxq41lWi8QhO+SN6spoqPp/wQXjSqJ7MuTZsemxPRnA==", "requires": { - "@cspell/cspell-service-bus": "^6.12.0", - "node-fetch": "^2.6.7" + "@cspell/cspell-service-bus": "6.31.1", + "node-fetch": "^2.6.9" } }, "cspell-lib": { - "version": "6.12.0", - "resolved": "https://registry.npmjs.org/cspell-lib/-/cspell-lib-6.12.0.tgz", - "integrity": "sha512-IKd2MzH/zoiXohc26Lqb1b8i+41Y2xGreyAe9ihv/7Z2dscGGVy7F/2taZvZK9kJIhaz33Yatxfx3htT6w0hqg==", + "version": "6.31.2", + "resolved": "https://registry.npmjs.org/cspell-lib/-/cspell-lib-6.31.2.tgz", + "integrity": "sha512-LqaB2ZfVfQHKL5aZzYoKU6/UxxAtWeXAYwpC9l+satXmajYyXtAh4kWmuW+y7kKRH2jA79rJQS3QE6ToeSqgQQ==", "requires": { - "@cspell/cspell-bundled-dicts": "^6.12.0", - "@cspell/cspell-pipe": "^6.12.0", - "@cspell/cspell-types": "^6.12.0", + "@cspell/cspell-bundled-dicts": "6.31.2", + "@cspell/cspell-pipe": "6.31.1", + "@cspell/cspell-types": "6.31.1", + "@cspell/strong-weak-map": "6.31.1", "clear-module": "^4.1.2", "comment-json": "^4.2.3", "configstore": "^5.0.1", - "cosmiconfig": "^7.0.1", - "cspell-dictionary": "^6.12.0", - "cspell-glob": "^6.12.0", - "cspell-grammar": "^6.12.0", - "cspell-io": "^6.12.0", - "cspell-trie-lib": "^6.12.0", + "cosmiconfig": "8.0.0", + "cspell-dictionary": "6.31.1", + "cspell-glob": "6.31.2", + "cspell-grammar": "6.31.1", + "cspell-io": "6.31.2", + "cspell-trie-lib": "6.31.1", "fast-equals": "^4.0.3", "find-up": "^5.0.0", - "fs-extra": "^10.1.0", - "gensequence": "^4.0.2", + "gensequence": "^5.0.2", "import-fresh": "^3.3.0", "resolve-from": "^5.0.0", "resolve-global": "^1.0.0", - "vscode-languageserver-textdocument": "^1.0.7", - "vscode-uri": "^3.0.6" + "vscode-languageserver-textdocument": "^1.0.8", + "vscode-uri": "^3.0.7" } }, "cspell-trie-lib": { - "version": "6.12.0", - "resolved": "https://registry.npmjs.org/cspell-trie-lib/-/cspell-trie-lib-6.12.0.tgz", - "integrity": "sha512-SJOdb51Wy3ewaKfttZwc9NYOIXaKlhyr+ykYKBExj3qMfV1J4d4iDLE95FriaRcqnq6X/qEM9jUvZHlvadDk3A==", + "version": "6.31.1", + "resolved": "https://registry.npmjs.org/cspell-trie-lib/-/cspell-trie-lib-6.31.1.tgz", + "integrity": "sha512-MtYh7s4Sbr1rKT31P2BK6KY+YfOy3dWsuusq9HnqCXmq6aZ1HyFgjH/9p9uvqGi/TboMqn1KOV8nifhXK3l3jg==", "requires": { - "@cspell/cspell-pipe": "^6.12.0", - "@cspell/cspell-types": "^6.12.0", - "fs-extra": "^10.1.0", - "gensequence": "^4.0.2" + "@cspell/cspell-pipe": "6.31.1", + "@cspell/cspell-types": "6.31.1", + "gensequence": "^5.0.2" } }, "dot-prop": { @@ -2062,11 +2269,31 @@ "resolved": "https://registry.npmjs.org/fast-equals/-/fast-equals-4.0.3.tgz", "integrity": "sha512-G3BSX9cfKttjr+2o1O22tYMLq0DPluZnYtq1rXumE1SpL/F/SLIfHx08WYQoWSIpeMYf8sRbJ8++71+v6Pnxfg==" }, + "fast-glob": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.0.tgz", + "integrity": "sha512-ChDuvbOypPuNjO8yIDf36x7BlZX1smcUMTTcyoIjycexOxd6DFsKsg21qVBzEmr3G7fUKIRy2/psii+CIUt7FA==", + "requires": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + } + }, "fast-json-stable-stringify": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" }, + "fastq": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", + "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==", + "requires": { + "reusify": "^1.0.4" + } + }, "file-entry-cache": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", @@ -2106,25 +2333,15 @@ "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz", "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==" }, - "fs-extra": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", - "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", - "requires": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - } - }, "fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" }, "gensequence": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/gensequence/-/gensequence-4.0.2.tgz", - "integrity": "sha512-mQiFskYFPFDSUpBJ/n3ebAV2Ufu6DZGvUPXzyWYzFfJr6/DyOOZVnjx6VTWE4y0RLvYWnc5tZq5sCjzEWhRjqQ==" + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/gensequence/-/gensequence-5.0.2.tgz", + "integrity": "sha512-JlKEZnFc6neaeSVlkzBGGgkIoIaSxMgvdamRoPN8r3ozm2r9dusqxeKqYQ7lhzmj2UhFQP8nkyfCaiLQxiLrDA==" }, "get-stdin": { "version": "8.0.0", @@ -2132,15 +2349,24 @@ "integrity": "sha512-sY22aA6xchAzprjyqmSEQv4UbAAzRN0L2dQB0NlN5acTTK9Don6nhoc3eAbUnpZiCANAMfd/+40kVdKfFygohg==" }, "glob": { - "version": "8.0.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-8.0.3.tgz", - "integrity": "sha512-ull455NHSHI/Y1FqGaaYFaLGkNMMJbavMrEGFXG/PGrg6y7sutWHUHrz6gy6WEBH6akM1M414dWKCNs+IhKdiQ==", + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", "requires": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", - "minimatch": "^5.0.1", - "once": "^1.3.0" + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "requires": { + "is-glob": "^4.0.1" } }, "global-dirs": { @@ -2152,9 +2378,9 @@ } }, "graceful-fs": { - "version": "4.2.10", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", - "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" }, "has-flag": { "version": "4.0.0", @@ -2190,6 +2416,11 @@ } } }, + "import-meta-resolve": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/import-meta-resolve/-/import-meta-resolve-2.2.2.tgz", + "integrity": "sha512-f8KcQ1D80V7RnqVm+/lirO9zkOxjGxhaTC1IPrBGd3MEfNgmNG67tSUO9gTi2F3Blr2Az6g1vocaxzkVnWl9MA==" + }, "imurmurhash": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", @@ -2219,6 +2450,19 @@ "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==" }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==" + }, + "is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "requires": { + "is-extglob": "^2.1.1" + } + }, "is-number": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", @@ -2239,20 +2483,19 @@ "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" }, + "js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "requires": { + "argparse": "^2.0.1" + } + }, "json-parse-even-better-errors": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==" }, - "jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", - "requires": { - "graceful-fs": "^4.1.6", - "universalify": "^2.0.0" - } - }, "lines-and-columns": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", @@ -2283,12 +2526,17 @@ }, "dependencies": { "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==" } } }, + "merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==" + }, "micromatch": { "version": "4.0.5", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", @@ -2299,17 +2547,17 @@ } }, "minimatch": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.0.tgz", - "integrity": "sha512-9TPBGGak4nHfGZsPBohm9AWg6NoT7QTCehS3BIJABslyZbzxfV78QM2Y6+i741OPZIafFAaiiEMh5OyIrJPgtg==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "requires": { - "brace-expansion": "^2.0.1" + "brace-expansion": "^1.1.7" } }, "node-fetch": { - "version": "2.6.7", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", - "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", + "version": "2.6.12", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.12.tgz", + "integrity": "sha512-C/fGU2E8ToujUivIO0H+tpQ6HWo4eEmchoPIoXtxCrVghxdKq+QOHqEZW7tuP3KlV3bC8FRMO5nMCC7Zm1VP6g==", "requires": { "whatwg-url": "^5.0.0" } @@ -2377,6 +2625,11 @@ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==" }, + "queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==" + }, "repeat-string": { "version": "1.6.1", "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", @@ -2395,50 +2648,31 @@ "global-dirs": "^0.1.1" } }, + "reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==" + }, "rimraf": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", "requires": { "glob": "^7.1.3" - }, - "dependencies": { - "brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "requires": { - "brace-expansion": "^1.1.7" - } - } + } + }, + "run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "requires": { + "queue-microtask": "^1.2.2" } }, "semver": { - "version": "7.3.8", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", - "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", "requires": { "lru-cache": "^6.0.0" } @@ -2493,20 +2727,15 @@ "crypto-random-string": "^2.0.0" } }, - "universalify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", - "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==" - }, "vscode-languageserver-textdocument": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/vscode-languageserver-textdocument/-/vscode-languageserver-textdocument-1.0.7.tgz", - "integrity": "sha512-bFJH7UQxlXT8kKeyiyu41r22jCZXG8kuuVVA33OEJn1diWOZK5n8zBSPZFHVBOu8kXZ6h0LIRhf5UnCo61J4Hg==" + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/vscode-languageserver-textdocument/-/vscode-languageserver-textdocument-1.0.8.tgz", + "integrity": "sha512-1bonkGqQs5/fxGT5UchTgjGVnfysL0O8v1AYMBjqTbWQTFn721zaPGDYFkOKtfDgFiSgXM3KwaG3FMGfW4Ed9Q==" }, "vscode-uri": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-3.0.6.tgz", - "integrity": "sha512-fmL7V1eiDBFRRnu+gfRWTzyPpNIHJTc4mWnFkwBUmO9U3KPgJAmTx7oxi2bl/Rh6HLdU7+4C9wlj0k2E4AdKFQ==" + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-3.0.7.tgz", + "integrity": "sha512-eOpPHogvorZRobNqJGhapa0JdwaxpjVvyBp0QIUMRMSf8ZAlqOdEquKuRmw9Qwu0qXtJIWqFtMkmvJjUZmMjVA==" }, "webidl-conversions": { "version": "3.0.1", @@ -2548,11 +2777,6 @@ "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" }, - "yaml": { - "version": "1.10.2", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", - "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==" - }, "yocto-queue": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", diff --git a/eng/common/testproxy/dotnet-devcert.crt b/eng/common/testproxy/dotnet-devcert.crt index 07976e52ef0e..254432686db6 100644 --- a/eng/common/testproxy/dotnet-devcert.crt +++ b/eng/common/testproxy/dotnet-devcert.crt @@ -1,20 +1,21 @@ -----BEGIN CERTIFICATE----- -MIIDSDCCAjCgAwIBAgIUIoKu8Oao7j10TLNxaUG2Bs0FrRwwDQYJKoZIhvcNAQEL -BQAwFDESMBAGA1UEAwwJbG9jYWxob3N0MB4XDTIyMDgwNTIxMTcyM1oXDTIzMDgw -NTIxMTcyM1owFDESMBAGA1UEAwwJbG9jYWxob3N0MIIBIjANBgkqhkiG9w0BAQEF -AAOCAQ8AMIIBCgKCAQEA0UPG7ER++5/9D/qa4SCtt7QvdHwcpidbwktPNU8iRW7V -pIDPWS4goLp/+7+maT0Z/mqwSO3JDtm/dtdlr3F/5EMgyUExnYcvUixZAiyFyEwj -j6wnAtNvqsg4rDqBlD17fuqTVsZm9Yo7QYub6p5PeznWYucOxRrczqFCiW4uj0Yk -GgUHPPmCvhSDKowV8CYRHfkD6R8R4SFkoP3/uejXHxeXoYJNMWq5K0GqGaOZtNFB -F7QWZHoLrRpZcY4h+DxwP3c+/FdlVcs9nstkF+EnTnwx5IRyKsaWb/pUEmYKvNDz -wi6qnRUdu+DghZuvyZZDgwoYrSZokcbKumk0MsLC3QIDAQABo4GRMIGOMA8GA1Ud +MIIDZzCCAk+gAwIBAgIUXjY6UxqL53TvxH8dtPNZm6/getIwDQYJKoZIhvcNAQEL +BQAwFDESMBAGA1UEAwwJbG9jYWxob3N0MB4XDTIzMDcyODIxMDM1MloXDTI0MDcy +NzIxMDM1MlowFDESMBAGA1UEAwwJbG9jYWxob3N0MIIBIjANBgkqhkiG9w0BAQEF +AAOCAQ8AMIIBCgKCAQEAsTPe57bim6NTmBHS1ldLAr7dnMT7AMtfttfjqPzggDgR +kNKj/mi5Xd86AOR6QfLMMipdL2NpPTZP557t4V1oVgODv+M3SiKRriY01TNbL9K5 +zjYlPDik1BzKJgHiLmHPmuKsWslTTMO86nau5YNzKfaOIFbiV5uTUCLTZh3NspDo +OaIeJ4Efud/6bHQkbIXggAt2TFjVum+jMXLYeyA8ZjwFgW1ENAlOOV5Gm8eFjkIt +OhQSZLlLc9BnJkOAhT0v6Xq0oRwCm0YW42+JFzmIvjK0cU/sFmjDqzKAxhtWexz7 +WT7KDiJU+GNsZmm8KjeU0EaQpzpK8q/MEbNRX1OqrQIDAQABo4GwMIGtMA8GA1Ud EwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGmMBYGA1UdJQEB/wQMMAoGCCsGAQUF BwMBMBcGA1UdEQEB/wQNMAuCCWxvY2FsaG9zdDA6BgorBgEEAYI3VAEBBCwMKkFT -UC5ORVQgQ29yZSBIVFRQUyBkZXZlbG9wbWVudCBjZXJ0aWZpY2F0ZTANBgkqhkiG -9w0BAQsFAAOCAQEARX4NxGbycdPVuqvu/CO+/LpWrEm1OcOl7N57/mD5npTIJT78 -TYtXk1J61akumKdf5CaBgCDRcl35LhioFZIMEsiOidffAp6t493xocncFBhIYYrZ -HS6aKsZKPu8h3wOLpYu+zh7f0Hx6pkHPAfw4+knmQjDYomz/hTwuo/MuT8k6Ee7B -NGWqxUamLI8bucuf2ZfT1XOq83uWaFF5KwAuVLhpzo39/TmPyYGnaoKRYf9QjabS -LUjecMNLJFWHUSD4cKHvXJjDYZEiCiy+MdUDytWIsfw0fzAUjz9Qaz8YpZ+fXufM -MNMNfyJHSMEMFIT2D1UaQiwryXWQWJ93OiSdjA== +UC5ORVQgQ29yZSBIVFRQUyBkZXZlbG9wbWVudCBjZXJ0aWZpY2F0ZTAdBgNVHQ4E +FgQU+9BDdfBwXH38ti7IGpL4Kn7IDVgwDQYJKoZIhvcNAQELBQADggEBAKoy2dp8 +gsKk1U51164IIhOYisaJ1egOI0++STd8j94SX9XlCAgwLaPr/mU/U438xKI1inSA +Miaboqtt2tqvfP5nceSYL3FPJ3K0ADw8UFgwApKiRYpRevAIspG+OaqHwHUFRhyG +bxkUZ4w96IEpVtDOGoy12sCmChZgdVk44+y8uurSza18Vj1LfkrN6ppZLt4FII5e +p8BFKtqCRToFRJIIjMePOdTUbeRwUCjBPyYv/h5jcJUfFXQJpPXvJs4LFcUivqA3 +sAut3tut6CDzToTMtAD5ebxSPh3DDM6JOsWhrGoT0if5qoio75tG6yV40gi3Tocr +KCwDu8B2O2HlL5Q= -----END CERTIFICATE----- diff --git a/eng/common/testproxy/dotnet-devcert.pfx b/eng/common/testproxy/dotnet-devcert.pfx index a971cd950a1e42e5c03a5f0aebde478d8a70614d..d8f717ce3cbe99ec93d580a07b985b393e0bb631 100644 GIT binary patch literal 2627 zcmai$S5Om(7KQ^Pk%X>-K?u@&Nk9ZaiBb$EaA`}&NC#0sFjRp+Hh^?RI*6euB1`We zRisKly7XQ`l_FIxJNJ(JxDRK}obR7A=k1$=AVN{JG;|0eWDg7x577+y$wYI3hD?Mk z0*R2>b3BP40`>oiz+@s&?Hrvi0nVG^KM4)O`1b%}LSPVL|BQ?XZXo?-L_Tr5oI!_{ zmL7m$1k?ZT8Z86_K)}He%MeW(J31hZIFNP0iVK!m-dq#rS(X;*&*KzGr0e~>*8AS` z#ZXYzf{^mBI4{@J!Lb^7@bdaeF%E^nENkT?NCdO{Ra zabfrmPjpFyVcuoM5m!@M>nVR`yU^^~NyW=5hgb5vAuAjZTe@)6@cW+|R(1{tAI zrd6@wo{lB~u@#{Dm%L?%W|bE`~9nbfzG#AvA!k&lfp)}iee zSBL4OHeT6_;TkG?-3mvYe&zv*@Pv=rolG1tg(FrZ6pyR>S)s*|2j zg#D7cZ5yv0CuOe~`_3KvQ~QL9v8^;BeN?+qt$K3Sj6~wTfKYmRfmJPUs;qpg+-{}U z>5;W>eBiDxL}SGxS&Vn}dSG?l^AfpMsjk^gEl`a94fslIEW;Oc62GbRvmm`F&S=>I zxnG?1p?T)ny_DGL27j$E_bGUcuoz(bS6nuKrM2h*zct8{gKpw7-vUk)s@L5Ihzs!T zYa5;8ufByJoy^=VSF%ib6RshmH}m8E=fOVv#qLm-ew`g!yd8BU2V<=h)dmrhYjcN~ z#=c7&;lxvCv6%|K$J+u(d6!wkh6d3LQd{MkN`&1gFR{6aWxUqB&ugL2A;gejgMnt- z@P~Bi?Dt-gXLF>N?tRB@YK%NgC|hJ_93CxW*+Vh2CwI6-wHq8a2fKdyxgOLobCC?EWH|c*BMOHd%1e8`mn=tDFLgO8d+E65 zX$l9G_y!|bx&gd`rFyWpLZi`on^L6+o=a@0H@zVVo44aVoNAs#=r72I%1bA_eZ?;? zp(Q9r=*|%4MEPfHlV!%Z9^CyX-|o;?KIOCg*A{bbpw=Lwt4{S+zH4RRONQGwDtid) z!m6Xsv2hm}eyW*?q;dq6agurQyU!TpPpNKltqAMptGo{IuQ$^((WR;xs72oo`xqWH z&1i!8s3Bq}@LO}*6jOfDKHEJ3o*J>|Ipu4Y}N_ zMI+!SGmYD@;~T^nWW;^6xPKP9bdNwO_COng(~aDgAoPY74oxZ4fTrsVY_aO0MXAmg zu80?BwPcV6mRE&^dW3cNSROp>{61s4XD72mlsolM*n> z?Y8`{$MDgF{*2J0FJ(VJWZR%`F;RV~&-V*&t|-bb?}8q#rlypypN9 zSr>WTk;7r87AyVrl0fG~unDIveTCJqm@YcvLHRH@@rmYLwJ~(aUQ8rM*ioHzT$kdD z&WL#UjD&2ZGfUXfC)c~MNs44|hdS5Z?N|m@mujJtYgxzF9cwZkyC&xd9>fEftK+8; zn&u~?U!&Qq&AR%BR?PN}B}Tv7(+s-~krL}OKfRv0lqQ<#fKUIC{Z0^3X4I6$y%Oi4 zuum=QSsDljM`1DL(8w^+nHSR|2>6QFny$8kkffMoQ<0&xuJT$au-*IxnmbY3`YiEQ zNKCJ$Ae_QQTKywOln0M3*0LG6cd1$O^)m01#W^QpoRP?#Ff#1~&ehtgEHJ4p^v^aE z-9UQvi1tk+b9(mCQ?HH~BzzP&@@{g5oQG0!vMM?qmy6jq&kNl$LG$DCSv0J%Y{adI zM%3IQc>34pm#c;!8K1jXzcPw{54KC)KjI-l?<6N}Xw+2oI(Pqh8tbolxL+UNozo$8 z?d!DvHwkFp($Jy5rN9Z#QF?X03amyJm!B4fQIYWl9dwWb45z0JaupvvF7@6yoj=sy zTDk6aC5>@uFY&fnl==0&Uo$oat8}?V&ZY`y_3Sbnz!?d6ErE1mK_8&Gl`}E#8-^FX zXHb3Ni$CiD=%RAGLe1IKh+6NaSq}T~1WYRvWbH*eSiqD3b8Lc*4|x8(Qijc@PKS7d zGZlwX6Lm#$rE|y9$ga(j#s>><(jtdlPmnL=@vi5?n(>-HRs;V!tlP4o&1<%+w~tU1 z@v^@ya8H3liLc;P=b>`vqg34ONDq?7zQ zDSl6;uf)=&!^AKj$(T+Rfh>`vkur)J2LwDd;M?T>DHHH!V+FXi&ghe>w~jP)%B7wF zVAWkvQ0z>=XyBC`A&JCb%c%m+E-$i#4ReY8ZfjAnQZkG98#2Pfd3G_iGA2cKbPcO) zK39->oKj^v)Nk_bNFI93_199rQB>0<-kPq`it$9$lvtvhAJiZN@IksT?P)UVb0HKF z;X+mW;OCEHXa2y(OfQE@?2?o^%ds%CfTI8Nez^h;78?i<#ummywb9M5@xiZBV0^R1 z!D@(fe!N>Jma@`7$<7^Ari?I0D?`A?M@ahwhO7 zD6^^nX0G+CZZUCY87yXP^mMpT*||orCnllmf~NgyQ|V3jxnv1Pj)gIkt?6NccP?ow z?Rr)#7yaKQ4h^#odrd0|l-@p$dg%AS21q)$EasV$Y>G^+slb&W1II0Ob z+mKXS7>lGq+(jS}OuyeRS{e`l$QwdvhR@%tI6OwW=*mc(I6AEr|dkVPut S3qbmovc2^DxN@7nRr_BOwaq91 literal 2445 zcmV;833B!@f(eNN0Ru3C2~P$IDuzgg_YDCD0ic2jKm>vbJTQU@I52_(?*<7fhDe6@ z4FLxRpn?P7FoFZz0s#Opf&yE|ZTQfT4iWVwNZb+}`5d0bdif ziJNtXUk{;*nvQ3MhOabxsH+@a_0kox3039v1vEEGpNN|x`?P(W zYiMhcNZ9wP=dc}Pbh8ikg$U1B;p@j~G;zy}R2T&uqC3cbRLWXCR%ctg2=Mp;*6EK> zazpCo%sVM~^b#L+TounBJ|;nwOif61 zK=?X=eAw>y%nto}qwKtO|8rVi!dhscXDs$Cs}){Hiu{K9iG*Uv zldi48axXfL8on>IN{%VrDqSG#QyB0vLcQtGO*;mT0<)(b+L#MvX2yWqS^ayJA+{^? zk(epulk%YQTx4Tsb8A8wKg*SMs5MwYoM(aTTk;(pY5sdw=cSFCOIN~xzZ)}heF85w zQ^1ce9_LDT2X;y?XDsR_Bj?|&0thFkU#|CwVB6?^SW)w>e6x=aNYC~{cRtrCr zS1yi3wX6FVN>v{^R@$YANAZbLQnQ|4%JTuST8g2OWW>XWVXTywq;-B&E60~TT{j~i z0~~$Pi<^znw(lUpj`k~GO)J?g$wl!%3uj0j%^}DRzhc0Z-!aJrk$trVPj5=<7{sOy z;UbeG)j(bza)!Rp6hsz&Zw(o-g(pc$1GqzuJGV$vl#;Qul;c2nk!3&k z>ryv!+t?mR)0WUt+^3zDnDF3mEiw6cNTym5PY;EHw2INA?`SgnmQPF z39QG@*sw{?=rw9%+SQN+gwd;7bzL%6Rso`Qey!>(&W-8%c!KKYTk4_qfi{S?8u?;k zu^d2=2Bse=;^>}(FoFd^1_>&LNQUVaU;V0(ZCA+%8uAzW@ z*1L{%_rVXFA)T(2JNumhI#NYTCGX*}8}A%zB@`Ib{=olmSLzwYh4g+!i~#Jal9F$#V3nuW9w!o8c}pwQH-Q7V`4UBBW@7$3xySUX z=P6zAMar6IdXdklA?OP4#PK{*wLR|{JZv=)gFZvU7`-``;?v*#qYKx^!Y?!+acc&# z0lyphnNf)DRf-)J2jfQ1jPN$)zsfU^T5(hJb)WT;S1MGWmLZZE<~SGZCM#wUM_U1J z0_<>Bt0h(tL`|x5qy;^Pmb9~S!c{{q+=(qjzPH1(g!}$iddA+vHDHF!FR-vlM2^0R zZ+u%K$(+3`pHc_ABlX;m5}nRuNi}n75*CT)_}?tVV`@Tl{W?j$xsPXj5zM;Xg9hjC z6kURaoGJ>P1weQ1C^-5#=;FeD8*%6NM6RS&eDdB%v_`OA+xN!Va@e5<`3~HM>>_NQ zyr{+^bK}9DaM(*^Ycu2X3@SA~!I*HibyS!KFJ@b|9>S^cr z)T4))4rRc;0UA_HFvUnY%-;!I*`v27C+F;TRvhr1w=ya{`FJ+6CUtAiDrKXFvevE+ z(&0?VNTaziW0&G_#|LaM*1&>Ek?$5*NWOFDt3X!tpG>K;>=RLQ^)F5>24xGh+z6aY;kICLeL#}L1>>mL8LLq@TzC!}s=hWU?<c9*SQGz56htwpj zSIFNT-Z2mDdaaa%Z#UbJ7o%vv&(UXsI%}nB;&9&a9{iCRXvYsy0&`fzN$|D6-}4St zEPB<%^pUVXNXq*4IhI?x2VCl2Bp7e_)kdC9!px^2$Ga?+!&u$Y0>|#a?#2+BfjCa? zOv~$I86b9#%vV2UFKSEc-*$I}5jkM*+ja_g1bFR-mu|L7^bhTzNU9<`nhM##6nNsQ zJ9+*d47mriG}ULLQyi_I!4N$CNnzG-fl;Mgc+ZZDW#Sgsl)(g0(P$)*-uV}*j>Faw zREakCBM(9Bh)QH`@hXfQlz99%U?VXlFe3&DDuzgg_YDCF6)_eB6hQ-Ud8Dhy8LAnF z9sVf`{>2f>lQ1zbAutIB1uG5%0vZJX1QfIlj%md)XQrRY&TUn`mX#c;W#/` or `//` etc. -3. The language also used to determine what the [recording directories within a repository are named](https://github.com/Azure/azure-sdk-tools/blob/main/eng/common/testproxy/transition-scripts/generate-assets-json.ps1#L47). +3. The language also used to determine what the [recording directories within a repository are named](https://github.com/Azure/azure-sdk-tools/blob/main/eng/common/testproxy/onboarding/generate-assets-json.ps1#L47). ## A final note about the initial push diff --git a/eng/common/testproxy/transition-scripts/generate-assets-json.ps1 b/eng/common/testproxy/onboarding/generate-assets-json.ps1 similarity index 91% rename from eng/common/testproxy/transition-scripts/generate-assets-json.ps1 rename to eng/common/testproxy/onboarding/generate-assets-json.ps1 index 3f43c7d3adff..3011a19e57aa 100644 --- a/eng/common/testproxy/transition-scripts/generate-assets-json.ps1 +++ b/eng/common/testproxy/onboarding/generate-assets-json.ps1 @@ -138,11 +138,18 @@ class Version { } Function Test-Exe-In-Path { - Param([string] $ExeToLookFor) + Param([string] $ExeToLookFor, [bool]$ExitOnError = $true) if ($null -eq (Get-Command $ExeToLookFor -ErrorAction SilentlyContinue)) { - Write-Error "Unable to find $ExeToLookFor in your PATH" - exit 1 + if ($ExitOnError) { + Write-Error "Unable to find $ExeToLookFor in your PATH" + exit 1 + } + else { + return $false + } } + + return $true } Function Test-TestProxyVersion { @@ -301,18 +308,17 @@ Function Invoke-ProxyCommand { # Get the shorthash directory under PROXY_ASSETS_FOLDER Function Get-AssetsRoot { param( - [string] $AssetsJsonFile + [string] $AssetsJsonFile, + [string] $TestProxyExe ) $repoRoot = Get-Repo-Root $relPath = [IO.Path]::GetRelativePath($repoRoot, $AssetsJsonFile).Replace("`\", "/") $assetsJsonDirectory = Split-Path $relPath - $breadcrumbFile = Join-Path $repoRoot ".assets" ".breadcrumb" - $breadcrumbString = Get-Content $breadcrumbFile | Where-Object { $_.StartsWith($relPath) } - $assetRepo = $breadcrumbString.Split(";")[1] - $assetsPrefix = (Get-Content $AssetsJsonFile | Out-String | ConvertFrom-Json).AssetsRepoPrefixPath + [array] $output = & "$TestProxyExe" config locate -a "$relPath" --storage-location="$repoRoot" + $assetsDirectory = $output[-1] - return Join-Path $repoRoot ".assets" $assetRepo $assetsPrefix $assetsJsonDirectory + return Join-Path $assetsDirectory $assetsJsonDirectory } Function Move-AssetsFromLangRepo { @@ -348,9 +354,29 @@ $language = Get-Repo-Language # in the path and that we're able to map the language's recording # directories if ($InitialPush) { - Test-Exe-In-Path -ExeToLookFor $TestProxyExe + $proxyPresent = Test-Exe-In-Path -ExeToLookFor $TestProxyExe -ExitOnError $false + + # try to fall back + if (-not $proxyPresent) { + $StandaloneTestProxyExe = "Azure.Sdk.Tools.TestProxy" + + if ($IsWindows) { + $StandaloneTestProxyExe += ".exe" + } + + $standalonePresent = Test-Exe-In-Path -ExeToLookFor $StandaloneTestProxyExe -ExitOnError $false + + if ($standalonePresent) { + Write-Host "Default proxy exe $TestProxyExe is not present, but standalone tool $StandaloneTestProxyExe is. Updating proxy exe to use the standalone version." + $TestProxyExe = $StandaloneTestProxyExe + } + else { + Write-Error "The user has selected option InitialPush to push their assets, neither $TestProxyExe nor standalone executable $StandaloneTestProxyExe are installed on this machine." + exit 1 + } + } - if ($TestProxyExe -eq "test-proxy") { + if ($TestProxyExe -eq "test-proxy" -or $TestProxyExe.StartsWith("Azure.Sdk.Tools.TestProxy")) { Test-TestProxyVersion -TestProxyExe $TestProxyExe } @@ -378,7 +404,7 @@ if ($InitialPush) { $CommandArgs = "restore --assets-json-path $assetsJsonRelPath" Invoke-ProxyCommand -TestProxyExe $TestProxyExe -CommandArgs $CommandArgs -TargetDirectory $repoRoot - $assetsRoot = (Get-AssetsRoot -AssetsJsonFile $assetsJsonFile) + $assetsRoot = (Get-AssetsRoot -AssetsJsonFile $assetsJsonFile -TestProxyExe $TestProxyExe) Write-Host "assetsRoot=$assetsRoot" Move-AssetsFromLangRepo -AssetsRoot $assetsRoot diff --git a/eng/common/testproxy/publish-proxy-logs.yml b/eng/common/testproxy/publish-proxy-logs.yml index 543527a4437c..543186edd353 100644 --- a/eng/common/testproxy/publish-proxy-logs.yml +++ b/eng/common/testproxy/publish-proxy-logs.yml @@ -5,12 +5,14 @@ steps: - pwsh: | Copy-Item -Path "${{ parameters.rootFolder }}/test-proxy.log" -Destination "${{ parameters.rootFolder }}/proxy.log" displayName: Copy Log File + condition: succeededOrFailed() - template: ../pipelines/templates/steps/publish-artifact.yml parameters: - ArtifactName: "$(System.JobName)-proxy-logs" + ArtifactName: "$(System.StageName)-$(System.JobName)-$(System.JobAttempt)-proxy-logs" ArtifactPath: "${{ parameters.rootFolder }}/proxy.log" - pwsh: | Remove-Item -Force ${{ parameters.rootFolder }}/proxy.log displayName: Cleanup Copied Log File + condition: succeededOrFailed() diff --git a/eng/common/testproxy/target_version.txt b/eng/common/testproxy/target_version.txt index 2e1adf9ccc4b..3ebae04c3478 100644 --- a/eng/common/testproxy/target_version.txt +++ b/eng/common/testproxy/target_version.txt @@ -1 +1 @@ -1.0.0-dev.20230427.1 +1.0.0-dev.20230802.1 diff --git a/eng/config.json b/eng/config.json index 39a8588ebe8b..070b0daf25b0 100644 --- a/eng/config.json +++ b/eng/config.json @@ -1,5 +1,9 @@ { "Packages": [ + { + "Name": "resourcemanager", + "CoverageGoal": 0.0 + }, { "Name": "azappconfig", "CoverageGoal": 0.19 @@ -22,7 +26,7 @@ }, { "Name": "azidentity", - "CoverageGoal": 0.68 + "CoverageGoal": 0.87 }, { "Name": "azqueue", @@ -36,6 +40,10 @@ "Name": "azfile", "CoverageGoal": 0.75 }, + { + "Name": "azopenai", + "CoverageGoal": 0.39 + }, { "Name": "aztemplate", "CoverageGoal": 0.50 @@ -50,7 +58,7 @@ }, { "Name": "keyvault/azsecrets", - "CoverageGoal": 0.80 + "CoverageGoal": 0.86 }, { "Name": "data", @@ -79,7 +87,7 @@ }, { "Name": "messaging/azservicebus", - "CoverageGoal": 0.50 + "CoverageGoal": 0.48 }, { "Name": "messaging/azeventhubs", @@ -94,12 +102,12 @@ "CoverageGoal": 0.85 }, { - "Name": "resourcemanager", - "CoverageGoal": 0.0 + "Name": "monitor/azingest", + "CoverageGoal": 0.75 }, { "Name": "security/keyvault/azadmin", "CoverageGoal": 0.80 } ] -} +} \ No newline at end of file diff --git a/eng/pipelines/templates/jobs/archetype-go-release.yml b/eng/pipelines/templates/jobs/archetype-go-release.yml index b0f5f2b3baa8..8308e94c1045 100644 --- a/eng/pipelines/templates/jobs/archetype-go-release.yml +++ b/eng/pipelines/templates/jobs/archetype-go-release.yml @@ -5,6 +5,8 @@ parameters: stages: - stage: CheckRelease + variables: + - template: /eng/pipelines/templates/variables/globals.yml displayName: 'Check Release: ${{ parameters.ServiceDirectory }}' dependsOn: ${{ parameters.DependsOn }} condition: and(succeeded(), ne(variables['SetDevVersion'], 'true'), ne(variables['Skip.Release'], 'true'), ne(variables['Build.Repository.Name'], 'Azure/azure-sdk-for-go-pr')) @@ -34,6 +36,8 @@ stages: env: GH_TOKEN: $(azuresdk-github-pat) - stage: Release + variables: + - template: /eng/pipelines/templates/variables/globals.yml displayName: 'Release: ${{ parameters.ServiceDirectory }}' dependsOn: CheckRelease condition: and(succeeded(), eq(dependencies.CheckRelease.outputs['CheckReleaseJob.Verify.NeedToRelease'], 'true')) @@ -98,5 +102,4 @@ stages: PRBranchName: increment-package-version-${{ parameters.ServiceDirectory }}-$(Build.BuildId) CommitMsg: "Increment package version after release of ${{ parameters.ServiceDirectory }}" PRTitle: "Increment version for ${{ parameters.ServiceDirectory }} releases" - PRLabels: "auto-merge" CloseAfterOpenForTesting: '${{ parameters.TestPipeline }}' diff --git a/eng/pipelines/templates/jobs/archetype-sdk-client.yml b/eng/pipelines/templates/jobs/archetype-sdk-client.yml index b7d86177b8e6..b2ce187eb444 100644 --- a/eng/pipelines/templates/jobs/archetype-sdk-client.yml +++ b/eng/pipelines/templates/jobs/archetype-sdk-client.yml @@ -71,25 +71,30 @@ parameters: - name: IncludeRelease type: boolean default: false + - name: ExcludeGoNMinus2 + type: boolean + default: false stages: - stage: Build + variables: + - template: /eng/pipelines/templates/variables/globals.yml jobs: - job: Test displayName: Build and Test on - variables: - - template: /eng/pipelines/templates/variables/globals.yml strategy: matrix: - Linux_Go118: - pool.name: azsdk-pool-mms-ubuntu-2004-general - image.name: MMSUbuntu20.04 - go.version: '1.18.10' - Windows_Go118: - pool.name: azsdk-pool-mms-win-2022-general - image.name: MMS2022 - go.version: '1.18.10' + ${{ if eq(parameters.ExcludeGoNMinus2, false) }}: + Linux_Go118: + pool.name: azsdk-pool-mms-ubuntu-2004-general + image.name: MMSUbuntu20.04 + go.version: '1.18.10' + ${{ if eq(parameters.ExcludeGoNMinus2, false) }}: + Windows_Go118: + pool.name: azsdk-pool-mms-win-2022-general + image.name: MMS2022 + go.version: '1.18.10' Linux_Go119: pool.name: azsdk-pool-mms-ubuntu-2004-general image.name: MMSUbuntu20.04 @@ -140,7 +145,9 @@ stages: - job: Analyze displayName: Analyze variables: - - template: /eng/pipelines/templates/variables/globals.yml + Codeql.Enabled: true + Codeql.BuildIdentifier: ${{ parameters.ServiceDirectory }} + Codeql.SkipTaskAutoInjection: false pool: name: azsdk-pool-mms-ubuntu-2004-general @@ -168,6 +175,8 @@ stages: - ${{ if or(contains(parameters.Clouds, cloud.key), and(contains(variables['Build.DefinitionName'], 'weekly'), contains(parameters.SupportedClouds, cloud.key))) }}: - ${{ if not(contains(parameters.UnsupportedClouds, cloud.key)) }}: - stage: ${{ cloud.key }} + variables: + - template: /eng/pipelines/templates/variables/globals.yml displayName: Live Test ${{ cloud.key }} dependsOn: [] jobs: diff --git a/eng/pipelines/templates/steps/analyze.yml b/eng/pipelines/templates/steps/analyze.yml index aa68d7f5be2d..85390cdf5180 100644 --- a/eng/pipelines/templates/steps/analyze.yml +++ b/eng/pipelines/templates/steps/analyze.yml @@ -40,6 +40,7 @@ steps: - task: Powershell@2 displayName: 'Dependency Check' + condition: ne(variables['Skip.DependencyCheck'], 'true') env: GO111MODULE: 'on' inputs: diff --git a/eng/pipelines/templates/steps/build-test.yml b/eng/pipelines/templates/steps/build-test.yml index 3fc3d3f05d83..ee6283bd046f 100644 --- a/eng/pipelines/templates/steps/build-test.yml +++ b/eng/pipelines/templates/steps/build-test.yml @@ -53,6 +53,8 @@ steps: - ${{ if eq(parameters.TestProxy, true) }}: - template: /eng/common/testproxy/test-proxy-tool.yml + parameters: + targetVersion: '1.0.0-dev.20230427.1' - task: PowerShell@2 displayName: 'Run Tests' diff --git a/eng/pipelines/templates/variables/globals.yml b/eng/pipelines/templates/variables/globals.yml index 98f4404689df..da8c7e8ffbb8 100644 --- a/eng/pipelines/templates/variables/globals.yml +++ b/eng/pipelines/templates/variables/globals.yml @@ -5,3 +5,6 @@ variables: # https://docs.opensource.microsoft.com/tools/cg/index.html # https://github.com/microsoft/component-detection/blob/main/src/Microsoft.ComponentDetection.Detectors/go/GoComponentDetector.cs EnableGoCliScan: true + + # Disable CodeQL injections except for where we specifically enable it + Codeql.SkipTaskAutoInjection: true diff --git a/eng/scripts/MgmtTestLib.ps1 b/eng/scripts/MgmtTestLib.ps1 index f2cb5bbbbb1c..2297704c021d 100644 --- a/eng/scripts/MgmtTestLib.ps1 +++ b/eng/scripts/MgmtTestLib.ps1 @@ -18,9 +18,8 @@ function Invoke-MgmtTestgen () [switch]$tidy, [string]$autorestPath = "", [string]$config = "autorest.md", - [string]$autorestVersion = "3.8.2", - [string]$goExtension = "@autorest/go@4.0.0-preview.48", - [string]$testExtension = "@autorest/gotest@4.6.0", + [string]$goExtension = "@autorest/go@4.0.0-preview.55", + [string]$testExtension = "@autorest/gotest@4.6.2", [string]$outputFolder ) if ($clean) @@ -73,8 +72,8 @@ function Invoke-MgmtTestgen () $removeUnreferencedTypesFlag = "true" } - Write-Host "autorest --version=$autorestVersion --use=$goExtension --use=$testExtension --go --track2 --output-folder=$outputFolder --clear-output-folder=false --go.clear-output-folder=false --generate-sdk=false --testmodeler.generate-mock-test=$mockTestFlag --testmodeler.generate-sdk-example=$exampleFlag --honor-body-placement=$honorBodyPlacement --remove-unreferenced-types=$removeUnreferencedTypesFlag $autorestPath" - npx autorest --version=$autorestVersion --use=$goExtension --use=$testExtension --go --track2 --output-folder=$outputFolder --clear-output-folder=false --go.clear-output-folder=false --generate-sdk=false --testmodeler.generate-mock-test=$mockTestFlag --testmodeler.generate-sdk-example=$exampleFlag --honor-body-placement=$honorBodyPlacement --remove-unreferenced-types=$removeUnreferencedTypesFlag $autorestPath + Write-Host "autorest --use=$goExtension --use=$testExtension --go --track2 --output-folder=$outputFolder --clear-output-folder=false --go.clear-output-folder=false --generate-sdk=false --testmodeler.generate-mock-test=$mockTestFlag --testmodeler.generate-sdk-example=$exampleFlag --honor-body-placement=$honorBodyPlacement --remove-unreferenced-types=$removeUnreferencedTypesFlag $autorestPath" + npx autorest --use=$goExtension --use=$testExtension --go --track2 --output-folder=$outputFolder --clear-output-folder=false --go.clear-output-folder=false --generate-sdk=false --testmodeler.generate-mock-test=$mockTestFlag --testmodeler.generate-sdk-example=$exampleFlag --honor-body-placement=$honorBodyPlacement --remove-unreferenced-types=$removeUnreferencedTypesFlag $autorestPath if ($LASTEXITCODE) { Write-Host "##[error]Error running autorest.gotest" diff --git a/eng/scripts/build.ps1 b/eng/scripts/build.ps1 index 98ebe8614e72..f60ff5d33cd2 100644 --- a/eng/scripts/build.ps1 +++ b/eng/scripts/build.ps1 @@ -11,8 +11,7 @@ param( [switch]$alwaysSetBodyParamRequired, [switch]$removeUnreferencedTypes, [string]$config = "autorest.md", - [string]$autorestVersion = "3.8.2", - [string]$goExtension = "@autorest/go@4.0.0-preview.48", + [string]$goExtension = "@autorest/go@4.0.0-preview.55", [string]$filePrefix, [string]$outputFolder ) @@ -32,7 +31,7 @@ function Process-Sdk () if ($cleanGenerated) { Write-Host "##[command]Cleaning auto-generated files in" $currentDirectory - (Get-ChildItem "*.go" | Where-Object { $_.Name -notlike '*_test.go' } | Select-String -Pattern "Code generated by Microsoft" | Select-Object -ExpandProperty path) | Remove-Item -Force + (Get-ChildItem -recurse "*.go" | Where-Object { $_.Name -notlike '*_test.go' } | Select-String -Pattern "Code generated by Microsoft" | Select-Object -ExpandProperty path) | Remove-Item -Force } if ($generate) @@ -59,13 +58,13 @@ function Process-Sdk () if ($filePrefix) { - Write-Host "autorest --version=$autorestVersion --use=$goExtension --go --track2 --output-folder=$outputFolder --file-prefix=$filePrefix --clear-output-folder=false --go.clear-output-folder=false --honor-body-placement=$honorBodyPlacement --remove-unreferenced-types=$removeUnreferencedTypesFlag $autorestPath" - autorest --version=$autorestVersion --use=$goExtension --go --track2 --output-folder=$outputFolder --file-prefix=$filePrefix --clear-output-folder=false --go.clear-output-folder=false --honor-body-placement=$honorBodyPlacement --remove-unreferenced-types=$removeUnreferencedTypesFlag $autorestPath + Write-Host "autorest --use=$goExtension --go --track2 --output-folder=$outputFolder --file-prefix=$filePrefix --clear-output-folder=false --go.clear-output-folder=false --honor-body-placement=$honorBodyPlacement --remove-unreferenced-types=$removeUnreferencedTypesFlag $autorestPath" + autorest --use=$goExtension --go --track2 --output-folder=$outputFolder --file-prefix=$filePrefix --clear-output-folder=false --go.clear-output-folder=false --honor-body-placement=$honorBodyPlacement --remove-unreferenced-types=$removeUnreferencedTypesFlag $autorestPath } else { - Write-Host "autorest --version=$autorestVersion --use=$goExtension --go --track2 --output-folder=$outputFolder --clear-output-folder=false --go.clear-output-folder=false --honor-body-placement=$honorBodyPlacement --remove-unreferenced-types=$removeUnreferencedTypesFlag $autorestPath" - autorest --version=$autorestVersion --use=$goExtension --go --track2 --output-folder=$outputFolder --clear-output-folder=false --go.clear-output-folder=false --honor-body-placement=$honorBodyPlacement --remove-unreferenced-types=$removeUnreferencedTypesFlag $autorestPath + Write-Host "autorest --use=$goExtension --go --track2 --output-folder=$outputFolder --clear-output-folder=false --go.clear-output-folder=false --honor-body-placement=$honorBodyPlacement --remove-unreferenced-types=$removeUnreferencedTypesFlag $autorestPath" + autorest --use=$goExtension --go --track2 --output-folder=$outputFolder --clear-output-folder=false --go.clear-output-folder=false --honor-body-placement=$honorBodyPlacement --remove-unreferenced-types=$removeUnreferencedTypesFlag $autorestPath } if ($LASTEXITCODE) diff --git a/eng/tools/generator/autorest/generation.go b/eng/tools/generator/autorest/generation.go index 9bc0e3d06361..9078f75d1683 100644 --- a/eng/tools/generator/autorest/generation.go +++ b/eng/tools/generator/autorest/generation.go @@ -292,7 +292,7 @@ func scannerPrint(scanner *bufio.Scanner, writer io.Writer, prefix string) error } for scanner.Scan() { line := scanner.Text() - if _, err := fmt.Fprintln(writer, fmt.Sprintf("%s%s", prefix, line)); err != nil { + if _, err := fmt.Fprintf(writer, "%s%s\n", prefix, line); err != nil { return err } } diff --git a/eng/tools/generator/autorest/model/changelog.go b/eng/tools/generator/autorest/model/changelog.go index 448ab4eb8926..bed024cce453 100644 --- a/eng/tools/generator/autorest/model/changelog.go +++ b/eng/tools/generator/autorest/model/changelog.go @@ -68,7 +68,7 @@ func (c Changelog) GetChangeSummary() string { func (c Changelog) GetBreakingChangeItems() []string { if c.RemovedPackage { return []string{ - fmt.Sprintf("Package was removed"), + "Package was removed", } } if c.Modified == nil { diff --git a/eng/tools/generator/cmd/v2/common/changelogProcessor_test.go b/eng/tools/generator/cmd/v2/common/changelogProcessor_test.go index 45fbb18b8ee8..35faa8bc88a3 100644 --- a/eng/tools/generator/cmd/v2/common/changelogProcessor_test.go +++ b/eng/tools/generator/cmd/v2/common/changelogProcessor_test.go @@ -4,7 +4,6 @@ package common_test import ( - "fmt" "testing" "github.com/Azure/azure-sdk-for-go/eng/tools/generator/autorest" @@ -31,7 +30,7 @@ func TestEnumFilter(t *testing.T) { common.FilterChangelog(changelog, common.EnumFilter) - excepted := fmt.Sprint("### Breaking Changes\n\n- Enum `EnumRemove` has been removed\n\n### Features Added\n\n- New value `EnumExistB` added to enum type `EnumExist`\n- New enum type `EnumAdd` with values `EnumAddA`, `EnumAddB`\n") + excepted := "### Breaking Changes\n\n- Enum `EnumRemove` has been removed\n\n### Features Added\n\n- New value `EnumExistB` added to enum type `EnumExist`\n- New enum type `EnumAdd` with values `EnumAddA`, `EnumAddB`\n" assert.Equal(t, excepted, changelog.ToCompactMarkdown()) } @@ -53,7 +52,7 @@ func TestFuncFilter(t *testing.T) { common.FilterChangelog(changelog, common.FuncFilter) - excepted := fmt.Sprint("### Breaking Changes\n\n- Function `*Client.BeingDelete` has been removed\n- Function `*Client.NewListPager` has been removed\n- Function `*Client.Update` has been removed\n\n### Features Added\n\n- New function `*Client.BeginCreateOrUpdate(string, *ClientBeginCreateOrUpdateOptions) (ClientBeginCreateOrUpdateResponse, error)`\n- New function `*Client.NewListBySubscriptionPager(*ClientListBySubscriptionOptions) *runtime.Pager[ClientListBySubscriptionResponse]`\n") + excepted := "### Breaking Changes\n\n- Function `*Client.BeingDelete` has been removed\n- Function `*Client.NewListPager` has been removed\n- Function `*Client.Update` has been removed\n\n### Features Added\n\n- New function `*Client.BeginCreateOrUpdate(string, *ClientBeginCreateOrUpdateOptions) (ClientBeginCreateOrUpdateResponse, error)`\n- New function `*Client.NewListBySubscriptionPager(*ClientListBySubscriptionOptions) *runtime.Pager[ClientListBySubscriptionResponse]`\n" assert.Equal(t, excepted, changelog.ToCompactMarkdown()) } @@ -75,7 +74,7 @@ func TestLROFilter(t *testing.T) { common.FilterChangelog(changelog, common.FuncFilter, common.LROFilter) - excepted := fmt.Sprint("### Breaking Changes\n\n- Operation `*Client.BeginDelete` has been changed to non-LRO, use `*Client.Delete` instead.\n- Operation `*Client.CreateOrUpdate` has been changed to LRO, use `*Client.BeginCreateOrUpdate` instead.\n") + excepted := "### Breaking Changes\n\n- Operation `*Client.BeginDelete` has been changed to non-LRO, use `*Client.Delete` instead.\n- Operation `*Client.CreateOrUpdate` has been changed to LRO, use `*Client.BeginCreateOrUpdate` instead.\n" assert.Equal(t, excepted, changelog.ToCompactMarkdown()) } @@ -97,7 +96,7 @@ func TestPageableFilter(t *testing.T) { common.FilterChangelog(changelog, common.FuncFilter, common.PageableFilter) - excepted := fmt.Sprint("### Breaking Changes\n\n- Operation `*Client.GetLog` has supported pagination, use `*Client.NewGetLogPager` instead.\n- Operation `*Client.NewListPager` does not support pagination anymore, use `*Client.List` instead.\n") + excepted := "### Breaking Changes\n\n- Operation `*Client.GetLog` has supported pagination, use `*Client.NewGetLogPager` instead.\n- Operation `*Client.NewListPager` does not support pagination anymore, use `*Client.List` instead.\n" assert.Equal(t, excepted, changelog.ToCompactMarkdown()) } @@ -119,7 +118,7 @@ func TestInterfaceToAnyFilter(t *testing.T) { common.FilterChangelog(changelog, common.InterfaceToAnyFilter) - excepted := fmt.Sprint("### Breaking Changes\n\n- Type of `Interface2Any.NewType` has been changed from `interface{}` to `string`\n") + excepted := "### Breaking Changes\n\n- Type of `Interface2Any.NewType` has been changed from `interface{}` to `string`\n" assert.Equal(t, excepted, changelog.ToCompactMarkdown()) } @@ -139,7 +138,7 @@ func TestTypeToAny(t *testing.T) { t.Fatal(err) } - excepted := fmt.Sprint("### Breaking Changes\n\n- Type of `Client.M` has been changed from `map[string]string` to `map[string]any`\n\n### Features Added\n\n- Type of `Client.A` has been changed from `*int` to `any`\n") + excepted := "### Breaking Changes\n\n- Type of `Client.M` has been changed from `map[string]string` to `map[string]any`\n\n### Features Added\n\n- Type of `Client.A` has been changed from `*int` to `any`\n" assert.Equal(t, excepted, changelog.ToCompactMarkdown()) } @@ -161,6 +160,6 @@ func TestFuncParameterChange(t *testing.T) { common.FilterChangelog(changelog, common.FuncFilter) - excepted := fmt.Sprint("### Breaking Changes\n\n- Function `*Client.AfterAny` parameter(s) have been changed from `(context.Context, string, string, interface{}, ClientOption)` to `(context.Context, string, string, any, Option)`\n- Function `*Client.BeforeAny` parameter(s) have been changed from `(context.Context, string, string, interface{}, ClientOption)` to `(context.Context, string, any, any, ClientOption)`\n") + excepted := "### Breaking Changes\n\n- Function `*Client.AfterAny` parameter(s) have been changed from `(context.Context, string, string, interface{}, ClientOption)` to `(context.Context, string, string, any, Option)`\n- Function `*Client.BeforeAny` parameter(s) have been changed from `(context.Context, string, string, interface{}, ClientOption)` to `(context.Context, string, any, any, ClientOption)`\n" assert.Equal(t, excepted, changelog.ToCompactMarkdown()) } diff --git a/eng/tools/generator/cmd/v2/common/fileProcessor.go b/eng/tools/generator/cmd/v2/common/fileProcessor.go index 1636f36bbe5c..30e625af72e3 100644 --- a/eng/tools/generator/cmd/v2/common/fileProcessor.go +++ b/eng/tools/generator/cmd/v2/common/fileProcessor.go @@ -5,6 +5,7 @@ package common import ( "fmt" + "io/fs" "io/ioutil" "log" "os" @@ -287,7 +288,10 @@ func CalculateNewVersion(changelog *model.Changelog, previousVersion string, isC } else { prl = FirstGALabel } - } else if changelog.HasBreakingChanges() || changelog.Modified.HasAdditiveChanges() { + } else if changelog.HasBreakingChanges() { + newVersion = version.IncMinor() + prl = BetaBreakingChangeLabel + } else if changelog.Modified.HasAdditiveChanges() { newVersion = version.IncMinor() prl = BetaLabel } else { @@ -492,3 +496,73 @@ func AddTagSet(path, tag string) error { return os.WriteFile(path, []byte(strings.Join(lines, "\n")), 0644) } + +func isGenerateFake(path string) bool { + b, _ := os.ReadFile(filepath.Join(path, "autorest.md")) + if strings.Contains(string(b), "generate-fakes: true") { + return true + } + + return false +} + +func replaceModuleImport(path, rpName, namespaceName, previousVersion, currentVersion, subPath string, suffixes ...string) error { + previous, err := semver.NewVersion(previousVersion) + if err != nil { + return err + } + + current, err := semver.NewVersion(currentVersion) + if err != nil { + return err + } + + if previous.Major() == current.Major() { + return nil + } + + oldModule := fmt.Sprintf("github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/%s/%s", rpName, namespaceName) + if previous.Major() > 1 { + oldModule = fmt.Sprintf("%s/v%d", oldModule, previous.Major()) + } + + newModule := fmt.Sprintf("github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/%s/%s", rpName, namespaceName) + if current.Major() > 1 { + newModule = fmt.Sprintf("%s/v%d", newModule, current.Major()) + } + + if oldModule == newModule { + return nil + } + + return filepath.Walk(filepath.Join(path, subPath), func(path string, info fs.FileInfo, err error) error { + if err != nil { + return err + } + + if info.IsDir() { + return nil + } + + suffix := false + for i := 0; i < len(suffixes) && !suffix; i++ { + suffix = strings.HasSuffix(info.Name(), suffixes[i]) + } + + if suffix { + b, err := os.ReadFile(path) + if err != nil { + return err + } + + newFile := strings.ReplaceAll(string(b), oldModule, newModule) + if newFile != string(b) { + if err = os.WriteFile(path, []byte(newFile), 0666); err != nil { + return err + } + } + } + + return nil + }) +} diff --git a/eng/tools/generator/cmd/v2/common/fileProcessor_test.go b/eng/tools/generator/cmd/v2/common/fileProcessor_test.go index b859f5daecf7..fdaeac0822ca 100644 --- a/eng/tools/generator/cmd/v2/common/fileProcessor_test.go +++ b/eng/tools/generator/cmd/v2/common/fileProcessor_test.go @@ -41,7 +41,7 @@ func TestCalculateNewVersion(t *testing.T) { newVersion, prl, err = CalculateNewVersion(breakingChange, "0.5.0", true) assert.NoError(t, err) assert.Equal(t, newVersion.String(), "0.6.0") - assert.Equal(t, BetaLabel, prl) + assert.Equal(t, BetaBreakingChangeLabel, prl) // additive with stable newVersion, prl, err = CalculateNewVersion(additiveChange, "0.5.0", false) diff --git a/eng/tools/generator/cmd/v2/common/generation.go b/eng/tools/generator/cmd/v2/common/generation.go index 6d5a408b220c..643e56c1ecec 100644 --- a/eng/tools/generator/cmd/v2/common/generation.go +++ b/eng/tools/generator/cmd/v2/common/generation.go @@ -173,7 +173,7 @@ func (ctx *GenerateContext) GenerateForSingleRPNamespace(generateParam *Generate } // add tag set - if !generateParam.RemoveTagSet && generateParam.NamespaceConfig != "" { + if !generateParam.RemoveTagSet && generateParam.NamespaceConfig != "" && !onBoard { log.Printf("Add tag in `autorest.md`...") autorestMdPath := filepath.Join(packagePath, "autorest.md") if err := AddTagSet(autorestMdPath, generateParam.NamespaceConfig); err != nil { @@ -298,6 +298,14 @@ func (ctx *GenerateContext) GenerateForSingleRPNamespace(generateParam *Generate return nil, err } + if changelog.HasBreakingChanges() && isGenerateFake(packagePath) { + log.Printf("Replace fake module v2+...") + if err = replaceModuleImport(packagePath, generateParam.RPName, generateParam.NamespaceName, previousVersion, version.String(), + "fake", "_server.go"); err != nil { + return nil, err + } + } + // Example generation should be the last step because the package import relay on the new calculated version if !generateParam.SkipGenerateExample { log.Printf("Generate examples...") diff --git a/eng/tools/generator/cmd/v2/release/releaseCmd.go b/eng/tools/generator/cmd/v2/release/releaseCmd.go index 4b4a96e4d753..78a0ddb4ffb6 100644 --- a/eng/tools/generator/cmd/v2/release/releaseCmd.go +++ b/eng/tools/generator/cmd/v2/release/releaseCmd.go @@ -183,6 +183,7 @@ func (c *commandContext) generate(sdkRepo repo.SDKRepository, specCommitHash str } func (c *commandContext) generateFromRequest(sdkRepo repo.SDKRepository, specRepoParam, specCommitHash string) error { + var generateErr []error var pullRequestUrls = make(map[string]string) var pushBranch = make(map[string]struct { requestLink string @@ -220,7 +221,8 @@ func (c *commandContext) generateFromRequest(sdkRepo repo.SDKRepository, specRep } err = c.generate(sdkRepo, specCommitHash) if err != nil { - return err + generateErr = append(generateErr, err) + continue } // get current branch name @@ -289,5 +291,12 @@ func (c *commandContext) generateFromRequest(sdkRepo repo.SDKRepository, specRep } } + if len(generateErr) != 0 { + fmt.Println("generator error:") + for _, e := range generateErr { + fmt.Println(e) + } + } + return nil } diff --git a/eng/tools/generator/template/rpName/packageName/README.md.tpl b/eng/tools/generator/template/rpName/packageName/README.md.tpl index a907bff3ba5a..5b1302fb2758 100644 --- a/eng/tools/generator/template/rpName/packageName/README.md.tpl +++ b/eng/tools/generator/template/rpName/packageName/README.md.tpl @@ -49,7 +49,7 @@ options := arm.ClientOptions { Cloud: cloud.AzureChina, }, } -client, err := {{packageName}}.NewClientFactory(, cred, &options) +clientFactory, err := {{packageName}}.NewClientFactory(, cred, &options) ``` ## Clients diff --git a/eng/tools/internal/report/packages.go b/eng/tools/internal/report/packages.go index 3a737f458803..d7f622295624 100644 --- a/eng/tools/internal/report/packages.go +++ b/eng/tools/internal/report/packages.go @@ -123,17 +123,13 @@ func (c *CommitPkgsReport) UpdateAffectedPackages(commit string, r PkgsReport) { c.AffectedPackages = map[string]PkgsList{} } - for _, pkg := range r.AddedPackages { - c.AffectedPackages[commit] = append(c.AffectedPackages[commit], pkg) - } + c.AffectedPackages[commit] = append(c.AffectedPackages[commit], r.AddedPackages...) for pkgName := range r.ModifiedPackages { c.AffectedPackages[commit] = append(c.AffectedPackages[commit], pkgName) } - for _, pkg := range r.RemovedPackages { - c.AffectedPackages[commit] = append(c.AffectedPackages[commit], pkg) - } + c.AffectedPackages[commit] = append(c.AffectedPackages[commit], r.RemovedPackages...) } // PkgsReport represents a complete report of added, removed, and modified packages diff --git a/eng/tools/mgmtreport/mgmtreport.tpl b/eng/tools/mgmtreport/mgmtreport.tpl index 267998a4b506..1c8055c24cfb 100644 --- a/eng/tools/mgmtreport/mgmtreport.tpl +++ b/eng/tools/mgmtreport/mgmtreport.tpl @@ -4,7 +4,11 @@ Azure GO SDK MGMT REPORT - + + + + +